diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9f86836a..86105bfb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,25 +5,10 @@ stages: - cleanup ############################################ -# System templates +# Windows ############################################ -# Windows -.template_windows_32: &win32 - tags: - - windows - - x86 - before_script: - - "echo off" - - 'call "%VS140COMNTOOLS%\..\..\VC\bin\vcvars32.bat"' - - set CMAKE_GENERATOR=Visual Studio 14 2015 - - set CI_DIR=C:\ci\%CI_BUILD_REF%_32 - - set NETGEN_BUILD_DIR=%CI_DIR%\build - - set INSTALL_DIR=%CI_DIR%\install - - set NETGENDIR=%INSTALL_DIR%\bin - - set PYTHONPATH=%INSTALL_DIR%\lib\site-packages - -.template_windows_64: &win64 +.template_windows: &win tags: - windows - x64 @@ -31,37 +16,14 @@ stages: - "echo off" - 'call "%VS140COMNTOOLS%\..\..\VC\bin\amd64\vcvars64.bat"' - set CMAKE_GENERATOR=Visual Studio 14 2015 Win64 - - set CI_DIR=C:\ci\%CI_BUILD_REF%_64 + - set CI_DIR=C:\ci\%CI_PIPELINE_ID% - set NETGEN_BUILD_DIR=%CI_DIR%\build - set INSTALL_DIR=%CI_DIR%\install - set NETGENDIR=%INSTALL_DIR%\bin - set PYTHONPATH=%INSTALL_DIR%\lib\site-packages -# Linux -.template_ubuntu: &ubuntu - tags: - - linux - before_script: - - pwd - - ls - - docker info - -.template_ubuntu_1510: &ubuntu_1510 - <<: *ubuntu - variables: - UBUNTU_VERSION: "15.10" - -.template_ubuntu_1604: &ubuntu_1604 - <<: *ubuntu - variables: - UBUNTU_VERSION: "16.04" - -############################################ -# Build stage -############################################ - -# Windows -.template_build_win: &tbuild_netgen_win +build_win: + <<: *win stage: build script: - git submodule update --init --recursive @@ -76,66 +38,52 @@ stages: -DCMAKE_BUILD_TYPE=Release - cmake --build . --target INSTALL --config Release -.build_netgen_win32: - <<: *win32 - <<: *tbuild_netgen_win - cache: - paths: - - build/ - - src/ - key: "netgen_win32_${CI_BUILD_REF_NAME}" +test_win: + <<: *win + stage: test + script: + - cd %NETGEN_BUILD_DIR%\netgen + - ctest -C Release -V + - cd .. -build_netgen_win64: - <<: *win64 - <<: *tbuild_netgen_win - cache: - paths: - - build/ - - src/ - key: "netgen_win64_${CI_BUILD_REF_NAME}" +cleanup_win: + <<: *win + stage: cleanup + tags: + - windows + - x64 + script: + - cd %CI_PROJECT_DIR% + - rd /s /q %CI_DIR% + when: always + allow_failure: true -# Linux -.template_build_linux: &build_linux +############################################ +# Ubuntu/Linux +############################################ + +.template_ubuntu: &ubuntu + tags: + - linux + before_script: + - pwd + - ls + - docker info + variables: + UBUNTU_VERSION: "18.04" + +build_ubuntu: + <<: *ubuntu stage: build script: - - docker build -t netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} -f tests/docker_${UBUNTU_VERSION} . + - docker build -t netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} -f tests/dockerfile . - rm -f netgen_${CI_BUILD_REF_NAME}_$UBUNTU_VERSION.id - docker run --cidfile netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build.sh - docker commit `cat netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id` netgen_${CI_BUILD_REF_NAME}_installed:${UBUNTU_VERSION} - rm netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id -.build_ubuntu_1510: - <<: *ubuntu_1510 - <<: *build_linux - -build_ubuntu_1604: - <<: *ubuntu_1604 - <<: *build_linux - - -############################################ -# Test stage -############################################ - -# Windows -.template_test_win: &test_win - stage: test - script: - - cd %NETGEN_BUILD_DIR%/netgen - - ctest -C Release -V - - cd .. - -# skip since we have no machine with 32 bits -.test_win32: - <<: *win32 - <<: *test_win - -test_win64: - <<: *win64 - <<: *test_win - -# Linux -.template_test_linux: &test_linux +test_ubuntu: + <<: *ubuntu stage: test script: - >- @@ -145,12 +93,76 @@ test_win64: netgen_${CI_BUILD_REF_NAME}_installed:${UBUNTU_VERSION} bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V"' -.test_ubuntu_1510: - <<: *ubuntu_1510 - <<: *test_linux -test_ubuntu_1604: - <<: *ubuntu_1604 - <<: *test_linux +# cpp guideline checks +test_guidelines: + <<: *ubuntu + stage: test + script: + - docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh + when: always + +cleanup_ubuntu: + stage: cleanup + tags: + - linux + script: + # remove intermediate and old docker images and containers + - docker rm -f `docker ps --no-trunc -aq` + - docker images --no-trunc -aqf "dangling=true" | xargs docker rmi -f || true + when: always + allow_failure: true + +############################################ +# MacOSX +############################################ + +.template_mac: &mac + tags: + - mac + before_script: + - export ROOT_DIR=/tmp/$CI_PIPELINE_ID + - 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 PATH=$CMAKE_INSTALL_PREFIX/Contents/MacOS:$PATH + +build_mac: + <<: *mac + stage: build + script: + - git submodule update --init --recursive + - rm -rf $BUILD_DIR + - mkdir -p $BUILD_DIR + - rm -rf $SRC_DIR + - mkdir -p $SRC_DIR + - cp -a . $SRC_DIR/ + - cd $BUILD_DIR + - >- + cmake $SRC_DIR + -DCMAKE_INSTALL_PREFIX=$CMAKE_INSTALL_PREFIX + -DCMAKE_BUILD_TYPE=Release + -DUSE_NATIVE_ARCH=OFF + -DUSE_CCACHE=ON + -DENABLE_UNIT_TESTS=ON + -DCMAKE_OSX_DEPLOYMENT_TARGET=10.9 + -DCMAKE_OSX_SYSROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk + - make -j5 install + +test_mac: + <<: *mac + stage: test + script: + - cd $BUILD_DIR/netgen + - ctest . --output-on-failure + +cleanup_mac: + <<: *mac + stage: cleanup + script: + - rm -rf $ROOT_DIR + when: always + allow_failure: true ############################################ # Deploy stage @@ -171,43 +183,3 @@ deploy_sourceforge: - git push github master only: - master - -############################################ -# Cleanup stage -############################################ - -linux_cleanup: - stage: cleanup - tags: - - linux - script: - # remove intermediate and old docker images and containers - - docker rm -f `docker ps --no-trunc -aq` - - docker images --no-trunc -aqf "dangling=true" | xargs docker rmi -f - when: always - allow_failure: true - -win64_cleanup: - <<: *win64 - stage: cleanup - tags: - - windows - - x64 - script: - - cd %CI_PROJECT_DIR% - - rd /s /q %CI_DIR% - when: always - allow_failure: true - -.win32_cleanup: - <<: *win32 - stage: cleanup - tags: - - windows - - x86 - script: - - cd %CI_PROJECT_DIR% - - rd /s /q %CI_DIR% - when: always - allow_failure: true - diff --git a/.gitmodules b/.gitmodules index fccd5ba0..e6108291 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "external_dependencies/pybind11"] path = external_dependencies/pybind11 - url = https://github.com/pybind/pybind11.git + url = https://github.com/ngsolve/pybind11.git diff --git a/CMakeLists.txt b/CMakeLists.txt index ef0ee424..14931c4d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,8 @@ option( INTEL_MIC "cross compile for intel xeon phi") option( INSTALL_PROFILES "install environment variable settings to /etc/profile.d" OFF ) 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_SUPERBUILD "use ccache" ON) @@ -341,8 +343,27 @@ execute_process(COMMAND hdiutil create -volname Netgen -srcfolder ${CMAKE_INSTAL enable_testing() include(CTest) +if(ENABLE_UNIT_TESTS) + include(${CMAKE_CURRENT_LIST_DIR}/cmake/external_projects/catch.cmake) +endif(ENABLE_UNIT_TESTS) + + ####################################################################### +if(ENABLE_CPP_CORE_GUIDELINES_CHECK) + find_program( + CLANG_TIDY_EXE + NAMES "clang-tidy" + DOC "Path to clang-tidy executable" + ) + if(NOT CLANG_TIDY_EXE) + message(WARNING "clang-tidy not found.") + else() + message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}") + set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-header-filter=libsrc/core/") + endif() +endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) + add_subdirectory(libsrc) add_subdirectory(ng) add_subdirectory(tutorials) diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 86daba2e..36ea3fcb 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -121,6 +121,8 @@ set_vars( NETGEN_CMAKE_ARGS CMAKE_SHARED_LINKER_FLAGS_RELEASE CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_RELEASE + CMAKE_OSX_DEPLOYMENT_TARGET + CMAKE_OSX_SYSROOT USE_GUI USE_PYTHON @@ -138,6 +140,8 @@ set_vars( NETGEN_CMAKE_ARGS INTEL_MIC CMAKE_PREFIX_PATH CMAKE_INSTALL_PREFIX + ENABLE_UNIT_TESTS + ENABLE_CPP_CORE_GUIDELINES_CHECK ) # propagate all variables set on the command line using cmake -DFOO=BAR diff --git a/cmake/external_projects/catch.cmake b/cmake/external_projects/catch.cmake new file mode 100644 index 00000000..0f79e6c7 --- /dev/null +++ b/cmake/external_projects/catch.cmake @@ -0,0 +1,18 @@ +include (ExternalProject) +find_program(GIT_EXECUTABLE git) +ExternalProject_Add( + project_catch + PREFIX ${CMAKE_BINARY_DIR}/catch + GIT_REPOSITORY https://github.com/catchorg/Catch2.git + GIT_TAG v2.0.1 + TIMEOUT 10 + UPDATE_COMMAND "" # ${GIT_EXECUTABLE} pull + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + +# Expose required variable (CATCH_INCLUDE_DIR) to parent scope +ExternalProject_Get_Property(project_catch source_dir) +set(CATCH_INCLUDE_DIR ${source_dir}/single_include CACHE INTERNAL "Path to include folder for Catch") diff --git a/cmake/external_projects/metis.cmake b/cmake/external_projects/metis.cmake index aa997e9e..0e5f4711 100644 --- a/cmake/external_projects/metis.cmake +++ b/cmake/external_projects/metis.cmake @@ -3,8 +3,8 @@ set(METIS_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/metis) ExternalProject_Add(project_metis PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dependencies - URL "http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/metis-5.1.0.tar.gz" - URL_MD5 5465e67079419a69e0116de24fce58fe + URL "http://ftp.mcs.anl.gov/pub/petsc/externalpackages/metis-5.1.0-p3.tar.gz" + URL_MD5 09d2d771c63a2efb3499882688100088 DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies CMAKE_ARGS -DGKLIB_PATH=${METIS_SRC_DIR}/GKlib diff --git a/cmake/external_projects/tcltk.cmake b/cmake/external_projects/tcltk.cmake index 3ef3c6b5..b7f0ba85 100644 --- a/cmake/external_projects/tcltk.cmake +++ b/cmake/external_projects/tcltk.cmake @@ -1,77 +1,61 @@ if(APPLE) # use system tcl/tk - find_package(TCL 8.5 REQUIRED) -# set(HOME $ENV{HOME}) -# set(tcl_prefix ${CMAKE_INSTALL_PREFIX}/../../) -# ExternalProject_Add(project_tcl -# URL "http://sourceforge.net/projects/tcl/files/Tcl/8.6.4/tcl8.6.4-src.tar.gz" -# URL_MD5 d7cbb91f1ded1919370a30edd1534304 -# DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies -# UPDATE_COMMAND "" # Disable update -# CONFIGURE_COMMAND ../project_tcl/macosx/configure --enable-threads --enable-framework --prefix=${tcl_prefix} --libdir=${tcl_prefix}/Contents/Frameworks --bindir=${tcl_prefix}/Contents/Frameworks/Tcl.framework/bin -# BUILD_COMMAND make -j4 binaries libraries -# INSTALL_COMMAND make install-binaries install-headers install-libraries install-private-headers -# LOG_DOWNLOAD 1 -# LOG_BUILD 1 -# LOG_CONFIGURE 1 -# LOG_INSTALL 1 -# ) -# -# ExternalProject_Add(project_tk -# DEPENDS project_tcl -# URL "http://sourceforge.net/projects/tcl/files/Tcl/8.6.4/tk8.6.4-src.tar.gz" -# URL_MD5 261754d7dc2a582f00e35547777e1fea -# DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies -# UPDATE_COMMAND "" # Disable update -# CONFIGURE_COMMAND ../project_tk/macosx/configure --enable-aqua=yes --enable-threads --enable-framework --prefix=${tcl_prefix} --libdir=${tcl_prefix}/Contents/Frameworks --bindir=${tcl_prefix}/Contents/Frameworks/Tcl.framework/bin --with-tcl=${tcl_prefix}/Contents/Frameworks/Tcl.framework -# BUILD_COMMAND make -j4 binaries libraries -# INSTALL_COMMAND make install-binaries install-headers install-libraries install-private-headers -# LOG_DOWNLOAD 1 -# LOG_BUILD 1 -# LOG_CONFIGURE 1 -# LOG_INSTALL 1 -# ) -# -# ExternalProject_Add(project_tkdnd -# URL "https://sourceforge.net/projects/tkdnd/files/OS%20X%20Binaries/TkDND%202.8/tkdnd2.8-OSX-MountainLion.tar.gz" -# URL_MD5 2dbb471b1d66c5f391f3c3c5b71548fb -# DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies -# BUILD_IN_SOURCE 1 -# CONFIGURE_COMMAND "" -# BUILD_COMMAND "" -# INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}/../MacOS -# LOG_DOWNLOAD 1 -# LOG_CONFIGURE 1 -# LOG_BUILD 1 -# LOG_INSTALL 1 -# ) -# -# list(APPEND NETGEN_DEPENDENCIES project_tcl project_tk project_tkdnd) -# list(APPEND CMAKE_PREFIX_PATH ${CMAKE_INSTALL_PREFIX}../Frameworks) -# set(TCL_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/../Frameworks/Tcl.framework/Headers) -# set(TCL_LIBRARY ${CMAKE_INSTALL_PREFIX}/../Frameworks/Tcl.framework) -# set(TK_LIBRARY ${CMAKE_INSTALL_PREFIX}/../Frameworks/Tk.framework) -# set(TK_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/../Frameworks/Tk.framework/Headers) -# + if(${PYTHON_VERSION_STRING} STREQUAL "3.7") + # fetch tcl/tk sources to match the one used in Python 3.7 + ExternalProject_Add(project_tcl + URL "https://prdownloads.sourceforge.net/tcl/tcl8.6.8-src.tar.gz" + URL_MD5 81656d3367af032e0ae6157eff134f89 + DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies + UPDATE_COMMAND "" # Disable update + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + ExternalProject_Add(project_tk + URL "https://prdownloads.sourceforge.net/tcl/tk8.6.8-src.tar.gz" + URL_MD5 5e0faecba458ee1386078fb228d008ba + DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies + UPDATE_COMMAND "" # Disable update + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + ) + get_filename_component(PYTHON_LIB_DIR ${PYTHON_LIBRARY} DIRECTORY) + find_library(TCL_LIBRARY libtcl8.6.dylib PATHS ${PYTHON_LIB_DIR} NO_DEFAULT_PATH) + find_library(TK_LIBRARY libtk8.6.dylib PATHS ${PYTHON_LIB_DIR} NO_DEFAULT_PATH) + set(TCL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tcl) + set(TK_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tk) + set(TCL_INCLUDE_PATH "${TCL_DIR}/generic;${TCL_DIR}/macosx") + set(TK_INCLUDE_PATH "${TK_DIR}/generic;${TK_DIR}/macosx;${TK_DIR}/xlib") + string(REPLACE ";" "$" TCL_INC "${TCL_INCLUDE_PATH}") + string(REPLACE ";" "$" TK_INC "${TK_INCLUDE_PATH}") -ExternalProject_Add(project_tkdnd - URL "http://sourceforge.net/projects/tkdnd/files/TkDND/TkDND%202.8/tkdnd2.8-src.tar.gz" - URL_MD5 a6d47a996ea957416469b12965d4db91 - DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies - PATCH_COMMAND patch -p1 < ${CMAKE_CURRENT_LIST_DIR}/tkdnd_macosx.patch - UPDATE_COMMAND "" # Disable update - BUILD_IN_SOURCE 1 - CONFIGURE_COMMAND ./configure --prefix=${CMAKE_INSTALL_PREFIX}/Contents/MacOS --libdir=${CMAKE_INSTALL_PREFIX}/Contents/MacOS - BUILD_COMMAND make - INSTALL_COMMAND make install - LOG_DOWNLOAD 1 - LOG_CONFIGURE 1 - LOG_BUILD 1 - LOG_INSTALL 1 -) + ExternalProject_Add(project_tkdnd + URL "http://sourceforge.net/projects/tkdnd/files/TkDND/TkDND%202.8/tkdnd2.8-src.tar.gz" + URL_MD5 a6d47a996ea957416469b12965d4db91 + DEPENDS project_tcl project_tk + DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies + PATCH_COMMAND patch < ${CMAKE_CURRENT_LIST_DIR}/tkdnd_macosx.patch + UPDATE_COMMAND "" # Disable update + BUILD_IN_SOURCE 1 + CMAKE_ARGS + -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS + -DTCL_INCLUDE_PATH=${TCL_INC} + -DTK_INCLUDE_PATH=${TK_INC} + -DTK_LIBRARY=${TK_LIBRARY} + -DTCL_LIBRARY=${TCL_LIBRARY} + LOG_DOWNLOAD 1 + LOG_CONFIGURE 1 + LOG_BUILD 1 + LOG_INSTALL 1 + ) + list(APPEND NETGEN_DEPENDENCIES project_tkdnd) + else() + find_package(TCL 8.5 REQUIRED) + endif() elseif(WIN32) diff --git a/cmake/external_projects/tkdnd_macosx.patch b/cmake/external_projects/tkdnd_macosx.patch index a2ed4217..7e97a39a 100644 --- a/cmake/external_projects/tkdnd_macosx.patch +++ b/cmake/external_projects/tkdnd_macosx.patch @@ -1,35 +1,55 @@ -diff -Naur orig/tkdnd2.8/configure changed/tkdnd2.8/configure ---- tkdnd2.8/configure 2015-05-13 19:24:32.000000000 +0200 -+++ tkdnd2.8/configure 2016-02-22 15:26:37.000000000 +0100 -@@ -6145,7 +6145,7 @@ +--- CMakeLists.txt 19:24:32.000000000 +0200 ++++ CMakeLists.txt 2018-12-05 11:34:59.000000000 +0100 +@@ -43,17 +43,18 @@ + ELSE ( WIN32 ) + ## Unix and OS X... + IF ( APPLE ) +- SET ( CMAKE_OSX_ARCHITECTURES "x86_64;i386" ) ++ SET ( CMAKE_OSX_ARCHITECTURES "x86_64") ++ SET( TK_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../project_tk/) ++ SET( TCL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../project_tcl/) + FIND_LIBRARY ( COCOA_LIBRARY Cocoa ) + INCLUDE_DIRECTORIES ( macosx ) +- INCLUDE_DIRECTORIES ( /Library/Frameworks/Tk.framework/Versions/8.6/PrivateHeaders ) +- INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) +- INCLUDE_DIRECTORIES ( /System/Library/Frameworks/Tk.framework/Versions/8.5/Headers/tk-private ) ++ INCLUDE_DIRECTORIES ( ${TCL_DIR}/macosx ${TCL_DIR}/generic ) ++ INCLUDE_DIRECTORIES ( ${TK_DIR}/macosx ${TK_DIR}/generic ${TK_DIR}/xlib ) + ADD_DEFINITIONS ( -DMAC_TK_COCOA -DMAC_OSX_TK) + ADD_DEFINITIONS ( -DMAC_OSX_TK ) + ADD_DEFINITIONS ( -std=gnu99 ) + ADD_DEFINITIONS ( -x objective-c ) +- ADD_DEFINITIONS ( -fobjc-gc ) ++# ADD_DEFINITIONS ( -fobjc-gc ) + ADD_DEFINITIONS ( -fno-objc-arc ) + # ADD_DEFINITIONS ( -fobjc-arc ) + LINK_LIBRARIES ( ${COCOA_LIBRARY} ) +@@ -125,8 +126,8 @@ + ## Locate Tcl/Tk + ## =========================================================================== + MESSAGE ( STATUS "Searching for Tcl/Tk..." ) +-FIND_PACKAGE ( TCL REQUIRED ) +-FIND_PACKAGE ( TclStub REQUIRED ) ++#FIND_PACKAGE ( TCL REQUIRED ) ++#FIND_PACKAGE ( TclStub REQUIRED ) + ## Tcl/Tk info (useful for debug purposes)... + # MESSAGE ( STATUS " TCL_TCLSH: " ${TCL_TCLSH} ) +@@ -139,13 +140,13 @@ + # MESSAGE ( STATUS " TK_LIBRARY: " ${TK_LIBRARY} ) + ## Enable Tcl/Tk stubs globally... +-ADD_DEFINITIONS ( -DUSE_TCL_STUBS ) +-ADD_DEFINITIONS ( -DUSE_TK_STUBS ) ++#ADD_DEFINITIONS ( -DUSE_TCL_STUBS ) ++#ADD_DEFINITIONS ( -DUSE_TK_STUBS ) + ADD_DEFINITIONS ( -DTCL_THREADS ) + INCLUDE_DIRECTORIES ( ${TCL_INCLUDE_PATH} ) + INCLUDE_DIRECTORIES ( ${TK_INCLUDE_PATH} ) +-LINK_LIBRARIES ( ${TCL_STUB_LIBRARY} ) +-LINK_LIBRARIES ( ${TK_STUB_LIBRARY} ) ++LINK_LIBRARIES ( ${TCL_LIBRARY} ) ++LINK_LIBRARIES ( ${TK_LIBRARY} ) -- PKG_CFLAGS="$PKG_CFLAGS -DMAC_TK_COCOA -std=gnu99 -x objective-c -fobjc-gc" -+ PKG_CFLAGS="$PKG_CFLAGS -DMAC_TK_COCOA -std=gnu99 -x objective-c" - - - -diff -Naur orig/tkdnd2.8/configure.in changed/tkdnd2.8/configure.in ---- tkdnd2.8/configure.in 2015-05-13 19:24:32.000000000 +0200 -+++ tkdnd2.8/configure.in 2016-02-22 15:26:44.000000000 +0100 -@@ -126,7 +126,7 @@ - - if test "${TEA_WINDOWINGSYSTEM}" = "aqua"; then - TEA_ADD_SOURCES([macosx/macdnd.m]) -- TEA_ADD_CFLAGS([-DMAC_TK_COCOA -std=gnu99 -x objective-c -fobjc-gc]) -+ TEA_ADD_CFLAGS([-DMAC_TK_COCOA -std=gnu99 -x objective-c]) - TEA_ADD_LIBS([-framework Cocoa -framework Carbon]) - fi - -diff -Naur orig/tkdnd2.8/macosx/macdnd.m changed/tkdnd2.8/macosx/macdnd.m ---- tkdnd2.8/macosx/macdnd.m 2015-07-06 21:49:14.000000000 +0200 -+++ tkdnd2.8/macosx/macdnd.m 2016-02-22 15:27:04.000000000 +0100 -@@ -16,6 +16,7 @@ - #import - #import - #import -+#undef panic - #import - #import - + IF ( WIN32 AND NO_MSVCRT ) + STRING ( REPLACE /MD /MT CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} ) diff --git a/external_dependencies/pybind11 b/external_dependencies/pybind11 index 2a5a5ec0..2a150736 160000 --- a/external_dependencies/pybind11 +++ b/external_dependencies/pybind11 @@ -1 +1 @@ -Subproject commit 2a5a5ec0a47c245fbf1bb1a8a90b4c3278e01693 +Subproject commit 2a150736601bb3113877bb673fb934bb60d46ec5 diff --git a/libsrc/CMakeLists.txt b/libsrc/CMakeLists.txt index 89dc88a5..eb67d688 100644 --- a/libsrc/CMakeLists.txt +++ b/libsrc/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(core) add_subdirectory(general) add_subdirectory(gprim) add_subdirectory(linalg) diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy new file mode 100644 index 00000000..290188fb --- /dev/null +++ b/libsrc/core/.clang-tidy @@ -0,0 +1,5 @@ +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' +CheckOptions: + - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor + value: 1 +WarningsAsErrors: '*' \ No newline at end of file diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt new file mode 100644 index 00000000..92f2e8b7 --- /dev/null +++ b/libsrc/core/CMakeLists.txt @@ -0,0 +1,16 @@ +add_library(ngcore SHARED archive.cpp) + +target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS) + +install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) + +if(USE_PYTHON) + target_include_directories(ngcore PUBLIC ${PYTHON_INCLUDE_DIRS}) +endif(USE_PYTHON) + +install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp + DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) + +if(ENABLE_CPP_CORE_GUIDELINES_CHECK) + set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") +endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp new file mode 100644 index 00000000..64789904 --- /dev/null +++ b/libsrc/core/archive.cpp @@ -0,0 +1,52 @@ + +#include "archive.hpp" + +#ifndef WIN32 +#include +#endif + +namespace ngcore +{ + // clang-tidy should ignore this static object + static std::map library_versions; // NOLINT + std::map& Archive :: GetLibraryVersions() + { + return library_versions; + } + const VersionInfo& GetLibraryVersion(const std::string& library) + { return library_versions[library]; } + + void SetLibraryVersion(const std::string& library, const VersionInfo& version) + { library_versions[library] = version; } + +#ifdef WIN32 + // windows does demangling in typeid(T).name() + std::string Demangle(const char* typeinfo) { return typeinfo; } +#else + std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, + nullptr, + nullptr, + &status); } +#endif + + // clang-tidy should ignore this static object + static std::unique_ptr> type_register; // NOLINT + const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) + { + if(type_register == nullptr) type_register = + std::make_unique>(); + return (*type_register)[classname]; + } + void Archive :: SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info) + { + if(type_register == nullptr) type_register = + std::make_unique>(); + (*type_register)[classname] = info; + } + bool Archive :: IsRegistered(const std::string& classname) + { + if(type_register == nullptr) type_register = + std::make_unique>(); + return type_register->count(classname) != 0; + } +} // namespace ngcore diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp new file mode 100644 index 00000000..fd2ee275 --- /dev/null +++ b/libsrc/core/archive.hpp @@ -0,0 +1,869 @@ +#ifndef NETGEN_CORE_ARCHIVE_HPP +#define NETGEN_CORE_ARCHIVE_HPP + +#include // for complex +#include // for size_t, strlen +#include // for operator<<, ifstream, ofstream, basic... +#include // for function +#include // for map, _Rb_tree_iterator +#include // for __shared_ptr_access, __shared_ptr_acc... +#include // for runtime_error +#include // for string, operator+ +#include // for declval, enable_if, false_type, is_co... +#include // for type_info +#include // for move, swap, pair +#include // for vector + +#include "ngcore_api.hpp" // for NGCORE_API, unlikely +#include "type_traits.hpp" // for all_of_tmpl +#include "version.hpp" // for VersionInfo + +#ifdef NG_PYTHON +#include +#endif // NG_PYTHON + +namespace ngcore +{ + // Libraries using this archive can store their version here to implement backwards compatibility + NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library); + NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version); + NGCORE_API std::string Demangle(const char* typeinfo); + + class NGCORE_API Archive; + + namespace detail + { + // create new pointer of type T if it is default constructible, else throw + template + T* constructIfPossible_impl(Rest... /*unused*/) + { throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } + + template::value>::type> + T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT + + template + T* constructIfPossible() { return constructIfPossible_impl(int{}); } + + //Type trait to check if a class implements a 'void DoArchive(Archive&)' function + template + struct has_DoArchive + { + private: + template + static constexpr auto check(T2*) -> + typename std::is_same().DoArchive(std::declval())),void>::type; + template + static constexpr std::false_type check(...); + using type = decltype(check(nullptr)); // NOLINT + public: + NGCORE_API static constexpr bool value = type::value; + }; + + // Check if class is archivable + template + struct is_Archivable_struct + { + private: + template + static constexpr auto check(T2*) -> + typename std::is_same() & std::declval()),Archive&>::type; + template + static constexpr std::false_type check(...); + using type = decltype(check(nullptr)); // NOLINT + public: + NGCORE_API static constexpr bool value = type::value; + }; + + 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 creator; + // 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 upcaster; + // 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 downcaster; + }; + } // namespace detail + + template + constexpr bool is_archivable = detail::is_Archivable_struct::value; + + // Base Archive class + class NGCORE_API Archive + { + const bool is_output; + // how many different shared_ptr/pointer have been (un)archived + int shared_ptr_count, ptr_count; + // maps for archived shared pointers and pointers + std::map shared_ptr2nr, ptr2nr; + // vectors for storing the unarchived (shared) pointers + std::vector> nr2shared_ptr; + std::vector nr2ptr; + protected: + bool shallow_to_python = false; + public: + Archive() = delete; + Archive(const Archive&) = delete; + Archive(Archive&&) = delete; + Archive (bool ais_output) : + is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } + + virtual ~Archive() { ; } + + template + Archive& Shallow(T& val) + { + static_assert(detail::is_any_pointer, "ShallowArchive must be given pointer type!"); +#ifdef NG_PYTHON + if(shallow_to_python) + { + if(is_output) + ShallowOutPython(pybind11::cast(val)); + else + val = pybind11::cast(ShallowInPython()); + } + else +#endif // NG_PYTHON + *this & val; + return *this; + } + +#ifdef NG_PYTHON + virtual void ShallowOutPython(pybind11::object /*unused*/) // NOLINT (copy by val is ok for this virt func) + { throw std::runtime_error("Should not get in ShallowToPython base class implementation!"); } + virtual pybind11::object ShallowInPython() + { throw std::runtime_error("Should not get in ShallowFromPython base class implementation!"); } +#endif // NG_PYTHON + + Archive& operator=(const Archive&) = delete; + Archive& operator=(Archive&&) = delete; + + bool Output () const { return is_output; } + bool Input () const { return !is_output; } + virtual const VersionInfo& GetVersion(const std::string& library) + { return GetLibraryVersions()[library]; } + + // Pure virtual functions that have to be implemented by In-/OutArchive + virtual Archive & operator & (double & d) = 0; + virtual Archive & operator & (int & i) = 0; + virtual Archive & operator & (long & i) = 0; + virtual Archive & operator & (size_t & i) = 0; + virtual Archive & operator & (short & i) = 0; + virtual Archive & operator & (unsigned char & i) = 0; + virtual Archive & operator & (bool & b) = 0; + virtual Archive & operator & (std::string & str) = 0; + virtual Archive & operator & (char *& str) = 0; + + virtual Archive & operator & (VersionInfo & version) + { + if(Output()) + (*this) << version.to_string(); + else + { + std::string s; + (*this) & s; + version = VersionInfo(s); + } + return *this; + } + + // Archive std classes ================================================ + template + Archive& operator & (std::complex& c) + { + if(Output()) + (*this) << c.real() << c.imag(); + else + { + T tmp; + (*this) & tmp; + c.real(tmp); + (*this) & tmp; + c.imag(tmp); + } + return (*this); + } + template + Archive& operator & (std::vector& v) + { + size_t size; + if(Output()) + size = v.size(); + (*this) & size; + if(Input()) + v.resize(size); + Do(&v[0], size); + return (*this); + } + template + Archive& operator& (std::map& map) + { + if(Output()) + { + (*this) << size_t(map.size()); + for(auto& pair : map) + (*this) << pair.first << pair.second; + } + else + { + size_t size = 0; + (*this) & size; + T1 key; T2 val; + for(size_t i = 0; i < size; i++) + { + T1 key; T2 val; + (*this) & key & val; + map[key] = val; + } + } + return (*this); + } + // Archive arrays ===================================================== + // this functions can be overloaded in Archive implementations for more efficiency + template >::type> + Archive & Do (T * data, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; // NOLINT + + virtual Archive & Do (double * d, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; // NOLINT + + virtual Archive & Do (int * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT + + virtual Archive & Do (long * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT + + virtual Archive & Do (size_t * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT + + virtual Archive & Do (short * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT + + virtual Archive & Do (unsigned char * i, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT + + virtual Archive & Do (bool * b, size_t n) + { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; // NOLINT + + // Archive a class implementing a (void DoArchive(Archive&)) method ======= + template::value>> + Archive& operator & (T& val) + { + val.DoArchive(*this); return *this; + } + + // Archive shared_ptrs ================================================= + template + Archive& operator & (std::shared_ptr& ptr) + { + if(Output()) + { + // save -2 for nullptr + if(!ptr) + return (*this) << -2; + + void* reg_ptr = ptr.get(); + bool neededDowncast = false; + // Downcasting is only possible for our registered classes + if(typeid(T) != typeid(*ptr)) + { + if(!IsRegistered(Demangle(typeid(*ptr).name()))) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*ptr).name()) + + " not registered for archive"); + 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(ptr.get()) ) + neededDowncast = true; + } + auto pos = shared_ptr2nr.find(reg_ptr); + // if not found store -1 and the pointer + if(pos == shared_ptr2nr.end()) + { + auto p = ptr.get(); + (*this) << -1; + (*this) & neededDowncast & p; + // if we did downcast we store the true type as well + if(neededDowncast) + (*this) << Demangle(typeid(*ptr).name()); + shared_ptr2nr[reg_ptr] = shared_ptr_count++; + return *this; + } + // if found store the position and if it has to be downcasted and how + (*this) << pos->second << neededDowncast; + if(neededDowncast) + (*this) << Demangle(typeid(*ptr).name()); + } + else // Input + { + int nr; + (*this) & nr; + // -2 restores a nullptr + if(nr == -2) + { + 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) + { + T* p = nullptr; + bool neededDowncast; + (*this) & neededDowncast & p; + ptr = std::shared_ptr(p); + // if we did downcast we need to store a shared_ptr to the true object + if(neededDowncast) + { + std::string name; + (*this) & name; + auto info = GetArchiveRegister(name); + // for this we use an aliasing constructor to create a shared pointer sharing lifetime + // with our shared ptr, but pointing to the true object + nr2shared_ptr.push_back(std::shared_ptr(std::static_pointer_cast(ptr), + info.downcaster(typeid(T), + ptr.get()))); + } + else + nr2shared_ptr.push_back(ptr); + } + else + { + auto other = nr2shared_ptr[nr]; + bool neededDowncast; + (*this) & neededDowncast; + if(neededDowncast) + { + // if there was a downcast we can expect the class to be registered (since archiving + // wouldn't have worked else) + std::string name; + (*this) & name; + auto info = GetArchiveRegister(name); + // same trick as above, create a shared ptr sharing lifetime with + // the shared_ptr in the register, but pointing to our object + ptr = std::static_pointer_cast(std::shared_ptr(other, + info.upcaster(typeid(T), + other.get()))); + } + else + ptr = std::static_pointer_cast(other); + } + } + return *this; + } + + // Archive pointers ======================================================= + template + Archive & operator& (T *& p) + { + if (Output()) + { + // if the pointer is null store -2 + if (!p) + return (*this) << -2; + auto reg_ptr = static_cast(p); + if(typeid(T) != typeid(*p)) + { + if(!IsRegistered(Demangle(typeid(*p).name()))) + throw std::runtime_error(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(p)); + } + auto pos = ptr2nr.find(reg_ptr); + // if the pointer is not found in the map create a new entry + if (pos == ptr2nr.end()) + { + ptr2nr[reg_ptr] = ptr_count++; + if(typeid(*p) == typeid(T)) + if (std::is_constructible::value) + { + return (*this) << -1 & (*p); + } + else + throw std::runtime_error(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 + // to avoid compile time issues we allow this behaviour only for "our" classes that + // implement a void DoArchive(Archive&) member function + // To recreate the object we need to store the true type of it + if(!IsRegistered(Demangle(typeid(*p).name()))) + throw std::runtime_error(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); + return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); + } + } + else + { + (*this) & pos->second; + bool downcasted = !(reg_ptr == static_cast(p) ); + // store if the class has been downcasted and the name + (*this) << downcasted << Demangle(typeid(*p).name()); + } + } + else + { + int nr; + (*this) & nr; + if (nr == -2) // restore a nullptr + p = nullptr; + else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) + { + p = detail::constructIfPossible(); + nr2ptr.push_back(p); + (*this) & *p; + } + else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... + { + // As stated above, we want this special behaviour only for our classes that implement DoArchive + std::string name; + (*this) & 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(info.creator(typeid(T))); + // 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)); + (*this) & *p; + } + else + { + bool downcasted; + std::string name; + (*this) & downcasted & name; + if(downcasted) + { + // if the class has been downcasted we can assume it is in the register + auto info = GetArchiveRegister(name); + p = static_cast(info.upcaster(typeid(T), nr2ptr[nr])); + } + else + p = static_cast(nr2ptr[nr]); + } + } + return *this; + } + + // const ptr + template + Archive& operator &(const T*& t) + { + return (*this) & const_cast(t); // NOLINT + } + + // Write a read only variable + template + Archive & operator << (const T & t) + { + T ht(t); + (*this) & ht; + return *this; + } + + virtual void FlushBuffer() {} + + protected: + static std::map& GetLibraryVersions(); + + private: + template + friend class RegisterClassForArchive; + + // Returns ClassArchiveInfo of Demangled typeid + static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname); + // Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of + // RegisterClassForArchive + static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info); + static bool IsRegistered(const std::string& classname); + + // Helper class for up-/downcasting + template + struct Caster{}; + + template + struct Caster + { + static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/) + { + throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!"); + } + static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/) + { + throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!"); + } + }; + + template + struct Caster + { + static void* tryUpcast(const std::type_info& ti, T* p) + { + try + { return GetArchiveRegister(Demangle(typeid(B1).name())). + upcaster(ti, static_cast(dynamic_cast(p))); } + catch(std::exception&) + { return Caster::tryUpcast(ti, p); } + } + + static void* tryDowncast(const std::type_info& ti, void* p) + { + if(typeid(B1) == ti) + return dynamic_cast(static_cast(p)); + try + { + return dynamic_cast(static_cast(GetArchiveRegister(Demangle(typeid(B1).name())). + downcaster(ti, p))); + } + catch(std::exception&) + { + return Caster::tryDowncast(ti, p); + } + } + }; + }; + + template + class RegisterClassForArchive + { + public: + RegisterClassForArchive() + { + static_assert(detail::all_of_tmpl::value...>, + "Variadic template arguments must be base classes of T"); + detail::ClassArchiveInfo info; + info.creator = [this,&info](const std::type_info& ti) -> void* + { return typeid(T) == ti ? detail::constructIfPossible() + : Archive::Caster::tryUpcast(ti, detail::constructIfPossible()); }; + info.upcaster = [this](const std::type_info& ti, void* p) -> void* + { return typeid(T) == ti ? p : Archive::Caster::tryUpcast(ti, static_cast(p)); }; + info.downcaster = [this](const std::type_info& ti, void* p) -> void* + { return typeid(T) == ti ? p : Archive::Caster::tryDowncast(ti, p); }; + Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info); + } + + + }; + + // BinaryOutArchive ====================================================================== + class NGCORE_API BinaryOutArchive : public Archive + { + static constexpr size_t BUFFERSIZE = 1024; + char buffer[BUFFERSIZE] = {}; + size_t ptr = 0; + protected: + std::shared_ptr stream; + public: + BinaryOutArchive() = delete; + BinaryOutArchive(const BinaryOutArchive&) = delete; + BinaryOutArchive(BinaryOutArchive&&) = delete; + BinaryOutArchive(std::shared_ptr&& astream) + : Archive(true), stream(std::move(astream)) + { } + BinaryOutArchive(const std::string& filename) + : BinaryOutArchive(std::make_shared(filename)) {} + ~BinaryOutArchive () override { FlushBuffer(); } + + BinaryOutArchive& operator=(const BinaryOutArchive&) = delete; + BinaryOutArchive& operator=(BinaryOutArchive&&) = delete; + + using Archive::operator&; + Archive & operator & (double & d) override + { return Write(d); } + Archive & operator & (int & i) override + { return Write(i); } + Archive & operator & (short & i) override + { return Write(i); } + Archive & operator & (long & i) override + { return Write(i); } + Archive & operator & (size_t & i) override + { return Write(i); } + Archive & operator & (unsigned char & i) override + { return Write(i); } + Archive & operator & (bool & b) override + { return Write(b); } + Archive & operator & (std::string & str) override + { + int len = str.length(); + (*this) & len; + FlushBuffer(); + if(len) + stream->write (&str[0], len); + return *this; + } + Archive & operator & (char *& str) override + { + long len = str ? strlen (str) : -1; + (*this) & len; + FlushBuffer(); + if(len > 0) + stream->write (&str[0], len); // NOLINT + return *this; + } + void FlushBuffer() override + { + if (ptr > 0) + { + stream->write(&buffer[0], ptr); + ptr = 0; + } + } + + private: + template + Archive & Write (T x) + { + if (unlikely(ptr > BUFFERSIZE-sizeof(T))) + { + stream->write(&buffer[0], ptr); + *reinterpret_cast(&buffer[0]) = x; // NOLINT + ptr = sizeof(T); + return *this; + } + *reinterpret_cast(&buffer[ptr]) = x; // NOLINT + ptr += sizeof(T); + return *this; + } + }; + + // BinaryInArchive ====================================================================== + class NGCORE_API BinaryInArchive : public Archive + { + protected: + std::shared_ptr stream; + public: + BinaryInArchive (std::shared_ptr&& astream) + : Archive(false), stream(std::move(astream)) + { } + BinaryInArchive (const std::string& filename) + : BinaryInArchive(std::make_shared(filename)) { ; } + + using Archive::operator&; + Archive & operator & (double & d) override + { Read(d); return *this; } + Archive & operator & (int & i) override + { Read(i); return *this; } + Archive & operator & (short & i) override + { Read(i); return *this; } + Archive & operator & (long & i) override + { Read(i); return *this; } + Archive & operator & (size_t & i) override + { Read(i); return *this; } + Archive & operator & (unsigned char & i) override + { Read(i); return *this; } + Archive & operator & (bool & b) override + { Read(b); return *this; } + Archive & operator & (std::string & str) override + { + int len; + (*this) & len; + str.resize(len); + if(len) + stream->read(&str[0], len); // NOLINT + return *this; + } + Archive & operator & (char *& str) override + { + long len; + (*this) & len; + if(len == -1) + str = nullptr; + else + { + str = new char[len+1]; // NOLINT + stream->read(&str[0], len); // NOLINT + str[len] = '\0'; // NOLINT + } + return *this; + } + + Archive & Do (double * d, size_t n) override + { stream->read(reinterpret_cast(d), n*sizeof(double)); return *this; } // NOLINT + Archive & Do (int * i, size_t n) override + { stream->read(reinterpret_cast(i), n*sizeof(int)); return *this; } // NOLINT + Archive & Do (size_t * i, size_t n) override + { stream->read(reinterpret_cast(i), n*sizeof(size_t)); return *this; } // NOLINT + + private: + template + inline void Read(T& val) + { stream->read(reinterpret_cast(&val), sizeof(T)); } // NOLINT + }; + + // TextOutArchive ====================================================================== + class NGCORE_API TextOutArchive : public Archive + { + protected: + std::shared_ptr stream; + public: + TextOutArchive (std::shared_ptr&& astream) + : Archive(true), stream(std::move(astream)) + { } + TextOutArchive (const std::string& filename) : + TextOutArchive(std::make_shared(filename)) { } + + using Archive::operator&; + Archive & operator & (double & d) override + { *stream << d << '\n'; return *this; } + Archive & operator & (int & i) override + { *stream << i << '\n'; return *this; } + Archive & operator & (short & i) override + { *stream << i << '\n'; return *this; } + Archive & operator & (long & i) override + { *stream << i << '\n'; return *this; } + Archive & operator & (size_t & i) override + { *stream << i << '\n'; return *this; } + Archive & operator & (unsigned char & i) override + { *stream << int(i) << '\n'; return *this; } + Archive & operator & (bool & b) override + { *stream << (b ? 't' : 'f') << '\n'; return *this; } + Archive & operator & (std::string & str) override + { + int len = str.length(); + *stream << len << '\n'; + if(len) + { + stream->write(&str[0], len); // NOLINT + *stream << '\n'; + } + return *this; + } + Archive & operator & (char *& str) override + { + long len = str ? strlen (str) : -1; + *this & len; + if(len > 0) + { + stream->write (&str[0], len); // NOLINT + *stream << '\n'; + } + return *this; + } + }; + + // TextInArchive ====================================================================== + class NGCORE_API TextInArchive : public Archive + { + protected: + std::shared_ptr stream; + public: + TextInArchive (std::shared_ptr&& astream) : + Archive(false), stream(std::move(astream)) + { } + TextInArchive (const std::string& filename) + : TextInArchive(std::make_shared(filename)) {} + + using Archive::operator&; + Archive & operator & (double & d) override + { *stream >> d; return *this; } + Archive & operator & (int & i) override + { *stream >> i; return *this; } + Archive & operator & (short & i) override + { *stream >> i; return *this; } + Archive & operator & (long & i) override + { *stream >> i; return *this; } + Archive & operator & (size_t & i) override + { *stream >> i; return *this; } + Archive & operator & (unsigned char & i) override + { int _i; *stream >> _i; i = _i; return *this; } + Archive & operator & (bool & b) override + { char c; *stream >> c; b = (c=='t'); return *this; } + Archive & operator & (std::string & str) override + { + int len; + *stream >> len; + char ch; + stream->get(ch); // '\n' + str.resize(len); + if(len) + stream->get(&str[0], len+1, '\0'); + return *this; + } + Archive & operator & (char *& str) override + { + long len; + (*this) & len; + char ch; + if(len == -1) + { + str = nullptr; + return (*this); + } + str = new char[len+1]; // NOLINT + if(len) + { + stream->get(ch); // \n + stream->get(&str[0], len+1, '\0'); // NOLINT + } + str[len] = '\0'; // NOLINT + return *this; + } + }; + +#ifdef NG_PYTHON + + template + class PyArchive : public ARCHIVE + { + private: + pybind11::list lst; + size_t index = 0; + using ARCHIVE::stream; + public: + PyArchive(const pybind11::object& alst = pybind11::none()) : + ARCHIVE(std::make_shared()), + lst(alst.is_none() ? pybind11::list() : pybind11::cast(alst)) + { + ARCHIVE::shallow_to_python = true; + if(Input()) + stream = std::make_shared + (pybind11::cast(lst[pybind11::len(lst)-1])); + } + + using ARCHIVE::Output; + using ARCHIVE::Input; + using ARCHIVE::FlushBuffer; + using ARCHIVE::operator&; + using ARCHIVE::operator<<; + using ARCHIVE::GetVersion; + void ShallowOutPython(pybind11::object val) override { lst.append(val); } + pybind11::object ShallowInPython() override { return lst[index++]; } + + pybind11::list WriteOut() + { + FlushBuffer(); + lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); + return lst; + } + }; + + template + auto NGSPickle(bool printoutput=false) + { + return pybind11::pickle([printoutput](T* self) + { + PyArchive ar; + ar & self; + auto output = pybind11::make_tuple(ar.WriteOut()); + if(printoutput) + pybind11::print("pickle output of", Demangle(typeid(T).name()),"=", output); + return output; + }, + [](pybind11::tuple state) + { + T* val = nullptr; + PyArchive ar(state[0]); + ar & val; + return val; + }); + } + +#endif // NG_PYTHON +} // namespace ngcore + +#endif // NETGEN_CORE_ARCHIVE_HPP diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp new file mode 100644 index 00000000..1c8fa591 --- /dev/null +++ b/libsrc/core/ngcore.hpp @@ -0,0 +1,7 @@ +#ifndef NETGEN_CORE_NGCORE_HPP +#define NETGEN_CORE_NGCORE_HPP + +#include "archive.hpp" +#include "version.hpp" + +#endif // NETGEN_CORE_NGCORE_HPP diff --git a/libsrc/core/ngcore_api.hpp b/libsrc/core/ngcore_api.hpp new file mode 100644 index 00000000..c08d0ac9 --- /dev/null +++ b/libsrc/core/ngcore_api.hpp @@ -0,0 +1,29 @@ +#ifndef NETGEN_CORE_NGCORE_API_HPP +#define NETGEN_CORE_NGCORE_API_HPP + +#ifdef WIN32 + #define NGCORE_API_EXPORT __declspec(dllexport) + #define NGCORE_API_IMPORT __declspec(dllimport) +#else + #define NGCORE_API_EXPORT + #define NGCORE_API_IMPORT +#endif + +#ifdef NGCORE_EXPORTS + #define NGCORE_API NGCORE_API_EXPORT +#else + #define NGCORE_API NGCORE_API_IMPORT +#endif + +namespace ngcore +{ +#if defined(__GNUC__) + inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); } + inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); } +#else + inline bool likely (bool x) { return x; } + inline bool unlikely (bool x) { return x; } +#endif +} // namespace ngcore + +#endif // NETGEN_CORE_NGCORE_API_HPP diff --git a/libsrc/core/type_traits.hpp b/libsrc/core/type_traits.hpp new file mode 100644 index 00000000..3863940b --- /dev/null +++ b/libsrc/core/type_traits.hpp @@ -0,0 +1,33 @@ +#ifndef NETGEN_CORE_TYPE_TRAITS_HPP +#define NETGEN_CORE_TYPE_TRAITS_HPP + +#include +#include + +namespace ngcore +{ + namespace detail + { + template struct _BoolArray{}; + + template + constexpr bool all_of_tmpl = std::is_same<_BoolArray, _BoolArray<(vals || true)...>>::value; // NOLINT + + template + struct is_any_pointer_impl : std::false_type {}; + + template + struct is_any_pointer_impl : std::true_type {}; + + template + struct is_any_pointer_impl> : std::true_type {}; + + template + struct is_any_pointer_impl> : std::true_type {}; + + template + constexpr bool is_any_pointer = is_any_pointer_impl::value; + } // namespace detail +} // namespace ngcore + +#endif // NETGEN_CORE_TYPE_TRAITS_HPP diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp new file mode 100644 index 00000000..69598716 --- /dev/null +++ b/libsrc/core/version.hpp @@ -0,0 +1,88 @@ +#ifndef NETGEN_CORE_VERSION_HPP +#define NETGEN_CORE_VERSION_HPP + +#include +#include + +#include "ngcore_api.hpp" + +namespace ngcore +{ + class VersionInfo + { + private: + size_t mayor_{}, minor_{}, release{}, patch{}; + std::string git_hash{}; + public: + VersionInfo() = default; + VersionInfo(std::string vstring) + { + minor_ = release = patch = 0; + git_hash = ""; + if(vstring.substr(0,1) == "v") + vstring = vstring.substr(1,vstring.size()-1); + auto dot = vstring.find('.'); + mayor_ = std::stoi(vstring.substr(0,dot)); + if(dot == size_t(-1)) vstring = ""; + else vstring = vstring.substr(dot+1, vstring.size()-dot-1); + if(!vstring.empty()) + { + dot = vstring.find('.'); + minor_ = std::stoi(vstring.substr(0,dot)); + if (dot == size_t(-1)) vstring = ""; + else vstring = vstring.substr(dot+1, vstring.size()-dot-1); + if(!vstring.empty()) + { + dot = vstring.find('-'); + release = std::stoi(vstring.substr(0,dot)); + if(dot == size_t(-1)) vstring = ""; + else vstring = vstring.substr(dot+1,vstring.size()-dot-1); + if(!vstring.empty()) + { + dot = vstring.find('-'); + patch = std::stoi(vstring.substr(0,dot)); + if(dot == size_t(-1)) vstring = ""; + else vstring = vstring.substr(dot+1, vstring.size()-dot-1); + if(!vstring.empty()) + git_hash = vstring; + } + } + } + } + VersionInfo(const char* cstr) : VersionInfo(std::string(cstr)) { } + + std::string to_string() const + { std::string vstring = "v" + std::to_string(mayor_); + if(minor_ || release || patch || !git_hash.empty()) + { + vstring += "." + std::to_string(minor_); + if(release || patch || !git_hash.empty()) + { + vstring += "." + std::to_string(release); + if(patch || !git_hash.empty()) + { + vstring += "-" + std::to_string(patch); + if(!git_hash.empty()) + vstring += "-" + git_hash; + } + } + } + return vstring; + } + bool operator <(const VersionInfo& other) const + { + return std::tie(mayor_, minor_, release, patch) < + std::tie(other.mayor_, other.minor_, other.release, other.patch); + } + bool operator ==(const VersionInfo& other) const + { + return mayor_ == other.mayor_ && minor_ == other.minor_ && release == other.release + && patch == other.patch; + } + bool operator >(const VersionInfo& other) const { return other < (*this); } + bool operator <=(const VersionInfo& other) const { return !((*this) > other); } + bool operator >=(const VersionInfo& other) const { return !((*this) < other); } + }; +} // namespace ngcore + +#endif // NETGEN_CORE_VERSION_HPP diff --git a/libsrc/csg/algprim.cpp b/libsrc/csg/algprim.cpp index 4636453b..0f870d98 100644 --- a/libsrc/csg/algprim.cpp +++ b/libsrc/csg/algprim.cpp @@ -557,7 +557,8 @@ namespace netgen Point<3> Sphere :: GetSurfacePoint () const { - return c + Vec<3> (r, 0, 0); + // if two spheres touch at exactly that point meshing fails. + return c + r * Vec<3> (0.12345, 0.54321, 0.8304715488203073); } @@ -1235,7 +1236,15 @@ namespace netgen return max2(bb/(aa*aa),aa/(bb*bb)); } + int EllipticCylinder :: IsIdentic(const Surface& s2, int& inv, double eps) const + { + const EllipticCylinder* ps2 = dynamic_cast(&s2); + if (!ps2) return 0; + if((vl - ps2->vl).Length() > eps || (vs - ps2->vs).Length() > eps || (a-ps2->a).Length() > eps) + return 0; + return 1; + } Point<3> EllipticCylinder :: GetSurfacePoint () const { @@ -1940,6 +1949,13 @@ void EllipticCone :: GetTriangleApproximation << R << " " << r << endl; } - - +RegisterClassForArchive regqs; +RegisterClassForArchive regpl; +RegisterClassForArchive regsph; +RegisterClassForArchive regcyl; +RegisterClassForArchive regelcyl; +RegisterClassForArchive regell; +RegisterClassForArchive regcone; +RegisterClassForArchive regellcone; +RegisterClassForArchive regtorus; } diff --git a/libsrc/csg/algprim.hpp b/libsrc/csg/algprim.hpp index 98715fd3..6daf643b 100644 --- a/libsrc/csg/algprim.hpp +++ b/libsrc/csg/algprim.hpp @@ -47,6 +47,11 @@ namespace netgen virtual void Print (ostream & str) const; virtual void Read (istream & ist); void PrintCoeff (ostream & ost) const; + virtual void DoArchive(Archive& ar) + { + OneSurfacePrimitive::DoArchive(ar); + ar & cxx & cyy & czz & cxy & cxz & cyz & cx & cy & cz & c1; + } }; @@ -64,6 +69,14 @@ namespace netgen public: /// Plane (const Point<3> & ap, Vec<3> an); + // default constructor for archive + Plane() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & p & n & eps_base; + } Point<3> P() const { return p; } Vec<3> N() const { return n; } virtual void GetPrimitiveData (const char *& classname, @@ -130,6 +143,14 @@ namespace netgen public: /// Sphere (const Point<3> & ac, double ar); + // default constructor for archive + Sphere() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & c & r & invr; + } virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; @@ -188,6 +209,14 @@ namespace netgen public: Cylinder (const Point<3> & aa, const Point<3> & ab, double ar); Cylinder (Array & coeffs); + // default constructor for archive + Cylinder() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & b & r & vab; + } Point<3> A() const { return a; } Point<3> B() const { return b; } double R() const { return r; } @@ -250,7 +279,14 @@ namespace netgen EllipticCylinder (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs); EllipticCylinder (Array & coeffs); + // default constructor for archive + EllipticCylinder() {} + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & vl & vs & vab & t0vec & t1vec & vabl & t0 & t1; + } // static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; @@ -267,7 +303,8 @@ namespace netgen const Box<3> & bbox, double facets) const; - + virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; + virtual double MaxCurvature () const; virtual double MaxCurvatureLoc (const Point<3> & /* c */ , @@ -299,6 +336,14 @@ namespace netgen const Vec<3> & av1, const Vec<3> & av2, const Vec<3> & av3); + // default constructor for archive + Ellipsoid() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & v1 & v2 & v3 & rmin; + } /// virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; /// @@ -339,6 +384,14 @@ namespace netgen /// Cone (const Point<3> & aa, const Point<3> & ab, double ara, double arb); /// + // default constructor for archive + Cone() {} + + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & b & ra & rb & minr & vab & t0vec & t1vec & vabl & t0 & t1 & cosphi; + } static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); @@ -383,7 +436,14 @@ namespace netgen /// EllipticCone (const Point<3> & aa, const Vec<3> & avl, const Vec<3> & avs, double ah, double avlr); + // default constructor for archive + EllipticCone() {} + virtual void DoArchive(Archive& ar) + { + QuadraticSurface::DoArchive(ar); + ar & a & vl & vs & h & vlr; + } static Primitive * CreateDefault (); virtual void GetPrimitiveData (const char *& classname, Array & coeffs) const; virtual void SetPrimitiveData (Array & coeffs); @@ -425,6 +485,14 @@ namespace netgen public: /// OK Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar); + // default constructor for archive + Torus() {} + + virtual void DoArchive(Archive& ar) + { + OneSurfacePrimitive::DoArchive(ar); + ar & c & n & R & r; + } /// OK const Point<3> & Center () const { return c; } /// OK diff --git a/libsrc/csg/brick.cpp b/libsrc/csg/brick.cpp index 54c23b17..b9508fba 100644 --- a/libsrc/csg/brick.cpp +++ b/libsrc/csg/brick.cpp @@ -523,4 +523,8 @@ void OrthoBrick :: Reduce (const BoxSphere<3> & box) surfaceactive.Elem(6) = (box.PMin()(0) < pmax(0)) && (pmax(0) < box.PMax()(0)); } + +RegisterClassForArchive regpar; +RegisterClassForArchive regbrick; +RegisterClassForArchive regob; } diff --git a/libsrc/csg/brick.hpp b/libsrc/csg/brick.hpp index 25b003e0..7db7b02d 100644 --- a/libsrc/csg/brick.hpp +++ b/libsrc/csg/brick.hpp @@ -28,8 +28,16 @@ namespace netgen public: Parallelogram3d (Point<3> ap1, Point<3> ap2, Point<3> ap3); + // default constructor for archive + Parallelogram3d() {} virtual ~Parallelogram3d (); + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & p1 & p2 & p3 & p4 & v12 & v13 & n; + } + void SetPoints (Point<3> ap1, Point<3> ap2, Point<3> ap3); virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; @@ -60,7 +68,15 @@ namespace netgen public: Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4); + // default constructor for archive + Brick() {} virtual ~Brick (); + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & p1 & p2 & p3 & p4 & v12 & v13 & v14 & faces; + } static Primitive * CreateDefault (); virtual Primitive * Copy () const; @@ -116,7 +132,15 @@ namespace netgen Point<3> pmin, pmax; public: OrthoBrick (const Point<3> & ap1, const Point<3> & ap2); - + // default constructor for archive + OrthoBrick() {} + + virtual void DoArchive(Archive& ar) + { + Brick::DoArchive(ar); + ar & pmin & pmax; + } + virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual void Reduce (const BoxSphere<3> & box); }; diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 40dda44e..87cae1b4 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -324,6 +324,14 @@ namespace netgen } + void CSGeometry :: DoArchive(Archive& archive) + { + archive & surfaces & solids & toplevelobjects & userpoints & userpoints_ref_factor + & identpoints & boundingbox & isidenticto & ideps + & filename & spline_surfaces & splinecurves2d & splinecurves3d & surf2prim; + if(archive.Input()) + FindIdenticSurfaces(1e-6); + } void CSGeometry :: SaveSurfaces (ostream & out) const { @@ -1584,5 +1592,5 @@ namespace netgen }; CSGInit csginit; - + static RegisterClassForArchive regcsg; } diff --git a/libsrc/csg/csgeom.hpp b/libsrc/csg/csgeom.hpp index f9266de4..f82407b4 100644 --- a/libsrc/csg/csgeom.hpp +++ b/libsrc/csg/csgeom.hpp @@ -39,7 +39,14 @@ namespace netgen public: TopLevelObject (Solid * asolid, Surface * asurface = NULL); + // default constructor for archive + TopLevelObject() {} + void DoArchive(Archive& archive) + { + archive & solid & surface & red & blue & green & visible & transp & maxh + & material & layer & bc & bcname; + } const Solid * GetSolid() const { return solid; } Solid * GetSolid() { return solid; } @@ -124,6 +131,11 @@ namespace netgen UserPoint() = default; UserPoint (Point<3> p, int _index) : Point<3>(p), index(_index) { ; } int GetIndex() const { return index; } + void DoArchive(Archive& archive) + { + archive & index; + Point<3>::DoArchive(archive); + } }; private: @@ -165,14 +177,14 @@ namespace netgen void Clean (); - virtual void Save (string filename) const; + virtual void Save (string filename) const override; void Save (ostream & ost) const; void Load (istream & ist); void SaveSurfaces (ostream & out) const; void LoadSurfaces (istream & in); - virtual void SaveToMeshFile (ostream & ost) const; + virtual void SaveToMeshFile (ostream & ost) const override; int GetChangeVal() { return changeval; } void Change() { changeval++; } @@ -198,6 +210,8 @@ namespace netgen void SetSplineCurve (const char * name, SplineGeometry<3> * spl); const SplineGeometry<2> * GetSplineCurve2d (const string & name) const; const SplineGeometry<3> * GetSplineCurve3d (const string & name) const; + + void DoArchive(Archive& archive) override; void SetFlags (const char * solidname, const Flags & flags); @@ -330,9 +344,9 @@ namespace netgen Array bcmodifications; - virtual int GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam); + virtual int GenerateMesh (shared_ptr & mesh, MeshingParameters & mparam) override; - virtual const Refinement & GetRefinement () const; + virtual const Refinement & GetRefinement () const override; void AddSplineSurface (shared_ptr ss) { spline_surfaces.Append(ss); } }; diff --git a/libsrc/csg/extrusion.cpp b/libsrc/csg/extrusion.cpp index 8b257c20..61446b0c 100644 --- a/libsrc/csg/extrusion.cpp +++ b/libsrc/csg/extrusion.cpp @@ -653,15 +653,15 @@ namespace netgen Extrusion :: Extrusion(const SplineGeometry<3> & path_in, const SplineGeometry<2> & profile_in, const Vec<3> & z_dir) : - path(path_in), profile(profile_in), z_direction(z_dir) + path(&path_in), profile(&profile_in), z_direction(z_dir) { surfaceactive.SetSize(0); surfaceids.SetSize(0); - for(int j=0; jGetNSplines(); j++) { - ExtrusionFace * face = new ExtrusionFace(&(profile.GetSpline(j)), - &path, + ExtrusionFace * face = new ExtrusionFace(&((*profile).GetSpline(j)), + path, z_direction); faces.Append(face); surfaceactive.Append(true); @@ -872,5 +872,6 @@ namespace netgen surfaceactive[i] = true; } - + RegisterClassForArchive regexf; + RegisterClassForArchive regextr; } diff --git a/libsrc/csg/extrusion.hpp b/libsrc/csg/extrusion.hpp index e80ac244..2d6b3bbe 100644 --- a/libsrc/csg/extrusion.hpp +++ b/libsrc/csg/extrusion.hpp @@ -49,9 +49,18 @@ namespace netgen const Vec<3> & z_direction); ExtrusionFace(const Array & raw_data); - + // default constructor for archive + ExtrusionFace() {} ~ExtrusionFace(); + + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & profile & path & glob_z_direction & deletable & spline3_path & line_path & + x_dir & y_dir & z_dir & loc_z_dir & p0 & profile_tangent & profile_par & + profile_spline_coeff & latest_seg & latest_t & latest_point2d & latest_point3d; + } virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; @@ -109,10 +118,10 @@ namespace netgen class Extrusion : public Primitive { private: - const SplineGeometry<3> & path; - const SplineGeometry<2> & profile; // closed, clockwise oriented curve + const SplineGeometry<3>* path; + const SplineGeometry<2>* profile; // closed, clockwise oriented curve - const Vec<3> & z_direction; + Vec<3> z_direction; Array faces; @@ -122,7 +131,15 @@ namespace netgen Extrusion(const SplineGeometry<3> & path_in, const SplineGeometry<2> & profile_in, const Vec<3> & z_dir); + // default constructor for archive + Extrusion() {} ~Extrusion(); + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & path & profile & z_direction & faces & latestfacenum; + } virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const; virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; diff --git a/libsrc/csg/identify.cpp b/libsrc/csg/identify.cpp index 8e5b8923..95a6bb13 100644 --- a/libsrc/csg/identify.cpp +++ b/libsrc/csg/identify.cpp @@ -1274,6 +1274,7 @@ BuildSurfaceElements (Array & segs, if (nst1 * dvec < 0) continue; Element2d el(s1[0], s1[1], s2[0], s2[1]); + el.SetIndex(s1.si); Vec<3> n = Cross (mesh[el[1]] - mesh[el[0]], mesh[el[3]] - mesh[el[0]]); diff --git a/libsrc/csg/python_csg.cpp b/libsrc/csg/python_csg.cpp index b99ea2d5..0db96e6d 100644 --- a/libsrc/csg/python_csg.cpp +++ b/libsrc/csg/python_csg.cpp @@ -235,13 +235,17 @@ DLL_HEADER void ExportCSG(py::module &m) return self.GetNP()-1; }), py::arg("x"),py::arg("y"),py::arg("z"),py::arg("hpref")=false) - .def("AddSegment", FunctionPointer - ([] (SplineSurface & self, int i1, int i2, string bcname, double maxh) + .def("AddSegment", [] (SplineSurface & self, int i1, int i2, string bcname, double maxh) { auto seg = make_shared>(self.GetPoint(i1),self.GetPoint(i2)); self.AppendSegment(seg,bcname,maxh); - }), + }, py::arg("pnt1"),py::arg("pnt2"),py::arg("bcname")="default", py::arg("maxh")=-1.) + .def("AddSegment", [] (SplineSurface& self, int i1, int i2, int i3, string bcname, double maxh) + { + auto seg = make_shared>(self.GetPoint(i1), self.GetPoint(i2), self.GetPoint(i3)); + self.AppendSegment(seg, bcname, maxh); + }, py::arg("pnt1"),py::arg("pnt2"), py::arg("pnt3"),py::arg("bcname")="default", py::arg("maxh")=-1.) ; py::class_> (m, "Solid") @@ -360,37 +364,15 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails! py::class_> (m, "CSGeometry") .def(py::init<>()) - .def("__init__", - [](CSGeometry *instance, const string & filename) - { - cout << "load geometry"; - ifstream ist(filename); - ParseCSG(ist, instance); - instance -> FindIdenticSurfaces(1e-8 * instance->MaxSize()); - }) - .def("__init__", - [](CSGeometry *instance, const py::list & solidlist) - { - cout << "csg from list"; - new (instance) CSGeometry(); - for (int i = 0; i < len(solidlist); i++) - { - py::object obj = solidlist[i]; - cout << "obj " << i << endl; - - py::extract> solid(solidlist[i]); - if(solid.check()) - { - cout << "its a solid" << endl; - solid()->AddSurfaces (*instance); - solid()->GiveUpOwner(); - int tlonr = instance->SetTopLevelObject (solid()->GetSolid()); - instance->GetTopLevelObject(tlonr) -> SetMaterial(solid()->GetMaterial()); - } - } - instance -> FindIdenticSurfaces(1e-8 * instance->MaxSize()); - }) - + .def(py::init([](const string& filename) + { + ifstream ist (filename); + auto geo = make_shared(); + ParseCSG(ist, geo.get()); + geo->FindIdenticSurfaces(1e-8 * geo->MaxSize()); + return geo; + }), py::arg("filename")) + .def(NGSPickle()) .def("Save", FunctionPointer([] (CSGeometry & self, string filename) { cout << "save geometry to file " << filename << endl; @@ -477,7 +459,12 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails! self.GetTopLevelObject(tlonr) -> SetBCProp(surf->GetBase()->GetBCProperty()); self.GetTopLevelObject(tlonr) -> SetBCName(surf->GetBase()->GetBCName()); self.GetTopLevelObject(tlonr) -> SetMaxH(surf->GetBase()->GetMaxH()); - for(auto p : surf->GetPoints()) + Array> non_midpoints; + for(auto spline : surf->GetSplines()) + { + non_midpoints.Append(spline->GetPoint(0)); + } + for(auto p : non_midpoints) self.AddUserPoint(p); self.AddSplineSurface(surf); }), diff --git a/libsrc/csg/revolution.cpp b/libsrc/csg/revolution.cpp index 4c13c109..dac2e277 100644 --- a/libsrc/csg/revolution.cpp +++ b/libsrc/csg/revolution.cpp @@ -640,9 +640,9 @@ namespace netgen Revolution :: Revolution(const Point<3> & p0_in, const Point<3> & p1_in, const SplineGeometry<2> & spline_in) : - p0(p0_in), p1(p1_in), splinecurve(spline_in), - nsplines(spline_in.GetNSplines()) + p0(p0_in), p1(p1_in) { + auto nsplines = spline_in.GetNSplines(); surfaceactive.SetSize(0); surfaceids.SetSize(0); @@ -650,21 +650,21 @@ namespace netgen v_axis.Normalize(); - if(splinecurve.GetSpline(0).StartPI()(1) <= 0. && - splinecurve.GetSpline(nsplines-1).EndPI()(1) <= 0.) + if(spline_in.GetSpline(0).StartPI()(1) <= 0. && + spline_in.GetSpline(nsplines-1).EndPI()(1) <= 0.) type = 2; - else if (Dist(splinecurve.GetSpline(0).StartPI(), - splinecurve.GetSpline(nsplines-1).EndPI()) < 1e-7) + else if (Dist(spline_in.GetSpline(0).StartPI(), + spline_in.GetSpline(nsplines-1).EndPI()) < 1e-7) type = 1; else cerr << "Surface of revolution cannot be constructed" << endl; - for(int i=0; i regrevf; + RegisterClassForArchive regrev; } diff --git a/libsrc/csg/revolution.hpp b/libsrc/csg/revolution.hpp index c9b4cb92..879829fd 100644 --- a/libsrc/csg/revolution.hpp +++ b/libsrc/csg/revolution.hpp @@ -45,9 +45,18 @@ namespace netgen const int id_in = 0); RevolutionFace(const Array & raw_data); + // default constructor for archive + RevolutionFace() {} ~RevolutionFace(); + virtual void DoArchive(Archive& ar) + { + Surface::DoArchive(ar); + ar & isfirst & islast & spline & deletable & p0 & v_axis & id & spline_coefficient + & spline_coefficient_shifted & checklines_vec & checklines_start & checklines_normal; + } + virtual int IsIdentic (const Surface & s2, int & inv, double eps) const; virtual double CalcFunctionValue (const Point<3> & point) const; @@ -96,8 +105,6 @@ namespace netgen private: Point<3> p0,p1; Vec<3> v_axis; - const SplineGeometry<2> & splinecurve; - const int nsplines; // 1 ... torus-like // 2 ... sphere-like @@ -112,9 +119,16 @@ namespace netgen Revolution(const Point<3> & p0_in, const Point<3> & p1_in, const SplineGeometry<2> & spline_in); + // default constructor for archive + Revolution() {} ~Revolution(); - + + virtual void DoArchive(Archive& ar) + { + Primitive::DoArchive(ar); + ar & p0 & p1 & v_axis & type & faces & intersecting_face; + } /* Check, whether box intersects solid defined by surface. diff --git a/libsrc/csg/solid.hpp b/libsrc/csg/solid.hpp index 724030bd..4d620c04 100644 --- a/libsrc/csg/solid.hpp +++ b/libsrc/csg/solid.hpp @@ -55,8 +55,22 @@ namespace netgen public: Solid (Primitive * aprim); Solid (optyp aop, Solid * as1, Solid * as2 = NULL); + // default constructor for archive + Solid () {} ~Solid (); + void DoArchive(Archive& archive) + { + archive & name & prim & s1 & s2 & visited & maxh & num_surfs; + if(archive.Output()) + archive << int(op); + else + { + int iop; + archive & iop; + op = optyp(iop); + } + } const char * Name () const { return name; } void SetName (const char * aname); diff --git a/libsrc/csg/splinesurface.cpp b/libsrc/csg/splinesurface.cpp index e8119db1..6134b1f4 100644 --- a/libsrc/csg/splinesurface.cpp +++ b/libsrc/csg/splinesurface.cpp @@ -62,7 +62,30 @@ void SplineSurface :: AppendPoint(const Point<3> & p, const double reffac, const cuttings->Append(plane); } else - throw NgException("Spline type not implemented for SplineSurface!"); + { + auto spline3 = dynamic_cast*>(spline.get()); + if(spline3) + { + auto p1 = Point<3>(spline3->StartPI()); + Project(p1); + auto p2 = Point<3>(spline3->TangentPoint()); + Project(p2); + auto p3 = Point<3>(spline3->EndPI()); + Project(p3); + Vec<3> v1 = p2-p1; + Vec<3> v2 = p2-p3; + Point<3> mid = p1 - v2; + cout << "mid point = " << mid << endl; + cout << "v1 = " << v1 << endl; + cout << "v2 = " << v2 << endl; + auto cyl = make_shared(mid, v1, v2); + if(maxh[i] > 0) + cyl->SetMaxH(maxh[i]); + cuttings->Append(cyl); + } + else + throw NgException("Spline type not implemented for SplineSurface!"); + } } all_cuts = cuttings; return cuttings; @@ -73,4 +96,5 @@ void SplineSurface :: AppendPoint(const Point<3> & p, const double reffac, const str << "SplineSurface with base " << *baseprimitive << endl; } + static RegisterClassForArchive regss; } diff --git a/libsrc/csg/splinesurface.hpp b/libsrc/csg/splinesurface.hpp index e17f3eef..a6e8a596 100644 --- a/libsrc/csg/splinesurface.hpp +++ b/libsrc/csg/splinesurface.hpp @@ -19,6 +19,8 @@ namespace netgen SplineSurface(shared_ptr abaseprimitive, shared_ptr>> acuts) : OneSurfacePrimitive(), baseprimitive(abaseprimitive), cuts(acuts) { ; } + // default constructor for archive + SplineSurface() {} virtual ~SplineSurface() { ; } const auto & GetSplines() const { return splines; } @@ -53,7 +55,11 @@ namespace netgen virtual INSOLID_TYPE BoxInSolid(const BoxSphere<3> & box) const { return baseprimitive->BoxInSolid(box); } - + + virtual void DoArchive(Archive& ar) + { + ar & geompoints & splines & bcnames & maxh & baseprimitive & cuts & all_cuts; + } /* virtual void Project (Point<3> & p3d) const; diff --git a/libsrc/csg/surface.cpp b/libsrc/csg/surface.cpp index db315e99..f829840b 100644 --- a/libsrc/csg/surface.cpp +++ b/libsrc/csg/surface.cpp @@ -566,4 +566,8 @@ void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp) if (Abs2 (rs) < 1e-24 && i > 1) i = 1; } } + +RegisterClassForArchive regsurf; +RegisterClassForArchive regprim; +RegisterClassForArchive regosf; } diff --git a/libsrc/csg/surface.hpp b/libsrc/csg/surface.hpp index 5e9afbdf..39a6ceee 100644 --- a/libsrc/csg/surface.hpp +++ b/libsrc/csg/surface.hpp @@ -63,6 +63,12 @@ namespace netgen //@} public: + virtual void DoArchive(Archive& archive) + { + archive & inverse & maxh & name & bcprop & bcname + & p1 & p2 & ex & ey & ez; + } + void SetName (const char * aname); const char * Name () const { return name; } @@ -234,6 +240,9 @@ namespace netgen class Primitive { + protected: + Array surfaceids; + Array surfaceactive; public: @@ -241,6 +250,10 @@ namespace netgen virtual ~Primitive(); + virtual void DoArchive(Archive& archive) + { + archive & surfaceids & surfaceactive; + } /* Check, whether box intersects solid defined by surface. @@ -299,9 +312,6 @@ namespace netgen virtual Surface & GetSurface (int i = 0) = 0; virtual const Surface & GetSurface (int i = 0) const = 0; - Array surfaceids; - Array surfaceactive; - int GetSurfaceId (int i = 0) const; void SetSurfaceId (int i, int id); int SurfaceActive (int i) const { return surfaceactive[i]; } @@ -329,6 +339,12 @@ namespace netgen OneSurfacePrimitive(); ~OneSurfacePrimitive(); + virtual void DoArchive(Archive& archive) + { + Surface::DoArchive(archive); + Primitive::DoArchive(archive); + } + virtual INSOLID_TYPE PointInSolid (const Point<3> & p, double eps) const; virtual INSOLID_TYPE VecInSolid (const Point<3> & p, diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index 5faf7c6c..00c59ea2 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -11,7 +11,7 @@ set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) install( FILES ngexception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel ) install(FILES - archive_base.hpp array.hpp autodiff.hpp autoptr.hpp bitarray.hpp + array.hpp autodiff.hpp autoptr.hpp bitarray.hpp dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp ngsimd.hpp mystring.hpp netgenout.hpp ngexception.hpp ngpython.hpp optmem.hpp parthreads.hpp profiler.hpp seti.hpp sort.hpp diff --git a/libsrc/general/archive_base.hpp b/libsrc/general/archive_base.hpp deleted file mode 100644 index 9e74b0e5..00000000 --- a/libsrc/general/archive_base.hpp +++ /dev/null @@ -1,144 +0,0 @@ -#ifndef NGS_ARCHIVE_BASE -#define NGS_ARCHIVE_BASE - -// copied from netgen - -#include -#include - -namespace ngstd -{ - - class Archive - { - bool is_output; - public: - Archive (bool ais_output) : is_output(ais_output) { ; } - virtual ~Archive() { ; } - - bool Output () { return is_output; } - bool Input () { return !is_output; } - - virtual Archive & operator & (double & d) = 0; - virtual Archive & operator & (int & i) = 0; - virtual Archive & operator & (long & i) = 0; - virtual Archive & operator & (size_t & i) = 0; - virtual Archive & operator & (short & i) = 0; - virtual Archive & operator & (unsigned char & i) = 0; - virtual Archive & operator & (bool & b) = 0; - virtual Archive & operator & (string & str) = 0; - virtual Archive & operator & (char *& str) = 0; - - template - Archive & Do (T * data, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; - - - virtual Archive & Do (double * d, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; - - virtual Archive & Do (int * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (long * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (size_t * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (short * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (unsigned char * i, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; - - virtual Archive & Do (bool * b, size_t n) - { for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; - - - // nvirtual Archive & Do (string * str, size_t n) - // { for (size_t j = 0; j < n; j++) { (*this) & str[j]; }; return *this; }; - // virtual Archive & operator & (char *& str) = 0; - - - // archive a pointer ... - - int cnt = 0; - std::map ptr2nr; - std::vector nr2ptr; - - /* - // necessary for msvc ??? - Archive & operator& (string* & ps) - { - return operator& (ps); - } - */ - - template - Archive & operator& (T *& p) - { - if (Output()) - { - if (!p) - { - int m2 = -2; - (*this) & m2; - return *this; - } - auto pos = ptr2nr.find( (void*) p); - if (pos == ptr2nr.end()) - { - ptr2nr[p] = cnt; - int m1 = -1; - (*this) & m1; - cnt++; - (*this) & (*p); - } - else - { - (*this) & pos->second; - } - } - else - { - int nr; - (*this) & nr; - // cout << "in, got nr " << nr << endl; - if (nr == -2) - { - p = nullptr; - } - else if (nr == -1) - { - p = new T; - // cout << "create new ptr, p = " << p << endl; - (*this) & *p; - nr2ptr.push_back(p); - } - else - { - p = (T*)nr2ptr[nr]; - // cout << "reuse ptr " << nr << ": " << p << endl; - } - } - return *this; - } - - - - - template - Archive & operator << (const T & t) - { - T ht(t); - (*this) & ht; - return *this; - } - }; - - -} - - -#endif diff --git a/libsrc/general/array.hpp b/libsrc/general/array.hpp index ead43dac..16bb6e78 100644 --- a/libsrc/general/array.hpp +++ b/libsrc/general/array.hpp @@ -400,6 +400,21 @@ namespace netgen ownmem = false; return data; } + + // Only provide this function if T is archivable + template + auto DoArchive(Archive& archive) -> typename std::enable_if, void>::type + { + if(archive.Output()) + archive << size; + else + { + size_t s; + archive & s; + SetSize(s); + } + archive.Do(data, size); + } private: @@ -778,30 +793,6 @@ namespace netgen if(in2.Contains(in1[i]) && in3.Contains(in1[i])) out.Append(in1[i]); } - - - - - template - ngstd::Archive & operator & (ngstd::Archive & archive, Array & a) - { - if (archive.Output()) - archive << a.Size(); - else - { - size_t size; - archive & size; - a.SetSize (size); - } - - /* - for (auto & ai : a) - archive & ai; - */ - archive.Do (&a[BASE], a.Size()); - return archive; - } - } #endif diff --git a/libsrc/general/hashtabl.hpp b/libsrc/general/hashtabl.hpp index 0898e58f..4d8fadc8 100644 --- a/libsrc/general/hashtabl.hpp +++ b/libsrc/general/hashtabl.hpp @@ -259,20 +259,13 @@ public: const T & GetData (const Iterator & it) const { return cont[it.BagNr()][it.Pos()]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { ar & hash & cont; - return ar; } }; - template - inline ngstd::Archive & operator & (ngstd::Archive & archive, INDEX_2_HASHTABLE & mp) - { return mp.DoArchive(archive); } - - - template inline ostream & operator<< (ostream & ost, const INDEX_2_HASHTABLE & ht) { @@ -436,24 +429,15 @@ public: { return cont[it.BagNr()][it.Pos()]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { ar & hash & cont; - return ar; } }; - - template - inline ngstd::Archive & operator & (ngstd::Archive & archive, INDEX_3_HASHTABLE & mp) - { return mp.DoArchive(archive); } - - - - template inline ostream & operator<< (ostream & ost, const INDEX_3_HASHTABLE & ht) { diff --git a/libsrc/general/myadt.hpp b/libsrc/general/myadt.hpp index 7c4374d8..601a3da0 100644 --- a/libsrc/general/myadt.hpp +++ b/libsrc/general/myadt.hpp @@ -17,11 +17,15 @@ #include "../include/mydefs.hpp" +#include "../core/ngcore.hpp" +namespace netgen +{ + using namespace ngcore; +} #include "ngexception.hpp" #include "parthreads.hpp" // #include "moveablemem.hpp" #include "dynamicmem.hpp" -#include "archive_base.hpp" #include "template.hpp" #include "array.hpp" diff --git a/libsrc/general/ngpython.hpp b/libsrc/general/ngpython.hpp index 396c8f06..fa9862b1 100644 --- a/libsrc/general/ngpython.hpp +++ b/libsrc/general/ngpython.hpp @@ -1,17 +1,5 @@ #ifdef NG_PYTHON -// BEGIN EVIL HACK: Patch PyThread_get_key_value inside pybind11 to avoid deadlocks -// see https://github.com/pybind/pybind11/pull/1211 -#include -#include -namespace pybind11 { - inline void * PyThread_get_key_value(int state) { - PyThreadState *tstate = (PyThreadState *) ::PyThread_get_key_value(state); - if (!tstate) tstate = PyGILState_GetThisThreadState(); - return tstate; - } -} -// END EVIL HACK #include #include #include diff --git a/libsrc/general/symbolta.hpp b/libsrc/general/symbolta.hpp index c246347f..b599ea42 100644 --- a/libsrc/general/symbolta.hpp +++ b/libsrc/general/symbolta.hpp @@ -69,6 +69,8 @@ public: /// Deletes symboltable inline void DeleteAll (); + void DoArchive(Archive& archive) { archive & names & data;} + inline T & operator[] (int i) { return data[i]; } inline const T & operator[] (int i) const diff --git a/libsrc/general/table.cpp b/libsrc/general/table.cpp index 6769e03c..c964c470 100644 --- a/libsrc/general/table.cpp +++ b/libsrc/general/table.cpp @@ -213,7 +213,7 @@ namespace netgen - ngstd::Archive & BASE_TABLE :: DoArchive (ngstd::Archive & ar, int elemsize) + void BASE_TABLE :: DoArchive (Archive & ar, int elemsize) { if (ar.Output()) { @@ -248,7 +248,6 @@ namespace netgen cnt += data[i].size*elemsize; } } - return ar; } diff --git a/libsrc/general/table.hpp b/libsrc/general/table.hpp index e112e135..6a08b3dc 100644 --- a/libsrc/general/table.hpp +++ b/libsrc/general/table.hpp @@ -89,7 +89,7 @@ public: void SetElementSizesToMaxSizes (); - ngstd::Archive & DoArchive (ngstd::Archive & ar, int elemsize); + void DoArchive (Archive & ar, int elemsize); }; @@ -238,21 +238,13 @@ public: return FlatArray (data[i-BASE].size, (T*)data[i-BASE].col); } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { - return BASE_TABLE::DoArchive(ar, sizeof(T)); + BASE_TABLE::DoArchive(ar, sizeof(T)); } }; - -template - inline ngstd::Archive & operator & (ngstd::Archive & archive, TABLE & mp) - { return mp.DoArchive(archive); } - - - - template inline ostream & operator<< (ostream & ost, const TABLE & table) { diff --git a/libsrc/geom2d/genmesh2d.cpp b/libsrc/geom2d/genmesh2d.cpp index 0ddfb8b4..43193e3a 100644 --- a/libsrc/geom2d/genmesh2d.cpp +++ b/libsrc/geom2d/genmesh2d.cpp @@ -207,6 +207,9 @@ namespace netgen // mesh size restrictions ... + + for (auto & point : geompoints) + mesh2d.RestrictLocalH (Point<3> (point(0), point(1), 0), point.hmax); for (int i = 0; i < splines.Size(); i++) { @@ -237,6 +240,23 @@ namespace netgen mesh2d.RestrictLocalH (Point<3> (x(0), x(1), 0), min2(hc, hcurve)); } } + + for (auto mspnt : mp.meshsize_points) + mesh2d.RestrictLocalH (mspnt.pnt, mspnt.h); + + // add point elements + for (auto & point : geompoints) + if (point.name.length()) + { + Point<3> newp(point(0), point(1), 0); + PointIndex npi = mesh2d.AddPoint (newp, 1, FIXEDPOINT); + mesh2d.AddLockedPoint(npi); + Element0d el(npi, npi); + el.name = point.name; + mesh2d.SetCD2Name(npi, point.name); + mesh2d.pointelements.Append (el); + searchtree.Insert (newp, npi); + } // first add all vertices (for compatible orientation on periodic bnds) { @@ -581,8 +601,10 @@ namespace netgen // not complete, use at own risk ... // meshing.Delaunay(*mesh, domnr, mp); mp.checkoverlap = 0; - meshing.GenerateMesh (*mesh, mp, h, domnr); - + auto res = meshing.GenerateMesh (*mesh, mp, h, domnr); + if (res != 0) + throw NgException("meshing failed"); + for (SurfaceElementIndex sei = oldnf; sei < mesh->GetNSE(); sei++) (*mesh)[sei].SetIndex (domnr); diff --git a/libsrc/geom2d/geom2dmesh.cpp b/libsrc/geom2d/geom2dmesh.cpp index 3de7f97f..be1fc6c9 100644 --- a/libsrc/geom2d/geom2dmesh.cpp +++ b/libsrc/geom2d/geom2dmesh.cpp @@ -47,8 +47,8 @@ namespace netgen auto ext = dynamic_cast(spline); if(ext) { - ss3 = dynamic_cast *>(&ext->seg); - ls = dynamic_cast *>(&ext->seg); + ss3 = dynamic_cast *>(ext->seg); + ls = dynamic_cast *>(ext->seg); } else { diff --git a/libsrc/geom2d/geometry2d.cpp b/libsrc/geom2d/geometry2d.cpp index 6bc93c57..f18dd335 100644 --- a/libsrc/geom2d/geometry2d.cpp +++ b/libsrc/geom2d/geometry2d.cpp @@ -1034,5 +1034,6 @@ namespace netgen }; SplineGeoInit sginit; - + static RegisterClassForArchive, NetgenGeometry> regspg2; + static RegisterClassForArchive> regssext; } diff --git a/libsrc/geom2d/geometry2d.hpp b/libsrc/geom2d/geometry2d.hpp index ad02f754..52e7a20e 100644 --- a/libsrc/geom2d/geometry2d.hpp +++ b/libsrc/geom2d/geometry2d.hpp @@ -21,7 +21,7 @@ namespace netgen class SplineSegExt : public SplineSeg<2> { public: - const SplineSeg<2> & seg; + SplineSeg<2>* seg; /// left domain int leftdom; @@ -42,35 +42,43 @@ namespace netgen /// int layer; - SplineSegExt (const SplineSeg<2> & hseg) - : seg(hseg) + SplineSegExt (SplineSeg<2> & hseg) + : seg(&hseg) { layer = 1; } + // default constructor for archive + SplineSegExt() {} ~SplineSegExt () { - delete &seg; + delete seg; + } + + virtual void DoArchive(Archive& ar) + { + ar & seg & leftdom & rightdom & reffak & hmax & bc & copyfrom + & hpref_left & hpref_right & layer; } virtual const GeomPoint<2> & StartPI () const { - return seg.StartPI(); + return seg->StartPI(); } virtual const GeomPoint<2> & EndPI () const { - return seg.EndPI(); + return seg->EndPI(); } virtual Point<2> GetPoint (double t) const { - return seg.GetPoint(t); + return seg->GetPoint(t); } virtual Vec<2> GetTangent (const double t) const { - return seg.GetTangent(t); + return seg->GetTangent(t); } virtual void GetDerivatives (const double t, @@ -78,27 +86,27 @@ namespace netgen Vec<2> & first, Vec<2> & second) const { - seg.GetDerivatives (t, point, first, second); + seg->GetDerivatives (t, point, first, second); } virtual void GetCoeff (Vector & coeffs) const { - seg.GetCoeff (coeffs); + seg->GetCoeff (coeffs); } virtual void GetPoints (int n, Array > & points) const { - seg.GetPoints (n, points); + seg->GetPoints (n, points); } virtual double MaxCurvature () const { - return seg.MaxCurvature(); + return seg->MaxCurvature(); } virtual string GetType () const { - return seg.GetType(); + return seg->GetType(); } virtual double CalcCurvature (double t) const @@ -112,7 +120,7 @@ namespace netgen virtual bool InConvexHull (Point<2> p, double eps) const { - return seg.InConvexHull (p, eps); + return seg->InConvexHull (p, eps); } }; @@ -143,7 +151,11 @@ namespace netgen void TestComment ( ifstream & infile ) ; - + void DoArchive(Archive& ar) + { + SplineGeometry<2>::DoArchive(ar); + ar & materials & maxh & quadmeshing & tensormeshing & layer & bcnames & elto0; + } const SplineSegExt & GetSpline (const int i) const { diff --git a/libsrc/geom2d/python_geom2d.cpp b/libsrc/geom2d/python_geom2d.cpp index f44b525e..a16c13f7 100644 --- a/libsrc/geom2d/python_geom2d.cpp +++ b/libsrc/geom2d/python_geom2d.cpp @@ -17,21 +17,20 @@ DLL_HEADER void ExportGeom2d(py::module &m) { py::class_> (m, "SplineGeometry", - "a 2d boundary representation geometry model by lines and splines") + "a 2d boundary representation geometry model by lines and splines", + py::multiple_inheritance()) .def(py::init<>()) - .def("__init__", - [](SplineGeometry2d *instance, const string & filename) - { - cout << "load geometry"; - ifstream ist(filename); - new (instance) SplineGeometry2d(); - instance->Load (filename.c_str()); - ng_geometry = shared_ptr(instance, NOOP_Deleter); - }) - - .def("Load",&SplineGeometry2d::Load) + .def(py::init([](const string& filename) + { + auto geo = make_shared(); + geo->Load(filename.c_str()); + ng_geometry = geo; + return geo; + })) + .def(NGSPickle()) + .def("Load",&SplineGeometry2d::Load) .def("AppendPoint", FunctionPointer - ([](SplineGeometry2d &self, double px, double py, double maxh, double hpref) + ([](SplineGeometry2d &self, double px, double py, double maxh, double hpref, string name) { Point<2> p; p(0) = px; @@ -39,10 +38,11 @@ DLL_HEADER void ExportGeom2d(py::module &m) GeomPoint<2> gp(p); gp.hmax = maxh; gp.hpref = hpref; + gp.name = name; self.geompoints.Append(gp); return self.geompoints.Size()-1; }), - py::arg("x"), py::arg("y"), py::arg("maxh") = 1e99, py::arg("hpref")=0) + py::arg("x"), py::arg("y"), py::arg("maxh") = 1e99, py::arg("hpref")=0, py::arg("name")="") .def("Append", FunctionPointer([](SplineGeometry2d &self, py::list segment, int leftdomain, int rightdomain, py::object bc, py::object copy, double maxh, double hpref) { diff --git a/libsrc/gprim/geomobjects.hpp b/libsrc/gprim/geomobjects.hpp index 388e9a54..ad215278 100644 --- a/libsrc/gprim/geomobjects.hpp +++ b/libsrc/gprim/geomobjects.hpp @@ -64,6 +64,12 @@ namespace netgen const T & operator() (int i) const { return x[i]; } operator const T* () const { return x; } + + void DoArchive(Archive& archive) + { + for(int i=0; i @@ -117,6 +123,12 @@ namespace netgen operator const T* () const { return x; } + void DoArchive(Archive& archive) + { + for(int i=0; i - inline Point SplineSeg3 :: GetPoint (double t) const + Point SplineSeg3 :: GetPoint (double t) const { double b1, b2, b3; @@ -551,11 +551,10 @@ namespace netgen template class SplineSeg3<2>; template class SplineSeg3<3>; - - - - - - - + RegisterClassForArchive> regss2; + RegisterClassForArchive> regss3; + RegisterClassForArchive, SplineSeg<2>> regls2; + RegisterClassForArchive, SplineSeg<3>> regls3; + RegisterClassForArchive, SplineSeg<2>> regsss2; + RegisterClassForArchive, SplineSeg<3>> regsss3; } diff --git a/libsrc/gprim/spline.hpp b/libsrc/gprim/spline.hpp index a628d07d..71700189 100644 --- a/libsrc/gprim/spline.hpp +++ b/libsrc/gprim/spline.hpp @@ -28,13 +28,19 @@ namespace netgen double hmax; /// hp-refinement double hpref; - + /// + string name; /// GeomPoint () { ; } /// GeomPoint (const Point & ap, double aref = 1, double ahpref=0) : Point(ap), refatpoint(aref), hmax(1e99), hpref(ahpref) { ; } + void DoArchive(Archive& ar) + { + Point::DoArchive(ar); + ar & refatpoint & hmax & hpref; + } }; @@ -72,6 +78,7 @@ namespace netgen second = 1.0/sqr(eps) * ( (pr-point)+(pl-point)); } + virtual void DoArchive(Archive& ar) = 0; /// returns initial point on curve virtual const GeomPoint & StartPI () const = 0; @@ -122,6 +129,12 @@ namespace netgen /// LineSeg (const GeomPoint & ap1, const GeomPoint & ap2); /// + // default constructor for archive + LineSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2; + } virtual double Length () const; /// inline virtual Point GetPoint (double t) const; @@ -172,8 +185,14 @@ namespace netgen SplineSeg3 (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3); + // default constructor for archive + SplineSeg3() {} /// - inline virtual Point GetPoint (double t) const; + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2 & p3 & weight & proj_latest_t; + } + virtual Point GetPoint (double t) const; /// virtual Vec GetTangent (const double t) const; @@ -226,6 +245,12 @@ namespace netgen CircleSeg (const GeomPoint & ap1, const GeomPoint & ap2, const GeomPoint & ap3); + // default constructor for archive + CircleSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & p1 & p2 & p3 & pm & radius & w1 & w3; + } /// virtual Point GetPoint (double t) const; /// @@ -270,6 +295,12 @@ namespace netgen public: /// DiscretePointsSeg (const Array > & apts); + // default constructor for archive + DiscretePointsSeg() {} + virtual void DoArchive(Archive& ar) + { + ar & pts & p1n & p2n; + } /// virtual ~DiscretePointsSeg (); /// @@ -624,8 +655,14 @@ namespace netgen /// BSplineSeg (const Array > & apts); /// + //default constructor for archive + BSplineSeg() {} virtual ~BSplineSeg(); /// + virtual void DoArchive(Archive& ar) + { + ar & pts & p1n & p2n & ti; + } virtual Point GetPoint (double t) const; /// virtual const GeomPoint & StartPI () const { return p1n; }; diff --git a/libsrc/gprim/splinegeometry.cpp b/libsrc/gprim/splinegeometry.cpp index 7cb75cb0..213f5224 100644 --- a/libsrc/gprim/splinegeometry.cpp +++ b/libsrc/gprim/splinegeometry.cpp @@ -129,6 +129,8 @@ namespace netgen template class SplineGeometry<2>; template class SplineGeometry<3>; + static RegisterClassForArchive> regsp2; + static RegisterClassForArchive> regsp3; } diff --git a/libsrc/gprim/splinegeometry.hpp b/libsrc/gprim/splinegeometry.hpp index 16574516..14a28b4b 100644 --- a/libsrc/gprim/splinegeometry.hpp +++ b/libsrc/gprim/splinegeometry.hpp @@ -34,6 +34,11 @@ namespace netgen DLL_HEADER int Load (const Array & raw_data, const int startpos = 0); + virtual void DoArchive(Archive& ar) + { + ar & geompoints & splines; + } + DLL_HEADER void GetRawData (Array & raw_data) const; @@ -55,7 +60,6 @@ namespace netgen // void SetGrading (const double grading); DLL_HEADER void AppendPoint (const Point & p, const double reffac = 1., const bool hpref = false); - void AppendSegment(SplineSeg * spline) { splines.Append (spline); diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 580a340a..33a596db 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -230,7 +230,7 @@ namespace netgen void LoadMesh (istream & str); void SaveMesh (ostream & str) const; void UpdateTopology (); - void DoArchive (ngstd::Archive & archive); + void DoArchive (Archive & archive); virtual ~Ngx_Mesh(); diff --git a/libsrc/include/nginterface_v2_impl.hpp b/libsrc/include/nginterface_v2_impl.hpp index aa538761..62e8068d 100644 --- a/libsrc/include/nginterface_v2_impl.hpp +++ b/libsrc/include/nginterface_v2_impl.hpp @@ -47,6 +47,7 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (size_t nr) const Ng_Element ret; ret.type = NG_PNT; ret.index = el.index; + ret.mat = &el.name; ret.points.num = 1; ret.points.ptr = (int*)&el.pnum; diff --git a/libsrc/interface/CMakeLists.txt b/libsrc/interface/CMakeLists.txt index ef52c30b..cb460fae 100644 --- a/libsrc/interface/CMakeLists.txt +++ b/libsrc/interface/CMakeLists.txt @@ -9,9 +9,7 @@ add_library(interface ${NG_LIB_TYPE} if(NOT WIN32) target_link_libraries(interface mesh csg geom2d) - if(USE_GUI) - target_link_libraries(interface visual) - endif(USE_GUI) + target_link_libraries(interface visual) install( TARGETS interface ${NG_INSTALL_DIR}) endif(NOT WIN32) diff --git a/libsrc/interface/nginterface.cpp b/libsrc/interface/nginterface.cpp index fe83b34a..ad0a72db 100644 --- a/libsrc/interface/nginterface.cpp +++ b/libsrc/interface/nginterface.cpp @@ -124,7 +124,6 @@ void Ng_LoadMesh (const char * filename) #ifdef PARALLEL MPI_Comm_size(MPI_COMM_WORLD, &ntasks); MPI_Comm_rank(MPI_COMM_WORLD, &id); - ng_geometry = nullptr; #endif { diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index 5e2bbd34..fee63976 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -69,7 +69,7 @@ namespace netgen mesh -> Save (ost); } - void Ngx_Mesh :: DoArchive (ngstd::Archive & archive) + void Ngx_Mesh :: DoArchive (Archive & archive) { if (archive.Input()) mesh = make_shared(); mesh->DoArchive(archive); diff --git a/libsrc/linalg/vector.hpp b/libsrc/linalg/vector.hpp index dec8b57d..97ad05ed 100644 --- a/libsrc/linalg/vector.hpp +++ b/libsrc/linalg/vector.hpp @@ -139,6 +139,14 @@ public: ~Vector () { if (ownmem) delete [] data; } + virtual void DoArchive(Archive& ar) + { + auto size = s; + ar & ownmem & size; + if(!ar.Output()) + SetSize(size); + ar.Do(data, size); + } Vector & operator= (const FlatVector & v) { memcpy (data, &v(0), s*sizeof(double)); return *this; } diff --git a/libsrc/meshing/CMakeLists.txt b/libsrc/meshing/CMakeLists.txt index e9e6e211..bc9f7f18 100644 --- a/libsrc/meshing/CMakeLists.txt +++ b/libsrc/meshing/CMakeLists.txt @@ -30,7 +30,7 @@ if(APPLE) endif(APPLE) if(NOT WIN32) - target_link_libraries( mesh ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) + target_link_libraries( mesh ngcore ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) install( TARGETS mesh ${NG_INSTALL_DIR}) endif(NOT WIN32) diff --git a/libsrc/meshing/adfront2.cpp b/libsrc/meshing/adfront2.cpp index 7eb426ad..11dd7421 100644 --- a/libsrc/meshing/adfront2.cpp +++ b/libsrc/meshing/adfront2.cpp @@ -22,7 +22,7 @@ namespace netgen mgi = new MultiPointGeomInfo (*amgi); for (int i = 1; i <= mgi->GetNPGI(); i++) if (mgi->GetPGI(i).trignum <= 0) - cout << "Add FrontPoint2, illegal geominfo = " << mgi->GetPGI(i).trignum << endl; + cout << "WARNING: Add FrontPoint2, illegal geominfo = " << mgi->GetPGI(i).trignum << endl; } else mgi = NULL; @@ -136,7 +136,7 @@ namespace netgen if (!gi1.trignum || !gi2.trignum) { - cout << "ERROR: in AdFront::AddLine, illegal geominfo" << endl; + cout << "WARNING: in AdFront::AddLine, illegal geominfo" << endl; } lines[li].SetGeomInfo (gi1, gi2); diff --git a/libsrc/meshing/basegeom.cpp b/libsrc/meshing/basegeom.cpp index 1de6af28..e9b9aa5e 100644 --- a/libsrc/meshing/basegeom.cpp +++ b/libsrc/meshing/basegeom.cpp @@ -74,4 +74,5 @@ namespace netgen throw NgException("Cannot save geometry - no geometry available"); } + static RegisterClassForArchive regnggeo; } diff --git a/libsrc/meshing/basegeom.hpp b/libsrc/meshing/basegeom.hpp index 0637e915..ceb703f2 100644 --- a/libsrc/meshing/basegeom.hpp +++ b/libsrc/meshing/basegeom.hpp @@ -22,6 +22,9 @@ namespace netgen virtual const Refinement & GetRefinement () const; + virtual void DoArchive(Archive&) + { throw NgException("DoArchive not implemented for " + Demangle(typeid(*this).name())); } + virtual void Save (string filename) const; virtual void SaveToMeshFile (ostream & /* ost */) const { ; } }; diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index 709c25e9..96a944fc 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -1752,6 +1752,18 @@ namespace netgen } } + + Point<2> _xi(xi); + Point<3> _x; + Mat<3,2> _dxdxi; + if (EvaluateMapping (info, _xi, _x, _dxdxi)) + { + if (x) *x = _x; + if (dxdxi) *dxdxi = _dxdxi; + return; + } + + ArrayMem,100> coefs(info.ndof); ArrayMem shapes_mem(info.ndof); TFlatVector shapes(info.ndof, &shapes_mem[0]); @@ -2254,6 +2266,18 @@ namespace netgen } break; } + case QUAD: + { + if (info.order >= 2) return false; // not yet supported + AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; + for (int j = 0; j < 4; j++) + { + Point<3> p = mesh[el[j]]; + for (int k = 0; k < DIM_SPACE; k++) + mapped_x[k] += p(k) * lami[j]; + } + break; + } default: return false; } diff --git a/libsrc/meshing/curvedelems.hpp b/libsrc/meshing/curvedelems.hpp index 99747034..29c911aa 100644 --- a/libsrc/meshing/curvedelems.hpp +++ b/libsrc/meshing/curvedelems.hpp @@ -48,6 +48,11 @@ public: int GetOrder () { return order; } + virtual void DoArchive(Archive& ar) + { + ar & edgeorder & faceorder & edgecoeffsindex & facecoeffsindex & edgecoeffs & facecoeffs + & edgeweight & order & rational & ishighorder; + } bool IsSegmentCurved (SegmentIndex segnr) const; bool IsSurfaceElementCurved (SurfaceElementIndex sei) const; diff --git a/libsrc/meshing/meshclass.hpp b/libsrc/meshing/meshclass.hpp index 2de6d3ee..fe72de2a 100644 --- a/libsrc/meshing/meshclass.hpp +++ b/libsrc/meshing/meshclass.hpp @@ -517,7 +517,7 @@ namespace netgen DLL_HEADER void Merge (const string & filename, const int surfindex_offset = 0); - DLL_HEADER void DoArchive (ngstd::Archive & archive); + DLL_HEADER void DoArchive (Archive & archive); /// DLL_HEADER void ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY); diff --git a/libsrc/meshing/meshtype.cpp b/libsrc/meshing/meshtype.cpp index cdfa7c7c..baed182e 100644 --- a/libsrc/meshing/meshtype.cpp +++ b/libsrc/meshing/meshtype.cpp @@ -148,9 +148,9 @@ namespace netgen return *this; } - ngstd::Archive & Segment :: DoArchive (ngstd::Archive & ar) + void Segment :: DoArchive (Archive & ar) { - return ar & pnums[0] & pnums[1] & pnums[2] + ar & pnums[0] & pnums[1] & pnums[2] & edgenr & singedge_left & singedge_right & si & cd2i & domin & domout & tlosurf & surfnr1 & surfnr2 @@ -2427,9 +2427,9 @@ namespace netgen bcn = &default_bcname; } - ngstd::Archive & FaceDescriptor :: DoArchive (ngstd::Archive & ar) + void FaceDescriptor :: DoArchive (Archive & ar) { - return ar & surfnr & domin & domout & tlosurf & bcprop + ar & surfnr & domin & domout & tlosurf & bcprop & surfcolour.X() & surfcolour.Y() & surfcolour.Z() & bcname & domin_singular & domout_singular ; @@ -2482,7 +2482,7 @@ namespace netgen maxidentnr = 0; } - ngstd::Archive & Identifications :: DoArchive (ngstd::Archive & ar) + void Identifications :: DoArchive (Archive & ar) { ar & maxidentnr; ar & identifiedpoints & identifiedpoints_nr; @@ -2503,7 +2503,6 @@ namespace netgen for (auto & t : type) ar & (unsigned char&)(t); } - return ar; } diff --git a/libsrc/meshing/meshtype.hpp b/libsrc/meshing/meshtype.hpp index 5fe1d8a6..5ded7330 100644 --- a/libsrc/meshing/meshtype.hpp +++ b/libsrc/meshing/meshtype.hpp @@ -171,13 +171,9 @@ namespace netgen enum { BASE = 1 }; #endif - ngstd::Archive & DoArchive (ngstd::Archive & ar) { return ar & i; } + void DoArchive (Archive & ar) { ar & i; } }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, PointIndex & mp) - { return mp.DoArchive(archive); } - - inline istream & operator>> (istream & ist, PointIndex & pi) { int i; ist >> i; pi = PointIndex(i); return ist; @@ -247,14 +243,9 @@ namespace netgen SurfaceElementIndex & operator-- () { --i; return *this; } SurfaceElementIndex & operator+= (int inc) { i+=inc; return *this; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) { return ar & i; } + void DoArchive (Archive & ar) { ar & i; } }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, SurfaceElementIndex & mp) - { return mp.DoArchive(archive); } - - - inline istream & operator>> (istream & ist, SurfaceElementIndex & pi) { int i; ist >> i; pi = i; return ist; @@ -337,19 +328,13 @@ namespace netgen static MPI_Datatype MyGetMPIType ( ); #endif - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { ar & x[0] & x[1] & x[2] & layer & singular; ar & (unsigned char&)(type); - return ar; } }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, MeshPoint & mp) - { return mp.DoArchive(archive); } - - - inline ostream & operator<<(ostream & s, const MeshPoint & pt) { return (s << Point<3> (pt)); @@ -497,7 +482,7 @@ namespace netgen /// const PointGeomInfo & GeomInfoPiMod (int i) const { return geominfo[(i-1) % np]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { short _np, _typ; bool _curved, _vis, _deleted; @@ -511,7 +496,6 @@ namespace netgen visible = _vis; deleted = _deleted; } for (size_t i = 0; i < np; i++) ar & pnum[i]; - return ar; } void SetIndex (int si) { index = si; } @@ -630,9 +614,6 @@ namespace netgen #endif }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, Element2d & mp) - { return mp.DoArchive(archive); } - ostream & operator<<(ostream & s, const Element2d & el); @@ -774,7 +755,7 @@ namespace netgen /// const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { short _np, _typ; if (ar.Output()) @@ -784,7 +765,6 @@ namespace netgen { np = _np; typ = ELEMENT_TYPE(_typ); } for (size_t i = 0; i < np; i++) ar & pnum[i]; - return ar; } /// @@ -928,9 +908,6 @@ namespace netgen int hp_elnr; }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, Element & mp) - { return mp.DoArchive(archive); } - ostream & operator<<(ostream & s, const Element & el); @@ -1049,12 +1026,9 @@ namespace netgen #else int GetPartition () const { return 0; } #endif - ngstd::Archive & DoArchive (ngstd::Archive & ar); + void DoArchive (Archive & ar); }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, Segment & mp) - { return mp.DoArchive(archive); } - ostream & operator<<(ostream & s, const Segment & seg); @@ -1062,6 +1036,7 @@ namespace netgen { public: PointIndex pnum; + string name; int index; Element0d () = default; Element0d (PointIndex _pnum, int _index) @@ -1142,13 +1117,9 @@ namespace netgen // friend ostream & operator<<(ostream & s, const FaceDescriptor & fd); friend class Mesh; - ngstd::Archive & DoArchive (ngstd::Archive & ar); + void DoArchive (Archive & ar); }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, FaceDescriptor & mp) - { return mp.DoArchive(archive); } - - ostream & operator<< (ostream & s, const FaceDescriptor & fd); @@ -1516,12 +1487,8 @@ namespace netgen DLL_HEADER void Print (ostream & ost) const; - ngstd::Archive & DoArchive (ngstd::Archive & ar); + void DoArchive (Archive & ar); }; - - inline ngstd::Archive & operator & (ngstd::Archive & archive, Identifications & mp) - { return mp.DoArchive(archive); } - } diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 682239c4..6360174a 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -61,6 +61,15 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) m.attr("_ngscript") = py::cast(script); + m.def("_GetStatus", []() + { + MyStr s; double percent; + GetStatus(s, percent); + return py::make_tuple(s.c_str(), percent); + }); + m.def("_PushStatus", [](string s) { PushStatus(MyStr(s)); }); + m.def("_SetThreadPercentage", [](double percent) { SetThreadPercent(percent); }); + py::class_(m, "NGDummyArgument") .def("__bool__", []( NGDummyArgument &self ) { return false; } ) ; @@ -263,6 +272,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) ) .def("__repr__", &ToString) .def_property("index", &Element::GetIndex, &Element::SetIndex) + .def_property("curved", &Element::IsCurved, &Element::SetCurved) .def_property_readonly("vertices", FunctionPointer ([](const Element & self) -> py::list { @@ -314,6 +324,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) "create surface element" ) .def_property("index", &Element2d::GetIndex, &Element2d::SetIndex) + .def_property("curved", &Element2d::IsCurved, &Element2d::SetCurved) .def_property_readonly("vertices", FunctionPointer([](const Element2d & self) -> py::list { @@ -477,11 +488,12 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) auto mesh = make_shared(); mesh -> SetDimension(dim); SetGlobalMesh(mesh); // for visualization - mesh -> SetGeometry (make_shared()); + mesh -> SetGeometry (nullptr); return mesh; } ), py::arg("dim")=3 ) + .def(NGSPickle()) /* .def("__init__", @@ -554,8 +566,6 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) break; } } - if (!ng_geometry) - ng_geometry = make_shared(); self.SetGeometry(ng_geometry); delete infile; }),py::call_guard()) diff --git a/libsrc/occ/CMakeLists.txt b/libsrc/occ/CMakeLists.txt index 2f10e54e..831a3875 100644 --- a/libsrc/occ/CMakeLists.txt +++ b/libsrc/occ/CMakeLists.txt @@ -4,13 +4,17 @@ add_library(occ ${NG_LIB_TYPE} Partition_Loop.cxx Partition_Loop2d.cxx Partition_Loop3d.cxx Partition_Spliter.cxx occconstruction.cpp occgenmesh.cpp occgeom.cpp occmeshsurf.cpp python_occ.cpp ) - -add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) +if(USE_GUI) + add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) +endif(USE_GUI) if(NOT WIN32) target_link_libraries( occ ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) - target_link_libraries( occvis occ ) - install( TARGETS occ occvis ${NG_INSTALL_DIR}) + install( TARGETS occ ${NG_INSTALL_DIR}) + if (USE_GUI) + target_link_libraries( occvis occ ) + install( TARGETS occvis ${NG_INSTALL_DIR}) + endif(USE_GUI) endif(NOT WIN32) install(FILES diff --git a/libsrc/occ/occgeom.cpp b/libsrc/occ/occgeom.cpp index d8aeff4a..cc721e57 100644 --- a/libsrc/occ/occgeom.cpp +++ b/libsrc/occ/occgeom.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "ShapeAnalysis_ShapeTolerance.hxx" #include "ShapeAnalysis_ShapeContents.hxx" #include "ShapeAnalysis_CheckSmallFace.hxx" @@ -1106,94 +1107,8 @@ void STEP_GetEntityName(const TopoDS_Shape & theShape, STEPCAFControl_Reader * a // } - - // Philippose - 23/02/2009 - /* Special IGES File load function including the ability - to extract individual surface colours via the extended - OpenCascade XDE and XCAF Feature set. - */ - OCCGeometry *LoadOCC_IGES(const char *filename) - { - OCCGeometry *occgeo; - occgeo = new OCCGeometry; - - // Initiate a dummy XCAF Application to handle the IGES XCAF Document - static Handle_XCAFApp_Application dummy_app = XCAFApp_Application::GetApplication(); - - // Create an XCAF Document to contain the IGES file itself - Handle_TDocStd_Document iges_doc; - - // Check if a IGES File is already open under this handle, if so, close it to prevent - // Segmentation Faults when trying to create a new document - if(dummy_app->NbDocuments() > 0) - { - dummy_app->GetDocument(1,iges_doc); - dummy_app->Close(iges_doc); - } - dummy_app->NewDocument ("IGES-XCAF",iges_doc); - - IGESCAFControl_Reader reader; - - Standard_Integer stat = reader.ReadFile((char*)filename); - - if(stat != IFSelect_RetDone) - { - delete occgeo; - return NULL; - } - - // Enable transfer of colours - reader.SetColorMode(Standard_True); - - reader.Transfer(iges_doc); - - // Read in the shape(s) and the colours present in the IGES File - Handle_XCAFDoc_ShapeTool iges_shape_contents = XCAFDoc_DocumentTool::ShapeTool(iges_doc->Main()); - Handle_XCAFDoc_ColorTool iges_colour_contents = XCAFDoc_DocumentTool::ColorTool(iges_doc->Main()); - - TDF_LabelSequence iges_shapes; - iges_shape_contents->GetShapes(iges_shapes); - - // List out the available colours in the IGES File as Colour Names - TDF_LabelSequence all_colours; - iges_colour_contents->GetColors(all_colours); - PrintMessage(1,"Number of colours in IGES File: ",all_colours.Length()); - for(int i = 1; i <= all_colours.Length(); i++) - { - Quantity_Color col; - stringstream col_rgb; - iges_colour_contents->GetColor(all_colours.Value(i),col); - col_rgb << " : (" << col.Red() << "," << col.Green() << "," << col.Blue() << ")"; - PrintMessage(1, "Colour [", i, "] = ",col.StringName(col.Name()),col_rgb.str()); - } - - - // For the IGES Reader, all the shapes can be exported as one compound shape - // using the "OneShape" member - occgeo->shape = reader.OneShape(); - occgeo->face_colours = iges_colour_contents; - occgeo->changed = 1; - occgeo->BuildFMap(); - - occgeo->CalcBoundingBox(); - PrintContents (occgeo); - - return occgeo; - } - - - - - - // Philippose - 29/01/2009 - /* Special STEP File load function including the ability - to extract individual surface colours via the extended - OpenCascade XDE and XCAF Feature set. - */ - OCCGeometry * LoadOCC_STEP (const char * filename) - { - OCCGeometry * occgeo; - occgeo = new OCCGeometry; + void LoadOCCInto(OCCGeometry* occgeo, const char* filename) + { // Initiate a dummy XCAF Application to handle the STEP XCAF Document static Handle_XCAFApp_Application dummy_app = XCAFApp_Application::GetApplication(); @@ -1219,8 +1134,7 @@ void STEP_GetEntityName(const TopoDS_Shape & theShape, STEPCAFControl_Reader * a if(stat != IFSelect_RetDone) { - delete occgeo; - return NULL; + throw NgException("Couldn't load OCC geometry"); } reader.Transfer(step_doc); @@ -1287,6 +1201,94 @@ void STEP_GetEntityName(const TopoDS_Shape & theShape, STEPCAFControl_Reader * a // cout << occgeo->enames[i] << endl; // cout << " " <NbDocuments() > 0) + { + dummy_app->GetDocument(1,iges_doc); + dummy_app->Close(iges_doc); + } + dummy_app->NewDocument ("IGES-XCAF",iges_doc); + + IGESCAFControl_Reader reader; + + Standard_Integer stat = reader.ReadFile((char*)filename); + + if(stat != IFSelect_RetDone) + { + throw NgException("Couldn't load occ"); + } + + // Enable transfer of colours + reader.SetColorMode(Standard_True); + + reader.Transfer(iges_doc); + + // Read in the shape(s) and the colours present in the IGES File + Handle_XCAFDoc_ShapeTool iges_shape_contents = XCAFDoc_DocumentTool::ShapeTool(iges_doc->Main()); + Handle_XCAFDoc_ColorTool iges_colour_contents = XCAFDoc_DocumentTool::ColorTool(iges_doc->Main()); + + TDF_LabelSequence iges_shapes; + iges_shape_contents->GetShapes(iges_shapes); + + // List out the available colours in the IGES File as Colour Names + TDF_LabelSequence all_colours; + iges_colour_contents->GetColors(all_colours); + PrintMessage(1,"Number of colours in IGES File: ",all_colours.Length()); + for(int i = 1; i <= all_colours.Length(); i++) + { + Quantity_Color col; + stringstream col_rgb; + iges_colour_contents->GetColor(all_colours.Value(i),col); + col_rgb << " : (" << col.Red() << "," << col.Green() << "," << col.Blue() << ")"; + PrintMessage(1, "Colour [", i, "] = ",col.StringName(col.Name()),col_rgb.str()); + } + + + // For the IGES Reader, all the shapes can be exported as one compound shape + // using the "OneShape" member + occgeo->shape = reader.OneShape(); + occgeo->face_colours = iges_colour_contents; + occgeo->changed = 1; + occgeo->BuildFMap(); + + occgeo->CalcBoundingBox(); + PrintContents (occgeo); + return occgeo; + } + + + + + + // Philippose - 29/01/2009 + /* Special STEP File load function including the ability + to extract individual surface colours via the extended + OpenCascade XDE and XCAF Feature set. + */ + OCCGeometry * LoadOCC_STEP (const char * filename) + { + OCCGeometry * occgeo; + occgeo = new OCCGeometry; + + LoadOCCInto(occgeo, filename); return occgeo; } @@ -1355,8 +1357,34 @@ void STEP_GetEntityName(const TopoDS_Shape & theShape, STEPCAFControl_Reader * a } } + void OCCGeometry :: DoArchive(Archive& ar) + { + if(ar.Output()) + { + std::stringstream ss; + STEPControl_Writer writer; + writer.Transfer(shape, STEPControl_AsIs); + auto filename = ".tmpfile_out.step"; + writer.Write(filename); + std::ifstream is(filename); + ss << is.rdbuf(); + ar << ss.str(); + std::remove(filename); + } + else + { + std::string str; + ar & str; - + auto filename = ".tmpfile.step"; + auto tmpfile = std::fopen(filename, "w"); + std::fputs(str.c_str(), tmpfile); + std::fclose(tmpfile); + LoadOCCInto(this, filename); + std::remove(filename); + } + } + const char * shapesname[] = {" ", "CompSolids", "Solids", "Shells", diff --git a/libsrc/occ/occgeom.hpp b/libsrc/occ/occgeom.hpp index 6229a7cc..8c93ff1f 100644 --- a/libsrc/occ/occgeom.hpp +++ b/libsrc/occ/occgeom.hpp @@ -246,6 +246,7 @@ namespace netgen DLL_HEADER virtual void Save (string filename) const; + void DoArchive(Archive& ar); DLL_HEADER void BuildFMap(); diff --git a/libsrc/occ/python_occ.cpp b/libsrc/occ/python_occ.cpp index 3d95bcd6..eec271a1 100644 --- a/libsrc/occ/python_occ.cpp +++ b/libsrc/occ/python_occ.cpp @@ -18,6 +18,7 @@ DLL_HEADER void ExportNgOCC(py::module &m) { py::class_, NetgenGeometry> (m, "OCCGeometry", R"raw_string(Use LoadOCCGeometry to load the geometry from a *.step file.)raw_string") .def(py::init<>()) + .def(NGSPickle()) .def("Heal",[](OCCGeometry & self, double tolerance, bool fixsmalledges, bool fixspotstripfaces, bool sewfaces, bool makesolids, bool splitpartitions) { self.tolerance = tolerance; diff --git a/libsrc/stlgeom/python_stl.cpp b/libsrc/stlgeom/python_stl.cpp index 66101d0f..4968078e 100644 --- a/libsrc/stlgeom/python_stl.cpp +++ b/libsrc/stlgeom/python_stl.cpp @@ -20,6 +20,7 @@ DLL_HEADER void ExportSTL(py::module & m) { py::class_, NetgenGeometry> (m,"STLGeometry") .def(py::init<>()) + .def(NGSPickle()) .def("_visualizationData", [](shared_ptr stl_geo) { std::vector vertices; diff --git a/libsrc/stlgeom/stlgeom.cpp b/libsrc/stlgeom/stlgeom.cpp index 79e57ab8..ebb5136f 100644 --- a/libsrc/stlgeom/stlgeom.cpp +++ b/libsrc/stlgeom/stlgeom.cpp @@ -3579,5 +3579,5 @@ void STLGeometry :: SmoothGeometry () STLInit stlinit; - +static RegisterClassForArchive stlgeo; } diff --git a/libsrc/stlgeom/stlgeom.hpp b/libsrc/stlgeom/stlgeom.hpp index dfed02de..8d8d640f 100644 --- a/libsrc/stlgeom/stlgeom.hpp +++ b/libsrc/stlgeom/stlgeom.hpp @@ -184,6 +184,10 @@ namespace netgen STLGeometry(); virtual ~STLGeometry(); + void DoArchive(Archive& ar) + { + STLTopology::DoArchive(ar); + } void Clear(); diff --git a/libsrc/stlgeom/stltopology.cpp b/libsrc/stlgeom/stltopology.cpp index baabe981..7c32b0e4 100644 --- a/libsrc/stlgeom/stltopology.cpp +++ b/libsrc/stlgeom/stltopology.cpp @@ -1074,5 +1074,5 @@ void STLTopology :: OrientAfterTrig (int trig) } } - +static RegisterClassForArchive stltop; } diff --git a/libsrc/stlgeom/stltopology.hpp b/libsrc/stlgeom/stltopology.hpp index f5ecb8f2..a76d5ee5 100644 --- a/libsrc/stlgeom/stltopology.hpp +++ b/libsrc/stlgeom/stltopology.hpp @@ -96,6 +96,17 @@ public: STLTriangle (const int * apts); STLTriangle () {pts[0]=0;pts[1]=0;pts[2]=0;} + void DoArchive(Archive& ar) + { + ar.Do(&topedges[0],3); + ar.Do(&nbtrigs[0][0], 6); + ar.Do(&pts[0],3); + ar.Do(&domains[0],2); + size_t i = flags.toperror; + ar & normal & box & center & rad & facenum & i; + flags.toperror = i; + } + int operator[] (int i) const { return pts[i]; } int & operator[] (int i) { return pts[i]; } @@ -279,6 +290,13 @@ public: void Save (const char* filename) const; void SaveBinary (const char* filename, const char* aname) const; void SaveSTLE (const char * filename) const; // stores trigs and edges + + virtual void DoArchive(Archive& ar) + { + ar & trias & points & boundingbox & pointtol; + if(ar.Input()) + FindNeighbourTrigs(); + } virtual void InitSTLGeometry (const Array & readtrigs); diff --git a/ng/CMakeLists.txt b/ng/CMakeLists.txt index 75de5b1c..2705aecf 100644 --- a/ng/CMakeLists.txt +++ b/ng/CMakeLists.txt @@ -24,19 +24,13 @@ if(USE_GUI) add_executable(netgen ngappinit.cpp onetcl.cpp) - target_link_libraries( gui PUBLIC nglib ${ZLIB_LIBRARIES} ${JPEG_LIBRARIES} ${FFMPEG_LIBRARIES} ${X11_X11_LIB} ${OCC_LIBRARIES} ) - target_link_libraries( gui PRIVATE ${LIBTOGL}) + target_link_libraries( gui PUBLIC nglib ) + target_link_libraries( gui PRIVATE ${LIBTOGL} ${ZLIB_LIBRARIES} ${JPEG_LIBRARIES} ${FFMPEG_LIBRARIES} ${X11_Xmu_LIB} ${X11_X11_LIB} ${OCC_LIBRARIES} ) + if(NOT APPLE) + target_link_libraries( gui PRIVATE ${TCL_LIBRARY} ${TK_LIBRARY}) + endif(NOT APPLE) - target_link_libraries( netgen nglib gui ) - - if(APPLE) - # Leave decision about which tcl/tk version to use open to python (and it's tkinter package). - # Thus, only link tcl/tk to the netgen executable and not to the gui library. - target_link_libraries( netgen ${TK_LIBRARY} ${TCL_LIBRARY}) - else(APPLE) - # On other systems assume that the found libraries are compatible with python/tkinter - target_link_libraries( gui PUBLIC ${TK_LIBRARY} ${TCL_LIBRARY}) - endif(APPLE) + target_link_libraries( netgen nglib gui ${LIBTOGL} ${ZLIB_LIBRARIES} ${JPEG_LIBRARIES} ${FFMPEG_LIBRARIES} ${X11_Xmu_LIB} ${X11_X11_LIB} ${OCC_LIBRARIES} ${TK_LIBRARY} ${TCL_LIBRARY}) if(NOT WIN32) target_link_libraries( netgen mesh stlvis stl geom2dvis interface geom2d csg stl visual csgvis ) @@ -57,7 +51,7 @@ endif(USE_GUI) if(USE_PYTHON) add_library(ngpy SHARED netgenpy.cpp) - target_link_libraries( ngpy nglib ) + target_link_libraries( ngpy PUBLIC nglib PRIVATE ${PYTHON_LIBRARIES}) if(APPLE) set_target_properties( ngpy PROPERTIES SUFFIX ".so") elseif(WIN32) diff --git a/ng/dialog.tcl b/ng/dialog.tcl index 50488c96..8faac639 100644 --- a/ng/dialog.tcl +++ b/ng/dialog.tcl @@ -2009,7 +2009,7 @@ proc surfacemeshsizedialog { } { frame $w.face -borderwidth 3 pack $w.face -fill x -padx 5 ttk::label $w.face.lab -text "face index:" - ttk::label $w.face.ent -text 1 -padx 4 + ttk::label $w.face.ent -text 1 ttk::button $w.face.next -text "next" -command { set w .surfacemeshsize_dlg; set facenr [$w.face.ent cget -text] diff --git a/ng/onetcl.cpp b/ng/onetcl.cpp index 3d0645d0..591af1a0 100644 --- a/ng/onetcl.cpp +++ b/ng/onetcl.cpp @@ -2687,7 +2687,7 @@ const char * ngscript[] = {"" ,"frame $w.face -borderwidth 3\n" ,"pack $w.face -fill x -padx 5\n" ,"ttk::label $w.face.lab -text \"face index:\"\n" -,"ttk::label $w.face.ent -text 1 -padx 4\n" +,"ttk::label $w.face.ent -text 1\n" ,"ttk::button $w.face.next -text \"next\" -command {\n" ,"set w .surfacemeshsize_dlg;\n" ,"set facenr [$w.face.ent cget -text]\n" diff --git a/nglib/CMakeLists.txt b/nglib/CMakeLists.txt index cf5e192d..ff8bd1d5 100644 --- a/nglib/CMakeLists.txt +++ b/nglib/CMakeLists.txt @@ -26,20 +26,22 @@ endif(WIN32) add_library(nglib SHARED nglib.cpp ${nglib_objects}) if(NOT WIN32) - target_link_libraries( nglib mesh stl interface geom2d csg stl visual) + target_link_libraries( nglib PUBLIC mesh stl interface geom2d csg stl visual) if(USE_GUI) - target_link_libraries( nglib stlvis geom2dvis csgvis ) + target_link_libraries( nglib PUBLIC stlvis geom2dvis csgvis ) endif(USE_GUI) endif(NOT WIN32) -target_link_libraries( nglib ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} ) +target_link_libraries(nglib PUBLIC ngcore) + +target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} ) if(USE_OCC AND NOT WIN32) - target_link_libraries(nglib occ) + target_link_libraries(nglib PUBLIC occ) endif(USE_OCC AND NOT WIN32) if(USE_PYTHON) - target_link_libraries(nglib ${PYTHON_LIBRARIES}) + target_link_libraries(nglib PRIVATE ${PYTHON_LIBRARIES}) endif(USE_PYTHON) install(TARGETS nglib ${NG_INSTALL_DIR}) diff --git a/python/gui.py b/python/gui.py index c9e73ef8..35fa1f34 100644 --- a/python/gui.py +++ b/python/gui.py @@ -11,5 +11,12 @@ def StartGUI(): win.tk.eval('load "'+netgen._netgen_lib_dir.replace('\\','/')+'/libgui[info sharedlibextension]" gui') win.tk.eval( netgen.libngpy._meshing._ngscript) + try: + from IPython import get_ipython + ipython = get_ipython() + ipython.magic('gui tk') + except: + pass + if not netgen.libngpy._meshing._netgen_executable_started: StartGUI() diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f898217f..a0783363 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1 +1,2 @@ +add_subdirectory(catch) add_subdirectory(pytest) diff --git a/tests/build_guidelines.sh b/tests/build_guidelines.sh new file mode 100644 index 00000000..111b1cd0 --- /dev/null +++ b/tests/build_guidelines.sh @@ -0,0 +1,8 @@ +cd +mkdir -p build/netgen +cd build/netgen +cmake ../../src/netgen -DUSE_CCACHE=ON -DENABLE_CPP_CORE_GUIDELINES_CHECK=ON -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang +make -j12 +make install + diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt new file mode 100644 index 00000000..fc0ebe41 --- /dev/null +++ b/tests/catch/CMakeLists.txt @@ -0,0 +1,37 @@ + +if(ENABLE_UNIT_TESTS) +add_custom_target(unit_tests) + +# Build catch_main test object +message("netgen include dir = ${NETGEN_INCLUDE_DIR_ABSOLUTE} --------------------------------------") +include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include}) +add_library(catch_main STATIC main.cpp) +set_target_properties(catch_main PROPERTIES CXX_STANDARD 17) +add_dependencies(unit_tests catch_main) +add_dependencies(catch_main project_catch) + +# ensure the test targets are built before testing +add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_tests --config ${CMAKE_BUILD_TYPE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../.. ) + +macro(add_unit_test name sources) + add_executable(test_${name} ${sources} ) + if (WIN32) + target_link_libraries(test_${name} ngcore catch_main) + else(WIN32) + target_link_libraries(test_${name} ngcore catch_main) + endif(WIN32) + + add_dependencies(unit_tests test_${name}) + add_test(NAME unit_${name} COMMAND test_${name}) + set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built) +endmacro() + +add_unit_test(archive archive.cpp) +add_unit_test(version version.cpp) + +if(ENABLE_CPP_CORE_GUIDELINES_CHECK) + set_target_properties(test_archive PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") + set_target_properties(test_version PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") +endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) + +endif(ENABLE_UNIT_TESTS) diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp new file mode 100644 index 00000000..b3f27d49 --- /dev/null +++ b/tests/catch/archive.cpp @@ -0,0 +1,306 @@ + +#include "catch.hpp" +#include <../core/ngcore.hpp> +using namespace ngcore; +using namespace std; + +class CommonBase +{ +public: + int a; + virtual ~CommonBase() {} + + virtual void DoArchive(Archive& archive) { archive & a; } +}; + +// pure abstract base class +class SharedPtrHolder : virtual public CommonBase +{ +public: + vector> names; + virtual ~SharedPtrHolder() + { } + + virtual void abstract() = 0; + virtual void DoArchive(Archive& archive) + { + CommonBase::DoArchive(archive); + archive & names; + } +}; + +class PtrHolder : virtual public CommonBase +{ +public: + vector numbers; + virtual ~PtrHolder() {} + + virtual void DoArchive(Archive& archive) + { + CommonBase::DoArchive(archive); + archive & numbers; + } +}; + +class SharedPtrAndPtrHolder : public SharedPtrHolder, public PtrHolder +{ +public: + virtual ~SharedPtrAndPtrHolder() {} + virtual void DoArchive(Archive& archive) + { + SharedPtrHolder::DoArchive(archive); + PtrHolder::DoArchive(archive); + } + virtual void abstract() {} +}; + +// Classes without virt. or multiple inheritance do not need to be registered +class SimpleClass : public CommonBase +{ +public: + double d; + virtual void DoArchive(Archive& ar) + { + CommonBase::DoArchive(ar); + ar & d; + } +}; + +class NotRegisteredForArchive : public SharedPtrAndPtrHolder {}; + +class ClassWithConstPtr +{ +private: + const int* ptr; +public: + ClassWithConstPtr(const int* aptr) : ptr(aptr) { } + // constructor only for archive + ClassWithConstPtr() {} + void DoArchive(Archive& ar) + { + ar & ptr; + } + const int* getPtr() { return ptr; } +}; + +class OneMoreDerivedClass : public SharedPtrAndPtrHolder {}; + +static RegisterClassForArchive regb; +static RegisterClassForArchive regsp; +static RegisterClassForArchive regp; +static RegisterClassForArchive regspp; +static RegisterClassForArchive regom; + +void testNullPtr(Archive& in, Archive& out) +{ + SharedPtrHolder* p = nullptr; + shared_ptr sp = nullptr; + out & p & sp; + out.FlushBuffer(); + SharedPtrHolder* pin = nullptr; + shared_ptr spin = nullptr; + in & pin & spin; + CHECK(pin == nullptr); + CHECK(spin == nullptr); +} + +void testSharedPointer(Archive& in, Archive& out) +{ + SECTION("Same shared ptr") + { + static_assert(detail::has_DoArchive::value, ""); + SharedPtrAndPtrHolder holder, holder2; + holder.names.push_back(make_shared("name")); + holder2.names = holder.names; // same shared ptr + out & holder & holder2; + out.FlushBuffer(); + SharedPtrAndPtrHolder inholder, inholder2; + in & inholder & inholder2; + CHECK(inholder.names.size() == 1); + CHECK(inholder.names[0] == inholder2.names[0]); + CHECK(inholder.names[0].use_count() == 3); // one shared ptr is still kept in the archive + CHECK(*inholder.names[0] == "name"); + } +} + +void testPointer(Archive& in, Archive& out) +{ + PtrHolder holder, holder2; + holder.numbers.push_back(new int(3)); + holder2.numbers = holder.numbers; // same shared ptr + out & holder & holder2; + out.FlushBuffer(); + PtrHolder inholder, inholder2; + in & inholder & inholder2; + CHECK(inholder.numbers.size() == 1); + CHECK(inholder.numbers[0] == inholder2.numbers[0]); + CHECK(*inholder.numbers[0] == 3); +} + +void testConstPointer(Archive& in, Archive& out) +{ + SECTION("Const pointer") + { + int* iptr = new int(4); + double d = 0.1; + ClassWithConstPtr cls(iptr); + out & cls & iptr & d; + out.FlushBuffer(); + ClassWithConstPtr incls; + int* iniptr; + double ind; + in & incls & iniptr & ind; + CHECK(*incls.getPtr() == 4); + CHECK(incls.getPtr() == iniptr); + CHECK(ind == 0.1); + delete iptr; + delete iniptr; + } +} + +void testMultipleInheritance(Archive& in, Archive& out) +{ + PtrHolder* p = new OneMoreDerivedClass; + p->numbers.push_back(new int(2)); + p->a = 5; + auto p2 = dynamic_cast(p); + p2->names.push_back(make_shared("test")); + auto sp1 = shared_ptr(p); + auto sp2 = dynamic_pointer_cast(sp1); + auto checkPtr = [] (auto pin, auto pin2) + { + CHECK(typeid(*pin) == typeid(*pin2)); + CHECK(typeid(*pin) == typeid(OneMoreDerivedClass)); + CHECK(*pin2->names[0] == "test"); + CHECK(*pin->numbers[0] == 2); + CHECK(dynamic_cast(pin) == dynamic_cast(pin2)); + CHECK(pin->a == pin2->a); + CHECK(pin->a == 5); + REQUIRE(dynamic_cast(pin2) != nullptr); + CHECK(*dynamic_cast(pin2)->numbers[0] == 2); + CHECK(*pin->numbers[0] == *dynamic_cast(pin2)->numbers[0]); + REQUIRE(dynamic_cast(pin) != nullptr); + CHECK(dynamic_cast(pin)->names[0] == pin2->names[0]); + }; + SECTION("Archive ptrs to leaves of mult. inh.") + { + out & p & p2; + out.FlushBuffer(); + PtrHolder* pin = nullptr; + SharedPtrHolder* pin2 = nullptr; + in & pin & pin2; + checkPtr(pin, pin2); + } + SECTION("Archive shared ptrs to leaves of mult. inh.") + { + out & sp1 & sp2; + out.FlushBuffer(); + shared_ptr pin; + shared_ptr pin2; + in & pin & pin2; + checkPtr(pin.get(), pin2.get()); + } + SECTION("Virtual base class") + { + CommonBase* b = dynamic_cast(p); + out & b & p; + PtrHolder* pin; + CommonBase* bin; + in & bin & pin; + checkPtr(pin, dynamic_cast(bin)); + } + SECTION("Simple class without register") + { + auto a = new SimpleClass; + a->a = 5; + a->d = 2.3; + SECTION("check pointer") + { + out & a; + out.FlushBuffer(); + SimpleClass* ain; + in & ain; + CHECK(ain->a == 5); + CHECK(ain->d == 2.3); + } + SECTION("check shared pointer") + { + auto spa = shared_ptr(a); + out & spa; + out.FlushBuffer(); + shared_ptr spain; + in & spain; + CHECK(spain->a == 5); + CHECK(spain->d == 2.3); + } + } +} + +void testArchive(Archive& in, Archive& out) +{ + SECTION("Empty String") + { + char* cstr = nullptr; + char* empty = new char[1]; + char* simple = new char[7] {'s','i','m','p','l','e','\0'}; + empty[0] = '\0'; + out << string("") << cstr << empty << simple << string("simple") << long(1); + out.FlushBuffer(); + string str; long i; char* readempty; char* readsimple; + string simplestr; + in & str & cstr & readempty & readsimple & simplestr & i; + CHECK(str == ""); + CHECK(cstr == nullptr); + CHECK(strcmp(readempty,"") == 0); + CHECK(strcmp(readsimple,"simple") == 0); + CHECK(i == 1); + CHECK(simplestr == "simple"); + delete[] readempty; + delete[] empty; + delete[] simple; + delete[] readsimple; + } + SECTION("SharedPtr") + { + testSharedPointer(in, out); + } + SECTION("Pointer") + { + testPointer(in, out); + } + SECTION("Const Pointer") + { + testConstPointer(in, out); + } + SECTION("Multiple inheritance") + { + testMultipleInheritance(in, out); + } + SECTION("Not registered") + { + SharedPtrAndPtrHolder* p = new NotRegisteredForArchive; + REQUIRE_THROWS(out & p, Catch::Contains("not registered for archive")); + } + SECTION("nullptr") + { + testNullPtr(in, out); + } +} + +TEST_CASE("BinaryArchive") +{ + SetLibraryVersion("netgen","v6.2.1811"); + auto stream = make_shared(); + BinaryOutArchive out(stream); + BinaryInArchive in(stream); + testArchive(in, out); +} + +TEST_CASE("TextArchive") +{ + SetLibraryVersion("netgen","v6.2.1811"); + auto stream = make_shared(); + TextOutArchive out(stream); + TextInArchive in(stream); + testArchive(in, out); +} diff --git a/tests/catch/main.cpp b/tests/catch/main.cpp new file mode 100644 index 00000000..de419564 --- /dev/null +++ b/tests/catch/main.cpp @@ -0,0 +1,3 @@ + +#define CATCH_CONFIG_MAIN +#include diff --git a/tests/catch/version.cpp b/tests/catch/version.cpp new file mode 100644 index 00000000..5655ab23 --- /dev/null +++ b/tests/catch/version.cpp @@ -0,0 +1,19 @@ + +#include "catch.hpp" +#include <../core/ngcore.hpp> +using namespace ngcore; +using namespace std; + + +TEST_CASE("Version") +{ + VersionInfo v("v6.2.1811-3-asdf"); + CHECK(v.to_string() == "v6.2.1811-3-asdf"); + VersionInfo v2("6.2"); + CHECK(v2.to_string() == "v6.2"); + CHECK(v < "v7"); + CHECK(v >= "6.2"); + CHECK(v > "6.2.1811"); + CHECK(v < "6.2.1811-5"); + CHECK(v == "v6.2.1811-3"); +} diff --git a/tests/docker_16.04 b/tests/docker_16.04 deleted file mode 100644 index 2195714b..00000000 --- a/tests/docker_16.04 +++ /dev/null @@ -1,4 +0,0 @@ -FROM ubuntu:16.04 -MAINTAINER Matthias Hochsteger -RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk -ADD . /root/src/netgen diff --git a/tests/docker_15.10 b/tests/dockerfile similarity index 62% rename from tests/docker_15.10 rename to tests/dockerfile index b386f250..ebed3dea 100644 --- a/tests/docker_15.10 +++ b/tests/dockerfile @@ -1,4 +1,5 @@ -FROM ubuntu:15.10 +FROM ubuntu:18.04 +ENV DEBIAN_FRONTEND=noninteractive MAINTAINER Matthias Hochsteger -RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk +RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy python3-distutils clang ADD . /root/src/netgen diff --git a/tests/pytest/test_pickling.py b/tests/pytest/test_pickling.py new file mode 100644 index 00000000..13e20f9e --- /dev/null +++ b/tests/pytest/test_pickling.py @@ -0,0 +1,105 @@ + +import pickle, numpy + +def test_pickle_csg(): + import netgen.csg as csg + geo = csg.CSGeometry() + geo.Add(csg.Sphere(csg.Pnt(0,0,0), 2).bc("sphere")) + brick = csg.OrthoBrick(csg.Pnt(-3,-3,-3), csg.Pnt(3,3,3)) + geo.Add(csg.Cylinder(csg.Pnt(0,0,0), csg.Pnt(1,0,0), 0.5) * brick) + geo.Add(csg.Ellipsoid(csg.Pnt(0,0,0), csg.Vec(1,0,0), csg.Vec(0,1,0), csg.Vec(0,0,0.5))) + geo.Add(csg.Cone(csg.Pnt(0,0,0), csg.Pnt(3,0,0), 1, 0.5) * brick) + geo.Add(csg.EllipticCone(csg.Pnt(0,0,0), csg.Vec(2,0,0), csg.Vec(0,1,0), 3, 0.5) * brick) + geo.Add(csg.Torus(csg.Pnt(0,0,0), csg.Vec(0,1,0), 0.3, 0.05)) + pts2d = [[1,1], [1,-1], [-1,-1], [-1,1]] + segs = [[0,1], [1,2], [2,3], [3,0]] + curve = csg.SplineCurve2d() + pnrs = [curve.AddPoint(*p) for p in pts2d] + for s in segs: + curve.AddSegment(pnrs[s[0]], pnrs[s[1]]) + geo.Add(csg.Revolution(csg.Pnt(0,0,0), csg.Pnt(1,0,0), curve)) + path = csg.SplineCurve3d() + pnts = [(0,0,0), (2,0,0), (2,2,0)] + segs = [(0,1,2)] + for pnt in pnts: + path.AddPoint (*pnt) + + for seg in segs: + path.AddSegment (*seg) + geo.Add(csg.Extrusion(path, curve, csg.Vec(0,0,1))) + + geo_dump = pickle.dumps(geo) + geo2 = pickle.loads(geo_dump) + vd1 = geo._visualizationData() + vd2 = geo2._visualizationData() + for val1, val2 in zip(vd1.values(), vd2.values()): + assert numpy.array_equal(val1, val2) + +def test_pickle_stl(): + import netgen.stl as stl + geo = stl.LoadSTLGeometry("../../tutorials/hinge.stl") + geo_dump = pickle.dumps(geo) + geo2 = pickle.loads(geo_dump) + vd1 = geo._visualizationData() + vd2 = geo2._visualizationData() + for val1, val2 in zip(vd1.values(), vd2.values()): + assert numpy.array_equal(val1, val2) + + +def test_pickle_occ(): + try: + import netgen.NgOCC as occ + except: + import pytest + pytest.skip("can't import occ") + geo = occ.LoadOCCGeometry("../../tutorials/frame.step") + geo_dump = pickle.dumps(geo) + geo2 = pickle.loads(geo_dump) + vd1 = geo._visualizationData() + vd2 = geo2._visualizationData() + # TODO: it looks fine, but tests fail, so I assume we loose some info? + # for val1, val2 in zip(vd1.values(), vd2.values()): + # assert numpy.allclose(val1, val2, rtol=0.01) + +def test_pickle_geom2d(): + import netgen.geom2d as geom2d + geo = geom2d.SplineGeometry() + + # point coordinates ... + pnts = [ (0,0), (1,0), (1,0.6), (0,0.6), \ + (0.2,0.6), (0.8,0.6), (0.8,0.8), (0.2,0.8), \ + (0.5,0.15), (0.65,0.3), (0.5,0.45), (0.35,0.3) ] + pnums = [geo.AppendPoint(*p) for p in pnts] + + # start-point, end-point, boundary-condition, domain on left side, domain on right side: + lines = [ (0,1,1,1,0), (1,2,2,1,0), (2,5,2,1,0), (5,4,2,1,2), (4,3,2,1,0), (3,0,2,1,0), \ + (5,6,2,2,0), (6,7,2,2,0), (7,4,2,2,0), \ + (8,9,2,3,1), (9,10,2,3,1), (10,11,2,3,1), (11,8,2,3,1) ] + + for p1,p2,bc,left,right in lines: + geo.Append( ["line", pnums[p1], pnums[p2]], bc=bc, leftdomain=left, rightdomain=right) + geo_dump = pickle.dumps(geo) + geo2 = pickle.loads(geo_dump) + vd1 = geo._visualizationData() + vd2 = geo2._visualizationData() + for val1, val2 in zip(vd1.values(), vd2.values()): + assert numpy.array_equal(val1, val2) + +def test_pickle_mesh(): + import netgen.csg as csg + geo = csg.CSGeometry() + brick = csg.OrthoBrick(csg.Pnt(-3,-3,-3), csg.Pnt(3,3,3)) + mesh = geo.GenerateMesh(maxh=0.2) + assert geo == mesh.GetGeometry() + dump = pickle.dumps([geo,mesh]) + geo2, mesh2 = pickle.loads(dump) + assert geo2 == mesh2.GetGeometry() + mesh.Save("msh1.vol.gz") + mesh2.Save("msh2.vol.gz") + import filecmp, os + assert filecmp.cmp("msh1.vol.gz", "msh2.vol.gz") + os.remove("msh1.vol.gz") + os.remove("msh2.vol.gz") + +if __name__ == "__main__": + test_pickle_mesh()