diff -Nru netgen-6.2.1804+dfsg1/cmake/external_projects/catch.cmake netgen-6.2.1905+dfsg1/cmake/external_projects/catch.cmake --- netgen-6.2.1804+dfsg1/cmake/external_projects/catch.cmake 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/cmake/external_projects/catch.cmake 2019-06-26 11:04:55.000000000 +0000 @@ -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 -Nru netgen-6.2.1804+dfsg1/cmake/external_projects/metis.cmake netgen-6.2.1905+dfsg1/cmake/external_projects/metis.cmake --- netgen-6.2.1804+dfsg1/cmake/external_projects/metis.cmake 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/cmake/external_projects/metis.cmake 2019-06-26 11:04:55.000000000 +0000 @@ -3,12 +3,15 @@ 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 https://bitbucket.org/petsc/pkg-metis/get/v5.1.0-p6.tar.gz + URL_MD5 55fc654bb838846b856ba898795143f1 DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies CMAKE_ARGS -DGKLIB_PATH=${METIS_SRC_DIR}/GKlib -DCMAKE_INSTALL_PREFIX=${METIS_DIR} + -DCMAKE_POSITION_INDEPENDENT_CODE=ON + -DCMAKE_C_COMPILER=${CMAKE_C_COMPILER} + -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER} UPDATE_COMMAND "" # Disable update BUILD_IN_SOURCE 1 ) diff -Nru netgen-6.2.1804+dfsg1/cmake/external_projects/spdlog.cmake netgen-6.2.1905+dfsg1/cmake/external_projects/spdlog.cmake --- netgen-6.2.1804+dfsg1/cmake/external_projects/spdlog.cmake 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/cmake/external_projects/spdlog.cmake 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,18 @@ +include(ExternalProject) +find_program(GIT_EXECUTABLE git) + +ExternalProject_Add( + project_spdlog + PREFIX ${CMAKE_BINARY_DIR}/spdlog + GIT_REPOSITORY https://github.com/gabime/spdlog.git + GIT_TAG v1.2.1 + TIMEOUT 01 + UPDATE_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + +ExternalProject_Get_Property(project_spdlog source_dir) +set(SPDLOG_INCLUDE_DIR ${source_dir}/include) diff -Nru netgen-6.2.1804+dfsg1/cmake/external_projects/tcltk.cmake netgen-6.2.1905+dfsg1/cmake/external_projects/tcltk.cmake --- netgen-6.2.1804+dfsg1/cmake/external_projects/tcltk.cmake 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/cmake/external_projects/tcltk.cmake 2019-06-26 11:04:55.000000000 +0000 @@ -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} VERSION_EQUAL "3.7") OR (${PYTHON_VERSION_STRING} VERSION_GREATER "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 -Nru netgen-6.2.1804+dfsg1/cmake/external_projects/tkdnd_macosx.patch netgen-6.2.1905+dfsg1/cmake/external_projects/tkdnd_macosx.patch --- netgen-6.2.1804+dfsg1/cmake/external_projects/tkdnd_macosx.patch 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/cmake/external_projects/tkdnd_macosx.patch 2019-06-26 11:04:55.000000000 +0000 @@ -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 @@ - - - -- 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 +--- 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} ) + IF ( WIN32 AND NO_MSVCRT ) + STRING ( REPLACE /MD /MT CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} ) diff -Nru netgen-6.2.1804+dfsg1/cmake/SuperBuild.cmake netgen-6.2.1905+dfsg1/cmake/SuperBuild.cmake --- netgen-6.2.1804+dfsg1/cmake/SuperBuild.cmake 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/cmake/SuperBuild.cmake 2019-06-26 11:04:55.000000000 +0000 @@ -121,6 +121,8 @@ 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,11 @@ INTEL_MIC CMAKE_PREFIX_PATH CMAKE_INSTALL_PREFIX + ENABLE_UNIT_TESTS + ENABLE_CPP_CORE_GUIDELINES_CHECK + USE_SPDLOG + DEBUG_LOG + CHECK_RANGE ) # propagate all variables set on the command line using cmake -DFOO=BAR diff -Nru netgen-6.2.1804+dfsg1/CMakeLists.txt netgen-6.2.1905+dfsg1/CMakeLists.txt --- netgen-6.2.1804+dfsg1/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -2,7 +2,13 @@ set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING INTERNAL) endif(NOT CMAKE_BUILD_TYPE) -cmake_minimum_required(VERSION 3.1.3) +if(WIN32) + # we are linking to object libraries on Windows + cmake_minimum_required(VERSION 3.12) +else(WIN32) + cmake_minimum_required(VERSION 3.1.3) +endif(WIN32) + if(NOT WIN32) option( USE_NATIVE_ARCH "build which -march=native" ON) endif(NOT WIN32) @@ -17,6 +23,11 @@ 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_SPDLOG "Enable spd log logging" OFF) +option( DEBUG_LOG "Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON" OFF) +option( CHECK_RANGE "Check array range access, automatically enabled if built in debug mode" OFF) option( USE_SUPERBUILD "use ccache" ON) @@ -256,6 +267,7 @@ ####################################################################### if (USE_PYTHON) + add_subdirectory(external_dependencies/pybind11) add_definitions(-DNG_PYTHON) find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h HINTS ${PYTHON_INCLUDE_DIR}) if( PYBIND_INCLUDE_DIR ) @@ -341,8 +353,32 @@ enable_testing() include(CTest) +if(ENABLE_UNIT_TESTS) + include(${CMAKE_CURRENT_LIST_DIR}/cmake/external_projects/catch.cmake) +endif(ENABLE_UNIT_TESTS) + + ####################################################################### +if(USE_SPDLOG) + include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/external_projects/spdlog.cmake) + include_directories(${SPDLOG_INCLUDE_DIR}) +endif(USE_SPDLOG) + +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 -Nru netgen-6.2.1804+dfsg1/debian/changelog netgen-6.2.1905+dfsg1/debian/changelog --- netgen-6.2.1804+dfsg1/debian/changelog 2019-03-01 18:44:35.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/changelog 2019-07-21 06:32:26.000000000 +0000 @@ -1,8 +1,23 @@ -netgen (6.2.1804+dfsg1-3) unstable; urgency=medium +netgen (6.2.1905+dfsg1-1~ubuntu19.10.1) eoan; urgency=medium - * [425e45e] Use new OpenCASCADE path + * [b11ff5d] New upstream version 6.2.1905+dfsg1 + * [962d15c] Fix opencascade include path + * [b3ffab5] Add fix-pybind11-include.patch + * [d600d49] Update missing files - -- Kurt Kremitzki Fri, 01 Mar 2019 12:44:35 -0600 + -- Kurt Kremitzki Sun, 21 Jul 2019 01:32:26 -0500 + +netgen (6.2.1810+dfsg1-1) unstable; urgency=medium + + [ Kurt Kremitzki ] + * [bcd99bb] New upstream version 6.2.1810+dfsg1 + * [89d2030] Add Replaces to handle libnglib rename + + [ Anton Gladky ] + * [c08e683] Add Breaks-section in d/control + + + -- Kurt Kremitzki Sun, 27 Jan 2019 04:12:57 -0600 netgen (6.2.1804+dfsg1-2) unstable; urgency=medium diff -Nru netgen-6.2.1804+dfsg1/debian/control netgen-6.2.1905+dfsg1/debian/control --- netgen-6.2.1804+dfsg1/debian/control 2018-12-29 03:49:10.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/control 2019-07-21 06:32:26.000000000 +0000 @@ -26,15 +26,16 @@ libbz2-dev, pybind11-dev, python3-dev, - python3-dbg -Standards-Version: 4.1.4 + python3-dbg, + python3-pytest +Standards-Version: 4.2.1 Vcs-Browser: https://salsa.debian.org/science-team/netgen Vcs-Git: https://salsa.debian.org/science-team/netgen.git Homepage: https://ngsolve.org Package: netgen Architecture: any -Depends: libnglib-6.2.1804 (= ${binary:Version}), +Depends: libnglib-6.2 (= ${binary:Version}), tix, ${shlibs:Depends}, ${misc:Depends} @@ -62,7 +63,7 @@ Package: libnglib-dev Architecture: any Section: libdevel -Depends: libnglib-6.2.1804 (= ${binary:Version}), +Depends: libnglib-6.2 (= ${binary:Version}), ${misc:Depends} Description: Automatic 3d tetrahedral mesh generator development files NETGEN is an automatic 3d tetrahedral mesh generator. It accepts @@ -74,13 +75,15 @@ . This package contains the static libraries and header files. -Package: libnglib-6.2.1804 +Package: libnglib-6.2 Architecture: any Multi-Arch: same Section: libs Depends: ${shlibs:Depends}, ${misc:Depends} Pre-Depends: ${misc:Pre-Depends} +Breaks: libnglib-6.2.1804 +Replaces: libnglib-6.2.1804 Description: Automatic 3d tetrahedral mesh generator shared library NETGEN is an automatic 3d tetrahedral mesh generator. It accepts input from constructive solid geometry (CSG) or boundary @@ -109,7 +112,8 @@ Package: python3-netgen Architecture: any Section: python -Depends: libnglib-6.2.1804 (= ${binary:Version}), +Depends: libnglib-6.2 (= ${binary:Version}), + python3-tk, ${shlibs:Depends}, ${misc:Depends}, ${python3:Depends} diff -Nru netgen-6.2.1804+dfsg1/debian/copyright netgen-6.2.1905+dfsg1/debian/copyright --- netgen-6.2.1804+dfsg1/debian/copyright 2018-12-29 03:49:10.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/copyright 2019-07-21 06:32:26.000000000 +0000 @@ -3,15 +3,11 @@ Source: https://sourceforge.net/projects/netgen-mesher/ Comment: The following files were removed because: windows: Windows cruft - external_dependencies/pybind11: Unused external dependency - libsrc/csg/splinesurface.cpp~: Temp file cruft removed in next upstream - libsrc/csg/splinesurface.hpp~: Temp file cruft removed in next upstream + external_dependencies/pybind11: Unused bundled code .gitlab-ci.yml: Upstream CI configuration Files-Excluded: windows external_dependencies/pybind11 - libsrc/csg/splinesurface.cpp~ - libsrc/csg/splinesurface.hpp~ .gitlab-ci.yml Files: * diff -Nru netgen-6.2.1804+dfsg1/debian/libnglib-6.2.1804.install netgen-6.2.1905+dfsg1/debian/libnglib-6.2.1804.install --- netgen-6.2.1804+dfsg1/debian/libnglib-6.2.1804.install 2018-12-29 03:49:10.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/libnglib-6.2.1804.install 1970-01-01 00:00:00.000000000 +0000 @@ -1,13 +0,0 @@ -usr/lib/*/netgen/libnglib.so -usr/lib/*/netgen/libvisual.so -usr/lib/*/netgen/libocc.so -usr/lib/*/netgen/libcsg.so -usr/lib/*/netgen/libcsgvis.so -usr/lib/*/netgen/libstlvis.so -usr/lib/*/netgen/libgeom2d.so -usr/lib/*/netgen/libinterface.so -usr/lib/*/netgen/libmesh.so -usr/lib/*/netgen/libstl.so -usr/lib/*/netgen/liboccvis.so -usr/lib/*/netgen/libgui.so -usr/lib/*/netgen/libgeom2dvis.so diff -Nru netgen-6.2.1804+dfsg1/debian/libnglib-6.2.install netgen-6.2.1905+dfsg1/debian/libnglib-6.2.install --- netgen-6.2.1804+dfsg1/debian/libnglib-6.2.install 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/libnglib-6.2.install 2019-07-21 06:32:26.000000000 +0000 @@ -0,0 +1,14 @@ +usr/lib/*/netgen/libnglib.so +usr/lib/*/netgen/libvisual.so +usr/lib/*/netgen/libocc.so +usr/lib/*/netgen/libcsg.so +usr/lib/*/netgen/libcsgvis.so +usr/lib/*/netgen/libstlvis.so +usr/lib/*/netgen/libgeom2d.so +usr/lib/*/netgen/libinterface.so +usr/lib/*/netgen/libmesh.so +usr/lib/*/netgen/libstl.so +usr/lib/*/netgen/liboccvis.so +usr/lib/*/netgen/libgui.so +usr/lib/*/netgen/libgeom2dvis.so +usr/lib/*/netgen/libngcore.so diff -Nru netgen-6.2.1804+dfsg1/debian/netgen-headers.install netgen-6.2.1905+dfsg1/debian/netgen-headers.install --- netgen-6.2.1804+dfsg1/debian/netgen-headers.install 2018-12-29 03:42:35.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/netgen-headers.install 2019-07-21 06:32:26.000000000 +0000 @@ -24,3 +24,4 @@ usr/include/netgen/meshing/*.hpp usr/include/netgen/gprim/*.hpp usr/include/netgen/geom2d/*.hpp +usr/include/netgen/core/*.hpp diff -Nru netgen-6.2.1804+dfsg1/debian/patches/fix-pybind11-include.patch netgen-6.2.1905+dfsg1/debian/patches/fix-pybind11-include.patch --- netgen-6.2.1804+dfsg1/debian/patches/fix-pybind11-include.patch 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/patches/fix-pybind11-include.patch 2019-07-21 06:32:26.000000000 +0000 @@ -0,0 +1,15 @@ +Description: Remove dependency on excluded copy of pybind11 +Author: Kurt Kremitzki +Last-Updated: 2019-07-21 + +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -267,7 +267,7 @@ + + ####################################################################### + if (USE_PYTHON) +- add_subdirectory(external_dependencies/pybind11) ++ find_package(pybind11 REQUIRED) + add_definitions(-DNG_PYTHON) + find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h HINTS ${PYTHON_INCLUDE_DIR}) + if( PYBIND_INCLUDE_DIR ) diff -Nru netgen-6.2.1804+dfsg1/debian/patches/series netgen-6.2.1905+dfsg1/debian/patches/series --- netgen-6.2.1804+dfsg1/debian/patches/series 2018-12-29 03:42:35.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/patches/series 2019-07-21 06:32:26.000000000 +0000 @@ -1,2 +1,3 @@ +fix-pybind11-include.patch disable-windows.patch add-sse-guard.patch diff -Nru netgen-6.2.1804+dfsg1/debian/python3-netgen.install netgen-6.2.1905+dfsg1/debian/python3-netgen.install --- netgen-6.2.1804+dfsg1/debian/python3-netgen.install 2018-12-29 03:42:35.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/python3-netgen.install 2019-07-21 06:32:26.000000000 +0000 @@ -1,3 +1,4 @@ +usr/lib/python3/dist-packages/pyngcore*.so usr/lib/python3/dist-packages/netgen/libngpy.so usr/lib/python3/dist-packages/netgen/geom2d.py usr/lib/python3/dist-packages/netgen/stl.py diff -Nru netgen-6.2.1804+dfsg1/debian/rules netgen-6.2.1905+dfsg1/debian/rules --- netgen-6.2.1804+dfsg1/debian/rules 2019-03-01 18:29:36.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/rules 2019-07-21 06:32:26.000000000 +0000 @@ -20,7 +20,8 @@ -DPYBIND_INCLUDE_DIR:PATH=/usr/include \ -DUSE_OCC:BOOL=ON \ -DUSE_SUPERBUILD:BOOL=OFF \ - -DUSE_NATIVE_ARCH:BOOL=OFF + -DUSE_NATIVE_ARCH:BOOL=OFF \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo disable_mpi_archs = mips mipsel ppc64el @@ -40,7 +41,10 @@ dh_auto_configure -- $(extra_flags) override_dh_auto_test: - # TODO: Get these working + # The '-N' arg names tests but does not run them; the autotests + # currently fail with ModuleNotFoundError: No module named 'netgen' + # These tests being disabled is offset by a basic autopkgtest present. + dh_auto_test -- ARGS\+="-VV -N" override_dh_missing: dh_missing --fail-missing diff -Nru netgen-6.2.1804+dfsg1/debian/tests/control netgen-6.2.1905+dfsg1/debian/tests/control --- netgen-6.2.1804+dfsg1/debian/tests/control 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/debian/tests/control 2019-07-21 06:32:26.000000000 +0000 @@ -0,0 +1,2 @@ +Test-Command: set -e ; cd "$AUTOPKGTEST_TMP" ; echo "Testing with python3:" ; python3 -c "import netgen; print(netgen)" +Depends: python3, python3-netgen diff -Nru netgen-6.2.1804+dfsg1/.gitmodules netgen-6.2.1905+dfsg1/.gitmodules --- netgen-6.2.1804+dfsg1/.gitmodules 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/.gitmodules 2019-06-26 11:04:55.000000000 +0000 @@ -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 -Nru netgen-6.2.1804+dfsg1/libsrc/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -1,3 +1,4 @@ +add_subdirectory(core) add_subdirectory(general) add_subdirectory(gprim) add_subdirectory(linalg) diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/archive.cpp netgen-6.2.1905+dfsg1/libsrc/core/archive.cpp --- netgen-6.2.1804+dfsg1/libsrc/core/archive.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/archive.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,42 @@ + +#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; } + + // 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 -Nru netgen-6.2.1804+dfsg1/libsrc/core/archive.hpp netgen-6.2.1905+dfsg1/libsrc/core/archive.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/archive.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/archive.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,1013 @@ +#ifndef NETGEN_CORE_ARCHIVE_HPP +#define NETGEN_CORE_ARCHIVE_HPP + +#include // for array +#include // for complex +#include // for size_t, strlen +#include // for ifstream, ofstream +#include // for function +#include // for map +#include // for shared_ptr +#include // for string +#include // for declval, enable_if_t, false_type, is_co... +#include // for type_info +#include // for move, swap, pair +#include // for vector + +#include "exception.hpp" // for UnreachableCodeException, Exception +#include "logging.hpp" // for logger +#include "ngcore_api.hpp" // for NGCORE_API +#include "type_traits.hpp" // for all_of_tmpl +#include "utils.hpp" // for Demangle, unlikely +#include "version.hpp" // for VersionInfo + +#ifdef NETGEN_PYTHON +#include +#endif // NETGEN_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); + + 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 Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } + + template::value>> + 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{0}, ptr_count{0}; + // 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; + std::map version_map = GetLibraryVersions(); + std::shared_ptr logger = GetLogger("Archive"); + public: + Archive() = delete; + Archive(const Archive&) = delete; + Archive(Archive&&) = delete; + Archive (bool ais_output) : is_output(ais_output) { ; } + + virtual ~Archive() { ; } + + // If the object is pickled, all shallow archived objects will be pickled as a list, + // instead of written as a binary archive. This allows pickle to serialize every object only + // once and put them together correctly afterwards. Therefore all objects that may live in + // Python should be archived using this Shallow function. If Shallow is called from C++ code + // it archives the object normally. + template + Archive& Shallow(T& val) + { + static_assert(detail::is_any_pointer, "ShallowArchive must be given pointer type!"); +#ifdef NETGEN_PYTHON + if(shallow_to_python) + { + if(is_output) + ShallowOutPython(pybind11::cast(val)); + else + val = pybind11::cast(ShallowInPython()); + } + else +#endif // NETGEN_PYTHON + *this & val; + return *this; + } + +#ifdef NETGEN_PYTHON + virtual void ShallowOutPython(const pybind11::object& /*unused*/) + { throw UnreachableCodeException{}; } + virtual pybind11::object ShallowInPython() + { throw UnreachableCodeException{}; } +#endif // NETGEN_PYTHON + + Archive& operator=(const Archive&) = delete; + Archive& operator=(Archive&&) = delete; + + bool Output () const { return is_output; } + bool Input () const { return !is_output; } + const VersionInfo& GetVersion(const std::string& library) + { return version_map[library]; } + + // only used for PyArchive + virtual void NeedsVersion(const std::string& /*unused*/, const std::string& /*unused*/) {} + + // 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; + + 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); + } + + // archive implementation for enums + template + auto operator & (T& val) -> std::enable_if_t::value, Archive&> + { + int enumval; + if(Output()) + enumval = int(val); + *this & enumval; + if(Input()) + val = T(enumval); + return *this; + } + + // vector has special implementation (like a bitarray) therefore + // it needs a special overload (this could probably be more efficient, but we + // don't use it that often anyway) + Archive& operator& (std::vector& v) + { + logger->debug("In special archive for std::vector"); + size_t size; + if(Output()) + size = v.size(); + (*this) & size; + if(Input()) + { + v.resize(size); + bool b; + for(size_t i=0; i + 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 >> + 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()) + { + logger->debug("Store shared ptr of type {}", Demangle(typeid(T).name())); + // save -2 for nullptr + if(!ptr) + { + logger->debug("Storing nullptr"); + return (*this) << -2; + } + + void* reg_ptr = ptr.get(); + bool neededDowncast = false; + // Downcasting is only possible for our registered classes + if(typeid(T) != typeid(*ptr)) + { + logger->debug("Typids are different: {} vs {}", + Demangle(typeid(T).name()), + Demangle(typeid(*ptr).name())); + if(!IsRegistered(Demangle(typeid(*ptr).name()))) + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*ptr).name()) + + " 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())) + { + logger->debug("Multiple/Virtual inheritance involved, need to cast pointer"); + neededDowncast = true; + } + } + auto pos = shared_ptr2nr.find(reg_ptr); + // if not found store -1 and the pointer + if(pos == shared_ptr2nr.end()) + { + logger->debug("Didn't find the shared_ptr, create new registry entry at {}", + shared_ptr_count); + auto p = ptr.get(); + (*this) << -1; + (*this) & neededDowncast & p; + // 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 + logger->debug("Found shared_ptr at position {}", pos->second); + (*this) << pos->second << neededDowncast; + if(neededDowncast) + (*this) << Demangle(typeid(*ptr).name()); + } + else // Input + { + logger->debug("Reading shared_ptr of type {}", Demangle(typeid(T).name())); + int nr; + (*this) & nr; + // -2 restores a nullptr + if(nr == -2) + { + logger->debug("Reading a nullptr"); + ptr = nullptr; + return *this; + } + // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it + if (nr == -1) + { + logger->debug("Createing new shared_ptr"); + 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) + { + logger->debug("Shared pointer needed downcasting"); + 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 + { + logger->debug("Shared pointer didn't need downcasting"); + nr2shared_ptr.push_back(ptr); + } + } + else + { + logger->debug("Reading already existing pointer at entry {}", nr); + auto other = nr2shared_ptr[nr]; + bool neededDowncast; + (*this) & neededDowncast; + if(neededDowncast) + { + logger->debug("Shared pointer needed pointer downcast"); + // if there was a downcast we can expect the class to be registered (since archiving + // wouldn't have worked else) + std::string name; + (*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 + { + logger->debug("Shared pointer didn't need pointer casts"); + ptr = std::static_pointer_cast(other); + } + } + } + return *this; + } + + // Archive pointers ======================================================= + template + Archive & operator& (T *& p) + { + if (Output()) + { + logger->debug("Store pointer of type {}",Demangle(typeid(T).name())); + // if the pointer is null store -2 + if (!p) + { + logger->debug("Storing nullptr"); + return (*this) << -2; + } + auto reg_ptr = static_cast(p); + if(typeid(T) != typeid(*p)) + { + logger->debug("Typeids are different: {} vs {}", + Demangle(typeid(T).name()), + Demangle(typeid(*p).name())); + if(!IsRegistered(Demangle(typeid(*p).name()))) + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); + reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); + if(reg_ptr != static_cast(p)) + { + logger->debug("Multiple/Virtual inheritance involved, need to cast pointer"); + } + } + auto pos = ptr2nr.find(reg_ptr); + // if the pointer is not found in the map create a new entry + if (pos == ptr2nr.end()) + { + logger->debug("Didn't find pointer, create new registry entry at {}", + ptr_count); + ptr2nr[reg_ptr] = ptr_count++; + if(typeid(*p) == typeid(T)) + if (std::is_constructible::value) + { + logger->debug("Store standard class pointer (no virt. inh,...)"); + return (*this) << -1 & (*p); + } + else + throw Exception(std::string("Archive error: Class ") + + Demangle(typeid(*p).name()) + " does not provide a default constructor!"); + else + { + // if a pointer to a base class is archived, the class hierarchy must be registered + // 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 Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); + logger->debug("Store a possibly more complicated pointer"); + return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); + } + } + else + { + (*this) & pos->second; + bool downcasted = !(reg_ptr == static_cast(p) ); + logger->debug("Store a the existing position in registry at {}", pos->second); + logger->debug("Pointer {} downcasting", downcasted ? "needs" : "doesn't need"); + // store if the class has been downcasted and the name + (*this) << downcasted << Demangle(typeid(*p).name()); + } + } + else + { + logger->debug("Reading pointer of type {}", Demangle(typeid(T).name())); + int nr; + (*this) & nr; + if (nr == -2) // restore a nullptr + { + logger->debug("Loading a nullptr"); + p = nullptr; + } + else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) + { + logger->debug("Load a new pointer to a simple class"); + p = detail::constructIfPossible(); + nr2ptr.push_back(p); + (*this) & *p; + } + else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... + { + logger->debug("Load a new pointer to a potentially more complicated class " + "(allows for multiple/virtual inheritance,...)"); + // As stated above, we want this special behaviour only for our classes that implement DoArchive + std::string name; + (*this) & name; + logger->debug("Name = {}", name); + auto info = GetArchiveRegister(name); + // the creator creates a new object of type name, and returns a void* pointing + // to T (which may have an offset) + p = static_cast(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 + { + logger->debug("Restoring pointer to already existing object at registry position {}", nr); + bool downcasted; + std::string name; + (*this) & downcasted & name; + logger->debug("{} object of type {}", downcasted ? "Downcasted" : "Not downcasted", name); + if(downcasted) + { + // if the class has been downcasted we can assume it is in the register + 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 Exception("Upcast not successful, some classes are not registered properly for archiving!"); + } + static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/) + { + throw Exception("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(const 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(const 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; + std::array buffer{}; + 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 ? static_cast(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 ? static_cast(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 NETGEN_PYTHON + + template + class PyArchive : public ARCHIVE + { + private: + pybind11::list lst; + size_t index = 0; + std::map version_needed; + protected: + using ARCHIVE::stream; + using ARCHIVE::version_map; + using ARCHIVE::logger; + using ARCHIVE::GetLibraryVersions; + 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])); + *this & version_needed; + logger->debug("versions needed for unpickling = {}", version_needed); + for(auto& libversion : version_needed) + if(libversion.second > GetLibraryVersion(libversion.first)) + throw Exception("Error in unpickling data:\nLibrary " + libversion.first + + " must be at least " + libversion.second.to_string()); + stream = std::make_shared + (pybind11::cast(lst[pybind11::len(lst)-2])); + *this & version_map; + stream = std::make_shared + (pybind11::cast(lst[pybind11::len(lst)-3])); + } + } + + void NeedsVersion(const std::string& library, const std::string& version) override + { + if(Output()) + { + logger->debug("Need version {} of library {}.", version, library); + version_needed[library] = version_needed[library] > version ? version_needed[library] : version; + } + } + + using ARCHIVE::Output; + using ARCHIVE::Input; + using ARCHIVE::FlushBuffer; + using ARCHIVE::operator&; + using ARCHIVE::operator<<; + using ARCHIVE::GetVersion; + void ShallowOutPython(const 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())); + stream = std::make_shared(); + *this & GetLibraryVersions(); + FlushBuffer(); + lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); + stream = std::make_shared(); + logger->debug("Writeout version needed = {}", version_needed); + *this & version_needed; + FlushBuffer(); + lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); + return lst; + } + }; + + template + auto NGSPickle() + { + return pybind11::pickle([](T* self) + { + PyArchive ar; + ar & self; + auto output = pybind11::make_tuple(ar.WriteOut()); + GetLogger("Archive")->trace("Pickling output for object of type {} = {}", + Demangle(typeid(T).name()), + std::string(pybind11::str(output))); + return output; + }, + [](const pybind11::tuple & state) + { + T* val = nullptr; + GetLogger("Archive")->trace("State for unpickling of object of type {} = {}", + Demangle(typeid(T).name()), + std::string(pybind11::str(state[0]))); + PyArchive ar(state[0]); + ar & val; + return val; + }); + } + +#endif // NETGEN_PYTHON +} // namespace ngcore + +#endif // NETGEN_CORE_ARCHIVE_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/.clang-tidy netgen-6.2.1905+dfsg1/libsrc/core/.clang-tidy --- netgen-6.2.1804+dfsg1/libsrc/core/.clang-tidy 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/.clang-tidy 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,8 @@ +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers' +CheckOptions: + - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor + value: 1 + - key: cppcoreguidelines-macro-usage.AllowedRegexp + value: NGCORE_*|NETGEN_*|NG_EXCEPTION* + +WarningsAsErrors: '*' diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/core/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/core/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,49 @@ + +add_library(ngcore SHARED archive.cpp logging.cpp paje_trace.cpp utils.cpp profiler.cpp) + +target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) +if(NOT WIN32) + target_compile_options(ngcore PRIVATE -fvisibility=hidden) +endif(NOT WIN32) + +target_compile_definitions(ngcore PUBLIC $<$:NETGEN_ENABLE_CHECK_RANGE>) + +if(CHECK_RANGE) + target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE) +endif(CHECK_RANGE) + +if(USE_SPDLOG) + include_directories(${SPDLOG_INCLUDE_DIR}) + install(DIRECTORY ${SPDLOG_INCLUDE_DIR} + DESTINATION ${NG_INSTALL_DIR_INCLUDE} + ) + add_dependencies(ngcore project_spdlog) + target_compile_definitions(ngcore PUBLIC NETGEN_USE_SPDLOG) + if(DEBUG_LOG) + target_compile_definitions(ngcore PUBLIC NETGEN_LOG_DEBUG) + endif(DEBUG_LOG) +endif(USE_SPDLOG) + +install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) + +if(USE_PYTHON) + target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON) + target_include_directories(ngcore PRIVATE ${PYTHON_INCLUDE_DIRS}) + target_link_libraries(ngcore PRIVATE ${PYTHON_LIBRARIES}) +endif(USE_PYTHON) + +install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp + exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp mpi_wrapper.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) + +if(USE_PYTHON) + pybind11_add_module(pyngcore SHARED python_ngcore.cpp) + target_link_libraries(pyngcore PUBLIC ngcore ${PYTHON_LIBRARIES}) + set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}") + install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen) +endif(USE_PYTHON) + diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/exception.hpp netgen-6.2.1905+dfsg1/libsrc/core/exception.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/exception.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/exception.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,90 @@ +#ifndef NETGEN_CORE_EXCEPTION_HPP +#define NETGEN_CORE_EXCEPTION_HPP + +#include // for stringstream +#include // for exception +#include // for string + +#include "ngcore_api.hpp" // for NGCORE_API + +namespace ngcore +{ + // Exception for code that shouldn't be executed + class NGCORE_API UnreachableCodeException : public std::exception + { + const char* what() const noexcept override + { + return "Shouldn't get here, something went wrong!"; + } + }; + + // Default exception class + class NGCORE_API Exception : public std::exception + { + /// a verbal description of the exception + std::string m_what; + public: + Exception() = default; + Exception(const Exception&) = default; + Exception(Exception&&) = default; + Exception(const std::string& s) : m_what(s) {} + Exception(const char* s) : m_what(s) {} + ~Exception() override = default; + + Exception& operator =(const Exception&) = default; + Exception& operator =(Exception&&) noexcept = default; + + /// append string to description + Exception & Append (const std::string & s) { m_what += s; return *this; } + /// append string to description + Exception & Append (const char * s) { m_what += s; return *this; } + + /// verbal description of exception + const std::string & What() const { return m_what; } + + /// implement virtual function of std::exception + const char* what() const noexcept override { return m_what.c_str(); } + }; + + // Out of Range exception + class NGCORE_API RangeException : public Exception + { + public: + /// where it occurs, index, minimal and maximal indices + RangeException (const std::string & where, + int ind, int imin, int imax) : Exception("") + { + std::stringstream str; + str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n"; + Append (str.str()); + } + + template + RangeException(const std::string& where, const T& value) + { + std::stringstream str; + str << where << " called with wrong value " << value << "\n"; + Append(str.str()); + } + }; + + // Exception used if no simd implementation is available to fall back to standard evaluation + class NGCORE_API ExceptionNOSIMD : public Exception + { public: using Exception::Exception; }; +} // namespace ngcore + +#define NETGEN_CORE_NGEXEPTION_STR_HELPER(x) #x +#define NETGEN_CORE_NGEXEPTION_STR(x) NETGEN_CORE_NGEXEPTION_STR_HELPER(x) + +// Convenience macro to append file name and line of exception origin to the string +#define NG_EXCEPTION(s) ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t"+std::string(s)) + +#ifdef NETGEN_ENABLE_CHECK_RANGE +#define NETGEN_CHECK_RANGE(value, min, max) \ + { if ((value)<(min) || (value)>=(max)) \ + throw ngcore::RangeException(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", (value), (min), (max)); } +#else // NETGEN_ENABLE_CHECK_RANGE +#define NETGEN_CHECK_RANGE(value, min, max) +#endif // NETGEN_ENABLE_CHECK_RANGE + +#endif // NETGEN_CORE_EXCEPTION_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/logging.cpp netgen-6.2.1905+dfsg1/libsrc/core/logging.cpp --- netgen-6.2.1804+dfsg1/libsrc/core/logging.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/logging.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,138 @@ +#include "logging.hpp" + +#ifdef NETGEN_USE_SPDLOG + +#include +#include +#include + +#else // NETGEN_USE_SPDLOG +#include +#endif // NETGEN_USE_SPDLOG + + +namespace ngcore +{ + std::ostream* testout = new std::ostream(nullptr); // NOLINT + + void Logger::log(level::level_enum level, std::string && s) + { +#ifdef NETGEN_USE_SPDLOG + logger->log(spdlog::level::level_enum(level), s); +#else // NETGEN_USE_SPDLOG + if(level>level::debug) + std::clog << s << '\n'; +#endif // NETGEN_USE_SPDLOG + } + +#ifdef NETGEN_USE_SPDLOG + namespace detail + { + std::vector>& GetDefaultSinks() + { + static std::vector> sinks = + { std::make_shared() }; + return sinks; + } + std::shared_ptr CreateDefaultLogger(const std::string& name) + { + auto& default_sinks = GetDefaultSinks(); + auto logger = std::make_shared(name, default_sinks.begin(), default_sinks.end()); + spdlog::details::registry::instance().register_and_init(logger); + return logger; + } + } // namespace detail + + std::shared_ptr GetLogger(const std::string& name) + { + auto logger = spdlog::get(name); + if(!logger) + logger = detail::CreateDefaultLogger(name); + return std::make_shared(logger); + } + + void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name) + { + if(!name.empty()) + spdlog::get(name)->set_level(level); + else + spdlog::set_level(level); + } + + void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger) + { + auto sink = std::make_shared(filename); + sink->set_level(level); + if(!logger.empty()) + GetLogger(logger)->logger->sinks().push_back(sink); + else + { + detail::GetDefaultSinks().push_back(sink); + spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); }); + } + } + + void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger) + { + auto sink = std::make_shared(); + sink->set_level(level); + if(!logger.empty()) + GetLogger(logger)->logger->sinks().push_back(sink); + else + { + detail::GetDefaultSinks().push_back(sink); + spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); }); + } + } + + void ClearLoggingSinks(const std::string& logger) + { + if(!logger.empty()) + GetLogger(logger)->logger->sinks().clear(); + else + { + detail::GetDefaultSinks().clear(); + spdlog::details::registry::instance().apply_all([](auto logger) { logger->sinks().clear(); }); + } + } + + void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger) + { + if(!logger.empty()) + GetLogger(logger)->logger->flush_on(level); + else + spdlog::flush_on(level); + } + +#else // NETGEN_USE_SPDLOG +} //namespace ngcore + +namespace spdlog +{ + class logger + { + public: + logger() = default; + }; +} // namespace spdlog + +namespace ngcore +{ + + // Dummy functions if no spdlog is available + + std::shared_ptr GetLogger(const std::string& /*unused*/) + { + return std::make_shared(std::make_shared()); + } + + void SetLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {} + void AddFileSink(const std::string& /*unused*/, level::level_enum /*unused*/, + const std::string& /*unused*/) + {} + void AddConsoleSink(level::level_enum /*unused*/, const std::string& /*unused*/) {} + void ClearLoggingSinks(const std::string& /*unused*/) {} + void FlushOnLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {} +} //namespace ngcore + +#endif // NETGEN_USE_SPDLOG diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/logging.hpp netgen-6.2.1905+dfsg1/libsrc/core/logging.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/logging.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/logging.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,126 @@ +#ifndef NETGEN_CORE_LOGGING_HPP +#define NETGEN_CORE_LOGGING_HPP + +#undef NETGEN_USE_SPDLOG +#include +#include +#include +#include + +#include "exception.hpp" +#include "ngcore_api.hpp" +#include "utils.hpp" + +#ifdef NETGEN_USE_SPDLOG +#include +#include // to be able to parse anything to logger that implements operator << ostream +#ifdef NETGEN_LOG_DEBUG +#define SPDLOG_DEBUG_ON +#define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__) +#endif // NETGEN_LOG_DEBUG +#endif // NETGEN_USE_SPDLOG + +#ifndef NETGEN_DEBUG_LOG +#define NETGEN_DEBUG_LOG(logger, ...) +#endif // NETGEN_DEBUG_LOG + +namespace spdlog +{ + class logger; +} // namespace spdlog + +namespace ngcore +{ + NGCORE_API extern std::ostream* testout; // NOLINT + + namespace level + { + enum level_enum + { + trace = 0, + debug = 1, + info = 2, + warn = 3, + err = 4, + critical = 5, + off = 6 + }; + } // namespace level + + class Logger + { + public: + std::shared_ptr logger; + + Logger(std::shared_ptr l) : logger(std::move(l)) {} + + void NGCORE_API log( level::level_enum level, std::string && s); + +#ifdef NETGEN_USE_SPDLOG + template + void log( level::level_enum level, const char* str, Args ... args) + { + log(level, fmt::format(str, args...)); + } +#else // NETGEN_USE_SPDLOG + template + std::string replace(std::string s, const T & t) + { + auto p0 = s.find_first_of('{'); + auto p1 = s.find_first_of('}', p0); + if(p0==std::string::npos || p1==std::string::npos) + throw Exception("invalid format string"); + s.replace(p0, p1-p0+1, ToString(t)); + return s; + } + + std::string log_helper(std::string s) + { + return s; + } + + template + std::string log_helper(std::string s, const T &t) + { + return replace(s,t); + } + + template + std::string log_helper( std::string s, const T &t, Args ... args) + { + return log_helper(replace(s,t), args...); + } + + template + void log( level::level_enum level, const char* str, Args ... args) + { + log(level, log_helper(std::string(str), args...)); + } +#endif // NETGEN_USE_SPDLOG + + template + void trace( const char* str, Args ... args) { log(level::level_enum::trace, str, args...); } + template + void debug( const char* str, Args ... args) { log(level::level_enum::debug, str, args...); } + template + void info( const char* str, Args ... args) { log(level::level_enum::info, str, args...); } + template + void warn( const char* str, Args ... args) { log(level::level_enum::warn, str, args...); } + template + void error( const char* str, Args ... args) { log(level::level_enum::err, str, args...); } + template + void critical( const char* str, Args ... args) { log(level::level_enum::critical, str, args...); } + }; + + + + + NGCORE_API std::shared_ptr GetLogger(const std::string& name); + NGCORE_API void SetLoggingLevel(level::level_enum level, const std::string& name); + NGCORE_API void AddFileSink(const std::string& filename, level::level_enum level, const std::string& logger); + NGCORE_API void AddConsoleSink(level::level_enum level, const std::string& logger); + NGCORE_API void ClearLoggingSinks(const std::string& logger); + NGCORE_API void FlushOnLoggingLevel(level::level_enum level, const std::string& logger); +} // namespace ngcore + +#endif // NETGEN_CORE_LOGGING_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/mpi_wrapper.hpp netgen-6.2.1905+dfsg1/libsrc/core/mpi_wrapper.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/mpi_wrapper.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/mpi_wrapper.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,256 @@ +#ifndef NGCORE_MPIWRAPPER_HPP +#define NGCORE_MPIWRAPPER_HPP + +#ifdef PARALLEL +#define OMPI_SKIP_MPICXX +#include +#endif + + +namespace ngcore +{ + +#ifdef PARALLEL + + template struct MPI_typetrait { }; + + template <> struct MPI_typetrait { + static MPI_Datatype MPIType () { return MPI_INT; } }; + + template <> struct MPI_typetrait { + static MPI_Datatype MPIType () { return MPI_SHORT; } }; + + template <> struct MPI_typetrait { + static MPI_Datatype MPIType () { return MPI_CHAR; } }; + + template <> struct MPI_typetrait { + static MPI_Datatype MPIType () { return MPI_CHAR; } }; + + template <> struct MPI_typetrait { + static MPI_Datatype MPIType () { return MPI_UINT64_T; } }; + + template <> struct MPI_typetrait { + static MPI_Datatype MPIType () { return MPI_DOUBLE; } }; + + template <> struct MPI_typetrait { + static MPI_Datatype MPIType () { return MPI_C_BOOL; } }; + + + template ::MPIType())> + inline MPI_Datatype GetMPIType () { + return MPI_typetrait::MPIType(); + } + + + class NgMPI_Comm + { + protected: + MPI_Comm comm; + bool valid_comm; + int * refcount; + int rank, size; + public: + NgMPI_Comm () + : valid_comm(false), refcount(nullptr), rank(0), size(1) + { ; } + + NgMPI_Comm (MPI_Comm _comm, bool owns = false) + : comm(_comm), valid_comm(true) + { + if (!owns) + refcount = nullptr; + else + refcount = new int{1}; + + MPI_Comm_rank(comm, &rank); + MPI_Comm_size(comm, &size); + } + + NgMPI_Comm (const NgMPI_Comm & c) + : comm(c.comm), valid_comm(c.valid_comm), refcount(c.refcount), + rank(c.rank), size(c.size) + { + if (refcount) (*refcount)++; + } + + NgMPI_Comm (NgMPI_Comm && c) + : comm(c.comm), valid_comm(c.valid_comm), refcount(c.refcount), + rank(c.rank), size(c.size) + { + c.refcount = nullptr; + } + + ~NgMPI_Comm() + { + if (refcount) + if (--(*refcount) == 0) + MPI_Comm_free(&comm); + } + + NgMPI_Comm & operator= (const NgMPI_Comm & c) + { + if (refcount) + if (--(*refcount) == 0) + MPI_Comm_free(&comm); + + refcount = c.refcount; + if (refcount) (*refcount)++; + comm = c.comm; + valid_comm = c.valid_comm; + size = c.size; + rank = c.rank; + return *this; + } + + class InvalidCommException : public Exception { + public: + InvalidCommException() : Exception("Do not have a valid communicator") { ; } + }; + + operator MPI_Comm() const { + if (!valid_comm) throw InvalidCommException(); + return comm; + } + + int Rank() const { return rank; } + int Size() const { return size; } + void Barrier() const { + if (size > 1) MPI_Barrier (comm); + } + + + /** --- blocking P2P --- **/ + + template())> + void Send (T & val, int dest, int tag) const { + MPI_Send (&val, 1, GetMPIType(), dest, tag, comm); + } + + template())> + void Recv (T & val, int src, int tag) const { + MPI_Recv (&val, 1, GetMPIType(), src, tag, comm, MPI_STATUS_IGNORE); + } + + + /** --- non-blocking P2P --- **/ + + template())> + MPI_Request ISend (T & val, int dest, int tag) const + { + MPI_Request request; + MPI_Isend (&val, 1, GetMPIType(), dest, tag, comm, &request); + return request; + } + + template())> + MPI_Request IRecv (T & val, int dest, int tag) const + { + MPI_Request request; + MPI_Irecv (&val, 1, GetMPIType(), dest, tag, comm, &request); + return request; + } + + /** --- collectives --- **/ + + template ())> + T Reduce (T d, const MPI_Op & op, int root = 0) const + { + if (size == 1) return d; + + T global_d; + MPI_Reduce (&d, &global_d, 1, GetMPIType(), op, root, comm); + return global_d; + } + + template ())> + T AllReduce (T d, const MPI_Op & op) const + { + if (size == 1) return d; + + T global_d; + MPI_Allreduce ( &d, &global_d, 1, GetMPIType(), op, comm); + return global_d; + } + + template ())> + void Bcast (T & s, int root = 0) const { + if (size == 1) return ; + MPI_Bcast (&s, 1, GetMPIType(), root, comm); + } + + void Bcast (std::string & s, int root = 0) const + { + if (size == 1) return; + int len = s.length(); + Bcast (len, root); + if (rank != 0) s.resize (len); + MPI_Bcast (&s[0], len, MPI_CHAR, root, comm); + } + + + }; + + +#else + class MPI_Comm { + int nr; + public: + MPI_Comm (int _nr = 0) : nr(_nr) { ; } + operator int() const { return nr; } + bool operator== (MPI_Comm c2) const { return nr == c2.nr; } + }; + static MPI_Comm MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 10000; + + typedef int MPI_Op; + typedef int MPI_Request; + + enum { MPI_SUM = 0, MPI_MIN = 1, MPI_MAX = 2 }; + + class NgMPI_Comm + { + + public: + NgMPI_Comm () { ; } + NgMPI_Comm (MPI_Comm _comm, bool owns = false) { ; } + + size_t Rank() const { return 0; } + size_t Size() const { return 1; } + void Barrier() const { ; } + operator MPI_Comm() const { return MPI_Comm(); } + + template + void Send( T & val, int dest, int tag) const { ; } + + template + void MyMPI_Recv (T & val, int src, int tag) const { ; } + + template + MPI_Request ISend (T & val, int dest, int tag) const { return 0; } + + template + MPI_Request IRecv (T & val, int dest, int tag) const { return 0; } + + template + T Reduce (T d, const MPI_Op & op, int root = 0) { return d; } + + template + T AllReduce (T d, const MPI_Op & op) const { return d; } + + template + void Bcast (T & s, int root = 0) const { ; } + }; + +#endif + + + + + + + + + +} + +#endif + diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/ngcore_api.hpp netgen-6.2.1905+dfsg1/libsrc/core/ngcore_api.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/ngcore_api.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/ngcore_api.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,37 @@ +#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 __attribute__((visibility("default"))) + #define NGCORE_API_IMPORT __attribute__((visibility("default"))) +#endif + +#ifdef NGCORE_EXPORTS + #define NGCORE_API NGCORE_API_EXPORT +#else + #define NGCORE_API NGCORE_API_IMPORT +#endif + +#ifdef __INTEL_COMPILER + #ifdef WIN32 + #define NETGEN_INLINE __forceinline inline + #define NETGEN_LAMBDA_INLINE + #else + #define NETGEN_INLINE __forceinline inline + #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) + #endif +#else + #ifdef __GNUC__ + #define NETGEN_INLINE __attribute__ ((__always_inline__)) inline + #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) + #define NETGEN_VLA + #else + #define NETGEN_INLINE inline + #define NETGEN_LAMBDA_INLINE + #endif +#endif + +#endif // NETGEN_CORE_NGCORE_API_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/ngcore.hpp netgen-6.2.1905+dfsg1/libsrc/core/ngcore.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/ngcore.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/ngcore.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,12 @@ +#ifndef NETGEN_CORE_NGCORE_HPP +#define NETGEN_CORE_NGCORE_HPP + +#include "archive.hpp" +#include "exception.hpp" +#include "logging.hpp" +#include "profiler.hpp" +#include "symboltable.hpp" +#include "version.hpp" +#include "mpi_wrapper.hpp" + +#endif // NETGEN_CORE_NGCORE_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/paje_trace.cpp netgen-6.2.1905+dfsg1/libsrc/core/paje_trace.cpp --- netgen-6.2.1804+dfsg1/libsrc/core/paje_trace.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/paje_trace.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,809 @@ +#include +#include +#include +#include +#include +#include + +#include "archive.hpp" // for Demangle +#include "paje_trace.hpp" +#include "profiler.hpp" + +extern const char *header; + +namespace ngcore +{ + // Produce no traces by default + size_t PajeTrace::max_tracefile_size = 0; + + // If true, produce variable counting active threads + // increases trace by a factor of two + bool PajeTrace::trace_thread_counter = true; + bool PajeTrace::trace_threads = true; + + PajeTrace :: PajeTrace(int anthreads, std::string aname) + { + start_time = GetTimeCounter(); + + nthreads = anthreads; + tracefile_name = std::move(aname); + + int bytes_per_event=33; + max_num_events_per_thread = std::min( static_cast(std::numeric_limits::max()), max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7); + if(max_num_events_per_thread>0) + { + logger->info( "Tracefile size = {}MB", max_tracefile_size/1024/1024); + logger->info( "Tracing {} events per thread", max_num_events_per_thread); + } + + tasks.resize(nthreads); + int reserve_size = std::min(1000000U, max_num_events_per_thread); + for(auto & t : tasks) + t.reserve(reserve_size); + + links.resize(nthreads); + for(auto & l : links) + l.reserve(reserve_size); + + jobs.reserve(reserve_size); + timer_events.reserve(reserve_size); + + tracing_enabled = true; + } + + PajeTrace :: ~PajeTrace() + { + if(!tracefile_name.empty()) + Write(tracefile_name); + } + + + void PajeTrace::StopTracing() + { + if(tracing_enabled && max_num_events_per_thread>0) + { + logger->warn("Maximum number of traces reached, tracing is stopped now."); + } + tracing_enabled = false; + } + + class PajeFile + { + public: + static void Hue2RGB ( double x, double &r, double &g, double &b ) + { + double d = 1.0/6.0; + if(x logger = GetLogger("PajeTrace"); + + + double ConvertTime(TTimePoint t) { + // return time in milliseconds as double + // return std::chrono::duration(t-start_time).count()*1000.0; + // return std::chrono::duration(t-start_time).count() / 2.7e3; + return 1000.0*static_cast(t-start_time) / ticks_per_second; + } + + enum PType + { + SET_VARIABLE=1, + ADD_VARIABLE, + SUB_VARIABLE, + PUSH_STATE, + POP_STATE, + START_LINK, + STOP_LINK + }; + + struct PajeEvent + { + PajeEvent( int aevent_type, double atime, int atype, int acontainer, double avar_value ) + : time(atime), var_value(avar_value), event_type(aevent_type), type(atype), container(acontainer) + { } + + PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue = 0, int aid = 0, bool avalue_is_alias = true ) + : time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), id(aid), value_is_alias(avalue_is_alias) + { } + + PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue, int astart_container, int akey ) + : time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), start_container(astart_container), id(akey) + { } + + double time; + double var_value = 0.0; + int event_type; + int type; + int container; + int value = 0; + int start_container = 0; + int id = 0; + bool value_is_alias = true; + + bool operator < (const PajeEvent & other) const { + // Same start and stop times can occur for very small tasks -> take "starting" events first (eg. PajePushState before PajePopState) + if(time == other.time) + return event_type < other.event_type; + return (time < other.time); + } + + int write(FILE *stream) + { + const int &key = id; + const int &end_container = start_container; + switch(event_type) + { + case PajeSetVariable: + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); // NOLINT + case PajeAddVariable: + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); // NOLINT + case PajeSubVariable: + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSubVariable, time, type, container, var_value ); // NOLINT + case PajePushState: + if(value_is_alias) + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT + else + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT + case PajePopState: + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); // NOLINT + case PajeStartLink: + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeStartLink, time, type, container, value, start_container, key ); // NOLINT + case PajeEndLink: + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeEndLink, time, type, container, value, end_container, key ); // NOLINT + } + return 0; + } + }; + + std::vector events; + + public: + PajeFile() = delete; + PajeFile(const PajeFile &) = delete; + PajeFile(PajeFile &&) = delete; + void operator=(const PajeFile &) = delete; + void operator=(PajeFile &&) = delete; + + PajeFile( const std::string & filename, TTimePoint astart_time ) + { + start_time = astart_time; + ctrace_stream = fopen (filename.c_str(),"w"); // NOLINT + fprintf(ctrace_stream, "%s", header ); // NOLINT + alias_counter = 0; + } + + ~PajeFile() + { + fclose (ctrace_stream); // NOLINT + } + + int DefineContainerType ( int parent_type, const std::string & name ) + { + int alias = ++alias_counter; + if(parent_type!=0) + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT + else + fprintf( ctrace_stream, "%d\ta%d\t%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT + return alias; + } + + int DefineVariableType ( int container_type, const std::string & name ) + { + int alias = ++alias_counter; + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"1.0 1.0 1.0\"\n", PajeDefineVariableType, alias, container_type, name.c_str() ); // NOLINT + return alias; + } + + int DefineStateType ( int type, const std::string & name ) + { + int alias = ++alias_counter; + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineStateType, alias, type, name.c_str() ); // NOLINT + return alias; + } + + // int DefineEventType () + // { + // Write("event not implemented"); + // } + + int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, const std::string & name) + { + int alias = ++alias_counter; + fprintf( ctrace_stream, "%d\ta%d\ta%d\ta%d\ta%d\t\"%s\"\n", PajeDefineLinkType, alias, parent_container_type, start_container_type, stop_container_type, name.c_str() ); // NOLINT + return alias; + } + + int DefineEntityValue (int type, const std::string & name, double hue = -1) + { + if(hue==-1) + { + std::hash shash; + size_t h = shash(name); + h ^= h>>32U; + h = static_cast(h); + hue = h*1.0/std::numeric_limits::max(); + } + + int alias = ++alias_counter; + double r; + double g; + double b; + Hue2RGB( hue, r, g, b ); + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"%.15g %.15g %.15g\"\n", PajeDefineEntityValue, alias, type, name.c_str(), r,g,b ); // NOLINT + return alias; + } + + int CreateContainer ( int type, int parent, const std::string & name ) + { + int alias = ++alias_counter; + if(parent!=0) + fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\ta%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT + else + fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\t%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT + return alias; + } + void DestroyContainer () + {} + + void SetVariable (TTimePoint time, int type, int container, double value ) + { + events.emplace_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) ); + } + + void AddVariable (TTimePoint time, int type, int container, double value ) + { + events.emplace_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) ); + } + + void SubVariable (TTimePoint time, int type, int container, double value ) + { + events.emplace_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) ); + } + + void SetState () + {} + + void PushState ( TTimePoint time, int type, int container, int value, int id = 0, bool value_is_alias = true ) + { + events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id, value_is_alias) ); + } + + void PopState ( TTimePoint time, int type, int container ) + { + events.emplace_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) ); + } + + void ResetState () + {} + + void StartLink ( TTimePoint time, int type, int container, int value, int start_container, int key ) + { + events.emplace_back( PajeEvent( PajeStartLink, ConvertTime(time), type, container, value, start_container, key ) ); + } + + void EndLink ( TTimePoint time, int type, int container, int value, int end_container, int key ) + { + events.emplace_back( PajeEvent( PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) ); + } + + void NewEvent () + {} + + void WriteEvents() + { + logger->info("Sorting traces..."); + std::sort (events.begin(), events.end()); + + logger->info("Writing traces... "); + for (auto & event : events) + { + event.write( ctrace_stream ); +// fprintf( ctrace_stream, "%s", buf ); // NOLINT + } + logger->info("Done"); + } + + private: + enum + { + PajeDefineContainerType = 0, + PajeDefineVariableType = 1, + PajeDefineStateType = 2, + PajeDefineEventType = 3, + PajeDefineLinkType = 4, + PajeDefineEntityValue = 5, + PajeCreateContainer = 6, + PajeDestroyContainer = 7, + PajeSetVariable = 8, + PajeAddVariable = 9, + PajeSubVariable = 10, + PajeSetState = 11, + PajePushState = 12, + PajePopState = 13, + PajeResetState = 14, + PajeStartLink = 15, + PajeEndLink = 16, + PajeNewEvent = 17 + }; + + }; + + NGCORE_API PajeTrace *trace; + + void PajeTrace::Write( const std::string & filename ) + { + auto n_events = jobs.size() + timer_events.size(); + for(auto & vtasks : tasks) + n_events += vtasks.size(); + + logger->info("{} events traced", n_events); + + if(n_events==0) + { + logger->info("No data traced, skip writing trace file"); + return; + } + + if(!tracing_enabled) + { + logger->warn("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024); + } + + PajeFile paje(filename, start_time); + + const int container_type_task_manager = paje.DefineContainerType( 0, "Task Manager" ); + const int container_type_node = paje.DefineContainerType( container_type_task_manager, "Node"); + const int container_type_thread = paje.DefineContainerType( container_type_task_manager, "Thread"); + const int container_type_timer = container_type_thread; //paje.DefineContainerType( container_type_task_manager, "Timers"); + const int container_type_jobs = paje.DefineContainerType( container_type_task_manager, "Jobs"); + + const int state_type_job = paje.DefineStateType( container_type_jobs, "Job" ); + const int state_type_task = paje.DefineStateType( container_type_thread, "Task" ); + const int state_type_timer = paje.DefineStateType( container_type_timer, "Timer state" ); + + const int variable_type_active_threads = paje.DefineVariableType( container_type_jobs, "Active threads" ); + + const int container_task_manager = paje.CreateContainer( container_type_task_manager, 0, "The task manager" ); + const int container_jobs = paje.CreateContainer( container_type_jobs, container_task_manager, "Jobs" ); + paje.SetVariable( start_time, variable_type_active_threads, container_jobs, 0.0 ); + + const int num_nodes = 1; //task_manager ? task_manager->GetNumNodes() : 1; + + std::vector container_nodes; + container_nodes.reserve(num_nodes); + for(int i=0; i thread_aliases; + thread_aliases.reserve(nthreads); + if(trace_threads) + for (int i=0; i job_map; + std::map job_task_map; + + for(Job & j : jobs) + if(job_map.find(j.type) == job_map.end()) + { + std::string name = Demangle(j.type->name()); + job_map[j.type] = paje.DefineEntityValue( state_type_job, name, -1 ); + job_task_map[j.type] = paje.DefineEntityValue( state_type_task, name, -1 ); + } + + for(Job & j : jobs) + { + paje.PushState( j.start_time, state_type_job, container_jobs, job_map[j.type] ); + paje.PopState( j.stop_time, state_type_job, container_jobs ); + } + + std::set timer_ids; + std::map timer_aliases; + + for(auto & event : timer_events) + timer_ids.insert(event.timer_id); + + + for(auto & vtasks : tasks) + for (Task & t : vtasks) + if(t.id_type==Task::ID_TIMER) + timer_ids.insert(t.id); + + for(auto id : timer_ids) + timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id), -1 ); + + int timerdepth = 0; + int maxdepth = 0; + for(auto & event : timer_events) + { + if(event.is_start) + { + timerdepth++; + maxdepth = timerdepth>maxdepth ? timerdepth : maxdepth; + } + else + timerdepth--; + } + + std::vector timer_container_aliases; + timer_container_aliases.resize(maxdepth); + for(int i=0; i links_merged; + links_merged.reserve(nlinks); + std::vector pos(nthreads); + + int nlinks_merged = 0; + while(nlinks_merged < nlinks) + { + int minpos = -1; + TTimePoint mintime = -1; + for (int t = 0; t started_links; + + int link_type = paje.DefineLinkType(container_type_node, container_type_thread, container_type_thread, "links"); + + // match links + for ( auto & l : links_merged ) + { + if(l.is_start) + { + started_links.push_back(l); + } + else + { + unsigned int i = 0; + while(i children; + double time = 0.0; + std::string name; + TTimePoint start_time = 0; + }; + + void PrintNode (const TreeNode &n, int &level, std::ofstream & f); + void PrintNode (const TreeNode &n, int &level, std::ofstream & f) + { + f << "{ name: \"" + n.name + "\", size: " + ToString(n.time); + int size = n.children.size(); + if(size>0) + { + int i = 0; + f << ", children: ["; + for(auto & c : n.children) + { + PrintNode(c.second, level, f); + if(++i events; + + TreeNode root; + root.time=0; + root.name="all"; + TreeNode *current = &root; + + std::vector node_stack; + + node_stack.push_back(&root); + + TTimePoint stop_time = 0; + + for(auto & event : timer_events) + { + events.push_back(event); + stop_time = std::max(event.time, stop_time); + } + + std::map jobs_map; + std::vector job_names; + for(auto & job : jobs) + { + auto name = Demangle(job.type->name()); + int id = job_names.size(); + if(jobs_map.count(name)==0) + { + jobs_map[name] = id; + job_names.push_back(name); + } + else + id = jobs_map[name]; + + events.push_back(TimerEvent{-1, job.start_time, true, id}); + events.push_back(TimerEvent{-1, job.stop_time, false, id}); + stop_time = std::max(job.stop_time, stop_time); + } + + std::sort (events.begin(), events.end()); + + root.time = 1000.0*static_cast(stop_time-start_time)/ticks_per_second; + + for(auto & event : events) + { + bool is_timer_event = event.timer_id != -1; + int id = is_timer_event ? event.timer_id : event.thread_id; + + if(event.is_start) + { + bool need_init = !current->children.count(id); + + node_stack.push_back(current); + current = ¤t->children[id]; + + if(need_init) + { + current->name = is_timer_event ? NgProfiler::GetName(id) : job_names[id]; + current->time = 0.0; + current->id = id; + } + + current->start_time = event.time; + } + else + { + double time = 1000.0*static_cast(event.time-current->start_time)/ticks_per_second; + current->time += time; + current = node_stack.back(); + current->time -= time; + node_stack.pop_back(); + } + } + + int level = 0; + std::ofstream f(tracefile_name+".html"); + f.precision(4); + f << R"CODE_( + + + + + + + +
+ + + +)CODE_" << std::endl; + } + +} // namespace ngcore + +const char *header = + "%EventDef PajeDefineContainerType 0 \n" + "% Alias string \n" + "% Type string \n" + "% Name string \n" + "%EndEventDef \n" + "%EventDef PajeDefineVariableType 1 \n" + "% Alias string \n" + "% Type string \n" + "% Name string \n" + "% Color color \n" + "%EndEventDef \n" + "%EventDef PajeDefineStateType 2 \n" + "% Alias string \n" + "% Type string \n" + "% Name string \n" + "%EndEventDef \n" + "%EventDef PajeDefineEventType 3 \n" + "% Alias string \n" + "% Type string \n" + "% Name string \n" + "% Color color \n" + "%EndEventDef \n" + "%EventDef PajeDefineLinkType 4 \n" + "% Alias string \n" + "% Type string \n" + "% StartContainerType string \n" + "% EndContainerType string \n" + "% Name string \n" + "%EndEventDef \n" + "%EventDef PajeDefineEntityValue 5 \n" + "% Alias string \n" + "% Type string \n" + "% Name string \n" + "% Color color \n" + "%EndEventDef \n" + "%EventDef PajeCreateContainer 6 \n" + "% Time date \n" + "% Alias string \n" + "% Type string \n" + "% Container string \n" + "% Name string \n" + "%EndEventDef \n" + "%EventDef PajeDestroyContainer 7 \n" + "% Time date \n" + "% Type string \n" + "% Name string \n" + "%EndEventDef \n" + "%EventDef PajeSetVariable 8 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "% Value double \n" + "%EndEventDef\n" + "%EventDef PajeAddVariable 9 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "% Value double \n" + "%EndEventDef\n" + "%EventDef PajeSubVariable 10 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "% Value double \n" + "%EndEventDef\n" + "%EventDef PajeSetState 11 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "% Value string \n" + "%EndEventDef\n" + "%EventDef PajePushState 12 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "% Value string \n" + "% Id string \n" + "%EndEventDef\n" + "%EventDef PajePopState 13 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "%EndEventDef\n" + "%EventDef PajeResetState 14 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "%EndEventDef\n" + "%EventDef PajeStartLink 15 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "% Value string \n" + "% StartContainer string \n" + "% Key string \n" + "%EndEventDef\n" + "%EventDef PajeEndLink 16 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "% Value string \n" + "% EndContainer string \n" + "% Key string \n" + "%EndEventDef\n" + "%EventDef PajeNewEvent 17 \n" + "% Time date \n" + "% Type string \n" + "% Container string \n" + "% Value string \n" + "%EndEventDef\n"; diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/paje_trace.hpp netgen-6.2.1905+dfsg1/libsrc/core/paje_trace.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/paje_trace.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/paje_trace.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,191 @@ +#ifndef NETGEN_CORE_PAJE_TRACE_HPP +#define NETGEN_CORE_PAJE_TRACE_HPP + +#include +#include + +#include "logging.hpp" // for logger +#include "ngcore_api.hpp" // for NGCORE_API +#include "utils.hpp" + +namespace ngcore +{ + + extern NGCORE_API class PajeTrace *trace; + class PajeTrace + { + public: + using TClock = std::chrono::system_clock; + + protected: + std::shared_ptr logger = GetLogger("PajeTrace"); + private: + NGCORE_API static size_t max_tracefile_size; + NGCORE_API static bool trace_thread_counter; + NGCORE_API static bool trace_threads; + + bool tracing_enabled; + TTimePoint start_time; + int nthreads; + + public: + void WriteSunburstHTML(); + + // Approximate number of events to trace. Tracing will + // be stopped if any thread reaches this number of events + unsigned int max_num_events_per_thread; + + static void SetTraceThreads( bool atrace_threads ) + { + trace_threads = atrace_threads; + } + + static void SetTraceThreadCounter( bool trace_threads ) + { + trace_thread_counter = trace_threads; + } + + static void SetMaxTracefileSize( size_t max_size ) + { + max_tracefile_size = max_size; + } + + std::string tracefile_name; + + struct Job + { + int job_id; + const std::type_info *type; + TTimePoint start_time; + TTimePoint stop_time; + }; + + struct Task + { + int thread_id; + + int id; + int id_type; + + int additional_value; + + TTimePoint start_time; + TTimePoint stop_time; + + static constexpr int ID_NONE = -1; + static constexpr int ID_JOB = 1; + static constexpr int ID_TIMER = 2; + }; + + struct TimerEvent + { + int timer_id; + TTimePoint time; + bool is_start; + int thread_id; + + bool operator < (const TimerEvent & other) const { return time < other.time; } + }; + + struct ThreadLink + { + int thread_id; + int key; + TTimePoint time; + bool is_start; + bool operator < (const ThreadLink & other) const { return time < other.time; } + }; + + std::vector > tasks; + std::vector jobs; + std::vector timer_events; + std::vector > links; + + public: + NGCORE_API void StopTracing(); + + PajeTrace() = delete; + PajeTrace(const PajeTrace &) = delete; + PajeTrace(PajeTrace &&) = delete; + NGCORE_API PajeTrace(int anthreads, std::string aname = ""); + NGCORE_API ~PajeTrace(); + + void operator=(const PajeTrace &) = delete; + void operator=(PajeTrace &&) = delete; + + void StartTimer(int timer_id) + { + if(!tracing_enabled) return; + if(unlikely(timer_events.size() == max_num_events_per_thread)) + StopTracing(); + timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), true}); + } + + void StopTimer(int timer_id) + { + if(!tracing_enabled) return; + if(unlikely(timer_events.size() == max_num_events_per_thread)) + StopTracing(); + timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), false}); + } + + NETGEN_INLINE int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1) + { + if(!tracing_enabled) return -1; + if(!trace_threads && !trace_thread_counter) return -1; + if(unlikely(tasks[thread_id].size() == max_num_events_per_thread)) + StopTracing(); + int task_num = tasks[thread_id].size(); + tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter()} ); + return task_num; + } + + void StopTask(int thread_id, int task_num) + { + if(!trace_threads && !trace_thread_counter) return; + if(task_num>=0) + tasks[thread_id][task_num].stop_time = GetTimeCounter(); + } + + void SetTask(int thread_id, int task_num, int additional_value) { + if(!trace_threads && !trace_thread_counter) return; + if(task_num>=0) + tasks[thread_id][task_num].additional_value = additional_value; + } + + void StartJob(int job_id, const std::type_info & type) + { + if(!tracing_enabled) return; + if(jobs.size() == max_num_events_per_thread) + StopTracing(); + jobs.push_back( Job{job_id, &type, GetTimeCounter()} ); + } + + void StopJob() + { + if(tracing_enabled) + jobs.back().stop_time = GetTimeCounter(); + } + + void StartLink(int thread_id, int key) + { + if(!tracing_enabled) return; + if(links[thread_id].size() == max_num_events_per_thread) + StopTracing(); + links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), true} ); + } + + void StopLink(int thread_id, int key) + { + if(!tracing_enabled) return; + if(links[thread_id].size() == max_num_events_per_thread) + StopTracing(); + links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} ); + } + + void Write( const std::string & filename ); + + }; +} // namespace ngcore + +#endif // NETGEN_CORE_PAJE_TRACE_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/profiler.cpp netgen-6.2.1905+dfsg1/libsrc/core/profiler.cpp --- netgen-6.2.1804+dfsg1/libsrc/core/profiler.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/profiler.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,117 @@ +#include + +#include "profiler.hpp" + +namespace ngcore +{ + std::vector NgProfiler::timers(NgProfiler::SIZE); // NOLINT + + std::string NgProfiler::filename; + + std::array NgProfiler::dummy_thread_times; + size_t * NgProfiler::thread_times = NgProfiler::dummy_thread_times.data(); // NOLINT + std::array NgProfiler::dummy_thread_flops; + size_t * NgProfiler::thread_flops = NgProfiler::dummy_thread_flops.data(); // NOLINT + + std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT + + NgProfiler :: NgProfiler() + { + for (auto & t : timers) + { + t.tottime = 0.0; + t.usedcounter = 0; + t.flops = 0.0; + } + } + + NgProfiler :: ~NgProfiler() + { + if (filename.length()) + { + logger->debug( "write profile to file {}", filename ); + FILE *prof = fopen(filename.c_str(),"w"); // NOLINT + Print (prof); + fclose(prof); // NOLINT + } + + if (getenv ("NGPROFILE")) + { + std::string filename = "netgen.prof"; +#ifdef PARALLEL + filename += "."+ToString(id); +#endif + if (id == 0) logger->info( "write profile to file {}", filename ); + FILE *prof = fopen(filename.c_str(),"w"); // NOLINT + Print (prof); + fclose(prof); // NOLINT + } + } + + void NgProfiler :: Print (FILE * prof) + { + int i = 0; + for (auto & t : timers) + { + if (t.count != 0 || t.usedcounter != 0) + { + fprintf(prof,"job %3i calls %8li, time %6.4f sec",i,t.count,t.tottime); // NOLINT + if(t.flops != 0.0) + fprintf(prof,", MFlops = %6.2f",t.flops / (t.tottime) * 1e-6); // NOLINT + if(t.loads != 0.0) + fprintf(prof,", MLoads = %6.2f",t.loads / (t.tottime) * 1e-6); // NOLINT + if(t.stores != 0.0) + fprintf(prof,", MStores = %6.2f",t.stores / (t.tottime) * 1e-6); // NOLINT + if(t.usedcounter) + fprintf(prof," %s",t.name.c_str()); // NOLINT + fprintf(prof,"\n"); // NOLINT + } + i++; + } + } + + + int NgProfiler :: CreateTimer (const std::string & name) + { + static std::mutex createtimer_mutex; + int nr = -1; + { + std::lock_guard guard(createtimer_mutex); + for (int i = SIZE-1; i > 0; i--) + { + auto & t = timers[i]; + if (!t.usedcounter) + { + t.usedcounter = 1; + t.name = name; + nr = i; + break; + } + } + } + if (nr > -1) return nr; + static bool first_overflow = true; + if (first_overflow) + { + first_overflow = false; + NgProfiler::logger->warn("no more timer available, reusing last one"); + } + return 0; + } + + void NgProfiler :: Reset () + { + for(auto & t : timers) + { + t.tottime = 0.0; + t.count = 0; + t.flops = 0.0; + t.loads = 0; + t.stores = 0; + } + } + + NgProfiler prof; // NOLINT + + +} // namespace ngcore diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/profiler.hpp netgen-6.2.1905+dfsg1/libsrc/core/profiler.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/profiler.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/profiler.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,305 @@ +#ifndef NETGEN_CORE_PROFILER_HPP +#define NETGEN_CORE_PROFILER_HPP + +#include +#include +#include + +#include "logging.hpp" +#include "paje_trace.hpp" +#include "utils.hpp" + +namespace ngcore +{ + class NgProfiler + { + public: + /// maximal number of timers + enum { SIZE = 8*1024 }; + + struct TimerVal + { + TimerVal() = default; + + double tottime = 0.0; + double starttime = 0.0; + double flops = 0.0; + double loads = 0.0; + double stores = 0.0; + long count = 0; + std::string name = ""; + int usedcounter = 0; + }; + + NGCORE_API static std::vector timers; + + NGCORE_API static TTimePoint * thread_times; + NGCORE_API static TTimePoint * thread_flops; + NGCORE_API static std::shared_ptr logger; + NGCORE_API static std::array dummy_thread_times; + NGCORE_API static std::array dummy_thread_flops; + private: + + NGCORE_API static std::string filename; + public: + NgProfiler(); + ~NgProfiler(); + + NgProfiler(const NgProfiler &) = delete; + NgProfiler(NgProfiler &&) = delete; + void operator=(const NgProfiler &) = delete; + void operator=(NgProfiler &&) = delete; + + static void SetFileName (const std::string & afilename) { filename = afilename; } + + /// create new timer, use integer index + NGCORE_API static int CreateTimer (const std::string & name); + + NGCORE_API static void Reset (); + + + /// start timer of index nr + static void StartTimer (int nr) + { + timers[nr].starttime = WallTime(); timers[nr].count++; + } + + /// stop timer of index nr + static void StopTimer (int nr) + { + timers[nr].tottime += WallTime()-timers[nr].starttime; + } + + static void StartThreadTimer (size_t nr, size_t tid) + { + thread_times[tid*SIZE+nr] -= GetTimeCounter(); // NOLINT + } + + static void StopThreadTimer (size_t nr, size_t tid) + { + thread_times[tid*SIZE+nr] += GetTimeCounter(); // NOLINT + } + + static void AddThreadFlops (size_t nr, size_t tid, size_t flops) + { + thread_flops[tid*SIZE+nr] += flops; // NOLINT + } + + /// if you know number of flops, provide them to obtain the MFlop - rate + static void AddFlops (int nr, double aflops) { timers[nr].flops += aflops; } + static void AddLoads (int nr, double aloads) { timers[nr].loads += aloads; } + static void AddStores (int nr, double astores) { timers[nr].stores += astores; } + + static int GetNr (const std::string & name) + { + for (int i = SIZE-1; i >= 0; i--) + if (timers[i].name == name) + return i; + return -1; + } + + static double GetTime (int nr) + { + return timers[nr].tottime; + } + + static double GetTime (const std::string & name) + { + for (int i = SIZE-1; i >= 0; i--) + if (timers[i].name == name) + return GetTime (i); + return 0; + } + + static long int GetCounts (int nr) + { + return timers[nr].count; + } + + static double GetFlops (int nr) + { + return timers[nr].flops; + } + + /// change name + static void SetName (int nr, const std::string & name) { timers[nr].name = name; } + static std::string GetName (int nr) { return timers[nr].name; } + /// print profile + NGCORE_API static void Print (FILE * prof); + + class RegionTimer + { + int nr; + public: + /// start timer + RegionTimer (int anr) : nr(anr) { NgProfiler::StartTimer(nr); } + /// stop timer + ~RegionTimer () { NgProfiler::StopTimer(nr); } + + RegionTimer() = delete; + RegionTimer(const RegionTimer &) = delete; + RegionTimer(RegionTimer &&) = delete; + void operator=(const RegionTimer &) = delete; + void operator=(RegionTimer &&) = delete; + }; + }; + + + + class NGCORE_API Timer + { + int timernr; + int priority; + public: + Timer (const std::string & name, int apriority = 1) + : priority(apriority) + { + timernr = NgProfiler::CreateTimer (name); + } + void SetName (const std::string & name) + { + NgProfiler::SetName (timernr, name); + } + void Start () + { + if (priority <= 2) + NgProfiler::StartTimer (timernr); + if (priority <= 1) + if(trace) trace->StartTimer(timernr); + } + void Stop () + { + if (priority <= 2) + NgProfiler::StopTimer (timernr); + if (priority <= 1) + if(trace) trace->StopTimer(timernr); + } + void AddFlops (double aflops) + { + if (priority <= 2) + NgProfiler::AddFlops (timernr, aflops); + } + + double GetTime () { return NgProfiler::GetTime(timernr); } + long int GetCounts () { return NgProfiler::GetCounts(timernr); } + double GetMFlops () + { return NgProfiler::GetFlops(timernr) + / NgProfiler::GetTime(timernr) * 1e-6; } + operator int () { return timernr; } + }; + + + /** + Timer object. + Start / stop timer at constructor / destructor. + */ + class RegionTimer + { + Timer & timer; + public: + /// start timer + RegionTimer (Timer & atimer) : timer(atimer) { timer.Start(); } + /// stop timer + ~RegionTimer () { timer.Stop(); } + + RegionTimer() = delete; + RegionTimer(const RegionTimer &) = delete; + RegionTimer(RegionTimer &&) = delete; + void operator=(const RegionTimer &) = delete; + void operator=(RegionTimer &&) = delete; + }; + + class ThreadRegionTimer + { + size_t nr; + size_t tid; + public: + /// start timer + ThreadRegionTimer (size_t _nr, size_t _tid) : nr(_nr), tid(_tid) + { NgProfiler::StartThreadTimer(nr, tid); } + /// stop timer + ~ThreadRegionTimer () + { NgProfiler::StopThreadTimer(nr, tid); } + + ThreadRegionTimer() = delete; + ThreadRegionTimer(ThreadRegionTimer &&) = delete; + ThreadRegionTimer(const ThreadRegionTimer &) = delete; + void operator=(const ThreadRegionTimer &) = delete; + void operator=(ThreadRegionTimer &&) = delete; + }; + + class RegionTracer + { + int nr; + int thread_id; + public: + static constexpr int ID_JOB = PajeTrace::Task::ID_JOB; + static constexpr int ID_NONE = PajeTrace::Task::ID_NONE; + static constexpr int ID_TIMER = PajeTrace::Task::ID_TIMER; + + RegionTracer() = delete; + RegionTracer(RegionTracer &&) = delete; + RegionTracer(const RegionTracer &) = delete; + void operator=(const RegionTracer &) = delete; + void operator=(RegionTracer &&) = delete; + + /// start trace + RegionTracer (int athread_id, int region_id, int id_type = ID_NONE, int additional_value = -1 ) + : thread_id(athread_id) + { + if (trace) + nr = trace->StartTask (athread_id, region_id, id_type, additional_value); + } + /// start trace with timer + RegionTracer (int athread_id, Timer & timer, int additional_value = -1 ) + : thread_id(athread_id) + { + if (trace) + nr = trace->StartTask (athread_id, static_cast(timer), ID_TIMER, additional_value); + } + + /// set user defined value + void SetValue( int additional_value ) + { + if (trace) + trace->SetTask( thread_id, nr, additional_value ); + } + + /// stop trace + ~RegionTracer () + { + if (trace) + trace->StopTask (thread_id, nr); + } + }; + + + // Helper function for timings + // Run f() at least min_iterations times until max_time seconds elapsed + // returns minimum runtime for a call of f() + template + double RunTiming( TFunc f, double max_time = 0.5, int min_iterations = 10 ) + { + // Make sure the whole test run does not exceed maxtime + double tend = WallTime()+max_time; + + // warmup + f(); + + double tres = std::numeric_limits::max(); + int iteration = 0; + while(WallTime() + +#include "logging.hpp" + +namespace py = pybind11; +using namespace ngcore; + +PYBIND11_MODULE(pyngcore, m) // NOLINT +{ + py::enum_(m, "LOG_LEVEL", "Logging level") + .value("Trace", level::trace) + .value("Debug", level::debug) + .value("Info", level::info) + .value("Warn", level::warn) + .value("Error", level::err) + .value("Critical", level::critical) + .value("Off", level::off); + + m.def("SetLoggingLevel", &SetLoggingLevel, py::arg("level"), py::arg("logger")="", + "Set logging level, if name is given only to the specific logger, else set the global logging level"); + m.def("AddFileSink", &AddFileSink, py::arg("filename"), py::arg("level"), py::arg("logger")="", + "Add File sink, either only to logger specified or globally to all loggers"); + m.def("AddConsoleSink", &AddConsoleSink, py::arg("level"), py::arg("logger")="", + "Add console output for specific logger or all if none given"); + m.def("ClearLoggingSinks", &ClearLoggingSinks, py::arg("logger")="", + "Clear sinks of specific logger, or all if none given"); + m.def("FlushOnLoggingLevel", &FlushOnLoggingLevel, py::arg("level"), py::arg("logger")="", + "Flush every message with level at least `level` for specific logger or all loggers if none given."); +} diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/symboltable.hpp netgen-6.2.1905+dfsg1/libsrc/core/symboltable.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/symboltable.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/symboltable.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,144 @@ +#ifndef NETGEN_CORE_SYMBOLTABLE_HPP +#define NETGEN_CORE_SYMBOLTABLE_HPP + +#include +#include +#include + +#include "archive.hpp" +#include "exception.hpp" +#include "ngcore_api.hpp" + +namespace ngcore +{ + /** + A symbol table. + + The symboltable provides a mapping from string identifiers + to the generic type T. The strings are copied. + Complexity by name access is linear, by index is constant. + */ + template + class SymbolTable + { + std::vector names; + std::vector data; + public: + using value_type = T; + using reference = typename std::vector::reference; + using const_reference = typename std::vector::const_reference; + + /// Creates a symboltable + SymbolTable () = default; + SymbolTable (const SymbolTable &) = default; + SymbolTable (SymbolTable &&) noexcept = default; + + ~SymbolTable() = default; + + SymbolTable& operator=(const SymbolTable&) = default; + SymbolTable& operator=(SymbolTable&&) = default; + + template + auto DoArchive(Archive& ar) -> typename std::enable_if_t> + { + ar & names & data; + } + + /// INDEX of symbol name, throws exception if unused + size_t Index (const std::string & name) const + { + for (size_t i = 0; i < names.size(); i++) + if (names[i] == name) return i; + throw RangeException("SymbolTable", name); + } + + /// Index of symbol name, returns -1 if unused + int CheckIndex (const std::string & name) const + { + for (int i = 0; i < names.size(); i++) + if (names[i] == name) return i; + return -1; + } + + /// number of identifiers + size_t Size() const + { + return data.size(); + } + + /// Returns reference to element. exception for unused identifier + reference operator[] (const std::string & name) + { + return data[Index (name)]; + } + + const_reference operator[] (const std::string & name) const + { + return data[Index (name)]; + } + + /// Returns reference to i-th element, range check only in debug build + reference operator[] (size_t i) + { + NETGEN_CHECK_RANGE(i, 0, data.size()); + return data[i]; + } + + /// Returns const reference to i-th element, range check only in debug build + const_reference operator[] (size_t i) const + { + NETGEN_CHECK_RANGE(i, 0, data.size()); + return data[i]; + } + + /// Returns name of i-th element, range check only in debug build + const std::string & GetName (size_t i) const + { + NETGEN_CHECK_RANGE(i, 0, names.size()); + return names[i]; + } + + /// Associates el to the string name, overrides if name is used + void Set (const std::string & name, const T & el) + { + int i = CheckIndex (name); + if (i >= 0) + data[i] = el; + else + { + data.push_back(el); + names.push_back(name); + } + } + + bool Used (const std::string & name) const + { + return CheckIndex(name) >= 0; + } + + /// Deletes symboltable + inline void DeleteAll () + { + names.clear(); + data.clear(); + } + + // Adds all elements from other symboltable + SymbolTable& Update(const SymbolTable& tbl2) + { + for (size_t i = 0; i < tbl2.Size(); i++) + Set (tbl2.GetName(i), tbl2[i]); + return *this; + } + }; + + template + std::ostream & operator<< (std::ostream & ost, const SymbolTable & st) + { + for (int i = 0; i < st.Size(); i++) + ost << st.GetName(i) << " : " << st[i] << std::endl; + return ost; + } +} // namespace ngcore + +#endif // NETGEN_CORE_SYMBOLTABLE_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/type_traits.hpp netgen-6.2.1905+dfsg1/libsrc/core/type_traits.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/type_traits.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/type_traits.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -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 -Nru netgen-6.2.1804+dfsg1/libsrc/core/utils.cpp netgen-6.2.1905+dfsg1/libsrc/core/utils.cpp --- netgen-6.2.1804+dfsg1/libsrc/core/utils.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/utils.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,42 @@ +#include "utils.hpp" +#include "logging.hpp" + +#ifndef WIN32 +#include +#endif +#include + +namespace ngcore +{ + // parallel netgen + int id = 0, ntasks = 1; + +#ifdef WIN32 + // windows does demangling in typeid(T).name() + NGCORE_API std::string Demangle(const char* typeinfo) { return typeinfo; } +#else + NGCORE_API std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, + nullptr, + nullptr, + &status); } +#endif + + double ticks_per_second = [] () noexcept + { + auto tick_start = GetTimeCounter(); + double tstart = WallTime(); + double tend = WallTime()+0.001; + + // wait for 1ms and compare wall time with time counter + while(WallTime()(tick_end-tick_start)/(tend-tstart); + }(); + + const std::chrono::time_point wall_time_start = TClock::now(); + +} // namespace ngcore + diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/utils.hpp netgen-6.2.1905+dfsg1/libsrc/core/utils.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/utils.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/utils.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,70 @@ +#ifndef NETGEN_CORE_UTILS_HPP +#define NETGEN_CORE_UTILS_HPP + +#include +#include +#include +#include +#include + +#ifdef WIN32 +#include // for __rdtsc() CPU time step counter +#else +#include // for __rdtsc() CPU time step counter +#endif // WIN32 + +#include "ngcore_api.hpp" // for NGCORE_API + +namespace ngcore +{ + // MPI rank, nranks TODO: Rename + extern NGCORE_API int id, ntasks; + + NGCORE_API std::string Demangle(const char* typeinfo); + +#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 + + using TClock = std::chrono::system_clock; + extern NGCORE_API const std::chrono::time_point wall_time_start; + + // Time in seconds since program start + inline double WallTime () noexcept + { + std::chrono::time_point now = TClock::now(); + std::chrono::duration elapsed_seconds = now-wall_time_start; + return elapsed_seconds.count(); + } + + // High precision clock counter register + using TTimePoint = size_t; + extern NGCORE_API double ticks_per_second; + + inline TTimePoint GetTimeCounter() noexcept + { + return TTimePoint(__rdtsc()); + } + + template + inline std::string ToString (const T& t) + { + std::stringstream ss; + ss << t; + return ss.str(); + } + + template + std::ostream& operator << (std::ostream& ost, const std::map& map) + { + for(auto& val : map) + ost << "\n" << val.first << ": " << val.second; + return ost; + } +} // namespace ngcore + +#endif // NETGEN_CORE_UTILS_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/core/version.hpp netgen-6.2.1905+dfsg1/libsrc/core/version.hpp --- netgen-6.2.1804+dfsg1/libsrc/core/version.hpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/core/version.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,94 @@ +#ifndef NETGEN_CORE_VERSION_HPP +#define NETGEN_CORE_VERSION_HPP + +#include +#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); } + }; + + inline std::ostream& operator << (std::ostream& ost, const VersionInfo& version) + { + return ost << version.to_string(); + } +} // namespace ngcore + +#endif // NETGEN_CORE_VERSION_HPP diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/algprim.cpp netgen-6.2.1905+dfsg1/libsrc/csg/algprim.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/algprim.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/algprim.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -557,7 +557,8 @@ 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 @@ 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 @@ << R << " " << r << endl; } - - +RegisterClassForArchive regqs; +RegisterClassForArchive regpl; +RegisterClassForArchive regsph; +RegisterClassForArchive regcyl; +RegisterClassForArchive regelcyl; +RegisterClassForArchive regell; +RegisterClassForArchive regcone; +RegisterClassForArchive regellcone; +RegisterClassForArchive regtorus; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/algprim.hpp netgen-6.2.1905+dfsg1/libsrc/csg/algprim.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/algprim.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/algprim.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -47,6 +47,11 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ /// 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 @@ /// 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 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/brick.cpp netgen-6.2.1905+dfsg1/libsrc/csg/brick.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/brick.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/brick.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -523,4 +523,8 @@ surfaceactive.Elem(6) = (box.PMin()(0) < pmax(0)) && (pmax(0) < box.PMax()(0)); } + +RegisterClassForArchive regpar; +RegisterClassForArchive regbrick; +RegisterClassForArchive regob; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/brick.hpp netgen-6.2.1905+dfsg1/libsrc/csg/brick.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/brick.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/brick.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -28,8 +28,16 @@ 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 @@ 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 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/csg/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/csg/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -11,12 +11,12 @@ set_target_properties( csg PROPERTIES SUFFIX ".so") endif(APPLE) +target_link_libraries(csg PUBLIC mesh ${PYTHON_LIBRARIES}) if(NOT WIN32) - target_link_libraries(csg mesh ${PYTHON_LIBRARIES}) - target_link_libraries(csg ${PYTHON_LIBRARIES}) - install( TARGETS csg ${NG_INSTALL_DIR}) + install( TARGETS csg ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries(csg PUBLIC ngcore) if(USE_GUI) add_library(csgvis ${NG_LIB_TYPE} vscsg.cpp ) diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/csgeom.cpp netgen-6.2.1905+dfsg1/libsrc/csg/csgeom.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/csgeom.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/csgeom.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -324,6 +324,14 @@ } + 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 { @@ -554,7 +562,7 @@ const Surface * CSGeometry :: GetSurface (const char * name) const { if (surfaces.Used(name)) - return surfaces.Get(name); + return surfaces[name]; else return NULL; } @@ -577,7 +585,7 @@ Solid * oldsol = NULL; if (solids.Used (name)) - oldsol = solids.Get(name); + oldsol = solids[name]; solids.Set (name, sol); sol->SetName (name); @@ -597,7 +605,7 @@ const Solid * CSGeometry :: GetSolid (const char * name) const { if (solids.Used(name)) - return solids.Get(name); + return solids[name]; else return NULL; } @@ -608,8 +616,8 @@ const Solid * CSGeometry :: GetSolid (const string & name) const { - if (solids.Used(name.c_str())) - return solids.Get(name.c_str()); + if (solids.Used(name)) + return solids[name]; else return NULL; } @@ -629,15 +637,15 @@ const SplineGeometry<2> * CSGeometry :: GetSplineCurve2d (const string & name) const { - if (splinecurves2d.Used(name.c_str())) - return splinecurves2d.Get(name.c_str()); + if (splinecurves2d.Used(name)) + return splinecurves2d[name]; else return NULL; } const SplineGeometry<3> * CSGeometry :: GetSplineCurve3d (const string & name) const { - if (splinecurves3d.Used(name.c_str())) - return splinecurves3d.Get(name.c_str()); + if (splinecurves3d.Used(name)) + return splinecurves3d[name]; else return NULL; } @@ -713,7 +721,7 @@ void CSGeometry :: SetFlags (const char * solidname, const Flags & flags) { - Solid * solid = solids.Elem(solidname); + Solid * solid = solids[solidname]; Array surfind; int i; @@ -1584,5 +1592,5 @@ }; CSGInit csginit; - + static RegisterClassForArchive regcsg; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/csgeom.hpp netgen-6.2.1905+dfsg1/libsrc/csg/csgeom.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/csgeom.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/csgeom.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -39,7 +39,14 @@ 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; } @@ -95,7 +102,7 @@ { private: /// all surfaces - SYMBOLTABLE surfaces; + SymbolTable surfaces; public: /// primitive of surface @@ -105,12 +112,12 @@ Array delete_them; /// all named solids - SYMBOLTABLE solids; + SymbolTable solids; /// all 2d splinecurves - SYMBOLTABLE< SplineGeometry<2>* > splinecurves2d; + SymbolTable< SplineGeometry<2>* > splinecurves2d; /// all 3d splinecurves - SYMBOLTABLE< SplineGeometry<3>* > splinecurves3d; + SymbolTable< SplineGeometry<3>* > splinecurves3d; /// all top level objects: solids and surfaces Array toplevelobjects; @@ -124,6 +131,11 @@ 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 @@ 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++; } @@ -191,13 +203,15 @@ const Solid * GetSolid (const string & name) const; int GetNSolids () const { return solids.Size(); } const Solid * GetSolid (int i) const { return solids[i]; } - const SYMBOLTABLE & GetSolids () const { return solids; } + const SymbolTable & GetSolids () const { return solids; } void SetSplineCurve (const char * name, SplineGeometry<2> * spl); 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); @@ -226,7 +240,7 @@ void AddUserPoint (const Point<3> & p, double ref_factor = 0) - { userpoints.Append (UserPoint(p,1)); userpoints_ref_factor.Append (ref_factor); } + { userpoints.Append (UserPoint(p,userpoints.Size()+1)); userpoints_ref_factor.Append (ref_factor); } void AddUserPoint (const UserPoint up, double ref_factor = 0) { userpoints.Append (up); userpoints_ref_factor.Append (ref_factor); } int GetNUserPoints () const @@ -330,9 +344,9 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/edgeflw.cpp netgen-6.2.1905+dfsg1/libsrc/csg/edgeflw.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/edgeflw.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/edgeflw.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -1186,7 +1186,7 @@ { auto othersolid = geometry.GetTopLevelObject(kk)->GetSolid(); auto othersurf = geometry.GetTopLevelObject(kk)->GetSurface(); - if(!othersurf) + if(!othersurf && dynamic_cast(othersurf)) { if(othersolid->IsIn(edgepoints[0]) && othersolid->IsIn(edgepoints[edgepoints.Size()-1])) diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/extrusion.cpp netgen-6.2.1905+dfsg1/libsrc/csg/extrusion.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/extrusion.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/extrusion.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -653,15 +653,15 @@ 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 @@ surfaceactive[i] = true; } - + RegisterClassForArchive regexf; + RegisterClassForArchive regextr; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/extrusion.hpp netgen-6.2.1905+dfsg1/libsrc/csg/extrusion.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/extrusion.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/extrusion.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -49,9 +49,18 @@ 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 @@ 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 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/identify.cpp netgen-6.2.1905+dfsg1/libsrc/csg/identify.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/identify.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/identify.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -1274,6 +1274,7 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/meshsurf.hpp netgen-6.2.1905+dfsg1/libsrc/csg/meshsurf.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/meshsurf.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/meshsurf.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -51,11 +51,11 @@ MeshOptimize2dSurfaces (const CSGeometry & ageometry); /// - virtual void ProjectPoint (INDEX surfind, Point<3> & p) const; + virtual void ProjectPoint (INDEX surfind, Point<3> & p) const override; /// - virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const; + virtual void ProjectPoint2 (INDEX surfind, INDEX surfind2, Point<3> & p) const override; /// - virtual void GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const; + virtual void GetNormalVector(INDEX surfind, const Point<3> & p, Vec<3> & n) const override; }; @@ -72,24 +72,24 @@ int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, - Point<3> & newp, PointGeomInfo & newgi) const; + Point<3> & newp, PointGeomInfo & newgi) const override; virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, - Point<3> & newp, EdgePointGeomInfo & newgi) const; + Point<3> & newp, EdgePointGeomInfo & newgi) const override; virtual Vec<3> GetTangent (const Point<3> & p, int surfi1, int surfi2, - const EdgePointGeomInfo & ap1) const; + const EdgePointGeomInfo & ap1) const override; virtual Vec<3> GetNormal (const Point<3> & p, int surfi1, - const PointGeomInfo & gi) const; + const PointGeomInfo & gi) const override; - virtual void ProjectToSurface (Point<3> & p, int surfi) const; + virtual void ProjectToSurface (Point<3> & p, int surfi) const override; - virtual void ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const; + virtual void ProjectToEdge (Point<3> & p, int surfi1, int surfi2, const EdgePointGeomInfo & egi) const override; }; diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/python_csg.cpp netgen-6.2.1905+dfsg1/libsrc/csg/python_csg.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/python_csg.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/python_csg.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -235,13 +235,17 @@ 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 @@ 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,11 +459,27 @@ 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); }), py::arg("SplineSurface")) + .def("SingularFace", [] (CSGeometry & self, shared_ptr sol, shared_ptr surfaces, double factor) + { + int tlonum = -1; + for (int i = 0; i < self.GetNTopLevelObjects(); i++) + if (self.GetTopLevelObject(i)->GetSolid() == sol->GetSolid()) + tlonum = i; + if (tlonum == -1) throw NgException("not a top-level-object"); + if (!surfaces) surfaces = sol; + auto singface = new SingularFace(tlonum+1, surfaces->GetSolid(), factor); + self.singfaces.Append(singface); + }, py::arg("solid"), py::arg("surfaces")=nullptr, py::arg("factor")=0.25) .def("SingularEdge", [] (CSGeometry & self, shared_ptr s1,shared_ptr s2, double factor) { auto singedge = new SingularEdge(1, -1, self, s1->GetSolid(), s2->GetSolid(), factor); @@ -623,6 +621,68 @@ }) ) .def_property_readonly ("ntlo", &CSGeometry::GetNTopLevelObjects) + .def("_visualizationData", [](shared_ptr csg_geo) + { + std::vector vertices; + std::vector trigs; + std::vector normals; + std::vector min = {std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()}; + std::vector max = {std::numeric_limits::lowest(), + std::numeric_limits::lowest(), + std::numeric_limits::lowest()}; + std::vector surfnames; + for (int i = 0; i < csg_geo->GetNSurf(); i++) + { + auto surf = csg_geo->GetSurface(i); + surfnames.push_back(surf->GetBCName()); + } + csg_geo->FindIdenticSurfaces(1e-6); + csg_geo->CalcTriangleApproximation(0.01,100); + auto nto = csg_geo->GetNTopLevelObjects(); + size_t np = 0; + size_t ntrig = 0; + for (int i = 0; i < nto; i++){ + np += csg_geo->GetTriApprox(i)->GetNP(); + ntrig += csg_geo->GetTriApprox(i)->GetNT(); + } + vertices.reserve(np*3); + trigs.reserve(ntrig*4); + normals.reserve(np*3); + int offset_points = 0; + for (int i = 0; i < nto; i++) + { + auto triapprox = csg_geo->GetTriApprox(i); + for (int j = 0; j < triapprox->GetNP(); j++) + for(int k = 0; k < 3; k++) { + float val = triapprox->GetPoint(j)[k]; + vertices.push_back(val); + min[k] = min2(min[k], val); + max[k] = max2(max[k],val); + normals.push_back(triapprox->GetNormal(j)[k]); + } + for (int j = 0; j < triapprox->GetNT(); j++) + { + for(int k = 0; k < 3; k++) + trigs.push_back(triapprox->GetTriangle(j)[k]+offset_points); + trigs.push_back(triapprox->GetTriangle(j).SurfaceIndex()); + } + offset_points += triapprox->GetNP(); + } + py::gil_scoped_acquire ac; + py::dict res; + py::list snames; + for(auto name : surfnames) + snames.append(py::cast(name)); + res["vertices"] = MoveToNumpy(vertices); + res["triangles"] = MoveToNumpy(trigs); + res["normals"] = MoveToNumpy(normals); + res["surfnames"] = snames; + res["min"] = MoveToNumpy(min); + res["max"] = MoveToNumpy(max); + return res; + }, py::call_guard()) ; m.def("GenerateMesh", FunctionPointer diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/revolution.cpp netgen-6.2.1905+dfsg1/libsrc/csg/revolution.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/revolution.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/revolution.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -305,6 +305,7 @@ } else { + hesse = 0; (*testout) << "hesse4: " << hesse < & 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 +651,21 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/revolution.hpp netgen-6.2.1905+dfsg1/libsrc/csg/revolution.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/revolution.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/revolution.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -45,9 +45,18 @@ 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 @@ 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 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/solid.cpp netgen-6.2.1905+dfsg1/libsrc/csg/solid.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/solid.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/solid.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -419,9 +419,9 @@ - static Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE & solids); - static Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE & solids); - static Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE & solids); + static Solid * CreateSolidExpr (istream & ist, const SymbolTable & solids); + static Solid * CreateSolidTerm (istream & ist, const SymbolTable & solids); + static Solid * CreateSolidPrim (istream & ist, const SymbolTable & solids); static void ReadString (istream & ist, char * str) { @@ -461,7 +461,7 @@ } - Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidExpr (istream & ist, const SymbolTable & solids) { // cout << "create expr" << endl; @@ -484,7 +484,7 @@ return s1; } - Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidTerm (istream & ist, const SymbolTable & solids) { // cout << "create term" << endl; @@ -508,7 +508,7 @@ return s1; } - Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidPrim (istream & ist, const SymbolTable & solids) { Solid * s1; char ch; @@ -533,7 +533,7 @@ } (*testout) << "get terminal " << str << endl; - s1 = solids.Get(str); + s1 = solids[str]; if (s1) { // cout << "primitive: " << str << endl; @@ -545,7 +545,7 @@ } - Solid * Solid :: CreateSolid (istream & ist, const SYMBOLTABLE & solids) + Solid * Solid :: CreateSolid (istream & ist, const SymbolTable & solids) { Solid * nsol = CreateSolidExpr (ist, solids); nsol = new Solid (ROOT, nsol); diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/solid.hpp netgen-6.2.1905+dfsg1/libsrc/csg/solid.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/solid.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/solid.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -55,8 +55,22 @@ 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); @@ -144,7 +158,7 @@ { return maxh; } void GetSolidData (ostream & ost, int first = 1) const; - static Solid * CreateSolid (istream & ist, const SYMBOLTABLE & solids); + static Solid * CreateSolid (istream & ist, const SymbolTable & solids); static BlockAllocator ball; @@ -220,7 +234,7 @@ class ReducePrimitiveIterator : public SolidIterator { - const BoxSphere<3> & box; + BoxSphere<3> box; public: ReducePrimitiveIterator (const BoxSphere<3> & abox) : SolidIterator(), box(abox) { ; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/specpoin.cpp netgen-6.2.1905+dfsg1/libsrc/csg/specpoin.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/specpoin.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/specpoin.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -1449,11 +1449,9 @@ int dir = 0; for (int j = 1; j < 3; j++) - if (fabs (v12(j)) > v12(dir)) + if (fabs (v12(j)) < fabs(v12(dir))) dir = j; - // *testout << "dir = " << dir << endl; - Vec<3> ei = 0.0; ei(dir) = 1; a2 = Cross (v12, ei); diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/splinesurface.cpp netgen-6.2.1905+dfsg1/libsrc/csg/splinesurface.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/splinesurface.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/splinesurface.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -62,7 +62,30 @@ 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 @@ str << "SplineSurface with base " << *baseprimitive << endl; } + static RegisterClassForArchive regss; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/splinesurface.hpp netgen-6.2.1905+dfsg1/libsrc/csg/splinesurface.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/splinesurface.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/splinesurface.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -19,6 +19,8 @@ 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 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/surface.cpp netgen-6.2.1905+dfsg1/libsrc/csg/surface.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/surface.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/surface.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -566,4 +566,8 @@ if (Abs2 (rs) < 1e-24 && i > 1) i = 1; } } + +RegisterClassForArchive regsurf; +RegisterClassForArchive regprim; +RegisterClassForArchive regosf; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/csg/surface.hpp netgen-6.2.1905+dfsg1/libsrc/csg/surface.hpp --- netgen-6.2.1804+dfsg1/libsrc/csg/surface.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/surface.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -63,6 +63,12 @@ //@} 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 @@ class Primitive { + protected: + Array surfaceids; + Array surfaceactive; public: @@ -241,6 +250,10 @@ virtual ~Primitive(); + virtual void DoArchive(Archive& archive) + { + archive & surfaceids & surfaceactive; + } /* Check, whether box intersects solid defined by surface. @@ -299,9 +312,6 @@ 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 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/csg/zrefine.cpp netgen-6.2.1905+dfsg1/libsrc/csg/zrefine.cpp --- netgen-6.2.1804+dfsg1/libsrc/csg/zrefine.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/csg/zrefine.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -714,7 +714,29 @@ } - + void CombineSingularPrisms(Mesh& mesh) + { + for(int i = 1; i<=mesh.GetNE(); i++) + { + Element& el = mesh.VolumeElement(i); + if(el.GetType() != PRISM) + continue; + if(el.PNum(3) == el.PNum(6)) + { + if(el.PNum(2) == el.PNum(5)) + { + el.SetType(TET); + } + else + { + el.SetType(PYRAMID); + int pnr5 = el.PNum(3); + el.PNum(3) = el.PNum(5); + el.PNum(5) = pnr5; + } + } + } + } void ZRefinement (Mesh & mesh, const NetgenGeometry * hgeom, ZRefinementOptions & opt) @@ -729,6 +751,8 @@ MakePrismsClosePoints (mesh); RefinePrisms (mesh, geom, opt); + + CombineSingularPrisms(mesh); } diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/archive_base.hpp netgen-6.2.1905+dfsg1/libsrc/general/archive_base.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/archive_base.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/archive_base.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -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 -Nru netgen-6.2.1804+dfsg1/libsrc/general/array.hpp netgen-6.2.1905+dfsg1/libsrc/general/array.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/array.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/array.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -243,10 +243,10 @@ } explicit Array(size_t asize) - : FlatArray (asize, new T[asize]) + : FlatArray (asize, asize ? new T[asize] : nullptr) { - allocsize = asize; - ownmem = 1; + allocsize = asize; + ownmem = (asize == 0) ? 0 : 1; } /// Generate array in user data @@ -394,6 +394,27 @@ Swap (ownmem, a2.ownmem); return *this; } + + T * Release() + { + 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: @@ -772,30 +793,6 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/general/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/general/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/general/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -1,21 +1,19 @@ add_definitions(-DNGINTERFACE_EXPORTS) -add_library(gen OBJECT - array.cpp bitarray.cpp dynamicmem.cpp flags.cpp - hashtabl.cpp mystring.cpp ngexception.cpp optmem.cpp parthreads.cpp - profiler.cpp seti.cpp sort.cpp spbita2d.cpp symbolta.cpp table.cpp - mpi_interface.cpp gzstream.cpp +add_library(gen INTERFACE) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources(gen INTERFACE + ${sdir}/array.cpp ${sdir}/bitarray.cpp ${sdir}/dynamicmem.cpp ${sdir}/flags.cpp + ${sdir}/hashtabl.cpp ${sdir}/mystring.cpp ${sdir}/optmem.cpp ${sdir}/parthreads.cpp + ${sdir}/seti.cpp ${sdir}/sort.cpp ${sdir}/spbita2d.cpp ${sdir}/table.cpp + ${sdir}/mpi_interface.cpp ${sdir}/gzstream.cpp ) -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 - spbita2d.hpp stack.hpp symbolta.hpp table.hpp template.hpp + ngsimd.hpp mystring.hpp netgenout.hpp ngpython.hpp + optmem.hpp parthreads.hpp seti.hpp sort.hpp + spbita2d.hpp stack.hpp table.hpp template.hpp gzstream.h DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel ) diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/flags.cpp netgen-6.2.1905+dfsg1/libsrc/general/flags.cpp --- netgen-6.2.1804+dfsg1/libsrc/general/flags.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/flags.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -83,7 +83,7 @@ Flags :: GetStringFlag (const char * name, const char * def) const { if (strflags.Used (name)) - return strflags.Get(name); + return strflags[name]; else return def; } @@ -91,7 +91,7 @@ double Flags :: GetNumFlag (const char * name, double def) const { if (numflags.Used (name)) - return numflags.Get(name); + return numflags[name]; else return def; } @@ -99,7 +99,7 @@ const double * Flags :: GetNumFlagPtr (const char * name) const { if (numflags.Used (name)) - return & ((SYMBOLTABLE&)numflags).Elem(name); + return & ((SymbolTable&)numflags)[name]; else return NULL; } @@ -107,7 +107,7 @@ double * Flags :: GetNumFlagPtr (const char * name) { if (numflags.Used (name)) - return & ((SYMBOLTABLE&)numflags).Elem(name); + return & ((SymbolTable&)numflags)[name]; else return NULL; } @@ -122,7 +122,7 @@ Flags :: GetStringListFlag (const char * name) const { if (strlistflags.Used (name)) - return *strlistflags.Get(name); + return *strlistflags[name]; else { static Array dummy_array(0); @@ -134,7 +134,7 @@ Flags ::GetNumListFlag (const char * name) const { if (numlistflags.Used (name)) - return *numlistflags.Get(name); + return *numlistflags[name]; else { static Array dummy_array(0); @@ -170,9 +170,9 @@ ofstream outfile (filename); for (i = 1; i <= strflags.Size(); i++) - outfile << strflags.GetName(i) << " = " << strflags.Get(i) << endl; + outfile << strflags.GetName(i) << " = " << strflags[i] << endl; for (i = 1; i <= numflags.Size(); i++) - outfile << numflags.GetName(i) << " = " << numflags.Get(i) << endl; + outfile << numflags.GetName(i) << " = " << numflags[i] << endl; for (i = 1; i <= defflags.Size(); i++) outfile << defflags.GetName(i) << endl; } @@ -184,9 +184,9 @@ int i; for (i = 1; i <= strflags.Size(); i++) - ost << strflags.GetName(i) << " = " << strflags.Get(i) << endl; + ost << strflags.GetName(i) << " = " << strflags[i] << endl; for (i = 1; i <= numflags.Size(); i++) - ost << numflags.GetName(i) << " = " << numflags.Get(i) << endl; + ost << numflags.GetName(i) << " = " << numflags[i] << endl; for (i = 1; i <= defflags.Size(); i++) ost << defflags.GetName(i) << endl; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/flags.hpp netgen-6.2.1905+dfsg1/libsrc/general/flags.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/flags.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/flags.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -19,15 +19,15 @@ class Flags { /// - SYMBOLTABLE strflags; + SymbolTable strflags; /// - SYMBOLTABLE numflags; + SymbolTable numflags; /// - SYMBOLTABLE defflags; + SymbolTable defflags; /// - SYMBOLTABLE*> strlistflags; + SymbolTable*> strlistflags; /// - SYMBOLTABLE*> numlistflags; + SymbolTable*> numlistflags; public: /// DLL_HEADER Flags (); diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/hashtabl.hpp netgen-6.2.1905+dfsg1/libsrc/general/hashtabl.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/hashtabl.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/hashtabl.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -259,20 +259,13 @@ 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 @@ { 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 -Nru netgen-6.2.1804+dfsg1/libsrc/general/mpi_interface.cpp netgen-6.2.1905+dfsg1/libsrc/general/mpi_interface.cpp --- netgen-6.2.1804+dfsg1/libsrc/general/mpi_interface.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/mpi_interface.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -43,8 +43,10 @@ return string(buf); } + // #else + // MPI_Comm MPI_COMM_WORLD, MPI_COMM_NULL; #endif +} -} diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/mpi_interface.hpp netgen-6.2.1905+dfsg1/libsrc/general/mpi_interface.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/mpi_interface.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/mpi_interface.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -14,101 +14,176 @@ namespace netgen { + // using ngcore::id; + // using ngcore::ntasks; - extern DLL_HEADER int id, ntasks; - +#ifndef PARALLEL + /** without MPI, we need a dummy typedef **/ + // typedef int MPI_Comm; +#endif + + /** This is the "standard" communicator that will be used for netgen-objects. **/ + // extern DLL_HEADER NgMPI_Comm ng_comm; +#ifdef OLD #ifdef PARALLEL + inline int MyMPI_GetNTasks (MPI_Comm comm /* = ng_comm */) + { + int ntasks; + MPI_Comm_size(comm, &ntasks); + return ntasks; + } + inline int MyMPI_GetId (MPI_Comm comm /* = ng_comm */) + { + int id; + MPI_Comm_rank(comm, &id); + return id; + } +#else + // enum { MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 0}; + inline int MyMPI_GetNTasks (MPI_Comm comm /* = ng_comm */) { return 1; } + inline int MyMPI_GetId (MPI_Comm comm /* = ng_comm */) { return 0; } +#endif +#endif - enum { MPI_TAG_CMD = 110 }; - enum { MPI_TAG_MESH = 210 }; - enum { MPI_TAG_VIS = 310 }; - - extern MPI_Comm mesh_comm; - + /* +#ifdef PARALLEL + // For python wrapping of communicators + struct PyMPI_Comm { + MPI_Comm comm; + bool owns_comm; + PyMPI_Comm (MPI_Comm _comm, bool _owns_comm = false) : comm(_comm), owns_comm(_owns_comm) { } + PyMPI_Comm (const PyMPI_Comm & c) = delete; + ~PyMPI_Comm () { + if (owns_comm) + MPI_Comm_free(&comm); + } + inline int Rank() const { return MyMPI_GetId(comm); } + inline int Size() const { return MyMPI_GetNTasks(comm); } + }; +#else + // dummy without MPI + struct PyMPI_Comm { + MPI_Comm comm = 0; + PyMPI_Comm (MPI_Comm _comm, bool _owns_comm = false) { } + ~PyMPI_Comm () { } + inline int Rank() const { return 0; } + inline int Size() const { return 1; } + }; +#endif + */ + +#ifdef PARALLEL template - MPI_Datatype MyGetMPIType ( ) + inline MPI_Datatype MyGetMPIType ( ) { cerr << "ERROR in GetMPIType() -- no type found" << endl;return 0; } - template <> inline MPI_Datatype MyGetMPIType ( ) { return MPI_INT; } - template <> inline MPI_Datatype MyGetMPIType ( ) { return MPI_DOUBLE; } + template <> + inline MPI_Datatype MyGetMPIType ( ) + { return MPI_CHAR; } + template<> + inline MPI_Datatype MyGetMPIType ( ) + { return MPI_UINT64_T; } +#else + typedef int MPI_Datatype; + template inline MPI_Datatype MyGetMPIType ( ) { return 0; } +#endif - - inline void MyMPI_Send (int i, int dest, int tag) +#ifdef PARALLEL + inline MPI_Comm MyMPI_SubCommunicator(MPI_Comm comm, Array & procs) + { + MPI_Comm subcomm; + MPI_Group gcomm, gsubcomm; + MPI_Comm_group(comm, &gcomm); + MPI_Group_incl(gcomm, procs.Size(), &(procs[0]), &gsubcomm); + MPI_Comm_create_group(comm, gsubcomm, 6969, &subcomm); + return subcomm; + } +#else + inline MPI_Comm MyMPI_SubCommunicator(MPI_Comm comm, Array & procs) + { return comm; } +#endif + +#ifdef PARALLEL + enum { MPI_TAG_CMD = 110 }; + enum { MPI_TAG_MESH = 210 }; + enum { MPI_TAG_VIS = 310 }; + + inline void MyMPI_Send (int i, int dest, int tag, MPI_Comm comm /* = ng_comm */) { int hi = i; - MPI_Send( &hi, 1, MPI_INT, dest, tag, MPI_COMM_WORLD); + MPI_Send( &hi, 1, MPI_INT, dest, tag, comm); } - inline void MyMPI_Recv (int & i, int src, int tag) + inline void MyMPI_Recv (int & i, int src, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; - MPI_Recv( &i, 1, MPI_INT, src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &i, 1, MPI_INT, src, tag, comm, &status); } - inline void MyMPI_Send (const string & s, int dest, int tag) + inline void MyMPI_Send (const string & s, int dest, int tag, MPI_Comm comm /* = ng_comm */) { - MPI_Send( const_cast (s.c_str()), s.length(), MPI_CHAR, dest, tag, MPI_COMM_WORLD); + MPI_Send( const_cast (s.c_str()), s.length(), MPI_CHAR, dest, tag, comm); } - inline void MyMPI_Recv (string & s, int src, int tag) + inline void MyMPI_Recv (string & s, int src, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; int len; MPI_Probe (src, tag, MPI_COMM_WORLD, &status); MPI_Get_count (&status, MPI_CHAR, &len); s.assign (len, ' '); - MPI_Recv( &s[0], len, MPI_CHAR, src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &s[0], len, MPI_CHAR, src, tag, comm, &status); } template - inline void MyMPI_Send (FlatArray s, int dest, int tag) + inline void MyMPI_Send (FlatArray s, int dest, int tag, MPI_Comm comm /* = ng_comm */) { - MPI_Send( &s.First(), s.Size(), MyGetMPIType(), dest, tag, MPI_COMM_WORLD); + MPI_Send( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm); } template - inline void MyMPI_Recv ( FlatArray s, int src, int tag) + inline void MyMPI_Recv ( FlatArray s, int src, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; - MPI_Recv( &s.First(), s.Size(), MyGetMPIType(), src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &s.First(), s.Size(), MyGetMPIType(), src, tag, comm, &status); } template - inline void MyMPI_Recv ( Array & s, int src, int tag) + inline void MyMPI_Recv ( Array & s, int src, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; int len; - MPI_Probe (src, tag, MPI_COMM_WORLD, &status); + MPI_Probe (src, tag, comm, &status); MPI_Get_count (&status, MyGetMPIType(), &len); s.SetSize (len); - MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, comm, &status); } template - inline int MyMPI_Recv ( Array & s, int tag) + inline int MyMPI_Recv ( Array & s, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Status status; int len; - MPI_Probe (MPI_ANY_SOURCE, tag, MPI_COMM_WORLD, &status); + MPI_Probe (MPI_ANY_SOURCE, tag, comm, &status); int src = status.MPI_SOURCE; MPI_Get_count (&status, MyGetMPIType(), &len); s.SetSize (len); - MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, comm, &status); return src; } @@ -130,7 +205,7 @@ */ template - inline MPI_Request MyMPI_ISend (FlatArray s, int dest, int tag, MPI_Comm comm = MPI_COMM_WORLD) + inline MPI_Request MyMPI_ISend (FlatArray s, int dest, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Request request; MPI_Isend( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm, &request); @@ -139,7 +214,7 @@ template - inline MPI_Request MyMPI_IRecv (FlatArray s, int dest, int tag, MPI_Comm comm = MPI_COMM_WORLD) + inline MPI_Request MyMPI_IRecv (FlatArray s, int dest, int tag, MPI_Comm comm /* = ng_comm */) { MPI_Request request; MPI_Irecv( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm, &request); @@ -204,12 +279,15 @@ template inline void MyMPI_ExchangeTable (TABLE & send_data, TABLE & recv_data, int tag, - MPI_Comm comm = MPI_COMM_WORLD) + const NgMPI_Comm & comm /* = ng_comm */) { - int ntasks, rank; - MPI_Comm_size(comm, &ntasks); - MPI_Comm_rank(comm, &rank); - + /* + int rank = MyMPI_GetId(comm); + int ntasks = MyMPI_GetNTasks(comm); + */ + int rank = comm.Rank(); + int ntasks = comm.Size(); + Array send_sizes(ntasks); Array recv_sizes(ntasks); for (int i = 0; i < ntasks; i++) @@ -252,22 +330,23 @@ template - inline void MyMPI_Bcast (T & s, MPI_Comm comm = MPI_COMM_WORLD) + inline void MyMPI_Bcast (T & s, MPI_Comm comm /* = ng_comm */) { MPI_Bcast (&s, 1, MyGetMPIType(), 0, comm); } template - inline void MyMPI_Bcast (Array & s, MPI_Comm comm = MPI_COMM_WORLD) + inline void MyMPI_Bcast (Array & s, NgMPI_Comm comm /* = ng_comm */) { int size = s.Size(); MyMPI_Bcast (size, comm); - if (id != 0) s.SetSize (size); + // if (MyMPI_GetId(comm) != 0) s.SetSize (size); + if (comm.Rank() != 0) s.SetSize (size); MPI_Bcast (&s[0], size, MyGetMPIType(), 0, comm); } template - inline void MyMPI_Bcast (Array & s, int root, MPI_Comm comm = MPI_COMM_WORLD) + inline void MyMPI_Bcast (Array & s, int root, MPI_Comm comm /* = ng_comm */) { int id; MPI_Comm_rank(comm, &id); @@ -280,19 +359,19 @@ } template - inline void MyMPI_Allgather (const T & send, FlatArray recv, MPI_Comm comm) + inline void MyMPI_Allgather (const T & send, FlatArray recv, MPI_Comm comm /* = ng_comm */) { MPI_Allgather( const_cast (&send), 1, MyGetMPIType(), &recv[0], 1, MyGetMPIType(), comm); } template - inline void MyMPI_Alltoall (FlatArray send, FlatArray recv, MPI_Comm comm) + inline void MyMPI_Alltoall (FlatArray send, FlatArray recv, MPI_Comm comm /* = ng_comm */) { MPI_Alltoall( &send[0], 1, MyGetMPIType(), &recv[0], 1, MyGetMPIType(), comm); } // template -// inline void MyMPI_Alltoall_Block (FlatArray send, FlatArray recv, int blocklen, MPI_Comm comm) +// inline void MyMPI_Alltoall_Block (FlatArray send, FlatArray recv, int blocklen, MPI_Comm comm = ng_comm) // { // MPI_Alltoall( &send[0], blocklen, MyGetMPIType(), &recv[0], blocklen, MyGetMPIType(), comm); // } diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/myadt.hpp netgen-6.2.1905+dfsg1/libsrc/general/myadt.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/myadt.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/myadt.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -17,11 +17,15 @@ #include "../include/mydefs.hpp" -#include "ngexception.hpp" +#include "../core/ngcore.hpp" +namespace netgen +{ + using namespace ngcore; + using NgException = Exception; +} #include "parthreads.hpp" // #include "moveablemem.hpp" #include "dynamicmem.hpp" -#include "archive_base.hpp" #include "template.hpp" #include "array.hpp" @@ -29,7 +33,6 @@ #include "hashtabl.hpp" -#include "symbolta.hpp" #include "bitarray.hpp" #include "flags.hpp" #include "spbita2d.hpp" @@ -40,7 +43,6 @@ #include "sort.hpp" #include "stack.hpp" #include "mystring.hpp" -#include "profiler.hpp" #include "mpi_interface.hpp" #include "netgenout.hpp" diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/netgenout.hpp netgen-6.2.1905+dfsg1/libsrc/general/netgenout.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/netgenout.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/netgenout.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -4,14 +4,11 @@ // #include // #include // #include +#include "mpi_interface.hpp" namespace netgen { -#ifdef PARALLEL -extern int id; -extern int ntasks; -#endif DLL_HEADER extern int printmessage_importance; DLL_HEADER extern int printdots; diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/ngexception.cpp netgen-6.2.1905+dfsg1/libsrc/general/ngexception.cpp --- netgen-6.2.1804+dfsg1/libsrc/general/ngexception.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/ngexception.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -/**************************************************************************/ -/* File: ngexception.cpp */ -/* Author: Joachim Schoeberl */ -/* Date: 16. Jan. 02 */ -/**************************************************************************/ - -#include - -namespace netgen -{ - //using namespace netgen; - - - - NgException :: NgException (const string & s) - : m_what(s) - { - ; - } - - - NgException :: ~NgException () - { - ; - } - - /// append string to description - void NgException :: Append (const string & s) - { - m_what += s; - } - -} diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/ngexception.hpp netgen-6.2.1905+dfsg1/libsrc/general/ngexception.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/ngexception.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/ngexception.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -#ifndef FILE_NGEXCEPTION -#define FILE_NGEXCEPTION - -/**************************************************************************/ -/* File: ngexception.hpp */ -/* Author: Joachim Schoeberl */ -/* Date: 16. Jan. 2002 */ -/**************************************************************************/ - -namespace netgen -{ - -/// Base class for all ng exceptions -class NgException : public std::exception -{ - /// verbal description of exception - string m_what; -public: - /// - DLL_HEADER NgException (const string & s); - /// - DLL_HEADER virtual ~NgException (); - - /// append string to description - DLL_HEADER void Append (const string & s); - // void Append (const char * s); - - /// verbal description of exception - const string & What() const { return m_what; } - virtual const char* what() const noexcept override { return m_what.c_str(); } -}; -} - -#endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/ngpython.hpp netgen-6.2.1905+dfsg1/libsrc/general/ngpython.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/ngpython.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/ngpython.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -2,11 +2,22 @@ #include #include +#include +#include namespace py = pybind11; #include #include +template +py::array MoveToNumpy(std::vector& vec) +{ + auto newvec = new std::vector(); + std::swap(*newvec, vec); + auto capsule = py::capsule(newvec, [](void *v) { delete reinterpret_cast*>(v); }); + return py::array(newvec->size(), newvec->data(), capsule); +} + namespace PYBIND11_NAMESPACE { template bool CheckCast( py::handle obj ) { @@ -56,16 +67,7 @@ return static_cast::pointer>(lambda); } - - template - inline std::string ToString (const T& t) - { - std::stringstream ss; - ss << t; - return ss.str(); - } - -} +} // namespace netgen #endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/profiler.cpp netgen-6.2.1905+dfsg1/libsrc/general/profiler.cpp --- netgen-6.2.1804+dfsg1/libsrc/general/profiler.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/profiler.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,131 +0,0 @@ -/**************************************************************************/ -/* File: profiler.cpp */ -/* Author: Joachim Schoeberl */ -/* Date: 19. Apr. 2002 */ -/**************************************************************************/ - - -#include - -namespace netgen -{ - //using namespace netgen; - - long int NgProfiler::tottimes[SIZE]; - long int NgProfiler::starttimes[SIZE]; - long int NgProfiler::counts[SIZE]; - string NgProfiler::names[SIZE]; - int NgProfiler::usedcounter[SIZE]; - - - NgProfiler :: NgProfiler() - { - for (int i = 0; i < SIZE; i++) - { - tottimes[i] = 0; - usedcounter[i] = 0; - } - - total_timer = CreateTimer ("total CPU time"); - StartTimer (total_timer); - } - - NgProfiler :: ~NgProfiler() - { -#ifndef PARALLEL - StopTimer (total_timer); -#endif - - //ofstream prof; - //prof.open("ng.prof"); - - // ofstream-constructor may be called after STL-stuff is destructed, - // which leads to an "order of destruction"-problem, - // thus we use the C-variant: - - if (getenv ("NGPROFILE")) - { - char filename[100]; -#ifdef PARALLEL - sprintf (filename, "netgen.prof.%d", id); -#else - sprintf (filename, "netgen.prof"); -#endif - - if (id == 0) printf ("write profile to file netgen.prof\n"); - FILE *prof = fopen(filename,"w"); - Print (prof); - fclose(prof); - } - } - - -// void NgProfiler :: Print (ostream & prof) -// { -// for (int i = 0; i < SIZE; i++) -// if (counts[i] != 0 || usedcounter[i] != 0) -// { -// prof.setf (ios::fixed, ios::floatfield); -// prof.setf (ios::showpoint); - -// prof // << "job " << setw(3) << i -// << "calls " << setw(8) << counts[i] -// << ", time " << setprecision(2) << setw(6) << double(tottimes[i]) / CLOCKS_PER_SEC << " sec"; - -// if (usedcounter[i]) -// prof << " " << names[i]; -// else -// prof << " " << i; - -// prof << endl; -// } -// } - - - void NgProfiler :: Print (FILE * prof) - { - for (int i = 0; i < SIZE; i++) - if (counts[i] != 0 || usedcounter[i] != 0) - { - //fprintf(prof,"job %3i calls %8i, time %6.2f sec",i,counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); -#ifndef USE_TSC - fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); -#else - fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / 2.7e9); -#endif - if(usedcounter[i]) - fprintf(prof," %s",names[i].c_str()); - else - fprintf(prof," %i",i); - fprintf(prof,"\n"); - } - } - - int NgProfiler :: CreateTimer (const string & name) - { - for (int i = SIZE-1; i > 0; i--) - if(names[i] == name) - return i; - - for (int i = SIZE-1; i > 0; i--) - if (!usedcounter[i]) - { - usedcounter[i] = 1; - names[i] = name; - return i; - } - return -1; - } - - - void NgProfiler :: ClearTimers () - { - for (int i = 0; i < SIZE; i++) - { - tottimes[i] = 0; - counts[i] = 0; - } - } - - NgProfiler prof; -} diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/profiler.hpp netgen-6.2.1905+dfsg1/libsrc/general/profiler.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/profiler.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/profiler.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,88 +0,0 @@ -#ifndef FILE_NG_PROFILER -#define FILE_NG_PROFILER - -/**************************************************************************/ -/* File: profiler.hpp */ -/* Author: Joachim Schoeberl */ -/* Date: 5. Jan. 2005 */ -/**************************************************************************/ - - - -#ifdef VTRACE -#include "vt_user.h" -#else - #define VT_USER_START(n) - #define VT_USER_END(n) - #define VT_TRACER(n) -#endif - - -// #define USE_TSC -#ifdef USE_TSC -#include // for __rdtsc() CPU time step counter -#endif - -namespace netgen -{ - -class NgProfiler -{ - enum { SIZE = 1000 }; - - static long int tottimes[SIZE]; - static long int starttimes[SIZE]; - static long int counts[SIZE]; - static string names[SIZE]; - static int usedcounter[SIZE]; - - int total_timer; -public: - NgProfiler(); - ~NgProfiler(); - static int CreateTimer (const string & name); -#ifndef USE_TSC - static void StartTimer (int nr) - { - starttimes[nr] = clock(); counts[nr]++; - // VT_USER_START (const_cast (names[nr].c_str())); - VT_USER_START ( (char * const) (names[nr].c_str())); - } - static void StopTimer (int nr) - { - tottimes[nr] += clock()-starttimes[nr]; - VT_USER_END (const_cast (names[nr].c_str())); - } -#else - static void StartTimer (int nr) - { - starttimes[nr] = __rdtsc(); counts[nr]++; - // VT_USER_START (const_cast (names[nr].c_str())); - // VT_USER_START ( (char * const) (names[nr].c_str())); - } - static void StopTimer (int nr) - { - tottimes[nr] += __rdtsc()-starttimes[nr]; - VT_USER_END (const_cast (names[nr].c_str())); - } -#endif - - - //static void Print (ostream & ost); - static void Print (FILE * prof); - - static void ClearTimers (); - - class RegionTimer - { - int nr; - public: - RegionTimer (int anr) : nr(anr) - { StartTimer (nr); } - ~RegionTimer () { StopTimer (nr); } - }; -}; - -} - -#endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/symbolta.cpp netgen-6.2.1905+dfsg1/libsrc/general/symbolta.cpp --- netgen-6.2.1804+dfsg1/libsrc/general/symbolta.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/symbolta.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,52 +0,0 @@ -/**************************************************************************/ -/* File: symbolta.cc */ -/* Author: Joachim Schoeberl */ -/* Date: 01. Jun. 95 */ -/**************************************************************************/ - -/* - Abstract data type Symbol Table -*/ - -#include -#include - - -#ifndef FILE_SYMBOLTABLECC -#define FILE_SYMBOLTABLECC -// necessary for SGI ???? - - -namespace netgen -{ - //using namespace netgen; - - BASE_SYMBOLTABLE :: BASE_SYMBOLTABLE () - { - ; - } - - - BASE_SYMBOLTABLE :: ~BASE_SYMBOLTABLE() - { - DelNames(); - } - - - void BASE_SYMBOLTABLE :: DelNames() - { - for (int i = 0; i < names.Size(); i++) - delete [] names[i]; - names.SetSize (0); - } - - int BASE_SYMBOLTABLE :: Index (const char * name) const - { - if (!name) return 0; - for (int i = 0; i < names.Size(); i++) - if (strcmp (names[i], name) == 0) return i+1; - return 0; - } -} - -#endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/symbolta.hpp netgen-6.2.1905+dfsg1/libsrc/general/symbolta.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/symbolta.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/symbolta.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,161 +0,0 @@ -#ifndef FILE_SYMBOLTA -#define FILE_SYMBOLTA - - -/**************************************************************************/ -/* File: symbolta.hh */ -/* Author: Joachim Schoeberl */ -/* Date: 01. Jun. 95 */ -/**************************************************************************/ - -namespace netgen -{ - -/** - Base class for the generic SYMBOLTABLE. - An array of identifiers is maintained. -*/ -class DLL_HEADER BASE_SYMBOLTABLE -{ -protected: - /// identifiers - Array names; - -public: - /// Constructor - BASE_SYMBOLTABLE (); - /// - ~BASE_SYMBOLTABLE (); - /// - void DelNames (); - /// Index of symbol name, returns 0 if not used. - int Index (const char * name) const; -}; - - -/** - Abstract data type Symbol Table. - - To a string an value of the generic type T is associated. - The string is not copied into the symbol table class! -*/ -template -class SYMBOLTABLE : public BASE_SYMBOLTABLE -{ -private: - /// Associated data - Array data; - -public: - /// Creates a symboltable - inline SYMBOLTABLE (); - /// Returns size of symboltable - inline INDEX Size() const; - /// Returns reference to element, error if not used - inline T & Elem (const char * name); - /// Returns reference to i-th element - inline T & Elem (int i) - { return data.Elem(i); } - /// Returns element, error if not used - inline const T & Get (const char * name) const; - /// Returns i-th element - inline const T & Get (int i) const; - /// Returns name of i-th element - inline const char* GetName (int i) const; - /// Associates el to the string name, overrides if name is used - inline void Set (const char * name, const T & el); - /// Checks whether name is used - inline bool Used (const char * name) const; - /// Deletes symboltable - inline void DeleteAll (); - - inline T & operator[] (int i) - { return data[i]; } - inline const T & operator[] (int i) const - { return data[i]; } - -private: - /// Prevents from copying symboltable by pointer assignment - SYMBOLTABLE & operator= (SYMBOLTABLE &); -}; - - - - -template -inline SYMBOLTABLE :: SYMBOLTABLE () -{ - ; -} - - -template -inline INDEX SYMBOLTABLE :: Size() const -{ - return data.Size(); -} - -template -inline T & SYMBOLTABLE :: Elem (const char * name) -{ - int i = Index (name); - if (i) - return data.Elem (i); - else - return data.Elem(1); -} - -template -inline const T & SYMBOLTABLE :: Get (const char * name) const -{ - int i; - i = Index (name); - if (i) - return data.Get(i); - else - return data.Get(1); -} - -template -inline const T & SYMBOLTABLE :: Get (int i) const -{ - return data.Get(i); -} - -template -inline const char* SYMBOLTABLE :: GetName (int i) const -{ - return names.Get(i); -} - -template -inline void SYMBOLTABLE :: Set (const char * name, const T & el) -{ - int i; - i = Index (name); - if (i) - data.Set(i, el); - else - { - data.Append (el); - char * hname = new char [strlen (name) + 1]; - strcpy (hname, name); - names.Append (hname); - } -} - -template -inline bool SYMBOLTABLE :: Used (const char * name) const -{ - return (Index(name)) ? true : false; -} - -template -inline void SYMBOLTABLE :: DeleteAll () -{ - DelNames(); - data.DeleteAll(); -} - -} -#endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/table.cpp netgen-6.2.1905+dfsg1/libsrc/general/table.cpp --- netgen-6.2.1804+dfsg1/libsrc/general/table.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/table.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -213,7 +213,7 @@ - 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 @@ cnt += data[i].size*elemsize; } } - return ar; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/general/table.hpp netgen-6.2.1905+dfsg1/libsrc/general/table.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/table.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/table.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -89,7 +89,7 @@ void SetElementSizesToMaxSizes (); - ngstd::Archive & DoArchive (ngstd::Archive & ar, int elemsize); + void DoArchive (Archive & ar, int elemsize); }; @@ -238,21 +238,13 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/general/template.hpp netgen-6.2.1905+dfsg1/libsrc/general/template.hpp --- netgen-6.2.1804+dfsg1/libsrc/general/template.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/general/template.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -23,7 +23,6 @@ // #include /** output stream for testing. testout is opened by main */ -DLL_HEADER extern ostream * testout; /** use instead of cout */ DLL_HEADER extern ostream * mycout; diff -Nru netgen-6.2.1804+dfsg1/libsrc/geom2d/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/geom2d/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/geom2d/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/geom2d/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -4,11 +4,13 @@ set_target_properties( geom2d PROPERTIES SUFFIX ".so") endif(APPLE) +target_link_libraries(geom2d mesh ${PYTHON_LIBRARIES}) if(NOT WIN32) - target_link_libraries(geom2d mesh ${PYTHON_LIBRARIES}) - install( TARGETS geom2d ${NG_INSTALL_DIR}) + install( TARGETS geom2d ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries(geom2d ngcore) + if(USE_GUI) add_library(geom2dvis ${NG_LIB_TYPE} vsgeom2d.cpp) if(NOT WIN32) @@ -19,6 +21,6 @@ install(FILES geom2dmesh.hpp geometry2d.hpp spline2d.hpp - splinegeometry2.hpp vsgeom2d.hpp + vsgeom2d.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/geom2d COMPONENT netgen_devel ) diff -Nru netgen-6.2.1804+dfsg1/libsrc/geom2d/genmesh2d.cpp netgen-6.2.1905+dfsg1/libsrc/geom2d/genmesh2d.cpp --- netgen-6.2.1804+dfsg1/libsrc/geom2d/genmesh2d.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/geom2d/genmesh2d.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -55,7 +55,8 @@ sum += dt / fun; } - int nel = int (sum+1); + int nel = int (sum+0.5); + if (nel == 0) nel = 1; fperel = sum / nel; points.Append (0); @@ -207,6 +208,9 @@ // 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 +241,23 @@ 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) { @@ -437,9 +458,9 @@ for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) if ( (*mesh)[si].si > maxsegmentindex) maxsegmentindex = (*mesh)[si].si; - mesh->SetNBCNames(maxsegmentindex+1); + mesh->SetNBCNames(maxsegmentindex); - for ( int sindex = 0; sindex <= maxsegmentindex; sindex++ ) + for ( int sindex = 0; sindex < maxsegmentindex; sindex++ ) mesh->SetBCName ( sindex, geometry.GetBCName( sindex+1 ) ); for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) @@ -581,8 +602,10 @@ // 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 -Nru netgen-6.2.1804+dfsg1/libsrc/geom2d/geom2dmesh.cpp netgen-6.2.1905+dfsg1/libsrc/geom2d/geom2dmesh.cpp --- netgen-6.2.1804+dfsg1/libsrc/geom2d/geom2dmesh.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/geom2d/geom2dmesh.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -47,8 +47,8 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/geom2d/geometry2d.cpp netgen-6.2.1905+dfsg1/libsrc/geom2d/geometry2d.cpp --- netgen-6.2.1804+dfsg1/libsrc/geom2d/geometry2d.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/geom2d/geometry2d.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -138,7 +138,7 @@ geompoints.Append (GeomPoint(x, hd)); geompoints.Last().hpref = flags.GetDefineFlag ("hpref"); - geompoints.Last().hmax = 1e99; + geompoints.Last().hmax = flags.GetNumFlag("hmax", 1e99); } PrintMessage (3, nump, " points loaded"); @@ -201,7 +201,6 @@ infile >> spex->reffak; spex -> leftdom = leftdom; spex -> rightdom = rightdom; - spex -> hmax = 1e99; splines.Append (spex); @@ -233,6 +232,7 @@ delete bcnames[mybc]; bcnames[mybc] = new string (flags.GetStringFlag("bcname","") ); } + spex -> hmax = flags.GetNumFlag("hmax", 1e99); } } @@ -1034,5 +1034,6 @@ }; SplineGeoInit sginit; - + static RegisterClassForArchive, NetgenGeometry> regspg2; + static RegisterClassForArchive> regssext; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/geom2d/geometry2d.hpp netgen-6.2.1905+dfsg1/libsrc/geom2d/geometry2d.hpp --- netgen-6.2.1804+dfsg1/libsrc/geom2d/geometry2d.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/geom2d/geometry2d.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -21,7 +21,7 @@ class SplineSegExt : public SplineSeg<2> { public: - const SplineSeg<2> & seg; + SplineSeg<2>* seg; /// left domain int leftdom; @@ -42,35 +42,43 @@ /// 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 @@ 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 @@ virtual bool InConvexHull (Point<2> p, double eps) const { - return seg.InConvexHull (p, eps); + return seg->InConvexHull (p, eps); } }; @@ -143,7 +151,11 @@ 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 { @@ -163,6 +175,7 @@ void CopyEdgeMesh (int from, int to, Mesh & mesh2d, Point3dTree & searchtree); + size_t GetNDomains() const { return materials.Size(); } void GetMaterial (int domnr, char* & material ); void SetMaterial (int domnr, const string & material); diff -Nru netgen-6.2.1804+dfsg1/libsrc/geom2d/python_geom2d.cpp netgen-6.2.1905+dfsg1/libsrc/geom2d/python_geom2d.cpp --- netgen-6.2.1804+dfsg1/libsrc/geom2d/python_geom2d.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/geom2d/python_geom2d.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -15,23 +15,38 @@ DLL_HEADER void ExportGeom2d(py::module &m) { + py::class_> + (m, "Spline", "Spline of a SplineGeometry object") + .def_property("leftdom", [] (SplineSegExt& self) { return self.leftdom; }, + [](SplineSegExt& self, int dom) { self.leftdom = dom; }) + .def_property("rightdom", [] (SplineSegExt& self) { return self.rightdom; }, + [](SplineSegExt& self, int dom) { self.rightdom = dom; }) + .def_property_readonly("bc", [] (SplineSegExt& self) { return self.bc; }) + .def("GetNormal", [](SplineSegExt& self, double t) + { + auto tang = self.GetTangent(t).Normalize(); + return Vec<2>(tang[1], -tang[0]); + }) + .def("StartPoint", [](SplineSegExt& self) { return Point<2>(self.StartPI()); }) + .def("EndPoint", [](SplineSegExt& self) { return Point<2>(self.EndPI()); }) + ; + 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 +54,11 @@ 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) { @@ -86,10 +102,8 @@ else if (py::extract(bc).check()) { string bcname = py::extract(bc)(); - int bcnum = self.GetBCNumber(bcname); - if (bcnum == 0) - bcnum = self.AddBCName(bcname); - seg->bc = bcnum; + seg->bc = self.GetNSplines()+1; + self.SetBCName(seg->bc, bcname); } else seg->bc = self.GetNSplines()+1; @@ -123,38 +137,62 @@ seg->copyfrom = -1; self.AppendSegment(seg); }), py::arg("point_indices"), py::arg("leftdomain") = 1, py::arg("rightdomain") = py::int_(0)) - //.def("AppendSegment", FunctionPointer([](SplineGeometry2d &self, int point_index1, int point_index2)//, int leftdomain, int rightdomain) - // { - // LineSeg<2> * l = new LineSeg<2>(self.GetPoint(point_index1), self.GetPoint(point_index2)); - // SplineSegExt * seg = new SplineSegExt(*l); - // seg->leftdom = 1;// leftdomain; - // seg->rightdom = 0;// rightdomain; - // seg->hmax = 1e99; - // seg->reffak = 1; - // seg->copyfrom = -1; - - // self.AppendSegment(seg); - // }))//, (py::arg("self"), py::arg("point_index1"), py::arg("point_index2"), py::arg("leftdomain") = 1, py::arg("rightdomain") = 0) ) - //.def("AppendSegment", FunctionPointer([](SplineGeometry2d &self, int point_index1, int point_index2, int point_index3)//, int leftdomain, int rightdomain) - // { - // SplineSeg3<2> * seg3 = new SplineSeg3<2>(self.GetPoint(point_index1), self.GetPoint(point_index2), self.GetPoint(point_index3)); - // SplineSegExt * seg = new SplineSegExt(*seg3); - // seg->leftdom = 1;// leftdomain; - // seg->rightdom = 0;// rightdomain; - // seg->hmax = 1e99; - // seg->reffak = 1; - // seg->copyfrom = -1; - // self.AppendSegment(seg); - // }))//, (py::arg("self"), py::arg("point_index1"), py::arg("point_index2"), py::arg("point_index3"), py::arg("leftdomain") = 1, py::arg("rightdomain") = 0 ) ) + .def("AddCurve", + [] (SplineGeometry2d & self, py::object func, + int leftdomain, int rightdomain, py::object bc, double maxh) + { + int n = 1000; + Array> points; + for (int i = 0; i <= n; i++) + { + double t = double(i)/n; + py::tuple xy = func(t); + double x = py::cast(xy[0]); + double y = py::cast(xy[1]); + points.Append (Point<2>(x,y)); + } + auto spline = new DiscretePointsSeg<2> (points); + SplineSegExt * spex = new SplineSegExt (*spline); + + spex -> leftdom = leftdomain; + spex -> rightdom = rightdomain; + spex->hmax = maxh; + spex->reffak = 1; + spex->copyfrom = -1; + + if (py::extract(bc).check()) + spex->bc = py::extract(bc)(); + else if (py::extract(bc).check()) + { + string bcname = py::extract(bc)(); + spex->bc = self.GetNSplines()+1; + self.SetBCName(spex->bc, bcname); + } + else + spex->bc = self.GetNSplines()+1; + + + self.AppendSegment (spex); + }, py::arg("func"), py::arg("leftdomain") = 1, py::arg("rightdomain") = py::int_(0), + py::arg("bc")=NGDummyArgument(), py::arg("maxh")=1e99, + "Curve is given as parametrization on the interval [0,1]") + .def("SetMaterial", &SplineGeometry2d::SetMaterial) .def("SetDomainMaxH", &SplineGeometry2d::SetDomainMaxh) + .def("GetBCName", [](SplineGeometry2d& self, size_t index) { return self.GetBCName(index); }) + .def("GetNDomains", [](SplineGeometry2d& self) { return self.GetNDomains(); }) + .def("GetNSplines", [](SplineGeometry2d& self) { return self.splines.Size(); }) + .def("GetSpline", [](SplineGeometry2d& self, size_t index) + { return shared_ptr(&self.GetSpline(index), NOOP_Deleter); }, + py::return_value_policy::reference_internal) + .def("GetNPoints", [](SplineGeometry2d& self) { return self.GetNP(); }) + .def("GetPoint", [](SplineGeometry2d& self, size_t index) { return Point<2>(self.GetPoint(index)); }) - .def("PlotData", FunctionPointer([](SplineGeometry2d &self) { Box<2> box(self.GetBoundingBox()); @@ -200,6 +238,79 @@ return py::tuple(py::make_tuple(xlim, ylim, xpoints, ypoints)); })) + .def("_visualizationData", [](SplineGeometry2d &self) + { + Box<2> box(self.GetBoundingBox()); + double xdist = box.PMax()(0) - box.PMin()(0); + double ydist = box.PMax()(1) - box.PMin()(1); + py::dict data; + py::dict segment_data; + auto min_val = py::make_tuple(box.PMin()(0), box.PMin()(1),0); + auto max_val = py::make_tuple(box.PMax()(1),box.PMax()(1),0); + py::list vertices; + py::list domains; + py::list segment_points; + py::list segment_normals; + py::list leftdom; + py::list rightdom; + int max_bcnr = 0; + for(int i = 0; i < self.splines.Size(); i++) + { + std::vector> lst; + if (self.splines[i]->GetType().compare("line") == 0) + lst = { self.splines[i]->StartPI(), self.splines[i]->EndPI() }; + else if(self.splines[i]->GetType().compare("spline3") == 0) + { + double len = self.splines[i]->Length(); + int n = floor(len/(0.05*min(xdist,ydist))); + lst.push_back(self.splines[i]->StartPI()); + for (int j = 1; j < n; j++){ + lst.push_back(self.splines[i]->GetPoint(j*1./n)); + lst.push_back(self.splines[i]->GetPoint(j*1./n)); + } + lst.push_back(self.splines[i]->EndPI()); + } + else + { + throw NgException("Spline is neither line nor spline3"); + } + for (auto point : lst) + { + for(auto val : {point(0), point(1), 0.}) + vertices.append(val); + int bcnr = self.GetSpline(i).bc; + max_bcnr = max2(max_bcnr, bcnr); + domains.append(bcnr); + domains.append(self.GetSpline(i).leftdom); + domains.append(self.GetSpline(i).rightdom); + } + + // segment data + auto pnt = self.splines[i]->GetPoint(0.5); + segment_points.append(py::make_tuple(pnt(0),pnt(1))); + auto normal = self.GetSpline(i).GetTangent(0.5); + std::swap(normal(0),normal(1)); + normal(1) *= -1; + normal *= 1./sqrt(normal(0) * normal(0) + normal(1)*normal(1)); + segment_normals.append(py::make_tuple(normal(0),normal(1))); + leftdom.append(self.GetSpline(i).leftdom); + rightdom.append(self.GetSpline(i).rightdom); + } + py::list bcnames; + for (int i = 1; i & geompoints, - Array & splines, - double & elto0); -/// -extern void PartitionBoundary (const Array & splines, - double h, double elto0, - Mesh & mesh2d); - - -class CSGScanner; - -class SplineGeometry2d -{ - Array geompoints; - Array splines; - double elto0; - - -private: - void AppendSegment(SplineSegment * spline, const int leftdomain, const int rightdomain, - const int bc, - const double reffac, const bool hprefleft, const bool hprefright, - const int copyfrom); - -public: - ~SplineGeometry2d(); - - void Load (const char * filename); - void CSGLoad (CSGScanner & scan); - void PartitionBoundary (double h, Mesh & mesh2d); - - void CopyEdgeMesh (int from, int to, Mesh & mesh2d, Point3dTree & searchtree); - - const Array & GetSplines () const - { return splines; } - - int GetNSplines (void) const { return splines.Size(); } - string GetSplineType (const int i) const { return splines[i]->GetType(); } - SplineSegment & GetSpline (const int i) {return *splines[i];} - const SplineSegment & GetSpline (const int i) const {return *splines[i];} - - void GetBoundingBox (Box<2> & box) const; - - int GetNP () const { return geompoints.Size(); } - const GeomPoint2d & GetPoint(int i) const { return geompoints[i]; } - - void SetGrading (const double grading); - void AppendPoint (const double x, const double y, const double reffac = 1., const bool hpref = false); - - void AppendLineSegment (const int n1, const int n2, - const int leftdomain, const int rightdomain, const int bc = -1, - const double reffac = 1., - const bool hprefleft = false, const bool hprefright = false, - const int copyfrom = -1); - void AppendSplineSegment (const int n1, const int n2, const int n3, - const int leftdomain, const int rightdomain, const int bc = -1, - const double reffac = 1., - const bool hprefleft = false, const bool hprefright = false, - const int copyfrom = -1); - void AppendCircleSegment (const int n1, const int n2, const int n3, - const int leftdomain, const int rightdomain, const int bc = -1, - const double reffac = 1., - const bool hprefleft = false, const bool hprefright = false, - const int copyfrom = -1); - void AppendDiscretePointsSegment (const Array< Point<2> > & points, - const int leftdomain, const int rightdomain, const int bc = -1, - const double reffac = 1., - const bool hprefleft = false, const bool hprefright = false, - const int copyfrom = -1); - -}; - - -void MeshFromSpline2D (SplineGeometry2d & geometry, - shared_ptr & mesh, - MeshingParameters & mp); - -#endif - -#endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/adtree.cpp netgen-6.2.1905+dfsg1/libsrc/gprim/adtree.cpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/adtree.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/adtree.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -2400,13 +2400,13 @@ Array & pis) const { Point<2*dim> tpmin, tpmax; - + double tol = Tolerance(); for (size_t i = 0; i < dim; i++) { tpmin(i) = boxpmin(i); - tpmax(i) = pmax(i); + tpmax(i) = pmax(i)+tol; - tpmin(i+dim) = pmin(i); + tpmin(i+dim) = pmin(i)-tol; tpmax(i+dim) = boxpmax(i); } diff -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/adtree.hpp netgen-6.2.1905+dfsg1/libsrc/gprim/adtree.hpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/adtree.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/adtree.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -570,9 +570,9 @@ { tree->DeleteElement(pi); } void GetIntersecting (const Point & pmin, const Point & pmax, Array & pis) const; - - // const T_ADTree<2*dim> & Tree() const { return *tree; }; - // T_ADTree<2*dim> & Tree() { return *tree; }; + double Tolerance() const { return 1e-7 * Dist(boxpmax, boxpmin); } // single precision + const auto & Tree() const { return *tree; }; + auto & Tree() { return *tree; }; }; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/gprim/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/gprim/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -1,11 +1,11 @@ add_definitions(-DNGINTERFACE_EXPORTS) -add_library(gprim OBJECT - adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp - geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp +add_library(gprim INTERFACE) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources(gprim INTERFACE + ${sdir}/adtree.cpp ${sdir}/geom2d.cpp ${sdir}/geom3d.cpp ${sdir}/geomfuncs.cpp + ${sdir}/geomtest3d.cpp ${sdir}/transform3d.cpp ${sdir}/spline.cpp ${sdir}/splinegeometry.cpp ) -set_target_properties( gprim PROPERTIES POSITION_INDEPENDENT_CODE ON ) - install(FILES adtree.hpp geom2d.hpp geom3d.hpp geomfuncs.hpp geomobjects2.hpp geomobjects.hpp geomops2.hpp geomops.hpp geomtest3d.hpp gprim.hpp diff -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/geomobjects.hpp netgen-6.2.1905+dfsg1/libsrc/gprim/geomobjects.hpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/geomobjects.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/geomobjects.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -64,6 +64,12 @@ 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 @@ operator const T* () const { return x; } + void DoArchive(Archive& archive) + { + for(int i=0; i & p1, const Point & p2, const Point & p3) + : Box(p1,p2) + { + Add (p3); + } + enum EB_TYPE { EMPTY_BOX = 1 }; Box ( EB_TYPE et ) { @@ -252,7 +270,8 @@ for (int i = 0; i < D; i++) { if (p(i) < pmin(i)) pmin(i) = p(i); - else if (p(i) > pmax(i)) pmax(i) = p(i); + /* else */ if (p(i) > pmax(i)) pmax(i) = p(i); + // optimization invalid for empty-box ! } } @@ -318,6 +337,9 @@ pmax(i) += dist; } } + + void DoArchive(Archive& archive) + { archive & pmin & pmax; } }; diff -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/spline.cpp netgen-6.2.1905+dfsg1/libsrc/gprim/spline.cpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/spline.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/spline.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -99,7 +99,7 @@ } template - inline Point SplineSeg3 :: GetPoint (double t) const + Point SplineSeg3 :: GetPoint (double t) const { double b1, b2, b3; @@ -551,11 +551,10 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/splinegeometry.cpp netgen-6.2.1905+dfsg1/libsrc/gprim/splinegeometry.cpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/splinegeometry.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/splinegeometry.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -129,6 +129,8 @@ template class SplineGeometry<2>; template class SplineGeometry<3>; + static RegisterClassForArchive> regsp2; + static RegisterClassForArchive> regsp3; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/splinegeometry.hpp netgen-6.2.1905+dfsg1/libsrc/gprim/splinegeometry.hpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/splinegeometry.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/splinegeometry.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -34,6 +34,11 @@ 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 @@ // 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 -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/spline.hpp netgen-6.2.1905+dfsg1/libsrc/gprim/spline.hpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/spline.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/spline.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -28,13 +28,19 @@ 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 @@ 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 @@ /// 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 @@ 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 @@ 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 @@ 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 @@ /// 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 -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/transform3d.cpp netgen-6.2.1905+dfsg1/libsrc/gprim/transform3d.cpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/transform3d.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/transform3d.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -162,4 +162,40 @@ } return ost; } + + template <> + Transformation<3> :: Transformation (const Point<3> & c, const Vec<3> & axes, double angle) + { + Vec<3> vc(c); + Transformation<3> tc(vc); + Transformation<3> tcinv(-vc); + Transformation<3> r, ht, ht2; + + // r.SetAxisRotation (3, alpha); + Vec<3> naxes = axes; + naxes.Normalize(); + Vec<3> n1 = naxes.GetNormal(); + Vec<3> n2 = Cross(naxes, n1); + r.v = Vec<3>(0,0,0); + double co = cos(angle); + double si = sin(angle); + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) + r.m(i,j) = naxes(i)*naxes(j) + co*(n1(i)*n1(j)+n2(i)*n2(j)) + si*( (n2(i)*n1(j)-n2(j)*n1(i)) ); + + ht.Combine (tc, r); + Combine (ht, tcinv); + } + + + template + Transformation :: Transformation (const Point * pp) + { + v = Vec (pp[0]); + for (int i = 0; i < D; i++) + for (int j = 0; j < D; j++) + m(j,i) = pp[i+1](j)-pp[0](j); + } + + template class Transformation<3>; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/gprim/transform3d.hpp netgen-6.2.1905+dfsg1/libsrc/gprim/transform3d.hpp --- netgen-6.2.1804+dfsg1/libsrc/gprim/transform3d.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/gprim/transform3d.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -102,6 +102,8 @@ m(i,i) = 1; } + Transformation (const Point & c, const Vec<3> & axes, double angle); + // rotation with ... Transformation (const Point & c, double alpha, double beta, double gamma) { diff -Nru netgen-6.2.1804+dfsg1/libsrc/include/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/include/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/include/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/include/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -4,7 +4,7 @@ acisgeom.hpp csg.hpp geometry2d.hpp gprim.hpp incopengl.hpp inctcl.hpp incvis.hpp linalg.hpp meshing.hpp myadt.hpp mydefs.hpp mystdlib.h nginterface_v2_impl.hpp occgeom.hpp ngsimd.hpp - opti.hpp parallel.hpp parallelinterface.hpp stlgeom.hpp visual.hpp + opti.hpp parallel.hpp stlgeom.hpp visual.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/include COMPONENT netgen_devel ) diff -Nru netgen-6.2.1804+dfsg1/libsrc/include/nginterface.h netgen-6.2.1905+dfsg1/libsrc/include/nginterface.h --- netgen-6.2.1804+dfsg1/libsrc/include/nginterface.h 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/include/nginterface.h 2019-06-26 11:04:55.000000000 +0000 @@ -11,6 +11,8 @@ /* Date: 20. Nov. 99 */ /**************************************************************************/ +#include "../core/ngcore.hpp" + /* Application program interface to Netgen @@ -32,21 +34,25 @@ // max number of nodes per element -#define NG_ELEMENT_MAXPOINTS 12 +#define NG_ELEMENT_MAXPOINTS 20 // max number of nodes per surface element #define NG_SURFACE_ELEMENT_MAXPOINTS 8 +// #ifndef PARALLEL +// typedef int MPI_Comm; +// #endif +// namespace netgen { extern DLL_HEADER ngcore::NgMPI_Comm ng_comm; } // implemented element types: enum NG_ELEMENT_TYPE { NG_PNT = 0, NG_SEGM = 1, NG_SEGM3 = 2, - NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, + NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14, NG_TET = 20, NG_TET10 = 21, - NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, - NG_HEX = 25 + NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, NG_PRISM15 = 27, NG_PYRAMID13 = 28, + NG_HEX = 25, NG_HEX20 = 26 }; typedef double NG_POINT[3]; // coordinates @@ -60,9 +66,9 @@ // load geometry from file DLL_HEADER void Ng_LoadGeometry (const char * filename); - + // load netgen mesh - DLL_HEADER void Ng_LoadMesh (const char * filename); + DLL_HEADER void Ng_LoadMesh (const char * filename, ngcore::NgMPI_Comm comm = ngcore::NgMPI_Comm{}); // load netgen mesh DLL_HEADER void Ng_LoadMeshFromString (const char * mesh_as_string); @@ -312,7 +318,7 @@ struct Ng_SolutionData { - string name; // name of gridfunction + std::string name; // name of gridfunction double * data; // solution values int components; // relevant (double) components in solution vector int dist; // # doubles per entry alignment! @@ -333,7 +339,7 @@ // redraw DLL_HEADER void Ng_Redraw(bool blocking = false); /// - DLL_HEADER void Ng_TclCmd(string cmd); + DLL_HEADER void Ng_TclCmd(std::string cmd); /// DLL_HEADER void Ng_SetMouseEventHandler (netgen::MouseEventHandler * handler); /// @@ -385,11 +391,11 @@ DLL_HEADER void Ng_InitPointCurve(double red, double green, double blue); DLL_HEADER void Ng_AddPointCurvePoint(const double * point); - -#ifdef PARALLEL - void Ng_SetElementPartition ( int elnr, int part ); - int Ng_GetElementPartition ( int elnr ); -#endif + + // #ifdef PARALLEL + // void Ng_SetElementPartition ( int elnr, int part ); + // int Ng_GetElementPartition ( int elnr ); + // #endif DLL_HEADER void Ng_SaveMesh ( const char * meshfile ); DLL_HEADER void Ng_Bisect ( const char * refinementfile ); @@ -477,7 +483,6 @@ #include namespace netgen { - DLL_HEADER extern std::ostream * testout; DLL_HEADER extern int printmessage_importance; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/include/nginterface_v2.hpp netgen-6.2.1905+dfsg1/libsrc/include/nginterface_v2.hpp --- netgen-6.2.1804+dfsg1/libsrc/include/nginterface_v2.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/include/nginterface_v2.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -8,13 +8,38 @@ /* Date: May 09 */ /**************************************************************************/ +#include "../core/ngcore.hpp" + /* C++ interface to Netgen */ +#ifndef NGINTERFACE + // implemented element types: +enum NG_ELEMENT_TYPE { + NG_PNT = 0, + NG_SEGM = 1, NG_SEGM3 = 2, + NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14, + NG_TET = 20, NG_TET10 = 21, + NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, NG_PRISM15 = 27, NG_PYRAMID13 = 28, + NG_HEX = 25, NG_HEX20 = 26 +}; + +enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; +#endif + +// #ifndef PARALLEL +// typedef int MPI_Comm; +// #endif + + namespace netgen { - + using namespace std; + using namespace ngcore; + + // extern DLL_HEADER NgMPI_Comm ng_comm; + static constexpr int POINTINDEX_BASE = 1; struct T_EDGE2 @@ -30,6 +55,34 @@ int nr; // 0-based }; + template + class Ng_Buffer + { + size_t s; + T * data; + public: + Ng_Buffer (size_t as, T * adata) + : s(as), data(adata) { ; } + Ng_Buffer (Ng_Buffer && buffer) + : s(buffer.Size()), data(buffer.Release()) { ; } + ~Ng_Buffer () { delete [] data; } + size_t Size() const { return s; } + T * Release() { T * hd = data; data = nullptr; return hd; } + }; + + template + class Ng_BufferMS + { + size_t s; + T data[S]; + public: + Ng_BufferMS (size_t as) : s(as) { ; } + size_t Size() const { return s; } + T & operator[] (size_t i) { return data[i]; } + T operator[] (size_t i) const { return data[i]; } + }; + + class Ng_Element { @@ -170,6 +223,7 @@ int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; } }; + /* class Ng_Edges { public: @@ -179,11 +233,11 @@ size_t Size() const { return ned; } int operator[] (size_t i) const { return ptr[i]-1; } }; - + */ public: Ng_Vertices vertices; - Ng_Edges edges; + // Ng_Edges edges; int surface_el; // -1 if face not on surface }; @@ -209,17 +263,24 @@ public: // Ngx_Mesh () { ; } // Ngx_Mesh(class Mesh * amesh) : mesh(amesh) { ; } - Ngx_Mesh(shared_ptr amesh = NULL); - void LoadMesh (const string & filename); - void LoadMesh (istream & str); + /** reuse a netgen-mesh **/ + Ngx_Mesh (shared_ptr amesh); + /** load a new mesh **/ + Ngx_Mesh (string filename, NgMPI_Comm acomm = NgMPI_Comm{}); + + void LoadMesh (const string & filename, NgMPI_Comm comm = NgMPI_Comm{}); + + void LoadMesh (istream & str, NgMPI_Comm comm = NgMPI_Comm{}); void SaveMesh (ostream & str) const; void UpdateTopology (); - void DoArchive (ngstd::Archive & archive); + void DoArchive (Archive & archive); + NgMPI_Comm GetCommunicator() const; + virtual ~Ngx_Mesh(); - bool Valid () { return mesh != NULL; } + bool Valid () const { return mesh != NULL; } int GetDimension() const; int GetNLevels() const; @@ -267,7 +328,8 @@ template const Ng_Node GetNode (int nr) const; - + + Ng_BufferMS GetFaceEdges (int fnr) const; template int GetNNodes (); @@ -276,15 +338,24 @@ // 3D only // std::pair GetBoundaryNeighbouringDomains (int bnr); + template + void SetRefinementFlag (size_t elnr, bool flag); + void Curve (int order); + void Refine (NG_REFINEMENT_TYPE reftype, void (*taskmanager)(function) = &DummyTaskManager2, void (*tracer)(string, bool) = &DummyTracer2); + int GetHPElementLevel (int ei, int dir) const; + void GetParentNodes (int ni, int * parents) const; int GetParentElement (int ei) const; int GetParentSElement (int ei) const; + int GetNIdentifications() const; + int GetIdentificationType(int idnr) const; + Ng_Buffer GetPeriodicVertices(int idnr) const; // Find element of point, returns local coordinates template @@ -294,12 +365,33 @@ int * const indices = NULL, int numind = 0) const; -#ifdef PARALLEL + // for MPI-parallel std::tuple GetDistantProcs (int nodetype, int locnum) const; -#endif shared_ptr GetMesh () const { return mesh; } shared_ptr SelectMesh () const; + inline auto GetTimeStamp() const; + + + // also added from nginterface.h, still 1-based, need redesign + void HPRefinement (int levels, double parameter = 0.125, + bool setorders = true,bool ref_level = false); + size_t GetNP() const; + int GetSurfaceElementSurfaceNumber (size_t ei) const; + int GetSurfaceElementFDNumber (size_t ei) const; + + int GetElementOrder (int enr) const; + void GetElementOrders (int enr, int * ox, int * oy, int * oz) const; + void SetElementOrder (int enr, int order); + void SetElementOrders (int enr, int ox, int oy, int oz); + int GetSurfaceElementOrder (int enr) const; + void GetSurfaceElementOrders (int enr, int * ox, int * oy) const; + void SetSurfaceElementOrder (int enr, int order); + void SetSurfaceElementOrders (int enr, int ox, int oy); + int GetClusterRepVertex (int vi) const; + int GetClusterRepEdge (int edi) const; + int GetClusterRepFace (int fai) const; + int GetClusterRepElement (int eli) const; }; diff -Nru netgen-6.2.1804+dfsg1/libsrc/include/nginterface_v2_impl.hpp netgen-6.2.1905+dfsg1/libsrc/include/nginterface_v2_impl.hpp --- netgen-6.2.1804+dfsg1/libsrc/include/nginterface_v2_impl.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/include/nginterface_v2_impl.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -47,6 +47,7 @@ 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; @@ -63,6 +64,13 @@ ret.facets.num = 1; ret.facets.base = 1; ret.facets.ptr = (int*)&el.pnum; + + if (mesh->GetDimension() == 1) + ret.mat = mesh->GetBCNamePtr(el.index-1); + else if (mesh->GetDimension() == 2) + ret.mat = mesh->GetCD2NamePtr(el.index-1); + else + ret.mat = mesh->GetCD3NamePtr(el.index-1); return ret; } @@ -217,8 +225,7 @@ template <> NGX_INLINE DLL_HEADER const string & Ngx_Mesh :: GetMaterialCD<3> (int region_nr) const { - static string def("default"); - return def; + return mesh->GetCD3Name(region_nr); } @@ -296,3 +303,33 @@ return node; } + +NGX_INLINE DLL_HEADER Ng_Buffer Ngx_Mesh :: GetPeriodicVertices(int idnr) const +{ + Array apairs; + mesh->GetIdentifications().GetPairs (idnr+1, apairs); + for(auto& ind : apairs) + { + ind.I1()--; + ind.I2()--; + } + typedef int ti2[2]; + return { apairs.Size(), (ti2*)(void*)apairs.Release() }; +} + + +NGX_INLINE void Ngx_Mesh :: GetParentNodes (int ni, int * parents) const +{ + ni++; + if (ni <= mesh->mlbetweennodes.Size()) + { + parents[0] = mesh->mlbetweennodes.Get(ni).I1()-1; + parents[1] = mesh->mlbetweennodes.Get(ni).I2()-1; + } + else + parents[0] = parents[1] = -1; +} + + + +inline auto Ngx_Mesh :: GetTimeStamp() const { return mesh->GetTimeStamp(); } diff -Nru netgen-6.2.1804+dfsg1/libsrc/include/parallelinterface.hpp netgen-6.2.1905+dfsg1/libsrc/include/parallelinterface.hpp --- netgen-6.2.1804+dfsg1/libsrc/include/parallelinterface.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/include/parallelinterface.hpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,49 +0,0 @@ -gibt's nicht mehr - - -#ifndef FILE_PARALLELINTERFACE -#define FILE_PARALLELINTERFACE - -#ifdef PARALLEL - -#ifdef __cplusplus -extern "C" { -#endif - - // this interface is 0-base !! - - - int NgPar_GetLoc2Glob_VolEl ( int locnum ); - - // int NgPar_GetDistantNodeNums ( int nt, int locnum, int * procs, int * distnum); - - // number on distant processor - - // gibt anzahl an distant pnums zurueck - // * pnums entspricht ARRAY - int NgPar_GetDistantNodeNums ( int nodetype, int locnum, int * pnums ); - int NgPar_GetNDistantNodeNums ( int nodetype, int locnum ); - - int NgPar_GetDistantPNum ( int proc, int locnum ) ; - int NgPar_GetDistantEdgeNum ( int proc, int locnum ) ; - int NgPar_GetDistantFaceNum ( int proc, int locnum ) ; - int NgPar_GetDistantElNum ( int proc, int locnum ); - - bool NgPar_IsExchangeFace ( int fnr ) ; - bool NgPar_IsExchangeVert ( int vnum ); - bool NgPar_IsExchangeEdge ( int ednum ); - bool NgPar_IsExchangeElement ( int elnum ); - - void NgPar_PrintParallelMeshTopology (); - bool NgPar_IsElementInPartition ( int elnum, int dest ); - - bool NgPar_IsGhostFace ( int facenum ); - bool NgPar_IsGhostEdge ( int edgenum ); - -#ifdef __cplusplus -} -#endif - -#endif - -#endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/interface/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/interface/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/interface/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/interface/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -7,12 +7,10 @@ wuchemnitz.cpp writegmsh2.cpp writeOpenFOAM15x.cpp ) +target_link_libraries(interface mesh csg geom2d) +target_link_libraries(interface visual) if(NOT WIN32) - target_link_libraries(interface mesh csg geom2d) - if(USE_GUI) - target_link_libraries(interface visual) - endif(USE_GUI) - install( TARGETS interface ${NG_INSTALL_DIR}) + install( TARGETS interface ${NG_INSTALL_DIR}) endif(NOT WIN32) install(FILES diff -Nru netgen-6.2.1804+dfsg1/libsrc/interface/nginterface.cpp netgen-6.2.1905+dfsg1/libsrc/interface/nginterface.cpp --- netgen-6.2.1804+dfsg1/libsrc/interface/nginterface.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/interface/nginterface.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -2,7 +2,7 @@ #include #include - +#include #ifdef SOCKETS #include "../sockets/sockets.hpp" @@ -17,6 +17,9 @@ namespace netgen { DLL_HEADER MeshingParameters mparam; + + /** Force linking of geom2d library (for SplineGeometryRegister)**/ + SplineGeometry2d dummy_2dgeom; } static std::thread meshingthread; @@ -114,120 +117,147 @@ } - - -void Ng_LoadMesh (const char * filename) +void Ng_LoadMesh (const char * filename, ngcore::NgMPI_Comm comm) { + int id = comm.Rank(); + int ntasks = comm.Size(); + { - ifstream infile(filename); - if(!infile.good()) - throw NgException(string("Error opening file ") + filename); + ifstream infile(filename); + if(!infile.good()) + throw NgException(string("Error opening file ") + filename); } -#ifdef PARALLEL - MPI_Comm_size(MPI_COMM_WORLD, &ntasks); - MPI_Comm_rank(MPI_COMM_WORLD, &id); - if (id == 0) + if ( string(filename).find(".vol") == string::npos ) { -#endif - if ( string(filename).find(".vol") == string::npos ) - /* - if ( (strlen (filename) > 4) && - strcmp (filename + (strlen (filename)-4), ".vol") != 0 ) - */ - { - mesh.reset (new Mesh()); - ReadFile(*mesh,filename); - - //mesh->SetGlobalH (mparam.maxh); - //mesh->CalcLocalH(); - return; - } + if(ntasks>1) + throw NgException("Not sure what to do with this?? Does this work with MPI??"); + mesh.reset (new Mesh()); + mesh->SetCommunicator(comm); + ReadFile(*mesh,filename); + //mesh->SetGlobalH (mparam.maxh); + //mesh->CalcLocalH(); + return; + } - string fn(filename); + istream * infile; + Array buf; // for distributing geometry! + int strs; + + if( id == 0) { + + string fn(filename); + if (fn.substr (fn.length()-3, 3) == ".gz") + infile = new igzstream (filename); + else + infile = new ifstream (filename); + mesh.reset (new Mesh()); + mesh->SetCommunicator(comm); + mesh -> Load(*infile); + SetGlobalMesh (mesh); + + // make string from rest of file (for geometry info!) + // (this might be empty, in which case we take the global ng_geometry) + stringstream geom_part; + geom_part << infile->rdbuf(); + string geom_part_string = geom_part.str(); + strs = geom_part_string.size(); + // buf = new char[strs]; + buf.SetSize(strs); + memcpy(&buf[0], geom_part_string.c_str(), strs*sizeof(char)); - istream * infile; - if (fn.substr (fn.length()-3, 3) == ".gz") - infile = new igzstream (filename); - else - infile = new ifstream (filename); + delete infile; - Ng_LoadMeshFromStream(*infile); - delete infile; - -#ifdef PARALLEL - if (ntasks > 1) - { + if (ntasks > 1) + { - char * weightsfilename = new char [strlen(filename)+1]; - strcpy (weightsfilename, filename); - weightsfilename[strlen (weightsfilename)-3] = 'w'; - weightsfilename[strlen (weightsfilename)-2] = 'e'; - weightsfilename[strlen (weightsfilename)-1] = 'i'; + char * weightsfilename = new char [strlen(filename)+1]; + strcpy (weightsfilename, filename); + weightsfilename[strlen (weightsfilename)-3] = 'w'; + weightsfilename[strlen (weightsfilename)-2] = 'e'; + weightsfilename[strlen (weightsfilename)-1] = 'i'; - ifstream weightsfile(weightsfilename); - delete [] weightsfilename; + ifstream weightsfile(weightsfilename); + delete [] weightsfilename; - if (!(weightsfile.good())) - { - // cout << "regular distribute" << endl; - mesh -> Distribute(); - } - else - { - char str[20]; - bool endfile = false; - int n, dummy; + if (!(weightsfile.good())) + { + // cout << "regular distribute" << endl; + mesh -> Distribute(); + } + else + { + char str[20]; + bool endfile = false; + int n, dummy; - Array segment_weights; - Array surface_weights; - Array volume_weights; + Array segment_weights; + Array surface_weights; + Array volume_weights; - while (weightsfile.good() && !endfile) - { - weightsfile >> str; + while (weightsfile.good() && !endfile) + { + weightsfile >> str; - if (strcmp (str, "edgeweights") == 0) - { - weightsfile >> n; - segment_weights.SetSize(n); - for (int i = 0; i < n; i++) - weightsfile >> dummy >> segment_weights[i]; - } + if (strcmp (str, "edgeweights") == 0) + { + weightsfile >> n; + segment_weights.SetSize(n); + for (int i = 0; i < n; i++) + weightsfile >> dummy >> segment_weights[i]; + } - if (strcmp (str, "surfaceweights") == 0) - { - weightsfile >> n; - surface_weights.SetSize(n); - for (int i=0; i> dummy >> surface_weights[i]; - } + if (strcmp (str, "surfaceweights") == 0) + { + weightsfile >> n; + surface_weights.SetSize(n); + for (int i=0; i> dummy >> surface_weights[i]; + } - if (strcmp (str, "volumeweights") == 0) - { - weightsfile >> n; - volume_weights.SetSize(n); - for (int i=0; i> dummy >> volume_weights[i]; - } + if (strcmp (str, "volumeweights") == 0) + { + weightsfile >> n; + volume_weights.SetSize(n); + for (int i=0; i> dummy >> volume_weights[i]; + } - if (strcmp (str, "endfile") == 0) - endfile = true; - } + if (strcmp (str, "endfile") == 0) + endfile = true; + } - mesh -> Distribute(volume_weights, surface_weights, segment_weights); - } - } - } - else - { - mesh.reset (new Mesh()); -// vssolution.SetMesh(mesh); -// vsmesh.SetMesh(mesh); - SetGlobalMesh (mesh); - mesh->SendRecvMesh(); - } + mesh -> Distribute(volume_weights, surface_weights, segment_weights); + } + } // ntasks>1 end + } // id==0 end + else { + mesh.reset (new Mesh()); + mesh->SetCommunicator(comm); + SetGlobalMesh (mesh); + mesh->SendRecvMesh(); + } + + if(ntasks>1) { +#ifdef PARALLEL + /** Scatter the geometry-string (no dummy-implementation in mpi_interface) **/ + int strs = buf.Size(); + MyMPI_Bcast(strs, comm); + if(strs>0) + MyMPI_Bcast(buf, comm); #endif + } + + shared_ptr geo; + if(buf.Size()) { // if we had geom-info in the file, take it + istringstream geom_infile(string((const char*)&buf[0], buf.Size())); + geo = geometryregister.LoadFromMeshFile(geom_infile); + } + if(geo!=nullptr) { + ng_geometry = geo; + mesh->SetGeometry(geo); + } + else if(ng_geometry!=nullptr) mesh->SetGeometry(ng_geometry); } void Ng_LoadMeshFromString (const char * mesh_as_string) @@ -2033,7 +2063,7 @@ - +/* #ifdef PARALLEL void Ng_SetElementPartition ( const int elnr, const int part ) { @@ -2045,6 +2075,7 @@ return mesh->VolumeElement(elnr+1).GetPartition(); } #endif +*/ void Ng_InitPointCurve(double red, double green, double blue) diff -Nru netgen-6.2.1804+dfsg1/libsrc/interface/nginterface_v2.cpp netgen-6.2.1905+dfsg1/libsrc/interface/nginterface_v2.cpp --- netgen-6.2.1804+dfsg1/libsrc/interface/nginterface_v2.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/interface/nginterface_v2.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -31,47 +31,52 @@ return hmesh; } - - Ngx_Mesh :: Ngx_Mesh (shared_ptr amesh) - { - if (amesh) - mesh = amesh; - else - mesh = netgen::mesh; - } + Ngx_Mesh :: Ngx_Mesh (shared_ptr amesh) + { mesh = amesh ? amesh : netgen::mesh; } + Ngx_Mesh :: Ngx_Mesh (string filename, NgMPI_Comm acomm) + { LoadMesh(filename, acomm); } - Ngx_Mesh * LoadMesh (const string & filename) + Ngx_Mesh * LoadMesh (const string & filename, NgMPI_Comm comm) { netgen::mesh.reset(); - Ng_LoadMesh (filename.c_str()); + Ng_LoadMesh (filename.c_str(), comm); return new Ngx_Mesh (netgen::mesh); } - void Ngx_Mesh :: LoadMesh (const string & filename) + void Ngx_Mesh :: LoadMesh (const string & filename, NgMPI_Comm comm) { netgen::mesh.reset(); - Ng_LoadMesh (filename.c_str()); + Ng_LoadMesh (filename.c_str(), comm); // mesh = move(netgen::mesh); mesh = netgen::mesh; } - void Ngx_Mesh :: LoadMesh (istream & ist) + void Ngx_Mesh :: LoadMesh (istream & ist, NgMPI_Comm comm) { netgen::mesh = make_shared(); + netgen::mesh->SetCommunicator(comm); netgen::mesh -> Load (ist); // mesh = move(netgen::mesh); mesh = netgen::mesh; SetGlobalMesh (mesh); } + NgMPI_Comm Ngx_Mesh :: GetCommunicator() const + { return Valid() ? mesh->GetCommunicator() : NgMPI_Comm{}; } + void Ngx_Mesh :: SaveMesh (ostream & ost) const { mesh -> Save (ost); } - void Ngx_Mesh :: DoArchive (ngstd::Archive & archive) + void Ngx_Mesh :: DoArchive (Archive & archive) { - if (archive.Input()) mesh = make_shared(); +#ifdef PARALLEL + if (archive.Input()) { + mesh = make_shared(); + mesh->SetCommunicator(GetCommunicator()); + } +#endif mesh->DoArchive(archive); if (archive.Input()) { @@ -675,19 +680,37 @@ } - void Ngx_Mesh :: GetParentNodes (int ni, int * parents) const + int Ngx_Mesh :: GetHPElementLevel (int ei, int dir) const { - ni++; - if (ni <= mesh->mlbetweennodes.Size()) + ei++; + int level = -1; + + if (mesh->hpelements) { - parents[0] = mesh->mlbetweennodes.Get(ni).I1()-1; - parents[1] = mesh->mlbetweennodes.Get(ni).I2()-1; - } - else - parents[0] = parents[1] = -1; - } + int hpelnr = -1; + if (mesh->GetDimension() == 2) + hpelnr = mesh->SurfaceElement(ei).hp_elnr; + else + hpelnr = mesh->VolumeElement(ei).hp_elnr; + if (hpelnr < 0) + throw NgException("Ngx_Mesh::GetHPElementLevel: Wrong hp-element number!"); + + if (dir == 1) + level = (*mesh->hpelements)[hpelnr].levelx; + else if (dir == 2) + level = (*mesh->hpelements)[hpelnr].levely; + else if (dir == 3) + level = (*mesh->hpelements)[hpelnr].levelz; + else + throw NgException("Ngx_Mesh::GetHPElementLevel: dir has to be 1, 2 or 3!"); + } + //else + // throw NgException("Ngx_Mesh::GetHPElementLevel only for HPRefinement implemented!"); + return level; + } + int Ngx_Mesh :: GetParentElement (int ei) const { ei++; @@ -720,6 +743,26 @@ return -1; } + int Ngx_Mesh :: GetNIdentifications () const + { + return mesh->GetIdentifications().GetMaxNr(); + } + + int Ngx_Mesh :: GetIdentificationType(int idnr) const + { + return mesh->GetIdentifications().GetType(idnr+1); + } + + Ng_BufferMS Ngx_Mesh::GetFaceEdges (int fnr) const + { + const MeshTopology & topology = mesh->GetTopology(); + ArrayMem ia; + topology.GetFaceEdges (fnr+1, ia); + Ng_BufferMS res(ia.Size()); + for (size_t i = 0; i < ia.Size(); i++) + res[i] = ia[i]-1; + return res; + } @@ -964,22 +1007,59 @@ int * const indices, int numind) const { - if (mesh->GetDimension() != 1) - throw NgException("FindElementOfPoint<1> called for multidim mesh"); - - Point<3> p(hp[0], 0,0); - for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) + switch (mesh->GetDimension()) { - auto & seg = (*mesh)[si]; - Point<3> p1 = (*mesh)[seg[0]]; - Point<3> p2 = (*mesh)[seg[1]]; - double lam = (p(0)-p1(0)) / (p2(0)-p1(0)); - if (lam >= -1e-10 && lam <= 1+1e-10) - { - lami[0] = 1-lam; - return si; - } + case 1: + { + Point<3> p(hp[0], 0,0); + for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) + { + auto & seg = (*mesh)[si]; + Point<3> p1 = (*mesh)[seg[0]]; + Point<3> p2 = (*mesh)[seg[1]]; + double lam = (p(0)-p1(0)) / (p2(0)-p1(0)); + if (lam >= -1e-10 && lam <= 1+1e-10) + { + lami[0] = 1-lam; + return si; + } + } + } + break; + case 2: + { + Point<3> p(hp[0], hp[1],0); + for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) + { + auto & seg = (*mesh)[si]; + Point<3> p1 = (*mesh)[seg[0]]; + Point<3> p2 = (*mesh)[seg[1]]; + double lam; + double r; + if (fabs(p2[0]-p1[0]) >= fabs(p2[1]-p1[1])) + { + lam = (p[0]-p1[0])/(p2[0]-p1[0]); + r = p[1] - p1[1] - lam*(p2[1]-p1[1]); + } + else + { + lam = (p[1]-p1[1])/(p2[1]-p1[1]); + r = p[0] - p1[0] - lam*(p2[0]-p1[0]); + } + if ( lam >= -1e-10 && lam <= 1+1e-10 && fabs(r) <= 1e-10 ) + { + lami[0] = 1-lam; + return si; + } + } + } + break; + case 3: + default: + throw Exception("FindElementOfPoint<1> only implemented for mesh-dimension 1 and 2!"); + break; } + return -1; } @@ -1009,7 +1089,7 @@ if (ind > 0) { - if(mesh->SurfaceElement(ind).GetType()==QUAD) + if(mesh->SurfaceElement(ind).GetType()==QUAD || mesh->SurfaceElement(ind).GetType()==TRIG6) { lami[0] = lam3[0]; lami[1] = lam3[1]; @@ -1045,6 +1125,19 @@ NgLock meshlock (mesh->MajorMutex(), true); mesh->BuildCurvedElements(order); } + + + template <> + DLL_HEADER void Ngx_Mesh :: SetRefinementFlag<2> (size_t elnr, bool flag) + { + mesh->SurfaceElement(elnr+1).SetRefinementFlag(flag); + } + + template <> + DLL_HEADER void Ngx_Mesh :: SetRefinementFlag<3> (size_t elnr, bool flag) + { + mesh->VolumeElement(elnr+1).SetRefinementFlag(flag); + } void Ngx_Mesh :: Refine (NG_REFINEMENT_TYPE reftype, void (*task_manager)(function), @@ -1073,13 +1166,127 @@ } + + + + // just copied with redesign + + size_t Ngx_Mesh::GetNP() const + { + return mesh->GetNP(); + } + + int Ngx_Mesh::GetSurfaceElementSurfaceNumber (size_t ei) const + { + if (mesh->GetDimension() == 3) + return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).SurfNr(); + else + return mesh->LineSegment(ei).si; + } + int Ngx_Mesh::GetSurfaceElementFDNumber (size_t ei) const + { + if (mesh->GetDimension() == 3) + return mesh->SurfaceElement(ei).GetIndex(); + else + return -1; + } + + + void Ngx_Mesh::HPRefinement (int levels, double parameter, bool setorders, + bool ref_level) + { + NgLock meshlock (mesh->MajorMutex(), true); + Refinement & ref = const_cast (mesh->GetGeometry()->GetRefinement()); + ::netgen::HPRefinement (*mesh, &ref, levels, parameter, setorders, ref_level); + } + +int Ngx_Mesh::GetElementOrder (int enr) const +{ + if (mesh->GetDimension() == 3) + return mesh->VolumeElement(enr).GetOrder(); + else + return mesh->SurfaceElement(enr).GetOrder(); +} + +void Ngx_Mesh::GetElementOrders (int enr, int * ox, int * oy, int * oz) const +{ + if (mesh->GetDimension() == 3) + mesh->VolumeElement(enr).GetOrder(*ox, *oy, *oz); + else + mesh->SurfaceElement(enr).GetOrder(*ox, *oy, *oz); +} + +void Ngx_Mesh::SetElementOrder (int enr, int order) +{ + if (mesh->GetDimension() == 3) + return mesh->VolumeElement(enr).SetOrder(order); + else + return mesh->SurfaceElement(enr).SetOrder(order); +} + +void Ngx_Mesh::SetElementOrders (int enr, int ox, int oy, int oz) +{ + if (mesh->GetDimension() == 3) + mesh->VolumeElement(enr).SetOrder(ox, oy, oz); + else + mesh->SurfaceElement(enr).SetOrder(ox, oy); +} + + +int Ngx_Mesh::GetSurfaceElementOrder (int enr) const +{ + return mesh->SurfaceElement(enr).GetOrder(); +} + +int Ngx_Mesh::GetClusterRepVertex (int pi) const +{ + return mesh->GetClusters().GetVertexRepresentant(pi); +} + +int Ngx_Mesh::GetClusterRepEdge (int pi) const +{ + return mesh->GetClusters().GetEdgeRepresentant(pi); +} + +int Ngx_Mesh::GetClusterRepFace (int pi) const +{ + return mesh->GetClusters().GetFaceRepresentant(pi); +} + +int Ngx_Mesh::GetClusterRepElement (int pi) const +{ + return mesh->GetClusters().GetElementRepresentant(pi); +} + + + + +//HERBERT: falsche Anzahl von Argumenten +//void Ngx_Mesh::GetSurfaceElementOrders (int enr, int * ox, int * oy, int * oz) +void Ngx_Mesh::GetSurfaceElementOrders (int enr, int * ox, int * oy) const +{ + int d; + mesh->SurfaceElement(enr).GetOrder(*ox, *oy, d); +} + +void Ngx_Mesh::SetSurfaceElementOrder (int enr, int order) +{ + return mesh->SurfaceElement(enr).SetOrder(order); +} + +void Ngx_Mesh::SetSurfaceElementOrders (int enr, int ox, int oy) +{ + mesh->SurfaceElement(enr).SetOrder(ox, oy); +} + + + -#ifdef PARALLEL std::tuple Ngx_Mesh :: GetDistantProcs (int nodetype, int locnum) const { - +#ifdef PARALLEL switch (nodetype) { case 0: @@ -1100,10 +1307,10 @@ default: return std::tuple(0,nullptr); } - } - +#else + return std::tuple(0,nullptr); #endif - + } } diff -Nru netgen-6.2.1804+dfsg1/libsrc/interface/read_fnf_mesh.cpp netgen-6.2.1905+dfsg1/libsrc/interface/read_fnf_mesh.cpp --- netgen-6.2.1804+dfsg1/libsrc/interface/read_fnf_mesh.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/interface/read_fnf_mesh.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -94,7 +94,7 @@ char ch; string name; sbuf >> ch >> name; - cout << "Title: " << name << endl; + PrintMessage(3, "Title: ", name); } else if (token == "%STATISTICS") { @@ -106,7 +106,7 @@ } else { - cout << "SECTION HEADER, unknown field: " << buf << endl; + PrintMessage(1, "SECTION HEADER, unknown field: ",buf); } } } @@ -142,7 +142,7 @@ } else { - cout << "SECTION ELEM_TYPE, unknown field: " << buf << endl; + PrintMessage(1, "SECTION ELEM_TYPE, unknown field: ", buf); } } } @@ -169,7 +169,21 @@ } } - + else if (token == "ANALYSIS") + { + // ignore this section + while (1) + { + ReadLine (fin, buf); + stringstream sbuf(buf); + string token; + sbuf >> token; + if (token == "%END_SECT") + { + break; + } + } + } else if (token == "MATERIALS") { @@ -219,7 +233,7 @@ } else { - cout << "SECTION MATERIALS, unknown field: " << buf << endl; + PrintMessage(1, "SECTION MATERIALS, unknown field: ", buf); } } } @@ -271,7 +285,7 @@ } else { - cout << "SECTION MESH, unknown: " << buf << endl; + PrintMessage(1, "SECTION MESH, unknown: ", buf); } } } @@ -335,6 +349,8 @@ int fnr = fnums[j+1]; const Element & el = mesh.VolumeElement (elnr); + if(j == 0) + mesh.GetFaceDescriptor(nr).SetDomainIn(el.GetIndex()); Element2d el2d; el.GetFace (fnr, el2d); el2d.SetIndex (nr); @@ -349,7 +365,7 @@ } else { - cout << "SECTION MESH, unknown: " << buf << endl; + PrintMessage(1, "SECTION MESH, unknown: ", buf); } } } @@ -378,10 +394,10 @@ sbuf >> lt->id >> def >> ch >> lt->name >> lt->placement >> lt->valuetype; if (lt->name == "DISPLACEMENT") - cout << "loadtype DISPLACEMENT found" << endl; + PrintMessage(3, "loadtype DISPLACEMENT found"); if (lt->placement != "FACE" && lt->placement != "EDGE" && lt->placement != "NODE") - cout << "unsupported placement " << lt->placement << endl; + PrintMessage(1, "unsupported placement ", lt->placement); loadtypes.Append (lt); } @@ -406,33 +422,37 @@ if (load_type_id == loadtypes[i]->id) loadtypes[i]->places.Append (placement); } - } + } + else if (token == "%CON_CASE") + { ; } else if (token == "%END_SECT") { for (int i = 0; i < loadtypes.Size(); i++) { + stringstream str; + str << loadtypes[i]->places; if (loadtypes[i]->placement == "FACE" && loadtypes[i]->name == "DISPLACEMENT") { mesh.SetUserData ("CONSTRAINT_DISP_FACE", loadtypes[i]->places); - cout << "constrained faces: " << loadtypes[i]->places << endl; + PrintMessage(3, "constrained faces: ", str.str()); } if (loadtypes[i]->placement == "EDGE" && loadtypes[i]->name == "DISPLACEMENT") { mesh.SetUserData ("CONSTRAINT_DISP_EDGE", loadtypes[i]->places); - cout << "constrained edges: " << loadtypes[i]->places << endl; + PrintMessage(3,"constrained edges: ", str.str()); } if (loadtypes[i]->placement == "NODE" && loadtypes[i]->name == "DISPLACEMENT") { mesh.SetUserData ("CONSTRAINT_DISP_NODE", loadtypes[i]->places); - cout << "constrained nodes: " << loadtypes[i]->places << endl; + PrintMessage(3, "constrained nodes: ", str.str()); } } break; } else { - cout << "SECTION LOADS, unknown field: " << buf << endl; + PrintMessage(1, "SECTION LOADS, unknown field: ", buf); } } } @@ -441,11 +461,11 @@ else { - cout << "unknown section " << token << endl; + PrintMessage(1, "unknown section ", token); } } else - cout << "parse line: (" << buf << ")" << endl; + PrintMessage(3, "parse line: (", buf, ")"); } } } diff -Nru netgen-6.2.1804+dfsg1/libsrc/interface/readuser.cpp netgen-6.2.1905+dfsg1/libsrc/interface/readuser.cpp --- netgen-6.2.1804+dfsg1/libsrc/interface/readuser.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/interface/readuser.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -18,7 +18,7 @@ void ReadFile (Mesh & mesh, const string & hfilename) { - cout << "Read User File" << endl; + PrintMessage(3, "Read User File"); const char * filename = hfilename.c_str(); @@ -95,14 +95,18 @@ mesh.ClearFaceDescriptors(); mesh.AddFaceDescriptor (FaceDescriptor(0,1,0,0)); + mesh.GetFaceDescriptor(1).SetBCProperty (1); + // map from unv element nr to our element number + an index if it is vol (0), bnd(1), ... + std::map> element_map; - + Array tmp_segments; while (in.good()) { in >> reco; - cout << "reco = " << reco << endl; + if (strcmp(reco, "-1") == 0) + continue; - if (strcmp (reco, "2411") == 0) + else if (strcmp (reco, "2411") == 0) { cout << "nodes found" << endl; @@ -118,15 +122,12 @@ in >> hi >> hi >> hi; in >> p(0) >> p(1) >> p(2); - cout << "p(" << pi << ") = " - << p << endl; - mesh.AddPoint (p); } cout << "read " << mesh.GetNP() << " points" << endl; } - if (strcmp (reco, "2412") == 0) + else if (strcmp (reco, "2412") == 0) { cout << "elements found" << endl; @@ -140,8 +141,6 @@ if (label == -1) break; in >> fe_id >> phys_prop >> mat_prop >> color >> nnodes; - cout << "fe_id = " << fe_id << " col = " << color << ", nnodes = " << nnodes << endl; - if (fe_id >= 11 && fe_id <= 32) in >> hi >> hi >> hi; @@ -151,34 +150,167 @@ switch (fe_id) { - case 41: + case 22: // (Tapered beam) SEGM + { + Segment el; + el[0] = nodes[0]; + el[1] = nodes[2]; + el[2] = nodes[1]; + + auto nr = tmp_segments.Size(); + tmp_segments.Append(el); + element_map[label] = std::make_tuple(nr+1, 2); + break; + } + case 41: // TRIG { Element2d el (TRIG); el.SetIndex (1); for (int j = 0; j < nnodes; j++) el[j] = nodes[j]; - mesh.AddSurfaceElement (el); - + auto nr = mesh.AddSurfaceElement (el); + element_map[label] = std::make_tuple(nr+1, 1); break; } - case 111: + case 42: // TRIG6 + { + Element2d el(TRIG6); + el.SetIndex(1); + int jj = 0; + for(auto j : {0,2,4,3,5,1}) + el[jj++] = nodes[j]; + auto nr = mesh.AddSurfaceElement(el); + element_map[label] = std::make_tuple(nr+1, 1); + break; + } + case 111: // TET { Element el (TET); el.SetIndex (1); for (int j = 0; j < nnodes; j++) el[j] = nodes[j]; - mesh.AddVolumeElement (el); - + auto nr = mesh.AddVolumeElement (el); + element_map[label] = std::make_tuple(nr+1, 0); break; } + case 118: // TET10 + { + Element el(TET10); + el.SetIndex(1); + int jj = 0; + for(auto j : {0,2,4,9,1,5,6,3,7,8}) + el[jj++] = nodes[j]; + auto nr = mesh.AddVolumeElement(el); + element_map[label] = std::make_tuple(nr+1, 0); + break; + } + default: + cout << "Do not know fe_id = " << fe_id << ", skipping it." << endl; + break; } } + cout << mesh.GetNE() << " elements found" << endl; + cout << mesh.GetNSE() << " surface elements found" << endl; + } + else if(strcmp (reco, "2467") == 0) + { + int matnr = 1; + cout << "Groups found" << endl; + while(in.good()) + { + int len; + string name; + in >> len; + if(len == -1) + break; + for(int i=0; i < 7; i++) + in >> len; + in >> name; + cout << len << " element are in group " << name << endl; + int hi, index; + int fdnr, ednr; + + in >> hi >> index >> hi >> hi; + int codim = get<1>(element_map[index]); + // use first element to determine if boundary or volume + + switch (codim) + { + case 0: + { + mesh.SetMaterial(++matnr, name); + mesh.VolumeElement(get<0>(element_map[index])).SetIndex(matnr); + break; + } + case 1: + { + int bcpr = mesh.GetNFD()+1; + fdnr = mesh.AddFaceDescriptor(FaceDescriptor(bcpr, 0,0,0)); + mesh.GetFaceDescriptor(fdnr).SetBCProperty(bcpr+1); + mesh.SetBCName(bcpr, name); + mesh.SurfaceElement(get<0>(element_map[index])).SetIndex(fdnr); + break; + } + case 2: + { + int bcpr = mesh.GetNCD2Names()+1; + auto ed = EdgeDescriptor(); + ed.SetSurfNr(0,bcpr);//? + ednr = mesh.AddEdgeDescriptor(ed); + mesh.SetCD2Name(bcpr, name); + auto nr = mesh.AddSegment(tmp_segments[get<0>(element_map[index])-1]); + mesh[nr].SetBCName(mesh.GetCD2NamePtr(mesh.GetNCD2Names())); + mesh[nr].edgenr = ednr+1; + break; + } + default: + { + cout << "Codim " << codim << " not implemented yet!" << endl; + } + } + + for(int i=0; i> hi >> index >> hi >> hi; + switch (codim) + { + case 0: + mesh.VolumeElement(get<0>(element_map[index])).SetIndex(matnr); + break; + case 1: + mesh.SurfaceElement(get<0>(element_map[index])).SetIndex(fdnr); + break; + case 2: + { + auto nr = mesh.AddSegment(tmp_segments[get<0>(element_map[index])-1]); + mesh[nr].edgenr = ednr+1; + mesh[nr].SetBCName(mesh.GetCD2NamePtr(mesh.GetNCD2Names())); + } + break; + default: + break; + } + } + } + } + else + { + cout << "Do not know data field type " << reco << ", skipping it" << endl; + while(in.good()) + { + in >> reco; + if(strcmp(reco, "-1") == 0) + break; + } } } Point3d pmin, pmax; + mesh.ComputeNVertices(); + mesh.RebuildSurfaceElementLists(); mesh.GetBox (pmin, pmax); + mesh.UpdateTopology(); cout << "bounding-box = " << pmin << "-" << pmax << endl; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/linalg/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/linalg/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/linalg/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/linalg/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -1,8 +1,8 @@ -add_library( la OBJECT - densemat.cpp polynomial.cpp bfgs.cpp linopt.cpp linsearch.cpp - ) - -set_target_properties(la PROPERTIES POSITION_INDEPENDENT_CODE ON ) +add_library( la INTERFACE ) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources( la INTERFACE + ${sdir}/densemat.cpp ${sdir}/polynomial.cpp ${sdir}/bfgs.cpp ${sdir}/linopt.cpp ${sdir}/linsearch.cpp +) install(FILES densemat.hpp linalg.hpp opti.hpp diff -Nru netgen-6.2.1804+dfsg1/libsrc/linalg/vector.hpp netgen-6.2.1905+dfsg1/libsrc/linalg/vector.hpp --- netgen-6.2.1804+dfsg1/libsrc/linalg/vector.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/linalg/vector.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -139,6 +139,14 @@ ~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 -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/adfront2.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/adfront2.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/adfront2.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/adfront2.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -22,7 +22,7 @@ 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 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/adfront3.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/adfront3.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/adfront3.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/adfront3.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -233,6 +233,7 @@ /// const MiniElement2d & GetFace (int i) const { return faces.Get(i).Face(); } + const auto & Faces() const { return faces; } /// void Print () const; /// diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/basegeom.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/basegeom.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/basegeom.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/basegeom.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -10,6 +10,17 @@ GeometryRegister :: ~GeometryRegister() { ; } + + shared_ptr GeometryRegisterArray :: LoadFromMeshFile (istream & ist) const + { + for (int i = 0; i < Size(); i++) + { + NetgenGeometry * hgeom = (*this)[i]->LoadFromMeshFile (ist); + if (hgeom) + return shared_ptr(hgeom); + } + return nullptr; + } @@ -63,4 +74,5 @@ throw NgException("Cannot save geometry - no geometry available"); } + static RegisterClassForArchive regnggeo; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/basegeom.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/basegeom.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/basegeom.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/basegeom.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -22,6 +22,9 @@ 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 { ; } }; @@ -49,6 +52,8 @@ for (int i = 0; i < Size(); i++) delete (*this)[i]; } + + virtual shared_ptr LoadFromMeshFile (istream & ist) const; }; // extern DLL_HEADER Array geometryregister; diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/bisect.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/bisect.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/bisect.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/bisect.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -144,9 +144,9 @@ class MarkedIdentification { public: - // number of points of one face (3 or 4) + // number of points of one face (3 or 4) - or edge (in 2d) int np; - /// 6 or 8 point numbers + /// 6 or 8 point numbers - or 4 in 2d PointIndex pnums[8]; /// marked for refinement int marked; @@ -1403,6 +1403,16 @@ } newid1.np = newid2.np = oldid.np; + if(oldid.np == 2) + { + newid1.pnums[1] = newp[0]; + newid2.pnums[0] = newp[0]; + newid1.pnums[3] = newp[1]; + newid2.pnums[2] = newp[1]; + newid1.markededge = 0; + newid2.markededge = 0; + } + if(oldid.np == 3) { newid1.pnums[(oldid.markededge+1)%3] = newp[0]; @@ -2129,12 +2139,42 @@ BTDefineMarkedQuad (el, edgenumber, mq); mquads.Append (mq); } - - MarkedIdentification mi; - for(int j=0; j 0 && seg[1] > 0 && (*map)[seg[0]] && (*map)[seg[1]]) + { + MarkedIdentification mi; + mi.np = 2; + mi.pnums[0] = seg[0]; + mi.pnums[1] = seg[1]; + mi.pnums[2] = (*map)[seg[0]]; + mi.pnums[3] = (*map)[seg[1]]; + auto min1 = mi.pnums[0] < mi.pnums[1] ? mi.pnums[0] : mi.pnums[1]; + auto min2 = mi.pnums[2] < mi.pnums[3] ? mi.pnums[2] : mi.pnums[3]; + if (min1 > min2) + continue; + mi.marked = 0; + mi.markededge = 0; + mi.incorder = 0; + mids.Append(mi); + } + } + } + } } @@ -3358,6 +3398,7 @@ size_t nsel = mtris.Size(); NgProfiler::StartTimer (timer_bisecttrig); + (*opt.tracer)("Bisect trigs", false); for (size_t i = 0; i < nsel; i++) if (mtris[i].marked) { @@ -3400,7 +3441,7 @@ } NgProfiler::StopTimer (timer_bisecttrig); - + (*opt.tracer)("Bisect trigs", true); int nquad = mquads.Size(); for (int i = 1; i <= nquad; i++) @@ -3499,7 +3540,7 @@ MarkHangingTris (mtris, cutedges, opt.task_manager) + MarkHangingQuads (mquads, cutedges); - hangingedge = 0; + hangingedge = mesh.GetDimension() == 3 ? 0 : MarkHangingIdentifications(mids, cutedges); NgProfiler::StopTimer (timer1b); NgProfiler::StartTimer (timer_bisectsegms); int nseg = mesh.GetNSeg (); diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/bisect.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/bisect.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/bisect.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/bisect.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -72,7 +72,7 @@ virtual void ProjectToSurface (Point<3> & p, int surfi) const; - virtual void ProjectToSurface (Point<3> & p, int surfi, const PointGeomInfo & /* gi */) const + virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & /* gi */) const { ProjectToSurface (p, surfi); } diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/clusters.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/clusters.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/clusters.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/clusters.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -19,13 +19,16 @@ void AnisotropicClusters :: Update(TaskManager tm, Tracer tracer) { static int timer = NgProfiler::CreateTimer ("clusters"); - static int timer1 = NgProfiler::CreateTimer ("clusters1"); - static int timer2 = NgProfiler::CreateTimer ("clusters2"); - static int timer3 = NgProfiler::CreateTimer ("clusters3"); + // static int timer1 = NgProfiler::CreateTimer ("clusters1"); + // static int timer2 = NgProfiler::CreateTimer ("clusters2"); + // static int timer3 = NgProfiler::CreateTimer ("clusters3"); NgProfiler::RegionTimer reg (timer); const MeshTopology & top = mesh.GetTopology(); + auto id = this->mesh.GetCommunicator().Rank(); + auto ntasks = this->mesh.GetCommunicator().Size(); + bool hasedges = top.HasEdges(); bool hasfaces = top.HasFaces(); @@ -49,7 +52,7 @@ Array nnums, ednums, fanums; int changed; - NgProfiler::StartTimer(timer1); + // NgProfiler::StartTimer(timer1); /* @@ -109,8 +112,8 @@ } }); - NgProfiler::StopTimer(timer1); - NgProfiler::StartTimer(timer2); + // NgProfiler::StopTimer(timer1); + // NgProfiler::StartTimer(timer2); /* for (int i = 1; i <= nse; i++) { @@ -163,8 +166,8 @@ }); - NgProfiler::StopTimer(timer2); - NgProfiler::StartTimer(timer3); + // NgProfiler::StopTimer(timer2); + // NgProfiler::StartTimer(timer3); static const int hex_cluster[] = @@ -338,7 +341,7 @@ (*tracer) ("update cluster, identify", true); } while (changed); - NgProfiler::StopTimer(timer3); + // NgProfiler::StopTimer(timer3); /* (*testout) << "cluster reps:" << endl; for (i = 1; i <= cluster_reps.Size(); i++) diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/meshing/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/meshing/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -1,12 +1,4 @@ add_definitions(-DNGINTERFACE_EXPORTS) -if(NOT WIN32) - set(mesh_object_libs - $ - $ - $ - ) -endif(NOT WIN32) - add_library(mesh ${NG_LIB_TYPE} adfront2.cpp adfront3.cpp bisect.cpp boundarylayer.cpp clusters.cpp curvedelems.cpp delaunay.cpp delaunay2d.cpp @@ -29,9 +21,11 @@ set_target_properties( mesh PROPERTIES SUFFIX ".so") endif(APPLE) +target_link_libraries( mesh PUBLIC ngcore PRIVATE gprim la gen ) + +target_link_libraries( mesh PUBLIC ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) if(NOT WIN32) - target_link_libraries( mesh ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) - install( TARGETS mesh ${NG_INSTALL_DIR}) + install( TARGETS mesh ${NG_INSTALL_DIR}) endif(NOT WIN32) install(FILES diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/curvedelems.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/curvedelems.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/curvedelems.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/curvedelems.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -409,6 +409,15 @@ static Array> jacpols2; + void CurvedElements::buildJacPols() + { + if (!jacpols2.Size()) + { + jacpols2.SetSize (100); + for (int i = 0; i < 100; i++) + jacpols2[i] = make_shared (100, i, 2); + } + } // compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1 template @@ -540,27 +549,31 @@ CurvedElements :: ~CurvedElements() { - jacpols2.SetSize(0); } void CurvedElements :: BuildCurvedElements(const Refinement * ref, int aorder, bool arational) { - bool working = (ntasks == 1) || (id > 0); ishighorder = 0; order = 1; - + // MPI_Comm curve_comm; + const auto & curve_comm = mesh.GetCommunicator(); #ifdef PARALLEL enum { MPI_TAG_CURVE = MPI_TAG_MESH+20 }; const ParallelMeshTopology & partop = mesh.GetParallelTopology (); - MPI_Comm curve_comm; - MPI_Comm_dup (MPI_COMM_WORLD, &curve_comm); + // MPI_Comm_dup (mesh.GetCommunicator(), &curve_comm); Array procs; +#else + // curve_comm = mesh.GetCommunicator(); #endif + int id = curve_comm.Rank(); + int ntasks = curve_comm.Size(); + + bool working = (ntasks == 1) || (id > 0); if (working) order = aorder; @@ -652,8 +665,8 @@ } } - - MyMPI_ExchangeTable (send_orders, recv_orders, MPI_TAG_CURVE, curve_comm); + if (ntasks > 1) + MyMPI_ExchangeTable (send_orders, recv_orders, MPI_TAG_CURVE, curve_comm); if (ntasks > 1 && working) { @@ -714,17 +727,12 @@ ComputeGaussRule (aorder+4, xi, weight); // on (0,1) - if (!jacpols2.Size()) - { - jacpols2.SetSize (100); - for (int i = 0; i < 100; i++) - jacpols2[i] = make_shared (100, i, 2); - } - + buildJacPols(); PrintMessage (3, "Curving edges"); if (mesh.GetDimension() == 3 || rational) { + static Timer tce("curve edges"); RegionTimer reg(tce); Array surfnr(nedges); Array gi0(nedges); Array gi1(nedges); @@ -1182,7 +1190,8 @@ } } - MyMPI_ExchangeTable (send_surfnr, recv_surfnr, MPI_TAG_CURVE, curve_comm); + if (ntasks > 1) + MyMPI_ExchangeTable (send_surfnr, recv_surfnr, MPI_TAG_CURVE, curve_comm); if (ntasks > 1 && working) { @@ -1198,7 +1207,8 @@ #endif if (mesh.GetDimension() == 3 && working) - { + { + static Timer tcf("curve faces"); RegionTimer reg(tcf); for (int f = 0; f < nfaces; f++) { int facenr = f; @@ -1285,7 +1295,10 @@ Point<3> pp = xa[jj]; // ref -> ProjectToSurface (pp, mesh.GetFaceDescriptor(el.GetIndex()).SurfNr()); - ref -> ProjectToSurface (pp, surfnr[facenr]); + SurfaceElementIndex sei = top.GetFace2SurfaceElement (f+1)-1; + PointGeomInfo gi = mesh[sei].GeomInfoPi(1); + + ref -> ProjectToSurface (pp, surfnr[facenr], gi); Vec<3> dist = pp-xa[jj]; CalcTrigShape (order1, lami[fnums[1]]-lami[fnums[0]], @@ -1365,8 +1378,8 @@ #ifdef PARALLEL - MPI_Barrier (curve_comm); - MPI_Comm_free (&curve_comm); + curve_comm.Barrier(); + // MPI_Comm_free (&curve_comm); #endif } @@ -1708,6 +1721,7 @@ case TRIG : info.nv = 3; break; case QUAD : info.nv = 4; break; case TRIG6: info.nv = 6; break; + case QUAD8 : info.nv = 8; break; default: cerr << "undef element in CalcSurfaceTrafo" << endl; } @@ -1752,6 +1766,18 @@ } } + + 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]); @@ -1915,6 +1941,24 @@ break; } + + case QUAD8: + { + auto x = xi(0), y = xi(1); + shapes(0) = (1-x)*(1-y); + shapes(1) = x*(1-y); + shapes(2) = x*y; + shapes(3) = (1-x)*y; + shapes(4) = 4*(1-x)*x*(1-y); + shapes(5) = 4*(1-x)*x*y; + shapes(6) = 4*(1-y)*y*(1-x); + shapes(7) = 4*(1-y)*y*x; + shapes(0) -= 0.5*(shapes(4)+shapes(6)); + shapes(1) -= 0.5*(shapes(4)+shapes(7)); + shapes(2) -= 0.5*(shapes(5)+shapes(7)); + shapes(3) -= 0.5*(shapes(5)+shapes(6)); + break; + } default: throw NgException("CurvedElements::CalcShape 2d, element type not handled"); @@ -2202,6 +2246,20 @@ switch (el.GetType()) { + case TRIG6: + { + AutoDiff<2,T> lam3 = 1-x-y; + AutoDiff<2,T> lami[6] = { x * (2*x-1), y * (2*y-1), lam3 * (2*lam3-1), + 4 * y * lam3, 4 * x * lam3, 4 * x * y }; + for (int j = 0; j < 6; j++) + { + Point<3> p = mesh[el[j]]; + for (int k = 0; k < DIM_SPACE; k++) + mapped_x[k] += p(k) * lami[j]; + } + break; + } + case TRIG: { // if (info.order >= 2) return false; // not yet supported @@ -2254,6 +2312,45 @@ } 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; + } + case QUAD8: + { + // AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; + AutoDiff<2,T> lami[8] = + { (1-x)*(1-y), + x*(1-y), + x*y, + (1-x)*y, + 4*(1-x)*x*(1-y), + 4*(1-x)*x*y, + 4*(1-y)*y*(1-x), + 4*(1-y)*y*x }; + + lami[0] -= 0.5*(lami[4]+lami[6]); + lami[1] -= 0.5*(lami[4]+lami[7]); + lami[2] -= 0.5*(lami[5]+lami[7]); + lami[3] -= 0.5*(lami[5]+lami[6]); + + for (int j = 0; j < 8; 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; } @@ -2716,6 +2813,32 @@ break; } + case PRISM15: + { + shapes = 0.0; + T x = xi(0); + T y = xi(1); + T z = xi(2); + T lam = 1-x-y; + T lamz = 1-z; + shapes[0] = (2*x*x-x) * (2*lamz*lamz-lamz); + shapes[1] = (2*y*y-y) * (2*lamz*lamz-lamz); + shapes[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); + shapes[3] = (2*x*x-x) * (2*z*z-z); + shapes[4] = (2*y*y-y) * (2*z*z-z); + shapes[5] = (2*lam*lam-lam) * (2*z*z-z); + shapes[6] = 4 * x * y * (2*lamz*lamz-lamz); + shapes[7] = 4 * x * lam * (2*lamz*lamz-lamz); + shapes[8] = 4 * y * lam * (2*lamz*lamz-lamz); + shapes[9] = x * 4 * z * (1-z); + shapes[10] = y * 4 * z * (1-z); + shapes[11] = lam * 4 * z * (1-z); + shapes[12] = 4 * x * y * (2*z*z-z); + shapes[13] = 4 * x * lam * (2*z*z-z); + shapes[14] = 4 * y * lam * (2*z*z-z); + break; + } + case PYRAMID: { shapes = 0.0; @@ -2765,6 +2888,29 @@ break; } + case PYRAMID13: + { + shapes = 0.0; + T x = xi(0); + T y = xi(1); + T z = xi(2); + z *= 1-1e-12; + shapes[0] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (-2*x - z + 2)*(-2*y - z + 2))*(-0.5*x - 0.5*y - 0.5*z + 0.25); + shapes[1] = (0.5*x - 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(-2*y - z + 2)); + shapes[2] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(2*y + z))*(0.5*x + 0.5*y + 0.5*z - 0.75); + shapes[3] = (-0.5*x + 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*y + z)*(-2*x - z + 2)); + shapes[4] = z*(2*z - 1); + shapes[5] = 2*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + shapes[6] = 4*x*y*(-2*x - 2*z + 2)/(-2*z + 2); + shapes[7] = 2*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + shapes[8] = 4*x*y*(-2*y - 2*z + 2)/(-2*z + 2); + shapes[9] = z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); + shapes[10] = 2*x*z*(-2*y - 2*z + 2)/(-z + 1); + shapes[11] = 4*x*y*z/(-z + 1); + shapes[12] = 2*y*z*(-2*x - 2*z + 2)/(-z + 1); + break; + } + case HEX: { shapes = 0.0; @@ -2815,6 +2961,46 @@ break; + } + + case HEX20: + { + shapes = 0.0; + T x = xi(0); + T y = xi(1); + T z = xi(2); + + shapes[0] = (1-x)*(1-y)*(1-z); + shapes[1] = x *(1-y)*(1-z); + shapes[2] = x * y *(1-z); + shapes[3] = (1-x)* y *(1-z); + shapes[4] = (1-x)*(1-y)*(z); + shapes[5] = x *(1-y)*(z); + shapes[6] = x * y *(z); + shapes[7] = (1-x)* y *(z); + + T sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), + (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; + + static const int e[12][2] = + { + { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, + { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, + { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, + }; + + for (int i = 0; i < 12; i++) + { + T lame = shapes[e[i][0]]+shapes[e[i][1]]; + T xi = sigma[e[i][1]]-sigma[e[i][0]]; + shapes[8+i] = (1-xi*xi)*lame; + } + for (int i = 0; i < 12; i++) + { + shapes[e[i][0]] -= 0.5 * shapes[8+i]; + shapes[e[i][1]] -= 0.5 * shapes[8+i]; + } + break; } default: @@ -3186,6 +3372,36 @@ } + case PRISM15: + { + AutoDiff<3,T> x(xi(0), 0); + AutoDiff<3,T> y(xi(1), 1); + AutoDiff<3,T> z(xi(2), 2); + AutoDiff<3,T> ad[15]; + AutoDiff<3,T> lam = 1-x-y; + AutoDiff<3,T> lamz = 1-z; + + ad[0] = (2*x*x-x) * (2*lamz*lamz-lamz); + ad[1] = (2*y*y-y) * (2*lamz*lamz-lamz); + ad[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); + ad[3] = (2*x*x-x) * (2*z*z-z); + ad[4] = (2*y*y-y) * (2*z*z-z); + ad[5] = (2*lam*lam-lam) * (2*z*z-z); + ad[6] = 4 * x * y * (2*lamz*lamz-lamz); + ad[7] = 4 * x * lam * (2*lamz*lamz-lamz); + ad[8] = 4 * y * lam * (2*lamz*lamz-lamz); + ad[9] = x * 4 * z * (1-z); + ad[10] = y * 4 * z * (1-z); + ad[11] = lam * 4 * z * (1-z); + ad[12] = 4 * x * y * (2*z*z-z); + ad[13] = 4 * x * lam * (2*z*z-z); + ad[14] = 4 * y * lam * (2*z*z-z); + + for(int i=0; i<15; i++) + for(int j=0; j<3; j++) + dshapes(i,j) = ad[i].DValue(j); + break; + } case PYRAMID: { // if (typeid(T) == typeid(SIMD)) return; @@ -3283,6 +3499,54 @@ break; } + case PYRAMID13: + { + T x = xi(0); + T y = xi(1); + T z = xi(2); + z *= 1-1e-12; + dshapes(0,0) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(4*y + 2*z + 2*z*(2*y + z - 1)/(-z + 1) - 4); + dshapes(0,1) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(4*x + 2*z + 2*z*(2*x + z - 1)/(-z + 1) - 4); + dshapes(0,2) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(2*x + 2*y + 2*z + z*(2*x + z - 1)/(-z + 1) + z*(2*y + z - 1)/(-z + 1) + z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) - 5 + (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); + dshapes(1,0) = -0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(-2*y - z + 2) + (0.5*x - 0.5*y - 0.25)*(-4*y - 2*z - 2*z*(2*y + z - 1)/(-z + 1) + 4); + dshapes(1,1) = 0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(2*x + z)*(-2*y - z + 2) + (-4*x - 2*z - 2*z*(2*x + z - 1)/(-z + 1))*(0.5*x - 0.5*y - 0.25); + dshapes(1,2) = (0.5*x - 0.5*y - 0.25)*(-2*x - 2*y - 2*z - z*(2*x + z - 1)/(-z + 1) - z*(2*y + z - 1)/(-z + 1) - z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) + 1 - (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); + dshapes(2,0) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (4*y + 2*z + 2*z*(2*y + z - 1)/(-z + 1))*(0.5*x + 0.5*y + 0.5*z - 0.75); + dshapes(2,1) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (4*x + 2*z + 2*z*(2*x + z - 1)/(-z + 1))*(0.5*x + 0.5*y + 0.5*z - 0.75); + dshapes(2,2) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (0.5*x + 0.5*y + 0.5*z - 0.75)*(2*x + 2*y + 2*z + z*(2*x + z - 1)/(-z + 1) + z*(2*y + z - 1)/(-z + 1) + z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) - 1 + (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); + dshapes(3,0) = 0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(2*y + z)*(-2*x - z + 2) + (-0.5*x + 0.5*y - 0.25)*(-4*y - 2*z - 2*z*(2*y + z - 1)/(-z + 1)); + dshapes(3,1) = -0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*y + z)*(-2*x - z + 2) + (-0.5*x + 0.5*y - 0.25)*(-4*x - 2*z - 2*z*(2*x + z - 1)/(-z + 1) + 4); + dshapes(3,2) = (-0.5*x + 0.5*y - 0.25)*(-2*x - 2*y - 2*z - z*(2*x + z - 1)/(-z + 1) - z*(2*y + z - 1)/(-z + 1) - z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) + 1 - (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); + dshapes(4,0) = 0; + dshapes(4,1) = 0; + dshapes(4,2) = 4*z - 1; + dshapes(5,0) = -4*x*(-2*y - 2*z + 2)/(-2*z + 2) + 2*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(5,1) = -4*x*(-2*x - 2*z + 2)/(-2*z + 2); + dshapes(5,2) = -4*x*(-2*x - 2*z + 2)/(-2*z + 2) - 4*x*(-2*y - 2*z + 2)/(-2*z + 2) + 4*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); + dshapes(6,0) = -8*x*y/(-2*z + 2) + 4*y*(-2*x - 2*z + 2)/(-2*z + 2); + dshapes(6,1) = 4*x*(-2*x - 2*z + 2)/(-2*z + 2); + dshapes(6,2) = -8*x*y/(-2*z + 2) + 8*x*y*(-2*x - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); + dshapes(7,0) = -4*y*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(7,1) = -4*y*(-2*x - 2*z + 2)/(-2*z + 2) + 2*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(7,2) = -4*y*(-2*x - 2*z + 2)/(-2*z + 2) - 4*y*(-2*y - 2*z + 2)/(-2*z + 2) + 4*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); + dshapes(8,0) = 4*y*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(8,1) = -8*x*y/(-2*z + 2) + 4*x*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(8,2) = -8*x*y/(-2*z + 2) + 8*x*y*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); + dshapes(9,0) = -2*z*(-2*y - 2*z + 2)/(-z + 1); + dshapes(9,1) = -2*z*(-2*x - 2*z + 2)/(-z + 1); + dshapes(9,2) = -2*z*(-2*x - 2*z + 2)/(-z + 1) - 2*z*(-2*y - 2*z + 2)/(-z + 1) + z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-z + 1)*(-z + 1)) + (-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); + dshapes(10,0) = 2*z*(-2*y - 2*z + 2)/(-z + 1); + dshapes(10,1) = -4*x*z/(-z + 1); + dshapes(10,2) = -4*x*z/(-z + 1) + 2*x*z*(-2*y - 2*z + 2)/((-z + 1)*(-z + 1)) + 2*x*(-2*y - 2*z + 2)/(-z + 1); + dshapes(11,0) = 4*y*z/(-z + 1); + dshapes(11,1) = 4*x*z/(-z + 1); + dshapes(11,2) = 4*x*y*z/((-z + 1)*(-z + 1)) + 4*x*y/(-z + 1); + dshapes(12,0) = -4*y*z/(-z + 1); + dshapes(12,1) = 2*z*(-2*x - 2*z + 2)/(-z + 1); + dshapes(12,2) = -4*y*z/(-z + 1) + 2*y*z*(-2*x - 2*z + 2)/((-z + 1)*(-z + 1)) + 2*y*(-2*x - 2*z + 2)/(-z + 1); + break; + } + case HEX: { // if (typeid(T) == typeid(SIMD)) return; @@ -3419,12 +3683,49 @@ *testout << "quad, num dshape = " << endl << dshapes << endl; */ break; - - - - break; } - + case HEX20: + { + AutoDiff<3,T> x(xi(0), 0); + AutoDiff<3,T> y(xi(1), 1); + AutoDiff<3,T> z(xi(2), 2); + AutoDiff<3,T> ad[20]; + + ad[0] = (1-x)*(1-y)*(1-z); + ad[1] = x *(1-y)*(1-z); + ad[2] = x * y *(1-z); + ad[3] = (1-x)* y *(1-z); + ad[4] = (1-x)*(1-y)*(z); + ad[5] = x *(1-y)*(z); + ad[6] = x * y *(z); + ad[7] = (1-x)* y *(z); + + AutoDiff<3,T> sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), + (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; + + static const int e[12][2] = + { + { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, + { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, + { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, + }; + + for (int i = 0; i < 12; i++) + { + auto lame = ad[e[i][0]]+ad[e[i][1]]; + auto xi = sigma[e[i][1]]-sigma[e[i][0]]; + ad[8+i] = (1-xi*xi)*lame; + } + for (int i = 0; i < 12; i++) + { + ad[e[i][0]] -= 0.5 * ad[8+i]; + ad[e[i][1]] -= 0.5 * ad[8+i]; + } + for (int i = 0; i < 20; i++) + for (int j = 0; j < 3; j++) + dshapes(i,j) = ad[i].DValue(j); + break; + } default: throw NgException("CurvedElements::CalcDShape 3d, element type not handled"); } @@ -3830,8 +4131,9 @@ case TRIG : info.nv = 3; break; case QUAD : info.nv = 4; break; case TRIG6: info.nv = 6; break; + case QUAD8 : info.nv = 8; break; default: - cerr << "undef element in CalcMultPointSurfaceTrao" << endl; + cerr << "undef element in CalcMultPointSurfaceTrafo" << endl; } info.ndof = info.nv; diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/curvedelems.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/curvedelems.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/curvedelems.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/curvedelems.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -33,6 +33,7 @@ bool rational; bool ishighorder; + void buildJacPols(); public: DLL_HEADER CurvedElements (const Mesh & amesh); @@ -48,6 +49,13 @@ int GetOrder () { return order; } + virtual void DoArchive(Archive& ar) + { + if(ar.Input()) + buildJacPols(); + ar & edgeorder & faceorder & edgecoeffsindex & facecoeffsindex & edgecoeffs & facecoeffs + & edgeweight & order & rational & ishighorder; + } bool IsSegmentCurved (SegmentIndex segnr) const; bool IsSurfaceElementCurved (SurfaceElementIndex sei) const; diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/delaunay.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/delaunay.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/delaunay.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/delaunay.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -6,7 +6,6 @@ namespace netgen { - static const int deltetfaces[][3] = { { 1, 2, 3 }, { 2, 0, 3 }, @@ -14,10 +13,6 @@ { 1, 0, 2 } }; - - - - class DelaunayTet { PointIndex pnums[4]; @@ -41,9 +36,6 @@ PointIndex & operator[] (int i) { return pnums[i]; } PointIndex operator[] (int i) const { return pnums[i]; } - int & NB1(int i) { return nb[i-1]; } - int NB1(int i) const { return nb[i-1]; } - int & NB(int i) { return nb[i]; } int NB(int i) const { return nb[i]; } @@ -57,27 +49,6 @@ return i; return 3; } - - void GetFace1 (int i, INDEX_3 & face) const - { - face.I(1) = pnums[deltetfaces[i-1][0]]; - face.I(2) = pnums[deltetfaces[i-1][1]]; - face.I(3) = pnums[deltetfaces[i-1][2]]; - } - - void GetFace (int i, INDEX_3 & face) const - { - face.I(1) = pnums[deltetfaces[i][0]]; - face.I(2) = pnums[deltetfaces[i][1]]; - face.I(3) = pnums[deltetfaces[i][2]]; - } - - INDEX_3 GetFace1 (int i) const - { - return INDEX_3 (pnums[deltetfaces[i-1][0]], - pnums[deltetfaces[i-1][1]], - pnums[deltetfaces[i-1][2]]); - } INDEX_3 GetFace (int i) const { @@ -85,13 +56,13 @@ pnums[deltetfaces[i][1]], pnums[deltetfaces[i][2]]); } - - void GetFace1 (int i, Element2d & face) const + + void GetFace (int i, Element2d & face) const { // face.SetType(TRIG); - face[0] = pnums[deltetfaces[i-1][0]]; - face[1] = pnums[deltetfaces[i-1][1]]; - face[2] = pnums[deltetfaces[i-1][2]]; + face[0] = pnums[deltetfaces[i][0]]; + face[1] = pnums[deltetfaces[i][1]]; + face[2] = pnums[deltetfaces[i][2]]; } }; @@ -101,8 +72,6 @@ - - /* Table to maintain neighbour elements */ @@ -135,7 +104,7 @@ // get neighbour of element elnr in direction fnr int GetNB (int elnr, int fnr) { - return tets.Get(elnr).NB1(fnr); + return tets.Get(elnr).NB(fnr); } // @@ -181,7 +150,6 @@ - /* connected lists of cosphereical elements */ @@ -253,24 +221,23 @@ Array & freelist, SphereList & list, IndexSet & insphere, IndexSet & closesphere) { + // static Timer t("Meshing3::AddDelaunayPoint"); RegionTimer reg(t); /* find any sphere, such that newp is contained in */ - DelaunayTet el; int cfelind = -1; const Point<3> * pp[4]; Point<3> pc; - double r2; Point3d tpmin, tpmax; tettree.GetIntersecting (newp, newp, treesearch); + double quot,minquot(1e20); - for (int j = 0; j < treesearch.Size(); j++) + for (auto jjj : treesearch) { - int jjj = treesearch[j]; quot = Dist2 (centers.Get(jjj), newp) / radi2.Get(jjj); if((cfelind == -1 || quot < 0.99*minquot) && quot < 1) @@ -284,46 +251,12 @@ } - /* - int i, j, k, l; - if (!felind) - { - cerr << "not in any sphere, 1" << endl; - // old, non tree search - - double mindist = 1e10; - for (j = 1; j <= tempels.Size(); j++) - { - if (tempels.Get(j).PNum(1)) - { - double toofar = - Dist2 (centers.Get(j), newp) - radi2.Get(j); - if (toofar < mindist || toofar < 1e-7) - { - mindist = toofar; - cout << " dist2 = " << Dist2 (centers.Get(j), newp) - << " radi2 = " << radi2.Get(j) << endl; - } - if (toofar < 0) - { - el = tempels.Get(j); - felind = j; - cout << "sphere found !" << endl; - break; - } - } - } - cout << "point is too far from sheres: " << mindist << endl; - } - */ - if (cfelind == -1) { PrintWarning ("Delaunay, point not in any sphere"); return; } - /* insphere: point is in sphere -> delete element closesphere: point is close to sphere -> considered for same center @@ -376,7 +309,7 @@ // check neighbour-tets for (int j = starti; j < nstarti; j++) - for (int k = 1; k <= 4; k++) + for (int k = 0; k < 4; k++) { int helind = insphere.GetArray().Get(j); int nbind = meshnb.GetNB (helind, k); @@ -404,61 +337,48 @@ } else { - /* - Element2d face; - tempels.Get(helind).GetFace (k, face); + INDEX_3 i3 = tempels.Get(helind).GetFace (k); - const Point3d & p1 = mesh.Point (face.PNum(1)); - const Point3d & p2 = mesh.Point (face[1]); - const Point3d & p3 = mesh.Point (face[2]); - */ - - INDEX_3 i3 = tempels.Get(helind).GetFace (k-1); - - const Point3d & p1 = mesh.Point ( PointIndex (i3.I1()) ); - const Point3d & p2 = mesh.Point ( PointIndex (i3.I2()) ); - const Point3d & p3 = mesh.Point ( PointIndex (i3.I3()) ); - - - Vec3d v1(p1, p2); - Vec3d v2(p1, p3); - Vec3d n = Cross (v1, v2); + const Point<3> & p1 = mesh.Point ( PointIndex (i3.I1()) ); + const Point<3> & p2 = mesh.Point ( PointIndex (i3.I2()) ); + const Point<3> & p3 = mesh.Point ( PointIndex (i3.I3()) ); + + Vec<3> v1 = p2-p1; + Vec<3> v2 = p3-p1; + Vec<3> n = Cross (v1, v2); n /= n.Length(); - if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k-1])) > 0) + if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k])) > 0) n *= -1; double dist = n * Vec3d (p1, newp); - if (dist > -1e-10) // 1e-10 { insphere.Add (nbind); changed = 1; } - - } } } } // while (changed) - // (*testout) << "newels: " << endl; - Array newels; + + // Array newels; + Array newels; Element2d face(TRIG); - for (int j = 1; j <= insphere.GetArray().Size(); j++) - for (int k = 1; k <= 4; k++) + for (int celind : insphere.GetArray()) + for (int k = 0; k < 4; k++) { - // int elind = insphere.GetArray().Get(j); - int celind = insphere.GetArray().Get(j); int nbind = meshnb.GetNB (celind, k); if (!nbind || !insphere.IsIn (nbind)) { - tempels.Get (celind).GetFace1 (k, face); + tempels.Get (celind).GetFace (k, face); - Element newel(TET); + // Element newel(TET); + DelaunayTet newel; for (int l = 0; l < 3; l++) newel[l] = face[l]; newel[3] = newpi; @@ -471,7 +391,7 @@ n.Normalize(); if (n * Vec3d(mesh.Point (face[0]), - mesh.Point (tempels.Get(insphere.GetArray().Get(j))[k-1])) + mesh.Point (tempels.Get(celind)[k])) > 0) n *= -1; @@ -492,38 +412,36 @@ meshnb.ResetFaceHT (10*insphere.GetArray().Size()+1); - for (int j = 1; j <= insphere.GetArray().Size(); j++) + for (auto celind : insphere.GetArray()) { - // int elind = - int celind = insphere.GetArray().Get(j); - meshnb.Delete (celind); list.DeleteElement (celind); for (int k = 0; k < 4; k++) tempels.Elem(celind)[k] = -1; - // ((ADTree6&)tettree.Tree()).DeleteElement (celind); tettree.DeleteElement (celind); freelist.Append (celind); } - int hasclose = 0; - for (int j = 1; j <= closesphere.GetArray().Size(); j++) + + + bool hasclose = false; + for (int ind : closesphere.GetArray()) { - int ind = closesphere.GetArray().Get(j); if (!insphere.IsIn(ind) && fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 ) - hasclose = 1; + hasclose = true; } for (int j = 1; j <= newels.Size(); j++) { + const auto & newel = newels.Get(j); int nelind; if (!freelist.Size()) { - tempels.Append (newels.Get(j)); + tempels.Append (newel); nelind = tempels.Size(); } else @@ -531,29 +449,29 @@ nelind = freelist.Last(); freelist.DeleteLast(); - tempels.Elem(nelind) = newels.Get(j); + tempels.Elem(nelind) = newel; } meshnb.Add (nelind); list.AddElement (nelind); for (int k = 0; k < 4; k++) - pp[k] = &mesh.Point (newels.Get(j)[k]); + pp[k] = &mesh.Point (newel[k]); if (CalcSphereCenter (&pp[0], pc) ) { PrintSysError ("Delaunay: New tet is flat"); (*testout) << "new tet is flat" << endl; - for (int k = 1; k <= 4; k++) - (*testout) << newels.Get(j).PNum(k) << " "; + for (int k = 0; k < 4; k++) + (*testout) << newel[k] << " "; (*testout) << endl; - for (int k = 1; k <= 4; k++) + for (int k = 0; k < 4; k++) (*testout) << *pp[k-1] << " "; (*testout) << endl; } - r2 = Dist2 (*pp[0], pc); + double r2 = Dist2 (*pp[0], pc); if (hasclose) for (int k = 1; k <= closesphere.GetArray().Size(); k++) { @@ -602,50 +520,40 @@ Array & tempels, int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax) { - Array > centers; + static Timer t("Meshing3::Delaunay1"); RegionTimer reg(t); + + Array> centers; Array radi2; - Point3d tpmin, tpmax; + Box<3> bbox(Box<3>::EMPTY_BOX); + for (auto & face : adfront->Faces()) + for (PointIndex pi : face.Face().PNums()) + bbox.Add (mesh.Point(pi)); - // new: local box - mesh.GetBox (pmax, pmin); // lower bound for pmax, upper for pmin - for (int i = 1; i <= adfront->GetNF(); i++) - { - const MiniElement2d & face = adfront->GetFace(i); - for (PointIndex pi : face.PNums()) - { - pmin.SetToMin (mesh.Point (pi)); - pmax.SetToMax (mesh.Point (pi)); - } - } - for (PointIndex pi : mesh.LockedPoints()) - { - pmin.SetToMin (mesh.Point (pi)); - pmax.SetToMax (mesh.Point (pi)); - } - + bbox.Add (mesh.Point (pi)); + pmin = bbox.PMin(); + pmax = bbox.PMax(); + - Vec3d vdiag(pmin, pmax); + Vec<3> vdiag = pmax-pmin; // double r1 = vdiag.Length(); - double r1 = sqrt (3.0) * max3(vdiag.X(), vdiag.Y(), vdiag.Z()); - vdiag = Vec3d (r1, r1, r1); + double r1 = sqrt (3.0) * max3(vdiag(0), vdiag(1), vdiag(2)); + vdiag = Vec<3> (r1, r1, r1); //double r2; - Point3d pmin2 = pmin - 8 * vdiag; - Point3d pmax2 = pmax + 8 * vdiag; - - Point3d cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2); - cp2.X() = pmin2.X(); - cp3.Y() = pmin2.Y(); - cp4.Z() = pmin2.Z(); + Point<3> pmin2 = pmin - 8 * vdiag; + Point<3> pmax2 = pmax + 8 * vdiag; + Point<3> cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2); + cp2(0) = pmin2(0); + cp3(1) = pmin2(1); + cp4(2) = pmin2(2); - - int np = mesh.GetNP(); + size_t np = mesh.GetNP(); startel[0] = mesh.AddPoint (cp1); startel[1] = mesh.AddPoint (cp2); @@ -655,24 +563,21 @@ // flag points to use for Delaunay: BitArrayChar usep(np); usep.Clear(); - for (int i = 1; i <= adfront->GetNF(); i++) - { - const MiniElement2d & face = adfront->GetFace(i); - for (int j = 0; j < face.GetNP(); j++) - usep.Set (face[j]); - } - for (int i = oldnp + PointIndex::BASE; + for (auto & face : adfront->Faces()) + for (PointIndex pi : face.Face().PNums()) + usep.Set (pi); + + for (size_t i = oldnp + PointIndex::BASE; i < np + PointIndex::BASE; i++) usep.Set (i); - for (int i = 0; i < mesh.LockedPoints().Size(); i++) - usep.Set (mesh.LockedPoints()[i]); - + for (PointIndex pi : mesh.LockedPoints()) + usep.Set (pi); + Array freelist; - int cntp = 0; MeshNB meshnb (tempels, mesh.GetNP() + 5); @@ -689,13 +594,12 @@ list.AddElement (1); Array connected, treesearch; - - tpmin = tpmax = mesh.Point(startel[0]); - for (int k = 1; k < 4; k++) - { - tpmin.SetToMin (mesh.Point (startel[k])); - tpmax.SetToMax (mesh.Point (startel[k])); - } + Box<3> tbox(Box<3>::EMPTY_BOX); + for (size_t k = 0; k < 4; k++) + tbox.Add (mesh.Point(startel[k])); + Point<3> tpmin = tbox.PMin(); + Point<3> tpmax = tbox.PMax(); + tpmax = tpmax + 0.01 * (tpmax - tpmin); tettree.Insert (tpmin, tpmax, 1); @@ -755,7 +659,7 @@ connected, treesearch, freelist, list, insphere, closesphere); } - + for (int i = tempels.Size(); i >= 1; i--) if (tempels.Get(i)[0] <= 0) tempels.DeleteElement (i); @@ -783,6 +687,8 @@ void Meshing3 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp) { + static Timer t("Meshing3::Delaunay"); RegionTimer reg(t); + int np, ne; PrintMessage (1, "Delaunay meshing"); @@ -810,26 +716,27 @@ // improve delaunay - mesh by swapping !!!! Mesh tempmesh; - for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) - tempmesh.AddPoint (mesh[pi]); + + for (auto & meshpoint : mesh.Points()) + tempmesh.AddPoint (meshpoint); - for (int i = 1; i <= tempels.Size(); i++) + for (auto & tempel : tempels) { Element el(4); for (int j = 0; j < 4; j++) - el[j] = tempels.Elem(i)[j]; + el[j] = tempel[j]; el.SetIndex (1); - const Point3d & lp1 = mesh.Point (el[0]); - const Point3d & lp2 = mesh.Point (el[1]); - const Point3d & lp3 = mesh.Point (el[2]); - const Point3d & lp4 = mesh.Point (el[3]); - Vec3d v1(lp1, lp2); - Vec3d v2(lp1, lp3); - Vec3d v3(lp1, lp4); + const Point<3> & lp1 = mesh.Point (el[0]); + const Point<3> & lp2 = mesh.Point (el[1]); + const Point<3> & lp3 = mesh.Point (el[2]); + const Point<3> & lp4 = mesh.Point (el[3]); + Vec<3> v1 = lp2-lp1; + Vec<3> v2 = lp3-lp1; + Vec<3> v3 = lp4-lp1; - Vec3d n = Cross (v1, v2); + Vec<3> n = Cross (v1, v2); double vol = n * v3; if (vol > 0) swap (el[2], el[3]); @@ -858,21 +765,20 @@ { Element2d self(TRIG); self.SetIndex (1); - startel.GetFace1 (i, self); + startel.GetFace (i-1, self); tempmesh.AddSurfaceElement (self); } // for (i = mesh.GetNP() - 3; i <= mesh.GetNP(); i++) // tempmesh.AddLockedPoint (i); - for (PointIndex pi = tempmesh.Points().Begin(); - pi < tempmesh.Points().End(); pi++) - tempmesh.AddLockedPoint (pi); + for (auto pi : tempmesh.Points().Range()) + tempmesh.AddLockedPoint (pi); - // tempmesh.PrintMemInfo(cout); + // tempmesh.PrintMemInfo(cout); // tempmesh.Save ("tempmesh.vol"); - for (int i = 1; i <= 2; i++) + for (int i = 1; i <= 4; i++) { tempmesh.FindOpenElements (); @@ -883,14 +789,14 @@ MeshOptimize3d meshopt(mp); // tempmesh.CalcSurfacesOfNode(); - meshopt.SwapImprove(tempmesh, OPT_CONFORM); + meshopt.SwapImprove(tempmesh, OPT_CONFORM); } MeshQuality3d (tempmesh); tempels.SetSize(0); - for (int i = 1; i <= tempmesh.GetNE(); i++) - tempels.Append (tempmesh.VolumeElement(i)); + for (auto & el : tempmesh.VolumeElements()) + tempels.Append (el); } @@ -1232,6 +1138,7 @@ INDEX_3_HASHTABLE boundaryfaces(mesh.GetNOpenElements()/3+1); + /* for (int i = 1; i <= mesh.GetNOpenElements(); i++) { const Element2d & tri = mesh.OpenElement(i); @@ -1239,6 +1146,13 @@ i3.Sort(); boundaryfaces.PrepareSet (i3); } + */ + for (const Element2d & tri : mesh.OpenElements()) + { + INDEX_3 i3 (tri[0], tri[1], tri[2]); + i3.Sort(); + boundaryfaces.PrepareSet (i3); + } boundaryfaces.AllocateElements(); for (int i = 1; i <= mesh.GetNOpenElements(); i++) { @@ -1248,14 +1162,23 @@ boundaryfaces.Set (i3, 1); } + /* for (int i = 0; i < tempels.Size(); i++) for (int j = 0; j < 4; j++) tempels[i].NB(j) = 0; - + */ + for (auto & el : tempels) + for (int j = 0; j < 4; j++) + el.NB(j) = 0; + TABLE elsonpoint(mesh.GetNP()); + /* for (int i = 0; i < tempels.Size(); i++) { const DelaunayTet & el = tempels[i]; + */ + for (const DelaunayTet & el : tempels) + { INDEX_4 i4(el[0], el[1], el[2], el[3]); i4.Sort(); elsonpoint.IncSizePrepare (i4.I1()); @@ -1279,7 +1202,8 @@ INDEX_3_CLOSED_HASHTABLE faceht(100); Element2d hel(TRIG); - for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) + // for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) + for (PointIndex pi : mesh.Points().Range()) { faceht.SetSize (4 * elsonpoint[pi].Size()); for (int ii = 0; ii < elsonpoint[pi].Size(); ii++) @@ -1289,7 +1213,7 @@ for (int j = 1; j <= 4; j++) { - el.GetFace1 (j, hel); + el.GetFace (j-1, hel); hel.Invert(); hel.NormalizeNumbering(); @@ -1303,8 +1227,8 @@ { INDEX_2 i2 = faceht.Get(i3); - tempels.Elem(i).NB1(j) = i2.I1(); - tempels.Elem(i2.I1()).NB1(i2.I2()) = i; + tempels.Elem(i).NB(j-1) = i2.I1(); + tempels.Elem(i2.I1()).NB(i2.I2()-1) = i; } else { @@ -1464,7 +1388,7 @@ for (int j = 1; j <= 4; j++) { - INDEX_3 i3 = tempels.Get(ei).GetFace1(j); + INDEX_3 i3 = tempels.Get(ei).GetFace(j-1); /* Element2d face; tempels.Get(ei).GetFace(j, face); @@ -1474,8 +1398,8 @@ i3.Sort(); - if (tempels.Get(ei).NB1(j)) - elstack.Append (tempels.Get(ei).NB1(j)); + if (tempels.Get(ei).NB(j-1)) + elstack.Append (tempels.Get(ei).NB(j-1)); /* if (innerfaces.Used(i3)) @@ -1660,7 +1584,6 @@ mesh.FindOpenElements(domainnr); mesh.Compress(); - PopStatus (); } } diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/global.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/global.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/global.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/global.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -18,7 +18,6 @@ // testout -> clear(ios::failbit); // ostream * testout = &cout; - ostream * testout = new ostream(0); // NetgenOutStream * testout = new NetgenOutStream; @@ -31,6 +30,9 @@ DLL_HEADER shared_ptr ng_geometry; // TraceGlobal glob2("global2"); + // global communicator for netgen + // DLL_HEADER NgMPI_Comm ng_comm; + weak_ptr global_mesh; void SetGlobalMesh (shared_ptr m) { @@ -50,10 +52,6 @@ string ngdir = "."; - // parallel netgen - int id = 0, ntasks = 1; - - void Ng_PrintDest(const char * s) { if (id == 0) diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/global.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/global.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/global.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/global.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -59,6 +59,10 @@ DLL_HEADER extern weak_ptr global_mesh; DLL_HEADER void SetGlobalMesh (shared_ptr m); + + // global communicator for netgen (dummy if no MPI) + // extern DLL_HEADER NgMPI_Comm ng_comm; + } #endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/hprefinement.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/hprefinement.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/hprefinement.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/hprefinement.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -22,8 +22,9 @@ { pnums[i] = -1; param[i][0] = param[i][1] = param[i][2] = 0; - domin=-1; domout=-1; // he: } + domin=-1; domout=-1; // he: + levelx = 0; levely = 0; levelz = 0; } HPRefElement :: HPRefElement () @@ -31,46 +32,40 @@ Reset(); } - HPRefElement :: HPRefElement(Element & el) + HPRefElement :: HPRefElement(Element & el) : + np(el.GetNV()), index(el.GetIndex()), levelx(0), levely(0), levelz(0), type(HP_NONE), domin(-1), domout(-1) //domin,out for segements { //Reset(); - np = el.GetNV(); for (int i=0; igeom) { @@ -829,18 +806,27 @@ HPRefElement newel(el); newel.type = hprs->neweltypes[j]; - // newel.index = elements[i].index; // newel.coarse_elnr = elements[i].coarse_elnr; - newel.levelx = newel.levely = newel.levelz = newlevel; + if (newel.type == HP_SEGM || + newel.type == HP_TRIG || + newel.type == HP_QUAD || + newel.type == HP_TET || + newel.type == HP_PRISM || + newel.type == HP_HEX || + newel.type == HP_PYRAMID) + newel.levelx = newel.levely = newel.levelz = newlevel; + else + newel.levelx = newel.levely = newel.levelz = newlevel+1; + switch(hprsnew->geom) { - case HP_SEGM: newel.np=2; break; - case HP_QUAD: newel.np=4; break; - case HP_TRIG: newel.np=3; break; - case HP_HEX: newel.np=8; break; - case HP_PRISM: newel.np=6; break; - case HP_TET: newel.np=4; break; + case HP_SEGM: newel.np=2; break; + case HP_QUAD: newel.np=4; break; + case HP_TRIG: newel.np=3; break; + case HP_HEX: newel.np=8; break; + case HP_PRISM: newel.np=6; break; + case HP_TET: newel.np=4; break; case HP_PYRAMID: newel.np=5; break; default: throw NgException (string("hprefinement.cpp: illegal type")); @@ -868,7 +854,7 @@ if (j == 0) elements[i] = newel; // overwrite old element - else + else elements.Append (newel); j++; } @@ -1337,7 +1323,7 @@ Array & hpelements = *mesh.hpelements; InitHPElements(mesh,hpelements); - + Array nplevel; nplevel.Append (mesh.GetNP()); diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/improve3.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/improve3.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/improve3.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/improve3.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -22,6 +22,8 @@ void MeshOptimize3d :: CombineImprove (Mesh & mesh, OPTIMIZEGOAL goal) { + static Timer t("MeshOptimize3d::CombineImprove"); RegionTimer reg(t); + int np = mesh.GetNP(); int ne = mesh.GetNE(); @@ -274,8 +276,10 @@ void MeshOptimize3d :: SplitImprove (Mesh & mesh, OPTIMIZEGOAL goal) { + static Timer t("MeshOptimize3d::SplitImprove"); RegionTimer reg(t); + static Timer tloop("MeshOptimize3d::SplitImprove loop"); + double bad1, bad2, badmax, badlimit; - int cnt = 0; int np = mesh.GetNP(); int ne = mesh.GetNE(); @@ -315,7 +319,6 @@ PrintMessage (5, "badmax = ", badmax); badlimit = 0.5 * badmax; - boundp.Clear(); for (auto & el : mesh.SurfaceElements()) for (PointIndex pi : el.PNums()) @@ -346,6 +349,7 @@ } } + tloop.Start(); for (ElementIndex ei : mesh.VolumeElements().Range()) { Element & elem = mesh[ei]; @@ -539,7 +543,7 @@ } } } - + tloop.Stop(); mesh.Compress(); PrintMessage (5, cnt, " splits performed"); @@ -569,6 +573,9 @@ void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal, const BitArray * working_elements) { + static Timer t("MeshOptimize3d::SwapImprove"); RegionTimer reg(t); + static Timer tloop("MeshOptimize3d::SwapImprove loop"); + PointIndex pi3(0), pi4(0), pi5(0), pi6(0); int cnt = 0; @@ -625,7 +632,8 @@ // INDEX_2_HASHTABLE edgeused(2 * ne + 5); INDEX_2_CLOSED_HASHTABLE edgeused(12 * ne + 5); - + + tloop.Start(); for (ElementIndex ei = 0; ei < ne; ei++) { if (multithread.terminate) @@ -1399,7 +1407,7 @@ */ } // (*mycout) << endl; - + tloop.Stop(); /* cout << "edgeused: "; edgeused.PrintMemInfo(cout); @@ -2303,6 +2311,8 @@ void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal) { + static Timer t("MeshOptimize3d::SwapImprove2"); RegionTimer reg(t); + PointIndex pi1(0), pi2(0), pi3(0), pi4(0), pi5(0); Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET); diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshclass.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshclass.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshclass.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshclass.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -43,6 +43,7 @@ bcnames.SetSize(0); cd2names.SetSize(0); + // this->comm = netgen :: ng_comm; #ifdef PARALLEL paralleltop = new ParallelMeshTopology (*this); #endif @@ -82,9 +83,14 @@ #endif } + void Mesh :: SetCommunicator(NgMPI_Comm acomm) + { + this->comm = acomm; + } Mesh & Mesh :: operator= (const Mesh & mesh2) { + dimension = mesh2.dimension; points = mesh2.points; // eltyps = mesh2.eltyps; segments = mesh2.segments; @@ -94,16 +100,31 @@ facedecoding = mesh2.facedecoding; dimension = mesh2.dimension; + + materials.SetSize( mesh2.materials.Size() ); + for ( int i = 0; i < mesh2.materials.Size(); i++ ) + if ( mesh2.materials[i] ) materials[i] = new string ( *mesh2.materials[i] ); + else materials[i] = 0; + + bcnames.SetSize( mesh2.bcnames.Size() ); for ( int i = 0; i < mesh2.bcnames.Size(); i++ ) if ( mesh2.bcnames[i] ) bcnames[i] = new string ( *mesh2.bcnames[i] ); else bcnames[i] = 0; + cd2names.SetSize(mesh2.cd2names.Size()); for (int i=0; i < mesh2.cd2names.Size(); i++) if (mesh2.cd2names[i]) cd2names[i] = new string(*mesh2.cd2names[i]); else cd2names[i] = 0; + cd3names.SetSize(mesh2.cd3names.Size()); + for (int i=0; i < mesh2.cd3names.Size(); i++) + if (mesh2.cd3names[i]) cd3names[i] = new string(*mesh2.cd3names[i]); + else cd3names[i] = 0; + + numvertices = mesh2.numvertices; + return *this; } @@ -313,7 +334,7 @@ SurfaceElementIndex si = surfelements.Size(); surfelements.Append (el); - if (el.index > facedecoding.Size()) + if (el.index<=0 || el.index > facedecoding.Size()) cerr << "has no facedecoding: fd.size = " << facedecoding.Size() << ", ind = " << el.index << endl; surfelements.Last().next = facedecoding[el.index-1].firstelement; @@ -879,6 +900,9 @@ throw NgException ("mesh file not found"); } + int rank = GetCommunicator().Rank(); + int ntasks = GetCommunicator().Size(); + char str[100]; int i, n; @@ -1172,7 +1196,7 @@ for (i = 1; i<= GetNSeg(); i++) { Segment & seg = LineSegment(i); - if ( seg.cd2i <= n ) + if ( seg.edgenr <= n ) seg.SetBCName (cd2names[seg.edgenr-1]); else seg.SetBCName(0); @@ -1303,7 +1327,7 @@ } - void Mesh :: DoArchive (ngstd::Archive & archive) + void Mesh :: DoArchive (Archive & archive) { archive & dimension; archive & points; @@ -1311,12 +1335,19 @@ archive & volelements; archive & segments; archive & facedecoding; - archive & materials & bcnames & cd2names; + archive & materials & bcnames & cd2names & cd3names; + archive & numvertices; archive & *ident; + + archive.Shallow(geometry); + archive & *curvedelems; if (archive.Input()) { + int rank = GetCommunicator().Rank(); + int ntasks = GetCommunicator().Size(); + RebuildSurfaceElementLists(); CalcSurfacesOfNode (); @@ -1669,6 +1700,7 @@ void Mesh :: CalcSurfacesOfNode () { + static Timer t("Mesh::CalcSurfacesOfNode"); RegionTimer reg (t); // surfacesonnode.SetSize (GetNP()); TABLE surfacesonnode(GetNP()); @@ -1853,8 +1885,7 @@ void Mesh :: FindOpenElements (int dom) { - static int timer = NgProfiler::CreateTimer ("Mesh::FindOpenElements"); - NgProfiler::RegionTimer reg (timer); + static Timer t("Mesh::FindOpenElements"); RegionTimer reg (t); int np = GetNP(); int ne = GetNE(); @@ -2706,6 +2737,8 @@ void Mesh :: CalcLocalH (double grading) { + static Timer t("Mesh::CalcLocalH"); RegionTimer reg(t); + if (!lochfunc) { Point3d pmin, pmax; @@ -3231,6 +3264,8 @@ void Mesh :: Compress () { + static Timer t("Mesh::Compress"); RegionTimer reg(t); + Array op2np(GetNP()); Array hpoints; BitArrayChar pused(GetNP()); @@ -3291,8 +3326,8 @@ for (int i = 0; i < segments.Size(); i++) { const Segment & seg = segments[i]; - pused.Set (seg[0]); - pused.Set (seg[1]); + for (int j = 0; j < seg.GetNP(); j++) + pused.Set (seg[j]); } for (int i = 0; i < openelements.Size(); i++) @@ -3356,8 +3391,8 @@ for (int i = 0; i < segments.Size(); i++) { Segment & seg = segments[i]; - seg[0] = op2np[seg[0]]; - seg[1] = op2np[seg[1]]; + for (int j = 0; j < seg.GetNP(); j++) + seg[j] = op2np[seg[j]]; } for (int i = 1; i <= openelements.Size(); i++) @@ -3370,7 +3405,7 @@ for (int i = 0; i < lockedpoints.Size(); i++) lockedpoints[i] = op2np[lockedpoints[i]]; - + /* for (int i = 0; i < facedecoding.Size(); i++) facedecoding[i].firstelement = -1; for (int i = surfelements.Size()-1; i >= 0; i--) @@ -3379,7 +3414,8 @@ surfelements[i].next = facedecoding[ind-1].firstelement; facedecoding[ind-1].firstelement = i; } - + */ + RebuildSurfaceElementLists (); CalcSurfacesOfNode(); @@ -3497,6 +3533,8 @@ int Mesh :: CheckOverlappingBoundary () { + static Timer t("Mesh::CheckOverlappingBoundary"); RegionTimer reg(t); + int i, j, k; Point3d pmin, pmax; @@ -4309,10 +4347,12 @@ elementsearchtree = NULL; int ne = (dimension == 2) ? GetNSE() : GetNE(); - + if (dimension == 3 && !GetNE() && GetNSE()) + ne = GetNSE(); + if (ne) { - if (dimension == 2) + if (dimension == 2 || (dimension == 3 && !GetNE()) ) { Box<3> box (Box<3>::EMPTY_BOX); for (SurfaceElementIndex sei = 0; sei < ne; sei++) @@ -4375,7 +4415,11 @@ sol.Y() = (-a12 * aTrhs.X() + a11 * aTrhs.Y()) / det; return 0; } - + + bool ValidBarCoord(double lami[3], double eps=1e-12) + { + return (lami[0]<=1.+eps && lami[0]>=0.-eps && lami[1]<=1.+eps && lami[1]>=0.-eps && lami[2]<=1.+eps && lami[2]>=0.-eps ); + } bool Mesh :: PointContainedIn2DElement(const Point3d & p, double lami[3], @@ -4406,16 +4450,167 @@ Vec3d c = p4 - a; Vec3d d = p3 - a - b - c; - + /*cout << "p = " << p << endl; + cout << "p1 = " << p1 << endl; + cout << "p2 = " << p2 << endl; + cout << "p3 = " << p3 << endl; + cout << "p4 = " << p4 << endl; + + cout << "a = " << a << endl; + cout << "b = " << b << endl; + cout << "c = " << c << endl; + cout << "d = " << d << endl;*/ + + + Vec3d pa = p-a; double dxb = d.X()*b.Y()-d.Y()*b.X(); - double dxc = d.X()*c.Y()-d.Y()*c.X(); + double dxc = d.X()*c.Y()-d.Y()*c.X(); + double bxc = b.X()*c.Y()-b.Y()*c.X(); + double bxpa = b.X()*pa.Y()-b.Y()*pa.X(); + double cxpa = c.X()*pa.Y()-c.Y()*pa.X(); + double dxpa = d.X()*pa.Y()-d.Y()*pa.X(); + + /*cout << "dxb = " << dxb << endl; + cout << "dxc = " << dxc << endl; + cout << "bxc = " << bxc << endl; + cout << "bxpa = " << bxpa << endl; + cout << "cxpa = " << cxpa << endl; + cout << "dxpa = " << dxpa << endl;*/ + + /* + P = a + b x + c y + d x y + 1) P1 = a1 + b1 x + c1 y + d1 x y + 2) P2 = a2 + b2 x + c2 y + d2 x y + + -> det(x,d) = det(a,d) + det(b,d) x + det(c,d) y + -> x = 1/det(b,d) *( det(P-a,d)-det(c,d) y ) + -> y = 1/det(c,d) *( det(P-a,d)-det(b,d) x ) + + -> x = (P1 - a1 - c1 y)/(b1 + d1 y) + -> det(c,d) y**2 + [det(d,P-a) + det(c,b)] y + det(b,P-a) = 0 + ( same if we express x = (P2 - a2 - c2 y)/(b2 + d2 y) ) + + -> y = (P1 - a1 - b1 x)/(c1 + d1 x) + -> det(b,d) x**2 + [det(d,P-a) + det(b,c)] x + det(c,P-a) = 0 + ( same if we express y = (P2 - a2 - b2 x)/(c2 + d2 x) + */ + + lami[2]=0.; + double eps = 1.E-12; + double c1,c2,r; + + //First check if point is "exactly" a vertex point + Vec3d d1 = p-p1; + Vec3d d2 = p-p2; + Vec3d d3 = p-p3; + Vec3d d4 = p-p4; + + //cout << " d1 = " << d1 << ", d2 = " << d2 << ", d3 = " << d3 << ", d4 = " << d4 << endl; + + if (d1.Length2() < sqr(eps)*d2.Length2() && d1.Length2() < sqr(eps)*d3.Length2() && d1.Length2() < sqr(eps)*d4.Length2()) + { + lami[0] = lami[1] = 0.; + return true; + } + else if (d2.Length2() < sqr(eps)*d1.Length2() && d2.Length2() < sqr(eps)*d3.Length2() && d2.Length2() < sqr(eps)*d4.Length2()) + { + lami[0] = 1.; + lami[1] = 0.; + return true; + } + else if (d3.Length2() < sqr(eps)*d1.Length2() && d3.Length2() < sqr(eps)*d2.Length2() && d3.Length2() < sqr(eps)*d4.Length2()) + { + lami[0] = lami[1] = 1.; + return true; + } + else if (d4.Length2() < sqr(eps)*d1.Length2() && d4.Length2() < sqr(eps)*d2.Length2() && d4.Length2() < sqr(eps)*d3.Length2()) + { + lami[0] = 0.; + lami[1] = 1.; + return true; + }//if d is nearly 0: solve resulting linear system + else if (d.Length2() < sqr(eps)*b.Length2() && d.Length2() < sqr(eps)*c.Length2()) + { + Vec2d sol; + SolveLinearSystemLS (b, c, p-a, sol); + lami[0] = sol.X(); + lami[1] = sol.Y(); + return ValidBarCoord(lami, eps); + }// if dxc is nearly 0: solve resulting linear equation for y and compute x + else if (fabs(dxc) < sqr(eps)) + { + lami[1] = -bxpa/(dxpa-bxc); + lami[0] = (dxpa-dxc*lami[1])/dxb; + return ValidBarCoord(lami, eps); + }// if dxb is nearly 0: solve resulting linear equation for x and compute y + else if (fabs(dxb) < sqr(eps)) + { + lami[0] = -cxpa/(dxpa+bxc); + lami[1] = (dxpa-dxb*lami[0])/dxc; + return ValidBarCoord(lami, eps); + }//if dxb >= dxc: solve quadratic equation in y and compute x + else if (fabs(dxb) >= fabs(dxc)) + { + c1 = (bxc-dxpa)/dxc; + c2 = -bxpa/dxc; + r = c1*c1/4.0-c2; + + //quadratic equation has only 1 (unstable) solution + if (fabs(r) < eps) //not eps^2! + { + lami[1] = -c1/2; + lami[0] = (dxpa-dxc*lami[1])/dxb; + return ValidBarCoord(lami, eps); + } + if (r < 0) return false; + + lami[1] = -c1/2+sqrt(r); + lami[0] = (dxpa-dxc*lami[1])/dxb; + + if (ValidBarCoord(lami, eps)) + return true; + else + { + lami[1] = -c1/2-sqrt(r); + lami[0] = (dxpa-dxc*lami[1])/dxb; + return ValidBarCoord(lami, eps); + } + }//if dxc > dxb: solve quadratic equation in x and compute y + else + { + c1 = (-bxc-dxpa)/dxb; + c2 = -cxpa/dxb; + r = c1*c1/4.0-c2; + + //quadratic equation has only 1 (unstable) solution + if (fabs(r) < eps) //not eps^2! + { + lami[0] = -c1/2; + lami[1] = (dxpa-dxb*lami[0])/dxc; + return ValidBarCoord(lami, eps); + } + if (r < 0) return false; + + lami[0] = -c1/2+sqrt(r); + lami[1] = (dxpa-dxb*lami[0])/dxc; + + if (ValidBarCoord(lami, eps)) + return true; + else + { + lami[0] = -c1/2-sqrt(r); + lami[1] = (dxpa-dxb*lami[0])/dxc; + return ValidBarCoord(lami, eps); + } + } + + /* double dxa = d.X()*a.Y()-d.Y()*a.X(); double dxp = d.X()*p.Y()-d.Y()*p.X(); double c0,c1,c2; // ,rt; - lami[2]=0.; - double eps = 1.E-12; + Vec3d dp13 = p3-p1; Vec3d dp24 = p4-p2; @@ -4435,12 +4630,12 @@ if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps) return true; - /* - lami[0]=(c.Y()*(p.X()-a.X())-c.X()*(p.Y()-a.Y()))/ - (b.X()*c.Y() -b.Y()*c.X()); - lami[1]=(-b.Y()*(p.X()-a.X())+b.X()*(p.Y()-a.Y()))/ - (b.X()*c.Y() -b.Y()*c.X()); - */ + + //lami[0]=(c.Y()*(p.X()-a.X())-c.X()*(p.Y()-a.Y()))/ + //(b.X()*c.Y() -b.Y()*c.X()); + //lami[1]=(-b.Y()*(p.X()-a.X())+b.X()*(p.Y()-a.Y()))/ + // (b.X()*c.Y() -b.Y()*c.X()); + } else if(fabs(dxb) <= eps*fabs(dxc)) @@ -4534,7 +4729,7 @@ if(lami[1]<=1.+eps && lami[1]>=0.-eps && lami[0]<=1.+eps && lami[0]>=0.-eps) return true; - } + }*/ //cout << "lam0,1 = " << lami[0] << ", " << lami[1] << endl; @@ -4596,6 +4791,42 @@ //(*testout) << "col1 " << col1 << " col2 " << col2 << " col3 " << col3 << " rhs " << rhs << endl; //(*testout) << "sol " << sol << endl; + if (SurfaceElement(element).GetType() ==TRIG6) + { + netgen::Point<2> lam(1./3,1./3); + Vec<3> rhs; + Vec<2> deltalam; + netgen::Point<3> x; + Mat<3,2> Jac,Jact; + + double delta=1; + + bool retval; + + int i = 0; + + const int maxits = 30; + while(delta > 1e-16 && iCalcSurfaceTransformation(lam,element-1,x,Jac); + rhs = p-x; + Jac.Solve(rhs,deltalam); + + lam += deltalam; + + delta = deltalam.Length2(); + + i++; + //(*testout) << "pcie i " << i << " delta " << delta << " p " << p << " x " << x << " lam " << lam << endl; + //<< "Jac " << Jac << endl; + } + + if(i==maxits) + return false; + + sol.X() = lam(0); + sol.Y() = lam(1); + } if (sol.X() >= -eps && sol.Y() >= -eps && sol.X() + sol.Y() <= 1+eps) { @@ -4694,7 +4925,7 @@ lam(2) > -eps && lam(0) + lam(1) + lam(2) < 1+eps); } - else if (el.GetType() == PRISM) + else if (el.GetType() == PRISM || el.GetType() == PRISM15) { retval = (lam(0) > -eps && lam(1) > -eps && @@ -4702,7 +4933,7 @@ lam(2) < 1+eps && lam(0) + lam(1) < 1+eps); } - else if (el.GetType() == PYRAMID) + else if (el.GetType() == PYRAMID || el.GetType() == PYRAMID13) { retval = (lam(0) > -eps && lam(1) > -eps && @@ -4710,7 +4941,7 @@ lam(0) + lam(2) < 1+eps && lam(1) + lam(2) < 1+eps); } - else if (el.GetType() == HEX) + else if (el.GetType() == HEX || el.GetType() == HEX20) { retval = (lam(0) > -eps && lam(0) < 1+eps && lam(1) > -eps && lam(1) < 1+eps && @@ -4813,10 +5044,15 @@ bool build_searchtree, const bool allowindex) const { - const double pointtol = 1e-12; - netgen::Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol); - netgen::Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol); - if (dimension == 2) + // const double pointtol = 1e-12; + // netgen::Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol); + // netgen::Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol); + + if ( (dimension == 2 && !GetNSE()) || + (dimension == 3 && !GetNE() && !GetNSE()) ) + return -1; + + if (dimension == 2 || (dimension==3 && !GetNE() && GetNSE())) { int ne; int ps_startelement = 0; // disable global buffering @@ -4828,8 +5064,11 @@ if (elementsearchtree || build_searchtree) { // update if necessary: - const_cast(*this).BuildElementSearchTree (); - elementsearchtree->GetIntersecting (pmin, pmax, locels); + const_cast(*this).BuildElementSearchTree (); + // double tol = elementsearchtree->Tolerance(); + // netgen::Point<3> pmin = p - Vec<3> (tol, tol, tol); + // netgen::Point<3> pmax = p + Vec<3> (tol, tol, tol); + elementsearchtree->GetIntersecting (p, p, locels); ne = locels.Size(); } else @@ -4871,8 +5110,11 @@ if (elementsearchtree || build_searchtree) { // update if necessary: - const_cast(*this).BuildElementSearchTree (); - elementsearchtree->GetIntersecting (pmin, pmax, locels); + const_cast(*this).BuildElementSearchTree (); + // double tol = elementsearchtree->Tolerance(); + // netgen::Point<3> pmin = p - Vec<3> (tol, tol, tol); + // netgen::Point<3> pmax = p + Vec<3> (tol, tol, tol); + elementsearchtree->GetIntersecting (p, p, locels); ne = locels.Size(); } else @@ -4970,6 +5212,14 @@ //(*testout) << "p " << p << endl; //(*testout) << "velement " << velement << endl; + if (!GetNE() && GetNSE() ) + { + lami[0] = vlam[0]; + lami[1] = vlam[1]; + lami[2] = vlam[2]; + return velement; + } + Array faces; topology.GetElementFaces(velement,faces); @@ -5624,34 +5874,17 @@ void Mesh :: ComputeNVertices () { - int i, j, nv; - int ne = GetNE(); - // int nse = GetNSE(); - numvertices = 0; - for (i = 1; i <= ne; i++) - { - const Element & el = VolumeElement(i); - nv = el.GetNV(); - for (j = 0; j < nv; j++) - if (el[j] > numvertices) - numvertices = el[j]; - } - /* - for (i = 1; i <= nse; i++) - { - const Element2d & el = SurfaceElement(i); - nv = el.GetNV(); - for (j = 1; j <= nv; j++) - if (el.PNum(j) > numvertices) - numvertices = el.PNum(j); - } - */ - for (auto & el : SurfaceElements()) + + for (const Element & el : VolumeElements()) + for (PointIndex v : el.Vertices()) + if (v > numvertices) numvertices = v; + + for (const Element2d & el : SurfaceElements()) for (PointIndex v : el.Vertices()) if (v > numvertices) numvertices = v; - numvertices += 1- PointIndex::BASE; + numvertices += 1-PointIndex::BASE; } int Mesh :: GetNV () const @@ -5967,10 +6200,52 @@ return defaultstring; } + void Mesh :: SetNCD3Names( int ncd3n ) + { + if (cd3names.Size()) + for(int i=0; i= cd3names.Size()) + { + int oldsize = cd3names.Size(); + cd3names.SetSize(cd3nr+1); + for(int i= oldsize; i<= cd3nr; i++) + cd3names[i] = nullptr; + } + if (abcname != "default") + cd3names[cd3nr] = new string(abcname); + else + cd3names[cd3nr] = nullptr; + } + + string Mesh :: cd3_default_name = "default"; + const string & Mesh :: GetCD3Name (int cd3nr) const + { + static string defaultstring = "default"; + if (!cd3names.Size()) + return defaultstring; + + if (cd3nr < 0 || cd3nr >= cd3names.Size()) + return defaultstring; + + if (cd3names[cd3nr]) + return *cd3names[cd3nr]; + else + return defaultstring; + } + void Mesh :: SetUserData(const char * id, Array & data) { if(userdata_int.Used(id)) - delete userdata_int.Get(id); + delete userdata_int[id]; Array * newdata = new Array(data); @@ -5980,10 +6255,10 @@ { if(userdata_int.Used(id)) { - if(data.Size() < (*userdata_int.Get(id)).Size()+shift) - data.SetSize((*userdata_int.Get(id)).Size()+shift); - for(int i=0; i<(*userdata_int.Get(id)).Size(); i++) - data[i+shift] = (*userdata_int.Get(id))[i]; + if(data.Size() < (*userdata_int[id]).Size()+shift) + data.SetSize((*userdata_int[id]).Size()+shift); + for(int i=0; i<(*userdata_int[id]).Size(); i++) + data[i+shift] = (*userdata_int[id])[i]; return true; } else @@ -5995,7 +6270,7 @@ void Mesh :: SetUserData(const char * id, Array & data) { if(userdata_double.Used(id)) - delete userdata_double.Get(id); + delete userdata_double[id]; Array * newdata = new Array(data); @@ -6005,10 +6280,10 @@ { if(userdata_double.Used(id)) { - if(data.Size() < (*userdata_double.Get(id)).Size()+shift) - data.SetSize((*userdata_double.Get(id)).Size()+shift); - for(int i=0; i<(*userdata_double.Get(id)).Size(); i++) - data[i+shift] = (*userdata_double.Get(id))[i]; + if(data.Size() < (*userdata_double[id]).Size()+shift) + data.SetSize((*userdata_double[id]).Size()+shift); + for(int i=0; i<(*userdata_double[id]).Size(); i++) + data[i+shift] = (*userdata_double[id])[i]; return true; } else diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshclass.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshclass.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshclass.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshclass.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -32,6 +32,9 @@ /// point coordinates T_POINTS points; + // The communicator for this mesh. Just a dummy if compiled without MPI. + NgMPI_Comm comm; + /// line-segments at edges Array segments; /// surface elements, 2d-inner elements @@ -91,6 +94,9 @@ /// labels for co dim 2 bboundary conditions Array cd2names; + /// labels for co dim 3 bbboundary conditions + Array cd3names; + /// Periodic surface, close surface, etc. identifications Identifications * ident; @@ -124,8 +130,8 @@ /// mesh access semaphors. NgMutex majormutex; - SYMBOLTABLE< Array* > userdata_int; - SYMBOLTABLE< Array* > userdata_double; + SymbolTable< Array* > userdata_int; + SymbolTable< Array* > userdata_double; mutable Array< Point3d > pointcurves; @@ -215,7 +221,7 @@ DLL_HEADER PointIndex AddPoint (const Point3d & p, int layer = 1); DLL_HEADER PointIndex AddPoint (const Point3d & p, int layer, POINTTYPE type); - int GetNP () const { return points.Size(); } + auto GetNP () const { return points.Size(); } // [[deprecated("Use Point(PointIndex) instead of int !")]] MeshPoint & Point(int i) { return points.Elem(i); } @@ -285,7 +291,7 @@ timestamp = NextTimeStamp(); } - int GetNSE () const { return surfelements.Size(); } + auto GetNSE () const { return surfelements.Size(); } // [[deprecated("Use SurfaceElement(SurfaceElementIndex) instead of int !")]] Element2d & SurfaceElement(int i) { return surfelements.Elem(i); } @@ -310,7 +316,7 @@ // write to pre-allocated container, thread-safe DLL_HEADER void SetVolumeElement (ElementIndex sei, const Element & el); - int GetNE () const { return volelements.Size(); } + auto GetNE () const { return volelements.Size(); } // [[deprecated("Use VolumeElement(ElementIndex) instead of int !")]] Element & VolumeElement(int i) { return volelements.Elem(i); } @@ -448,7 +454,8 @@ const Element2d & OpenElement(int i) const { return openelements.Get(i); } - + auto & OpenElements() const { return openelements; } + /// are also quads open elements bool HasOpenQuads () const; @@ -509,7 +516,7 @@ 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); @@ -598,6 +605,9 @@ int AddEdgeDescriptor(const EdgeDescriptor & fd) { edgedecoding.Append(fd); return edgedecoding.Size() - 1; } + auto GetCommunicator() const { return this->comm; } + void SetCommunicator(NgMPI_Comm acomm); + /// DLL_HEADER void SetMaterial (int domnr, const string & mat); /// @@ -626,6 +636,18 @@ } size_t GetNCD2Names() const { return cd2names.Size(); } + DLL_HEADER void SetNCD3Names (int ncd3n); + DLL_HEADER void SetCD3Name (int cd3nr, const string & abcname); + + DLL_HEADER const string & GetCD3Name (int cd3nr ) const; + DLL_HEADER static string cd3_default_name; + string * GetCD3NamePtr (int cd3nr ) const + { + if (cd3nr < cd3names.Size() && cd3names[cd3nr]) return cd3names[cd3nr]; + return &cd3_default_name; + } + size_t GetNCD3Names() const { return cd3names.Size(); } + DLL_HEADER static string default_bc; string * GetBCNamePtr (int bcnr) const { return (bcnr < bcnames.Size() && bcnames[bcnr]) ? bcnames[bcnr] : &default_bc; } @@ -839,6 +861,15 @@ /// loads a mesh sent from master processor void ReceiveParallelMesh (); + Array vol_partition; + Array surf_partition; + Array seg_partition; + +#else + void Distribute () {} + void SendRecvMesh () {} + void Distribute (Array & volume_weights, Array & surface_weights, + Array & segment_weights){ } #endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshfunc2d.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshfunc2d.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshfunc2d.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshfunc2d.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -6,11 +6,20 @@ DLL_HEADER void Optimize2d (Mesh & mesh, MeshingParameters & mp) { - static int timer = NgProfiler::CreateTimer ("optimize2d"); - NgProfiler::RegionTimer reg(timer); + static Timer timer("optimize2d"); RegionTimer reg(timer); mesh.CalcSurfacesOfNode(); + bool secondorder = mesh.GetNP() > mesh.GetNV(); + + + if (secondorder) + { + for (SurfaceElementIndex ei = 0; ei < mesh.GetNSE(); ei++) + mesh[ei].SetType(TRIG); + } + mesh.Compress(); + const char * optstr = mp.optimize2d.c_str(); int optsteps = mp.optsteps2d; @@ -52,6 +61,13 @@ cerr << "Optimization code " << optstr[j-1] << " not defined" << endl; } } + if (secondorder) + { + if (mesh.GetGeometry()) + mesh.GetGeometry()->GetRefinement().MakeSecondOrder(mesh); + else + Refinement().MakeSecondOrder(mesh); + } } } diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshfunc.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshfunc.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshfunc.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshfunc.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -14,6 +14,8 @@ // extern double teterrpow; MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d) { + static Timer t("MeshVolume"); RegionTimer reg(t); + int oldne; int meshed; @@ -144,11 +146,20 @@ for (PointIndex pi = mesh3d.Points().Begin(); pi < mesh3d.Points().End(); pi++) meshing.AddPoint (mesh3d[pi], pi); - + + /* mesh3d.GetIdentifications().GetPairs (0, connectednodes); for (int i = 1; i <= connectednodes.Size(); i++) meshing.AddConnectedPair (connectednodes.Get(i)); - + */ + for (int nr = 1; nr <= mesh3d.GetIdentifications().GetMaxNr(); nr++) + if (mesh3d.GetIdentifications().GetType(nr) != Identifications::PERIODIC) + { + mesh3d.GetIdentifications().GetPairs (nr, connectednodes); + for (auto pair : connectednodes) + meshing.AddConnectedPair (pair); + } + for (int i = 1; i <= mesh3d.GetNOpenElements(); i++) { Element2d hel = mesh3d.OpenElement(i); @@ -630,6 +641,8 @@ Mesh & mesh3d) // const CSGeometry * geometry) { + static Timer t("OptimizeVolume"); RegionTimer reg(t); + int i; PrintMessage (1, "Volume Optimization"); @@ -689,6 +702,8 @@ void RemoveIllegalElements (Mesh & mesh3d) { + static Timer t("RemoveIllegalElements"); RegionTimer reg(t); + int it = 10; int nillegal, oldn; diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshfunc.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshfunc.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshfunc.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshfunc.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -16,16 +16,16 @@ // class CSGeometry; /// Build tet-mesh -MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d); +DLL_HEADER MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d); /// Build mixed-element mesh // MESHING3_RESULT MeshMixedVolume (MeshingParameters & mp, Mesh& mesh3d); /// Optimize tet-mesh -MESHING3_RESULT OptimizeVolume (MeshingParameters & mp, Mesh& mesh3d); +DLL_HEADER MESHING3_RESULT OptimizeVolume (MeshingParameters & mp, Mesh& mesh3d); // const CSGeometry * geometry = NULL); -void RemoveIllegalElements (Mesh & mesh3d); +DLL_HEADER void RemoveIllegalElements (Mesh & mesh3d); enum MESHING_STEP { diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshing2.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshing2.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshing2.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshing2.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -195,7 +195,7 @@ MESHING2_RESULT Meshing2 :: GenerateMesh (Mesh & mesh, const MeshingParameters & mp, double gh, int facenr) { - static int timer = NgProfiler::CreateTimer ("surface meshing"); + static Timer timer("surface meshing"); RegionTimer reg(timer); static int timer1 = NgProfiler::CreateTimer ("surface meshing1"); static int timer2 = NgProfiler::CreateTimer ("surface meshing2"); @@ -206,8 +206,6 @@ static int ts3 = NgProfiler::CreateTimer ("surface meshing start 3"); - NgProfiler::RegionTimer reg (timer); - NgProfiler::StartTimer (ts1); Array pindex, lindex; diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshing3.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshing3.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshing3.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshing3.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -168,12 +168,17 @@ MESHING3_RESULT Meshing3 :: GenerateMesh (Mesh & mesh, const MeshingParameters & mp) { - static int meshing3_timer = NgProfiler::CreateTimer ("Meshing3::GenerateMesh"); - static int meshing3_timer_a = NgProfiler::CreateTimer ("Meshing3::GenerateMesh a"); - static int meshing3_timer_b = NgProfiler::CreateTimer ("Meshing3::GenerateMesh b"); - static int meshing3_timer_c = NgProfiler::CreateTimer ("Meshing3::GenerateMesh c"); - static int meshing3_timer_d = NgProfiler::CreateTimer ("Meshing3::GenerateMesh d"); - NgProfiler::RegionTimer reg (meshing3_timer); + static Timer t("Meshing3::GenerateMesh"); RegionTimer reg(t); + static Timer meshing3_timer_a("Meshing3::GenerateMesh a", 2); + static Timer meshing3_timer_b("Meshing3::GenerateMesh b", 2); + static Timer meshing3_timer_c("Meshing3::GenerateMesh c", 1); + static Timer meshing3_timer_d("Meshing3::GenerateMesh d", 2); + // static int meshing3_timer = NgProfiler::CreateTimer ("Meshing3::GenerateMesh"); + // static int meshing3_timer_a = NgProfiler::CreateTimer ("Meshing3::GenerateMesh a"); + // static int meshing3_timer_b = NgProfiler::CreateTimer ("Meshing3::GenerateMesh b"); + // static int meshing3_timer_c = NgProfiler::CreateTimer ("Meshing3::GenerateMesh c"); + // static int meshing3_timer_d = NgProfiler::CreateTimer ("Meshing3::GenerateMesh d"); + // NgProfiler::RegionTimer reg (meshing3_timer); Array locpoints; // local points @@ -269,20 +274,16 @@ } const MiniElement2d & bel = adfront->GetFace (baseelem); - const Point3d & p1 = adfront->GetPoint (bel[0]); - const Point3d & p2 = adfront->GetPoint (bel[1]); - const Point3d & p3 = adfront->GetPoint (bel[2]); - - // (*testout) << endl << "base = " << bel << endl; - + const Point<3> p1 = adfront->GetPoint (bel[0]); + const Point<3> p2 = adfront->GetPoint (bel[1]); + const Point<3> p3 = adfront->GetPoint (bel[2]); + - Point3d pmid = Center (p1, p2, p3); + Point<3> pmid = Center (p1, p2, p3); double his = (Dist (p1, p2) + Dist(p1, p3) + Dist(p2, p3)) / 3; - double hshould; - - hshould = mesh.GetH (pmid); - + double hshould = mesh.GetH (pmid); + if (adfront->GetFace (baseelem).GetNP() == 4) hshould = max2 (his, hshould); @@ -292,13 +293,13 @@ double hinner = hmax * (1 + stat.qualclass); double houter = hmax * (1 + 2 * stat.qualclass); - NgProfiler::StartTimer (meshing3_timer_a); + meshing3_timer_a.Start(); stat.qualclass = adfront -> GetLocals (baseelem, locpoints, locfaces, pindex, findex, connectedpairs, houter, hinner, locfacesplit); - NgProfiler::StopTimer (meshing3_timer_a); + meshing3_timer_a.Stop(); // (*testout) << "locfaces = " << endl << locfaces << endl; @@ -320,9 +321,6 @@ } - - - if (testmode) { (*testout) << "baseelem = " << baseelem << " qualclass = " << stat.qualclass << endl; @@ -479,7 +477,8 @@ (*testout) << endl; } - NgProfiler::StartTimer (meshing3_timer_c); + // NgProfiler::StartTimer (meshing3_timer_c); + meshing3_timer_c.Start(); found = ApplyRules (plainpoints, allowpoint, locfaces, locfacesplit, connectedpairs, @@ -489,8 +488,8 @@ if (found >= 0) impossible = 0; if (found < 0) found = 0; - - NgProfiler::StopTimer (meshing3_timer_c); + meshing3_timer_c.Stop(); + // NgProfiler::StopTimer (meshing3_timer_c); if (!found) loktestmode = 0; @@ -733,6 +732,8 @@ void Meshing3 :: BlockFill (Mesh & mesh, double gh) { + static Timer t("Mesing3::BlockFill"); RegionTimer reg(t); + PrintMessage (3, "Block-filling called (obsolete) "); int i, j(0), i1, i2, i3, j1, j2, j3; @@ -1097,10 +1098,12 @@ void Meshing3 :: BlockFillLocalH (Mesh & mesh, const MeshingParameters & mp) { + static Timer t("Mesing3::BlockFillLocalH"); RegionTimer reg(t); + double filldist = mp.filldist; - - (*testout) << "blockfill local h" << endl; - (*testout) << "rel filldist = " << filldist << endl; + + // (*testout) << "blockfill local h" << endl; + // (*testout) << "rel filldist = " << filldist << endl; PrintMessage (3, "blockfill local h"); diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshtype.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshtype.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshtype.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshtype.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -148,13 +148,14 @@ 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 - & bcname; + & bcname + & epgeominfo[0].edgenr & epgeominfo[1].edgenr; } @@ -1027,6 +1028,9 @@ case 6: typ = PRISM; break; case 8: typ = HEX; break; case 10: typ = TET10; break; + case 13: typ = PYRAMID13; break; + case 15: typ = PRISM15; break; + case 20: typ = HEX20; break; default: cerr << "Element::Element: unknown element with " << np << " points" << endl; } orderx = ordery = orderz = 1; @@ -1069,9 +1073,9 @@ flags.fixed = 0; orderx = ordery = orderz = 1; is_curved = typ != TET; // false; -#ifdef PARALLEL - partitionNumber = -1; -#endif + // #ifdef PARALLEL + // partitionNumber = -1; + // #endif } @@ -1107,6 +1111,9 @@ case 6: typ = PRISM; break; case 8: typ = HEX; break; case 10: typ = TET10; break; + case 13: typ = PYRAMID13; break; + case 15: typ = PRISM15; break; + case 20: typ = HEX20; break; // default: break; cerr << "Element::SetNP unknown element with " << np << " points" << endl; @@ -1125,11 +1132,15 @@ case PRISM: np = 6; break; case HEX: np = 8; break; case TET10: np = 10; break; + case PYRAMID13: np = 13; break; case PRISM12: np = 12; break; + case PRISM15: np = 15; break; + case HEX20: np = 20; break; default: break; cerr << "Element::SetType unknown type " << int(typ) << endl; } + is_curved = (np > 4); } @@ -1954,7 +1965,27 @@ shape(4) = p(2); break; } - + case PYRAMID13: + { + T x = p(0); + T y = p(1); + T z = p(2); + z *= 1-1e-12; + shape[0] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (-2*x - z + 2)*(-2*y - z + 2))*(-0.5*x - 0.5*y - 0.5*z + 0.25); + shape[1] = (0.5*x - 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(-2*y - z + 2)); + shape[2] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(2*y + z))*(0.5*x + 0.5*y + 0.5*z - 0.75); + shape[3] = (-0.5*x + 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*y + z)*(-2*x - z + 2)); + shape[4] = z*(2*z - 1); + shape[5] = 2*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + shape[6] = 4*x*y*(-2*x - 2*z + 2)/(-2*z + 2); + shape[7] = 2*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + shape[8] = 4*x*y*(-2*y - 2*z + 2)/(-2*z + 2); + shape[9] = z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); + shape[10] = 2*x*z*(-2*y - 2*z + 2)/(-z + 1); + shape[11] = 4*x*y*z/(-z + 1); + shape[12] = 2*y*z*(-2*x - 2*z + 2)/(-z + 1); + break; + } case PRISM: { shape(0) = p(0) * (1-p(2)); @@ -1965,6 +1996,30 @@ shape(5) = (1-p(0)-p(1)) * p(2); break; } + case PRISM15: + { + T x = p(0); + T y = p(1); + T z = p(2); + T lam = 1-x-y; + T lamz = 1-z; + shape[0] = (2*x*x-x) * (2*lamz*lamz-lamz); + shape[1] = (2*y*y-y) * (2*lamz*lamz-lamz); + shape[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); + shape[3] = (2*x*x-x) * (2*z*z-z); + shape[4] = (2*y*y-y) * (2*z*z-z); + shape[5] = (2*lam*lam-lam) * (2*z*z-z); + shape[6] = 4 * x * y * (2*lamz*lamz-lamz); + shape[7] = 4 * x * lam * (2*lamz*lamz-lamz); + shape[8] = 4 * y * lam * (2*lamz*lamz-lamz); + shape[9] = x * 4 * z * (1-z); + shape[10] = y * 4 * z * (1-z); + shape[11] = lam * 4 * z * (1-z); + shape[12] = 4 * x * y * (2*z*z-z); + shape[13] = 4 * x * lam * (2*z*z-z); + shape[14] = 4 * y * lam * (2*z*z-z); + break; + } case HEX: { shape(0) = (1-p(0))*(1-p(1))*(1-p(2)); @@ -1977,6 +2032,43 @@ shape(7) = (1-p(0))*( p(1))*( p(2)); break; } + case HEX20: + { + T x = p(0); + T y = p(1); + T z = p(2); + shape[0] = (1-x)*(1-y)*(1-z); + shape[1] = x *(1-y)*(1-z); + shape[2] = x * y *(1-z); + shape[3] = (1-x)* y *(1-z); + shape[4] = (1-x)*(1-y)*(z); + shape[5] = x *(1-y)*(z); + shape[6] = x * y *(z); + shape[7] = (1-x)* y *(z); + + T sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), + (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; + + static const int e[12][2] = + { + { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, + { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, + { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, + }; + + for (int i = 0; i < 12; i++) + { + T lame = shape[e[i][0]]+shape[e[i][1]]; + T xi = sigma[e[i][1]]-sigma[e[i][0]]; + shape[8+i] = (1-xi*xi)*lame; + } + for (int i = 0; i < 12; i++) + { + shape[e[i][0]] -= 0.5 * shape[8+i]; + shape[e[i][1]] -= 0.5 * shape[8+i]; + } + break; + } default: throw NgException("Element :: GetNewShape not implemented for that element"); } @@ -2426,9 +2518,9 @@ 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 ; @@ -2481,7 +2573,7 @@ maxidentnr = 0; } - ngstd::Archive & Identifications :: DoArchive (ngstd::Archive & ar) + void Identifications :: DoArchive (Archive & ar) { ar & maxidentnr; ar & identifiedpoints & identifiedpoints_nr; @@ -2502,7 +2594,6 @@ for (auto & t : type) ar & (unsigned char&)(t); } - return ar; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/meshtype.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/meshtype.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/meshtype.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/meshtype.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -21,8 +21,8 @@ SEGMENT = 1, SEGMENT3 = 2, TRIG = 10, QUAD=11, TRIG6 = 12, QUAD6 = 13, QUAD8 = 14, TET = 20, TET10 = 21, - PYRAMID = 22, PRISM = 23, PRISM12 = 24, - HEX = 25 + PYRAMID = 22, PRISM = 23, PRISM12 = 24, PRISM15 = 27, PYRAMID13 = 28, + HEX = 25, HEX20 = 26 }; /* @@ -45,7 +45,7 @@ }; -#define ELEMENT_MAXPOINTS 12 +#define ELEMENT_MAXPOINTS 20 #define ELEMENT2D_MAXPOINTS 8 @@ -171,13 +171,9 @@ 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 @@ 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 @@ 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)); @@ -392,9 +377,9 @@ unsigned int orderx:6; unsigned int ordery:6; -#ifdef PARALLEL - int partitionNumber; -#endif + // #ifdef PARALLEL + // int partitionNumber; + // #endif /// a linked list for all segments in the same face SurfaceElementIndex next; @@ -497,7 +482,7 @@ /// 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 @@ visible = _vis; deleted = _deleted; } for (size_t i = 0; i < np; i++) ar & pnum[i]; - return ar; } void SetIndex (int si) { index = si; } @@ -624,15 +608,14 @@ /// int hp_elnr; + /* #ifdef PARALLEL int GetPartition () const { return partitionNumber; } void SetPartition (int nr) { partitionNumber = nr; }; #endif + */ }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, Element2d & mp) - { return mp.DoArchive(archive); } - ostream & operator<<(ostream & s, const Element2d & el); @@ -666,7 +649,7 @@ /// ELEMENT_TYPE typ; /// number of points (4..tet, 5..pyramid, 6..prism, 8..hex, 10..quad tet, 12..quad prism) - int np:5; + int np:6; /// class flagstruct { public: @@ -695,11 +678,11 @@ float badness; bool is_curved:1; // element is (high order) curved -#ifdef PARALLEL + // #ifdef PARALLEL /// number of partition for parallel computation - int partitionNumber; + // int partitionNumber; -#endif + // #endif public: flagstruct flags; @@ -727,18 +710,21 @@ /// uint8_t GetNV() const { - __assume(typ >= TET && typ <= HEX); + __assume(typ >= TET && typ <= PYRAMID13); switch (typ) { case TET: case TET10: return 4; - case PRISM12: - case PRISM: + case PRISM12: + case PRISM15: + case PRISM: return 6; case PYRAMID: + case PYRAMID13: return 5; case HEX: + case HEX20: return 8; default: // not a 3D element #ifdef DEBUG @@ -765,6 +751,8 @@ FlatArray PNums () const { return FlatArray (np, &pnum[0]); } + FlatArray Vertices() const { return { GetNV(), &pnum[0] }; } + /// PointIndex & PNum (int i) { return pnum[i-1]; } /// @@ -774,17 +762,17 @@ /// const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; } - ngstd::Archive & DoArchive (ngstd::Archive & ar) + void DoArchive (Archive & ar) { short _np, _typ; + bool _curved; if (ar.Output()) - { _np = np; _typ = typ; } - ar & _np & _typ & index; + { _np = np; _typ = typ; _curved = is_curved; } + ar & _np & _typ & index & _curved; if (ar.Input()) - { np = _np; typ = ELEMENT_TYPE(_typ); } + { np = _np; typ = ELEMENT_TYPE(_typ); is_curved = _curved; } for (size_t i = 0; i < np; i++) ar & pnum[i]; - return ar; } /// @@ -814,10 +802,12 @@ { case TET: case TET10: return 4; - case PYRAMID: return 5; - case PRISM: + case PYRAMID: case PYRAMID13: return 5; + case PRISM: + case PRISM15: case PRISM12: return 5; - case HEX: return 6; + case HEX: case HEX20: + return 6; default: #ifdef DEBUG PrintSysError ("element3d::GetNFaces not implemented for typ", typ) @@ -917,20 +907,18 @@ bool IsCurved () const { return is_curved; } void SetCurved (bool acurved) { is_curved = acurved; } - + /* #ifdef PARALLEL int GetPartition () const { return partitionNumber; } void SetPartition (int nr) { partitionNumber = nr; }; #else int GetPartition () const { return 0; } #endif - + */ + int hp_elnr; }; - inline ngstd::Archive & operator & (ngstd::Archive & archive, Element & mp) - { return mp.DoArchive(archive); } - ostream & operator<<(ostream & s, const Element & el); @@ -985,10 +973,10 @@ /// int meshdocval; -#ifdef PARALLEL + // #ifdef PARALLEL /// number of partition for parallel computation - int partitionNumber; -#endif + // int partitionNumber; + // #endif private: string* bcname; @@ -1043,18 +1031,18 @@ bool IsCurved () const { return is_curved; } void SetCurved (bool acurved) { is_curved = acurved; } + /* #ifdef PARALLEL int GetPartition () const { return partitionNumber; } void SetPartition (int nr) { partitionNumber = nr; }; #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 +1050,7 @@ { public: PointIndex pnum; + string name; int index; Element0d () = default; Element0d (PointIndex _pnum, int _index) @@ -1142,13 +1131,9 @@ // 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 +1501,8 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/parallelmesh.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/parallelmesh.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/parallelmesh.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/parallelmesh.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -35,53 +35,24 @@ void Mesh :: SendRecvMesh () { - if (id == 0) - PrintMessage (1, "Send/Receive mesh"); + int id = GetCommunicator().Rank(); + int np = GetCommunicator().Size(); - { - // distribute global information - int nelglob, nseglob, nvglob; - if (id == 0) - { - paralleltop -> SetNV (GetNV()); - paralleltop -> SetNE (GetNE()); - paralleltop -> SetNSegm (GetNSeg()); - paralleltop -> SetNSE (GetNSE()); - - nelglob = GetNE(); - nseglob = GetNSE(); - nvglob = GetNV(); - } - - MyMPI_Bcast (dimension); - MyMPI_Bcast (nelglob); - MyMPI_Bcast (nseglob); - MyMPI_Bcast (nvglob); + if (np == 1) { + throw NgException("SendRecvMesh called, but only one rank in communicator!!"); } + + if (id == 0) + PrintMessage (1, "Send/Receive mesh"); - - - { - // distribute number of local elements - if (id == 0) - { - Array num_els_on_proc(ntasks); - num_els_on_proc = 0; - for (ElementIndex ei = 0; ei < GetNE(); ei++) - num_els_on_proc[(*this)[ei].GetPartition()]++; - - MPI_Scatter (&num_els_on_proc[0], 1, MPI_INT, - MPI_IN_PLACE, -1, MPI_INT, 0, MPI_COMM_WORLD); - } - else - { - int nelloc; - MPI_Scatter (NULL, 0, MPI_INT, - &nelloc, 1, MPI_INT, 0, MPI_COMM_WORLD); - - paralleltop -> SetNE (nelloc); - } - } + // Why is this here?? + if (id == 0) + { + paralleltop -> SetNV (GetNV()); + paralleltop -> SetNE (GetNE()); + paralleltop -> SetNSegm (GetNSeg()); + paralleltop -> SetNSE (GetNSE()); + } if (id == 0) SendMesh (); @@ -101,164 +72,217 @@ { Array sendrequests; - PrintMessage ( 3, "Sending vertices"); - + NgMPI_Comm comm = GetCommunicator(); + int id = comm.Rank(); + int ntasks = comm.Size(); + + int dim = GetDimension(); + MyMPI_Bcast(dim, comm); + + // If the topology is not already updated, we do not need to + // build edges/faces. + auto & top = const_cast(GetTopology()); + if(top.NeedsUpdate()) { + top.SetBuildEdges(false); + top.SetBuildFaces(false); + top.Update(); + } + + PrintMessage ( 3, "Sending nr of elements"); + Array num_els_on_proc(ntasks); num_els_on_proc = 0; for (ElementIndex ei = 0; ei < GetNE(); ei++) - num_els_on_proc[(*this)[ei].GetPartition()]++; + // num_els_on_proc[(*this)[ei].GetPartition()]++; + num_els_on_proc[vol_partition[ei]]++; + + MPI_Scatter (&num_els_on_proc[0], 1, MPI_INT, + MPI_IN_PLACE, -1, MPI_INT, 0, comm); TABLE els_of_proc (num_els_on_proc); for (ElementIndex ei = 0; ei < GetNE(); ei++) - els_of_proc.Add ( (*this)[ei].GetPartition(), ei); + // els_of_proc.Add ( (*this)[ei].GetPartition(), ei); + els_of_proc.Add (vol_partition[ei], ei); + PrintMessage ( 3, "Building vertex/proc mapping"); Array num_sels_on_proc(ntasks); num_sels_on_proc = 0; for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++) - num_sels_on_proc[(*this)[ei].GetPartition()]++; + // num_sels_on_proc[(*this)[ei].GetPartition()]++; + num_sels_on_proc[surf_partition[ei]]++; TABLE sels_of_proc (num_sels_on_proc); for (SurfaceElementIndex ei = 0; ei < GetNSE(); ei++) - sels_of_proc.Add ( (*this)[ei].GetPartition(), ei); + // sels_of_proc.Add ( (*this)[ei].GetPartition(), ei); + sels_of_proc.Add (surf_partition[ei], ei); Array num_segs_on_proc(ntasks); num_segs_on_proc = 0; for (SegmentIndex ei = 0; ei < GetNSeg(); ei++) - num_segs_on_proc[(*this)[ei].GetPartition()]++; + // num_segs_on_proc[(*this)[ei].GetPartition()]++; + num_segs_on_proc[seg_partition[ei]]++; TABLE segs_of_proc (num_segs_on_proc); for (SegmentIndex ei = 0; ei < GetNSeg(); ei++) - segs_of_proc.Add ( (*this)[ei].GetPartition(), ei); + segs_of_proc.Add (seg_partition[ei], ei); + /** + ----- STRATEGY FOR PERIODIC MESHES ----- + Whenever two vertices are identified by periodicity, any proc + that gets one of the vertices actually gets both of them. + This has to be transitive, that is, if + a <-> b and b <-> c, + then any proc that has vertex a also has vertices b and c! + + Surfaceelements and Segments that are identified by + periodicity are treated the same way. + + We need to duplicate these so we have containers to + hold the edges/facets. Afaik, a mesh cannot have nodes + that are not part of some sort of element. + + **/ + + /** First, we build tables for vertex identification. **/ + Array per_pairs; + Array pp2; + auto & idents = GetIdentifications(); + bool has_periodic = false; + for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) + { + if(idents.GetType(idnr)!=Identifications::PERIODIC) continue; + has_periodic = true; + idents.GetPairs(idnr, pp2); + per_pairs.Append(pp2); + } + Array npvs(GetNV()); + npvs = 0; + for (int k = 0; k < per_pairs.Size(); k++) { + npvs[per_pairs[k].I1()]++; + npvs[per_pairs[k].I2()]++; + } - Array vert_flag (GetNV()); - Array num_procs_on_vert (GetNV()); - Array num_verts_on_proc (ntasks); - - num_verts_on_proc = 0; - num_procs_on_vert = 0; - vert_flag = -1; - - - for (int dest = 1; dest < ntasks; dest++) - { - FlatArray els = els_of_proc[dest]; - for (int hi = 0; hi < els.Size(); hi++) - { - const Element & el = (*this) [ els[hi] ]; - for (int i = 0; i < el.GetNP(); i++) - { - PointIndex epi = el[i]; - if (vert_flag[epi] < dest) - { - vert_flag[epi] = dest; - - num_verts_on_proc[dest]++; - num_procs_on_vert[epi]++; - - paralleltop -> SetDistantPNum (dest, epi); - } - } - } - - - FlatArray sels = sels_of_proc[dest]; - for (int hi = 0; hi < sels.Size(); hi++) - { - const Element2d & el = (*this) [ sels[hi] ]; - for (int i = 0; i < el.GetNP(); i++) - { - PointIndex epi = el[i]; - if (vert_flag[epi] < dest) - { - vert_flag[epi] = dest; - - num_verts_on_proc[dest]++; - num_procs_on_vert[epi]++; - - paralleltop -> SetDistantPNum (dest, epi); - } - } - } + /** for each vertex, gives us all identified vertices **/ + TABLE per_verts(npvs); + for (int k = 0; k < per_pairs.Size(); k++) { + per_verts.Add(per_pairs[k].I1(), per_pairs[k].I2()); + per_verts.Add(per_pairs[k].I2(), per_pairs[k].I1()); + } + for (int k = PointIndex::BASE; k < GetNV()+PointIndex::BASE; k++) { + BubbleSort(per_verts[k]); + } - FlatArray segs = segs_of_proc[dest]; - for (int hi = 0; hi < segs.Size(); hi++) - { - const Segment & el = (*this) [segs[hi]]; - for (int i = 0; i < 2; i++) + /** The same table as per_verts, but TRANSITIVE!! **/ + auto iterate_per_verts_trans = [&](auto f){ + Array allvs; + for (int k = PointIndex::BASE; k < GetNV()+PointIndex::BASE; k++) + { + allvs.SetSize(0); + allvs.Append(per_verts[k]); + bool changed = true; + while(changed) { + changed = false; + for (int j = 0; j SetDistantPNum (dest, epi); + auto addv = pervs2[l]; + if (allvs.Contains(addv) || addv==k) continue; + changed = true; + allvs.Append(addv); } } } - } + f(k, allvs); + } + }; + iterate_per_verts_trans([&](auto k, auto & allvs) { + npvs[k] = allvs.Size(); + }); + TABLE per_verts_trans(npvs); + iterate_per_verts_trans([&](auto k, auto & allvs) { + for (int j = 0; j vert_flag (GetNV()); + Array num_procs_on_vert (GetNV()); + Array num_verts_on_proc (ntasks); + num_verts_on_proc = 0; + num_procs_on_vert = 0; + auto iterate_vertices = [&](auto f) { + vert_flag = -1; + for (int dest = 1; dest < ntasks; dest++) + { + FlatArray els = els_of_proc[dest]; + for (int hi = 0; hi < els.Size(); hi++) + { + const Element & el = (*this) [ els[hi] ]; + for (int i = 0; i < el.GetNP(); i++) + f(el[i], dest); + } + FlatArray sels = sels_of_proc[dest]; + for (int hi = 0; hi < sels.Size(); hi++) + { + const Element2d & el = (*this) [ sels[hi] ]; + for (int i = 0; i < el.GetNP(); i++) + f(el[i], dest); + } + FlatArray segs = segs_of_proc[dest]; + for (int hi = 0; hi < segs.Size(); hi++) + { + const Segment & el = (*this) [segs[hi]]; + for (int i = 0; i < 2; i++) + f(el[i], dest); + } + } + }; + /** count vertices per proc and procs per vertex **/ + iterate_vertices([&](auto vertex, auto dest){ + auto countit = [&] (auto vertex, auto dest) { + if (vert_flag[vertex] < dest) + { + vert_flag[vertex] = dest; + num_verts_on_proc[dest]++; + num_procs_on_vert[vertex]++; + GetParallelTopology().SetDistantPNum (dest, vertex); + } + }; + countit(vertex, dest); + auto pers = per_verts_trans[vertex]; + for(int j = 0; j < pers.Size(); j++) + countit(pers[j], dest); + }); TABLE verts_of_proc (num_verts_on_proc); TABLE procs_of_vert (num_procs_on_vert); TABLE loc_num_of_vert (num_procs_on_vert); - - vert_flag = -1; - for (int dest = 1; dest < ntasks; dest++) - { - FlatArray els = els_of_proc[dest]; - for (int hi = 0; hi < els.Size(); hi++) - { - const Element & el = (*this) [ els[hi] ]; - for (int i = 0; i < el.GetNP(); i++) - { - PointIndex epi = el[i]; - if (vert_flag[epi] < dest) - { - vert_flag[epi] = dest; - procs_of_vert.Add (epi, dest); - } - } - } - - FlatArray sels = sels_of_proc[dest]; - for (int hi = 0; hi < sels.Size(); hi++) - { - const Element2d & el = (*this) [ sels[hi] ]; - for (int i = 0; i < el.GetNP(); i++) - { - PointIndex epi = el[i]; - if (vert_flag[epi] < dest) - { - vert_flag[epi] = dest; - procs_of_vert.Add (epi, dest); - } - } - } - - FlatArray segs = segs_of_proc[dest]; - for (int hi = 0; hi < segs.Size(); hi++) - { - const Segment & el = (*this) [ segs[hi] ]; - for (int i = 0; i < 2; i++) - { - PointIndex epi = el[i]; - if (vert_flag[epi] < dest) - { - vert_flag[epi] = dest; - procs_of_vert.Add (epi, dest); - } - } - } - - } - + /** Write vertex/proc mappingfs to tables **/ + iterate_vertices([&](auto vertex, auto dest) { + auto addit = [&] (auto vertex, auto dest) { + if (vert_flag[vertex] < dest) + { + vert_flag[vertex] = dest; + procs_of_vert.Add (vertex, dest); + } + }; + addit(vertex, dest); + auto pers = per_verts_trans[vertex]; + for(int j = 0; j < pers.Size(); j++) + addit(pers[j], dest); + }); + /** + local vertex numbers on distant procs + (I think this was only used for debugging??) + **/ for (int vert = 1; vert <= GetNP(); vert++ ) { FlatArray procs = procs_of_vert[vert]; @@ -269,11 +293,12 @@ loc_num_of_vert.Add (vert, verts_of_proc[dest].Size()); } } + PrintMessage ( 3, "Sending Vertices - vertices"); for (int dest = 1; dest < ntasks; dest++) { FlatArray verts = verts_of_proc[dest]; - sendrequests.Append (MyMPI_ISend (verts, dest, MPI_TAG_MESH+1)); + sendrequests.Append (MyMPI_ISend (verts, dest, MPI_TAG_MESH+1, comm)); MPI_Datatype mptype = MeshPoint::MyGetMPIType(); @@ -289,13 +314,77 @@ MPI_Type_commit (&newtype); MPI_Request request; - MPI_Isend( &points[0], 1, newtype, dest, MPI_TAG_MESH+1, MPI_COMM_WORLD, &request); + MPI_Isend( &points[0], 1, newtype, dest, MPI_TAG_MESH+1, comm, &request); sendrequests.Append (request); } Array num_distpnums(ntasks); num_distpnums = 0; + + /** + Next, we send the identifications themselfs. + + Info about periodic identifications sent to each proc is an array of + integers. + - maxidentnr + - type for each identification + - nr of pairs for each identification (each pair is local!) + - pairs for each periodic ident (global numbers) + **/ + PrintMessage ( 3, "Sending Vertices - identifications"); + int maxidentnr = idents.GetMaxNr(); + Array ppd_sizes(ntasks); + ppd_sizes = 1 + 2*maxidentnr; + for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) + { + if(idents.GetType(idnr)!=Identifications::PERIODIC) continue; + idents.GetPairs(idnr, pp2); + for(int j = 0; j pp_data(ppd_sizes); + for(int dest = 0; dest < ntasks; dest++) + pp_data.Add(dest, maxidentnr); + for (int dest = 0; dest < ntasks; dest++) + { + for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) + pp_data.Add(dest, idents.GetType(idnr)); + for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) + pp_data.Add(dest, 0); + } + for (int idnr = 1; idnr < idents.GetMaxNr()+1; idnr++) + { + if(idents.GetType(idnr)!=Identifications::PERIODIC) continue; + idents.GetPairs(idnr, pp2); + for(int j = 0; j req_per; + for(int dest = 1; dest < ntasks; dest++) + req_per.Append(MyMPI_ISend(pp_data[dest], dest, MPI_TAG_MESH+1, comm)); + MPI_Waitall(req_per.Size(), &req_per[0], MPI_STATUS_IGNORE); + + PrintMessage ( 3, "Sending Vertices - distprocs"); + for (int vert = 1; vert <= GetNP(); vert++) { FlatArray procs = procs_of_vert[vert]; @@ -319,7 +408,7 @@ } for ( int dest = 1; dest < ntasks; dest ++ ) - sendrequests.Append (MyMPI_ISend (distpnums[dest], dest, MPI_TAG_MESH+1)); + sendrequests.Append (MyMPI_ISend (distpnums[dest], dest, MPI_TAG_MESH+1, comm)); @@ -330,7 +419,8 @@ for ( int ei = 1; ei <= GetNE(); ei++) { const Element & el = VolumeElement (ei); - int dest = el.GetPartition(); + // int dest = el.GetPartition(); + int dest = vol_partition[ei-1]; elarraysize[dest] += 3 + el.GetNP(); } @@ -339,8 +429,9 @@ for (int ei = 1; ei <= GetNE(); ei++) { const Element & el = VolumeElement (ei); - int dest = el.GetPartition(); - + // int dest = el.GetPartition(); + int dest = vol_partition[ei-1]; + elementarrays.Add (dest, ei); elementarrays.Add (dest, el.GetIndex()); elementarrays.Add (dest, el.GetNP()); @@ -349,7 +440,7 @@ } for (int dest = 1; dest < ntasks; dest ++ ) - sendrequests.Append (MyMPI_ISend (elementarrays[dest], dest, MPI_TAG_MESH+2)); + sendrequests.Append (MyMPI_ISend (elementarrays[dest], dest, MPI_TAG_MESH+2, comm)); PrintMessage ( 3, "Sending Face Descriptors" ); @@ -366,217 +457,328 @@ } for (int dest = 1; dest < ntasks; dest++) - sendrequests.Append (MyMPI_ISend (fddata, dest, MPI_TAG_MESH+3)); + sendrequests.Append (MyMPI_ISend (fddata, dest, MPI_TAG_MESH+3, comm)); + + /** Surface Elements **/ PrintMessage ( 3, "Sending Surface elements" ); - - Array nlocsel(ntasks), bufsize(ntasks); + // build sel-identification + size_t nse = GetNSE(); + Array ided_sel(nse); + ided_sel = -1; + bool has_ided_sels = false; + if(GetNE() && has_periodic) //we can only have identified surf-els if we have vol-els (right?) + { + Array os1, os2; + for(SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + { + if(ided_sel[sei]!=-1) continue; + const Element2d & sel = (*this)[sei]; + FlatArray points = sel.PNums(); + auto ided1 = per_verts[points[0]]; + os1.SetSize(0); + for (int j = 0; j < ided1.Size(); j++) + os1.Append(GetTopology().GetVertexSurfaceElements(ided1[j])); + for (int j = 1; j < points.Size(); j++) + { + os2.SetSize(0); + auto p2 = points[j]; + auto ided2 = per_verts[p2]; + for (int l = 0; l < ided2.Size(); l++) + os2.Append(GetTopology().GetVertexSurfaceElements(ided2[l])); + for (int m = 0; m1) { + throw NgException("SurfaceElement identified with more than one other??"); + } + const Element2d & sel2 = (*this)[sei]; + FlatArray points2 = sel2.PNums(); + has_ided_sels = true; + ided_sel[sei] = os1[0]; + ided_sel[os1[0]] = sei; + } + } + // build sel data to send + auto iterate_sels = [&](auto f) { + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++ ) + { + const Element2d & sel = (*this)[sei]; + // int dest = (*this)[sei].GetPartition(); + int dest = surf_partition[sei]; + f(sei, sel, dest); + if(ided_sel[sei]!=-1) + { + // int dest2 = (*this)[ided_sel[sei]].GetPartition(); + int dest2 = surf_partition[ided_sel[sei]]; + f(sei, sel, dest2); + } + } + }; + Array nlocsel(ntasks), bufsize(ntasks); nlocsel = 0; bufsize = 1; - - for (int sei = 1; sei <= GetNSE(); sei++ ) - { - const Element2d & sel = SurfaceElement (sei); - int dest = sel.GetPartition(); - nlocsel[dest] ++; + iterate_sels([&](SurfaceElementIndex sei, const Element2d & sel, int dest){ + nlocsel[dest]++; bufsize[dest] += 4 + 2*sel.GetNP(); - } - + }); TABLE selbuf(bufsize); - for (int dest = 1; dest < ntasks; dest++ ) selbuf.Add (dest, nlocsel[dest]); - - for (int sei = 1; sei <= GetNSE(); sei ++ ) - { - const Element2d & sel = SurfaceElement (sei); - int dest = sel.GetPartition(); - + iterate_sels([&](SurfaceElementIndex sei, const auto & sel, int dest) { selbuf.Add (dest, sei); selbuf.Add (dest, sel.GetIndex()); // selbuf.Add (dest, 0); selbuf.Add (dest, sel.GetNP()); - for ( int ii = 1; ii <= sel.GetNP(); ii++) { selbuf.Add (dest, sel.PNum(ii)); selbuf.Add (dest, sel.GeomInfoPi(ii).trignum); } - } - + }); + // distribute sel data for (int dest = 1; dest < ntasks; dest++) - sendrequests.Append (MyMPI_ISend(selbuf[dest], dest, MPI_TAG_MESH+4)); - - - PrintMessage ( 3, "Sending Edge Segments"); - + sendrequests.Append (MyMPI_ISend(selbuf[dest], dest, MPI_TAG_MESH+4, comm)); - Array nloc(ntasks); - nloc = 0; - bufsize = 1; - - for (int i = 1; i <= GetNSeg(); i++ ) - { - const Segment & seg = LineSegment (i); - int dest = seg.GetPartition(); - nloc[dest] ++; - bufsize[dest] += 14; - } - - TABLE segm_buf(bufsize); - - /* - for (int dest = 1; dest < ntasks; dest++ ) - segm_buf.Add (dest, nloc[dest]); - */ - for (int i = 1; i <= GetNSeg(); i++ ) - { - const Segment & seg = LineSegment (i); - int dest = seg.GetPartition(); - - segm_buf.Add (dest, i); - segm_buf.Add (dest, seg.si); - segm_buf.Add (dest, seg.pnums[0]); - segm_buf.Add (dest, seg.pnums[1]); - segm_buf.Add (dest, seg.geominfo[0].trignum); - segm_buf.Add (dest, seg.geominfo[1].trignum); - segm_buf.Add (dest, seg.surfnr1); - segm_buf.Add (dest, seg.surfnr2); - segm_buf.Add (dest, seg.edgenr); - segm_buf.Add (dest, seg.epgeominfo[0].dist); - segm_buf.Add (dest, seg.epgeominfo[1].edgenr); - segm_buf.Add (dest, seg.epgeominfo[1].dist); - segm_buf.Add (dest, seg.singedge_right); - segm_buf.Add (dest, seg.singedge_left); - } - - for (int dest = 1; dest < ntasks; dest++) - sendrequests.Append (MyMPI_ISend(segm_buf[dest], dest, MPI_TAG_MESH+5)); - /* - Array nlocseg(ntasks), segi(ntasks); - for ( int i = 0; i < ntasks; i++) - { - nlocseg[i] = 0; - bufsize[i] = 0; - segi[i] = 0; - } - - for (int segi = 1; segi <= GetNSeg(); segi ++ ) - { - Array volels; - const MeshTopology & topol = GetTopology(); - topol . GetSegmentSurfaceElements ( segi, volels ); - for (int j = 0; j < volels.Size(); j++) - { - int ei = volels[j]; - if ( ei > 0 && ei <= GetNSE() ) - { - const Element2d & el = SurfaceElement (ei); - int dest = el.GetPartition(); - nlocseg[dest] ++; - bufsize[dest] += 14; - } + /** Segments **/ + PrintMessage ( 3, "Sending Edge Segments"); + auto iterate_segs1 = [&](auto f) { + Array osegs1, osegs2, osegs_both; + Array type1, type2; + for(SegmentIndex segi = 0; segi < GetNSeg(); segi++) + { + const Segment & seg = (*this)[segi]; + int segnp = seg.GetNP(); + PointIndex pi1 = seg[0]; + auto ided1 = per_verts[pi1]; + PointIndex pi2 = seg[1]; + auto ided2 = per_verts[pi2]; + if (!(ided1.Size() && ided2.Size())) continue; + osegs1.SetSize(0); + type1.SetSize(0); + for (int l = 0; l segmbuf(bufsize); - - for ( int ls=1; ls <= GetNSeg(); ls++) + for(int l = 0; l per_seg_size(GetNSeg()); + per_seg_size = 0; + iterate_segs1([&](SegmentIndex segi1, SegmentIndex segi2) + { per_seg_size[segi1]++; }); + TABLE per_seg(per_seg_size); + iterate_segs1([&](SegmentIndex segi1, SegmentIndex segi2) + { per_seg.Add(segi1, segi2); }); + // make per_seg transitive + auto iterate_per_seg_trans = [&](auto f){ + Array allsegs; + for (SegmentIndex segi = 0; segi < GetNSeg(); segi++) + { + allsegs.SetSize(0); + allsegs.Append(per_seg[segi]); + bool changed = true; + while (changed) + { + changed = false; + for (int j = 0; j & segs){ + for (int j = 0; j < segs.Size(); j++) + per_seg_size[segi] = segs.Size(); + }); + TABLE per_seg_trans(per_seg_size); + iterate_per_seg_trans([&](SegmentIndex segi, Array & segs){ + for (int j = 0; j < segs.Size(); j++) + per_seg_trans.Add(segi, segs[j]); + }); + // build segment data + Array dests; + auto iterate_segs2 = [&](auto f) { - Array volels; - GetTopology().GetSegmentSurfaceElements ( ls, volels ); - const Segment & seg = LineSegment (ls); - - for (int j = 0; j < volels.Size(); j++) - { - int ei = volels[j]; - if ( ei > 0 && ei <= GetNSE() ) - { - const Element2d & el = SurfaceElement (ei); - int dest = el.GetPartition(); - - if ( dest > 0 ) - { - segmbuf.Add (dest, ls); - segmbuf.Add (dest, seg.si); - segmbuf.Add (dest, seg.pnums[0]); - segmbuf.Add (dest, seg.pnums[1]); - segmbuf.Add (dest, seg.geominfo[0].trignum); - segmbuf.Add (dest, seg.geominfo[1].trignum); - segmbuf.Add (dest, seg.surfnr1); - segmbuf.Add (dest, seg.surfnr2); - segmbuf.Add (dest, seg.edgenr); - segmbuf.Add (dest, seg.epgeominfo[0].dist); - segmbuf.Add (dest, seg.epgeominfo[1].edgenr); - segmbuf.Add (dest, seg.epgeominfo[1].dist); - segmbuf.Add (dest, seg.singedge_right); - segmbuf.Add (dest, seg.singedge_left); - segi[dest] += 14; - } - // paralleltop -> SetDistantSegm ( dest, ls, int ( segi[dest] / 14 ) ); + for (SegmentIndex segi = 0; segi nloc_seg(ntasks); + // bufsize = 1; //was originally this - why?? + bufsize = 0; + nloc_seg = 0; + iterate_segs2([&](auto segi, const auto & seg, int dest) + { + nloc_seg[dest]++; + bufsize[dest] += 14; + }); + TABLE segm_buf(bufsize); + iterate_segs2([&](auto segi, const auto & seg, int dest) + { + segm_buf.Add (dest, segi); + segm_buf.Add (dest, seg.si); + segm_buf.Add (dest, seg.pnums[0]); + segm_buf.Add (dest, seg.pnums[1]); + segm_buf.Add (dest, seg.geominfo[0].trignum); + segm_buf.Add (dest, seg.geominfo[1].trignum); + segm_buf.Add (dest, seg.surfnr1); + segm_buf.Add (dest, seg.surfnr2); + segm_buf.Add (dest, seg.edgenr); + segm_buf.Add (dest, seg.epgeominfo[0].dist); + segm_buf.Add (dest, seg.epgeominfo[1].edgenr); + segm_buf.Add (dest, seg.epgeominfo[1].dist); + segm_buf.Add (dest, seg.singedge_right); + segm_buf.Add (dest, seg.singedge_left); + }); + // distrubute segment data + for (int dest = 1; dest < ntasks; dest++) + sendrequests.Append (MyMPI_ISend(segm_buf[dest], dest, MPI_TAG_MESH+5, comm)); PrintMessage ( 3, "now wait ..."); MPI_Waitall (sendrequests.Size(), &sendrequests[0], MPI_STATUS_IGNORE); - PrintMessage ( 3, "Sending domain+bc - names"); + PrintMessage ( 3, "Sending names"); - sendrequests.SetSize(6*(ntasks-1)); - /** Send bc-names **/ - int nbcs = bcnames.Size(); - Array bcname_sizes(nbcs); - int tot_bcsize = 0; - for(int k=0;ksize(); - tot_bcsize += bcname_sizes[k]; - } - char compiled_bcnames[tot_bcsize]; - tot_bcsize = 0; - for(int k=0;k(1, &nbcs), k, MPI_TAG_MESH+6); - sendrequests[6*(k-1)+1] = MyMPI_ISend(bcname_sizes, k, MPI_TAG_MESH+6); - (void) MPI_Isend(compiled_bcnames, tot_bcsize, MPI_CHAR, k, MPI_TAG_MESH+6, MPI_COMM_WORLD, &sendrequests[6*(k-1)+2]); - } - - /** Send mat-names **/ - int nmats = materials.Size(); - Array mat_sizes(nmats); - int tot_matsize = 0; - for(int k=0;ksize(); - tot_matsize += mat_sizes[k]; - } - char compiled_mats[tot_matsize]; - tot_matsize = 0; - for(int k=0;k(1, &nmats), k, MPI_TAG_MESH+6); - sendrequests[6*(k-1)+4] = MyMPI_ISend(mat_sizes, k, MPI_TAG_MESH+6); - (void) MPI_Isend(compiled_mats, tot_matsize, MPI_CHAR, k, MPI_TAG_MESH+6, MPI_COMM_WORLD, &sendrequests[6*(k-1)+5]); - } + sendrequests.SetSize(3*ntasks); + /** Send bc/mat/cd*-names **/ + // nr of names + int nnames[4] = {0,0,0,0}; + nnames[0] = materials.Size(); + nnames[1] = bcnames.Size(); + nnames[2] = GetNCD2Names(); + nnames[3] = GetNCD3Names(); + int tot_nn = nnames[0] + nnames[1] + nnames[2] + nnames[3]; + for( int k = 1; k < ntasks; k++) + (void) MPI_Isend(nnames, 4, MPI_INT, k, MPI_TAG_MESH+6, comm, &sendrequests[k]); + auto iterate_names = [&](auto func) { + for (int k = 0; k < nnames[0]; k++) func(materials[k]); + for (int k = 0; k < nnames[1]; k++) func(bcnames[k]); + for (int k = 0; k < nnames[2]; k++) func(cd2names[k]); + for (int k = 0; k < nnames[3]; k++) func(cd3names[k]); + }; + // sizes of names + Array name_sizes(tot_nn); + tot_nn = 0; + iterate_names([&](auto ptr) { name_sizes[tot_nn++] = (ptr==NULL) ? 0 : ptr->size(); }); + for( int k = 1; k < ntasks; k++) + (void) MPI_Isend(&name_sizes[0], tot_nn, MPI_INT, k, MPI_TAG_MESH+6, comm, &sendrequests[ntasks+k]); + // names + int strs = 0; + iterate_names([&](auto ptr) { strs += (ptr==NULL) ? 0 : ptr->size(); }); + Array compiled_names(strs); + strs = 0; + iterate_names([&](auto ptr) { + if (ptr==NULL) return; + auto& name = *ptr; + for (int j=0; j < name.size(); j++) compiled_names[strs++] = name[j]; + }); + for( int k = 1; k < ntasks; k++) + (void) MPI_Isend(&(compiled_names[0]), strs, MPI_CHAR, k, MPI_TAG_MESH+6, comm, &sendrequests[2*ntasks+k]); - /* now wait ... **/ - PrintMessage( 3, "now wait for domain+bc - names"); + PrintMessage ( 3, "wait for names"); MPI_Waitall (sendrequests.Size(), &sendrequests[0], MPI_STATUS_IGNORE); - PrintMessage( 3, "send mesh complete"); + MPI_Barrier(comm); + + PrintMessage( 3, "Clean up local memory"); - MPI_Barrier(MPI_COMM_WORLD); + auto & self = const_cast(*this); + self.points = T_POINTS(0); + self.surfelements = T_SURFELEMENTS(0); + self.volelements = T_VOLELEMENTS(0); + self.segments = Array(0); + self.lockedpoints = Array(0); + auto cleanup_ptr = [](auto & ptr) { + if (ptr != nullptr) { + delete ptr; + ptr = nullptr; + } + }; + cleanup_ptr(self.boundaryedges); + cleanup_ptr(self.boundaryedges); + cleanup_ptr(self.segmentht); + cleanup_ptr(self.surfelementht); + self.openelements = Array(0); + self.opensegments = Array(0); + self.numvertices = 0; + self.mlbetweennodes = Array,PointIndex::BASE> (0); + self.mlparentelement = Array(0); + self.mlparentsurfaceelement = Array(0); + self.curvedelems = new CurvedElements (self); + self.clusters = new AnisotropicClusters (self); + self.ident = new Identifications (self); + self.topology = MeshTopology(*this); + self.topology.Update(); + self.BuildElementSearchTree(); + + // const_cast(*this).DeleteMesh(); + + PrintMessage( 3, "send mesh complete"); } @@ -595,14 +797,27 @@ int timer_sels = NgProfiler::CreateTimer ("Receive surface elements"); NgProfiler::RegionTimer reg(timer); - + NgMPI_Comm comm = GetCommunicator(); + int id = comm.Rank(); + int ntasks = comm.Size(); + + int dim; + MyMPI_Bcast(dim, comm); + SetDimension(dim); + + // Receive number of local elements + int nelloc; + MPI_Scatter (NULL, 0, MPI_INT, + &nelloc, 1, MPI_INT, 0, comm); + paralleltop -> SetNE (nelloc); + // string st; // receive vertices NgProfiler::StartTimer (timer_pts); Array verts; - MyMPI_Recv (verts, 0, MPI_TAG_MESH+1); + MyMPI_Recv (verts, 0, MPI_TAG_MESH+1, comm); int numvert = verts.Size(); paralleltop -> SetNV (numvert); @@ -622,10 +837,34 @@ MPI_Datatype mptype = MeshPoint::MyGetMPIType(); MPI_Status status; - MPI_Recv( &points[1], numvert, mptype, 0, MPI_TAG_MESH+1, MPI_COMM_WORLD, &status); + MPI_Recv( &points[1], numvert, mptype, 0, MPI_TAG_MESH+1, comm, &status); + + Array pp_data; + MyMPI_Recv(pp_data, 0, MPI_TAG_MESH+1, comm); + + int maxidentnr = pp_data[0]; + auto & idents = GetIdentifications(); + for (int idnr = 1; idnr < maxidentnr+1; idnr++) + { + + idents.SetType(idnr, (Identifications::ID_TYPE)pp_data[idnr]); + } + + int offset = 2*maxidentnr+1; + for(int idnr = 1; idnr < maxidentnr+1; idnr++) + { + int npairs = pp_data[maxidentnr+idnr]; + FlatArray pairdata(2*npairs, &pp_data[offset]); + offset += 2*npairs; + for (int k = 0; k dist_pnums; - MyMPI_Recv (dist_pnums, 0, MPI_TAG_MESH+1); + MyMPI_Recv (dist_pnums, 0, MPI_TAG_MESH+1, comm); for (int hi = 0; hi < dist_pnums.Size(); hi += 3) paralleltop -> @@ -635,19 +874,18 @@ *testout << "got " << numvert << " vertices" << endl; { - Element el; - Array elarray; - MyMPI_Recv (elarray, 0, MPI_TAG_MESH+2); + MyMPI_Recv (elarray, 0, MPI_TAG_MESH+2, comm); NgProfiler::RegionTimer reg(timer_els); for (int ind = 0, elnum = 1; ind < elarray.Size(); elnum++) { paralleltop->SetLoc2Glob_VolEl ( elnum, elarray[ind++]); - - el.SetIndex(elarray[ind++]); - el.SetNP(elarray[ind++]); + + int index = elarray[ind++]; + Element el(elarray[ind++]); + el.SetIndex(index); for ( int j = 0; j < el.GetNP(); j++) el[j] = glob2loc_vert_ht.Get (elarray[ind++]); @@ -658,7 +896,7 @@ { Array fddata; - MyMPI_Recv (fddata, 0, MPI_TAG_MESH+3); + MyMPI_Recv (fddata, 0, MPI_TAG_MESH+3, comm); for (int i = 0; i < fddata.Size(); i += 6) { int faceind = AddFaceDescriptor @@ -673,7 +911,7 @@ NgProfiler::RegionTimer reg(timer_sels); Array selbuf; - MyMPI_Recv ( selbuf, 0, MPI_TAG_MESH+4); + MyMPI_Recv ( selbuf, 0, MPI_TAG_MESH+4, comm); int ii = 0; int sel = 0; @@ -694,7 +932,6 @@ tri.PNum(j) = glob2loc_vert_ht.Get (selbuf[ii++]); tri.GeomInfoPi(j).trignum = selbuf[ii++]; } - paralleltop->SetLoc2Glob_SurfEl ( sel+1, globsel ); AddSurfaceElement (tri); sel ++; @@ -705,7 +942,7 @@ { Array segmbuf; - MyMPI_Recv ( segmbuf, 0, MPI_TAG_MESH+5); + MyMPI_Recv ( segmbuf, 0, MPI_TAG_MESH+5, comm); Segment seg; int globsegi; @@ -749,42 +986,37 @@ } /** Recv bc-names **/ - int nbcs; - MyMPI_Recv(nbcs, 0, MPI_TAG_MESH+6); - Array bcs(nbcs); - MyMPI_Recv(bcs, 0, MPI_TAG_MESH+6); - int size_bc = 0; - for(int k=0;k matsz(nmats); - MyMPI_Recv(matsz, 0, MPI_TAG_MESH+6); - int size_mats = 0; - for(int k=0;k name_sizes(tot_nn); + MPI_Recv(&name_sizes[0], tot_nn, MPI_INT, 0, MPI_TAG_MESH+6, comm, MPI_STATUS_IGNORE); + int tot_size = 0; + for (int k = 0; k < tot_nn; k++) tot_size += name_sizes[k]; + + Array compiled_names(tot_size); + MPI_Recv(&(compiled_names[0]), tot_size, MPI_CHAR, 0, MPI_TAG_MESH+6, comm, MPI_STATUS_IGNORE); + + tot_nn = tot_size = 0; + auto write_names = [&] (auto & array) { + for (int k = 0; k < array.Size(); k++) { + int s = name_sizes[tot_nn]; + array[k] = new string(&compiled_names[tot_size], s); + tot_nn++; + tot_size += s; + } + }; + write_names(materials); + write_names(bcnames); + write_names(cd2names); + write_names(cd3names); - MPI_Barrier(MPI_COMM_WORLD); + MPI_Barrier(comm); int timerloc = NgProfiler::CreateTimer ("Update local mesh"); int timerloc2 = NgProfiler::CreateTimer ("CalcSurfacesOfNode"); @@ -793,7 +1025,8 @@ stringstream str; str << "p" << id << ": got " << GetNE() << " elements and " << GetNSE() << " surface elements"; - cout << str.str() << endl; + PrintMessage(2, str.str()); + // cout << str.str() << endl; // PrintMessage (2, "Got ", GetNE(), " elements and ", GetNSE(), " surface elements"); // PrintMessage (2, "Got ", GetNSE(), " surface elements"); @@ -819,8 +1052,9 @@ // call it only for the master ! void Mesh :: Distribute () { - MPI_Comm_size(MPI_COMM_WORLD, &ntasks); - MPI_Comm_rank(MPI_COMM_WORLD, &id); + NgMPI_Comm comm = GetCommunicator(); + int id = comm.Rank(); + int ntasks = comm.Size(); if (id != 0 || ntasks == 1 ) return; @@ -879,75 +1113,133 @@ eptr.Append (eind.Size()); Array epart(ne), npart(nn); - idxtype nparts = ntasks-1; - idxtype edgecut; + idxtype nparts = GetCommunicator().Size()-1; - idxtype ncommon = 3; - METIS_PartMeshDual (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &ncommon, &nparts, - NULL, NULL, - &edgecut, &epart[0], &npart[0]); + vol_partition.SetSize(GetNE()); + surf_partition.SetSize(GetNSE()); + seg_partition.SetSize(GetNSeg()); + if (nparts == 1) + { + for (int i = 0; i < GetNE(); i++) + // VolumeElement(i+1).SetPartition(1); + vol_partition[i]= 1; + for (int i = 0; i < GetNSE(); i++) + // SurfaceElement(i+1).SetPartition(1); + surf_partition[i] = 1; + for (int i = 0; i < GetNSeg(); i++) + // LineSegment(i+1).SetPartition(1); + seg_partition[i] = 1; + } - /* - METIS_PartMeshNodal (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &nparts, - NULL, NULL, - &edgecut, &epart[0], &npart[0]); - */ - PrintMessage (3, "metis complete"); - // cout << "done" << endl; + else + + { - for (int i = 0; i < GetNE(); i++) - VolumeElement(i+1).SetPartition(epart[i] + 1); - for (int i = 0; i < GetNSE(); i++) - SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1); - for (int i = 0; i < GetNSeg(); i++) - LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1); + idxtype edgecut; + + idxtype ncommon = 3; + METIS_PartMeshDual (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &ncommon, &nparts, + NULL, NULL, + &edgecut, &epart[0], &npart[0]); + + /* + METIS_PartMeshNodal (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &nparts, + NULL, NULL, + &edgecut, &epart[0], &npart[0]); + */ + PrintMessage (3, "metis complete"); + // cout << "done" << endl; + + for (int i = 0; i < GetNE(); i++) + // VolumeElement(i+1).SetPartition(epart[i] + 1); + vol_partition[i]= epart[i] + 1; + for (int i = 0; i < GetNSE(); i++) + // SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1); + surf_partition[i] = epart[i+GetNE()] + 1; + for (int i = 0; i < GetNSeg(); i++) + // LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1); + seg_partition[i] = epart[i+GetNE()+GetNSE()] + 1; + } + + + // surface elements attached to volume elements + Array boundarypoints (GetNP()); + boundarypoints = false; + + if(GetDimension() == 3) + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + { + const Element2d & el = (*this)[sei]; + for (int j = 0; j < el.GetNP(); j++) + boundarypoints[el[j]] = true; + } + else + for (SegmentIndex segi = 0; segi < GetNSeg(); segi++) + { + const Segment & seg = (*this)[segi]; + for (int j = 0; j < 2; j++) + boundarypoints[seg[j]] = true; + } + + + // Build Pnt2Element table, boundary points only + Array cnt(GetNP()); + cnt = 0; + auto loop_els_2d = [&](auto f) { + for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) + { + const Element2d & el = (*this)[sei]; + for (int j = 0; j < el.GetNP(); j++) { + f(el[j], sei); + } + } + }; + auto loop_els_3d = [&](auto f) { + for (ElementIndex ei = 0; ei < GetNE(); ei++) + { + const Element & el = (*this)[ei]; + for (int j = 0; j < el.GetNP(); j++) + f(el[j], ei); + } + }; + auto loop_els = [&](auto f) + { + if (GetDimension() == 3 ) + loop_els_3d(f); + else + loop_els_2d(f); + }; + + + loop_els([&](auto vertex, int index) + { + if(boundarypoints[vertex]) + cnt[vertex]++; + }); + TABLE pnt2el(cnt); + loop_els([&](auto vertex, int index) + { + if(boundarypoints[vertex]) + pnt2el.Add(vertex, index); + }); if (GetDimension() == 3) { - - // surface elements attached to volume elements - Array boundarypoints (GetNP()); - boundarypoints = false; - - for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) - { - const Element2d & el = (*this)[sei]; - for (int j = 0; j < el.GetNP(); j++) - boundarypoints[el[j]] = true; - } - // Build Pnt2Element table, boundary points only - Array cnt(GetNP()); - cnt = 0; - for (ElementIndex ei = 0; ei < GetNE(); ei++) - { - const Element & el = (*this)[ei]; - for (int j = 0; j < el.GetNP(); j++) - if (boundarypoints[el[j]]) - cnt[el[j]]++; - } - TABLE pnt2el(cnt); - cnt = 0; - for (ElementIndex ei = 0; ei < GetNE(); ei++) - { - const Element & el = (*this)[ei]; - for (int j = 0; j < el.GetNP(); j++) - if (boundarypoints[el[j]]) - pnt2el.Add (el[j], ei); - } - for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { Element2d & sel = (*this)[sei]; PointIndex pi1 = sel[0]; - FlatArray els = pnt2el[pi1]; + // FlatArray els = pnt2el[pi1]; + FlatArray els = pnt2el[pi1]; - sel.SetPartition (-1); + // sel.SetPartition (-1); + surf_partition[sei] = -1; for (int j = 0; j < els.Size(); j++) { - const Element & el = (*this)[els[j]]; + const Element & el = (*this)[ElementIndex(els[j])]; bool hasall = true; @@ -963,11 +1255,13 @@ if (hasall) { - sel.SetPartition (el.GetPartition()); + // sel.SetPartition (el.GetPartition()); + surf_partition[sei] = vol_partition[ElementIndex(els[j])]; break; } } - if (sel.GetPartition() == -1) + // if (sel.GetPartition() == -1) + if (surf_partition[sei] == -1) cerr << "no volume element found" << endl; } @@ -976,13 +1270,14 @@ { Segment & sel = (*this)[si]; PointIndex pi1 = sel[0]; - FlatArray els = pnt2el[pi1]; + FlatArray els = pnt2el[pi1]; - sel.SetPartition (-1); + // sel.SetPartition (-1); + seg_partition[si] = -1; for (int j = 0; j < els.Size(); j++) { - const Element & el = (*this)[els[j]]; + const Element & el = (*this)[ElementIndex(els[j])]; bool haspi[9] = { false }; // max surfnp @@ -997,14 +1292,48 @@ if (hasall) { - sel.SetPartition (el.GetPartition()); + // sel.SetPartition (el.GetPartition()); + seg_partition[si] = vol_partition[ElementIndex(els[j])]; break; } } - if (sel.GetPartition() == -1) + // if (sel.GetPartition() == -1) + if (seg_partition[si] == -1) cerr << "no volume element found" << endl; } - + } + else + { + for (SegmentIndex segi = 0; segi < GetNSeg(); segi++) + { + Segment & seg = (*this)[segi]; + // seg.SetPartition(-1); + seg_partition[segi] = -1; + PointIndex pi1 = seg[0]; + + FlatArray sels = pnt2el[pi1]; + for (int j = 0; j < sels.Size(); j++) + { + SurfaceElementIndex sei = sels[j]; + Element2d & se = (*this)[sei]; + bool found = false; + for (int l = 0; l < se.GetNP(); l++ && !found) + found |= (se[l]==seg[1]); + if(found) { + // seg.SetPartition(se.GetPartition()); + seg_partition[segi] = surf_partition[sei]; + break; + } + } + + // if (seg.GetPartition() == -1) { + if (seg_partition[segi] == -1) { + cout << endl << "segi: " << segi << endl; + cout << "points: " << seg[0] << " " << seg[1] << endl; + cout << "surfels: " << endl << sels << endl; + throw NgException("no surface element found"); + } + } } } @@ -1023,8 +1352,9 @@ // call it only for the master ! void Mesh :: Distribute (Array & volume_weights , Array & surface_weights, Array & segment_weights) { - MPI_Comm_size(MPI_COMM_WORLD, &ntasks); - MPI_Comm_rank(MPI_COMM_WORLD, &id); + NgMPI_Comm comm = GetCommunicator(); + int id = comm.Rank(); + int ntasks = comm.Size(); if (id != 0 || ntasks == 1 ) return; @@ -1114,7 +1444,26 @@ eptr.Append (eind.Size()); Array epart(ne), npart(nn); - idxtype nparts = ntasks-1; + idxtype nparts = GetCommunicator().Size()-1; + vol_partition.SetSize(GetNE()); + surf_partition.SetSize(GetNSE()); + seg_partition.SetSize(GetNSeg()); + + if (nparts == 1) + { + for (int i = 0; i < GetNE(); i++) + // VolumeElement(i+1).SetPartition(1); + vol_partition[i] = 1; + for (int i = 0; i < GetNSE(); i++) + // SurfaceElement(i+1).SetPartition(1); + surf_partition[i] = 1; + for (int i = 0; i < GetNSeg(); i++) + // LineSegment(i+1).SetPartition(1); + seg_partition[i] = 1; + return; + } + + idxtype edgecut; @@ -1131,11 +1480,14 @@ // cout << "done" << endl; for (int i = 0; i < GetNE(); i++) - VolumeElement(i+1).SetPartition(epart[i] + 1); + // VolumeElement(i+1).SetPartition(epart[i] + 1); + vol_partition[i] = epart[i] + 1; for (int i = 0; i < GetNSE(); i++) - SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1); + // SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1); + surf_partition[i] = epart[i+GetNE()] + 1; for (int i = 0; i < GetNSeg(); i++) - LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1); + // LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1); + seg_partition[i] = epart[i+GetNE()+GetNSE()] + 1; } #endif @@ -1363,7 +1715,7 @@ #endif Array nodesinpart(ntasks); - + vol_partition.SetSize(ne); for ( int el = 1; el <= ne; el++ ) { Element & volel = VolumeElement(el); @@ -1379,7 +1731,8 @@ if ( nodesinpart[i] > nodesinpart[partition] ) partition = i; - volel.SetPartition(partition); + // volel.SetPartition(partition); + vol_partition[el-1] = partition; } delete [] xadj; @@ -1481,13 +1834,14 @@ Array nodesinpart(ntasks); + vol_partition.SetSize(ne); for ( int el = 1; el <= ne; el++ ) { // Element & volel = VolumeElement(el); nodesinpart = 0; - VolumeElement(el).SetPartition(part[el-1 ] + 1); - + // VolumeElement(el).SetPartition(part[el-1 ] + 1); + vol_partition[el-1] = part[el-1 ] + 1; } /* @@ -1594,8 +1948,10 @@ #endif + surf_partition.SetSize(ne); for (SurfaceElementIndex sei = 0; sei < ne; sei++) - (*this) [sei].SetPartition (part[sei]+1); + // (*this) [sei].SetPartition (part[sei]+1); + surf_partition[sei] = part[sei]+1; #else cout << "partdualmesh not available" << endl; #endif diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/paralleltop.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/paralleltop.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/paralleltop.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/paralleltop.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -24,6 +24,10 @@ void ParallelMeshTopology :: Reset () { *testout << "ParallelMeshTopology::Reset" << endl; + + NgMPI_Comm comm = mesh.GetCommunicator(); + int id = comm.Rank(); + int ntasks = comm.Size(); if ( ntasks == 1 ) return; @@ -122,7 +126,8 @@ *testout << "ParallelMeshTopology :: UpdateCoarseGridGlobal" << endl; const MeshTopology & topology = mesh.GetTopology(); - + MPI_Comm comm = mesh.GetCommunicator(); + if ( id == 0 ) { Array*> sendarrays(ntasks); @@ -136,7 +141,8 @@ topology.GetElementEdges (el, edges); const Element & volel = mesh.VolumeElement (el); - Array & sendarray = *sendarrays[volel.GetPartition()]; + // Array & sendarray = *sendarrays[volel.GetPartition()]; + Array & sendarray = *sendarrays[mesh.vol_partition[el-1]]; for ( int i = 0; i < edges.Size(); i++ ) sendarray.Append (edges[i]); @@ -148,7 +154,8 @@ { topology.GetSurfaceElementEdges (el, edges); const Element2d & surfel = mesh.SurfaceElement (el); - Array & sendarray = *sendarrays[surfel.GetPartition()]; + // Array & sendarray = *sendarrays[surfel.GetPartition()]; + Array & sendarray = *sendarrays[mesh.surf_partition[el-1]]; for ( int i = 0; i < edges.Size(); i++ ) sendarray.Append (edges[i]); @@ -157,7 +164,7 @@ Array sendrequests; for (int dest = 1; dest < ntasks; dest++) - sendrequests.Append (MyMPI_ISend (*sendarrays[dest], dest, MPI_TAG_MESH+10)); + sendrequests.Append (MyMPI_ISend (*sendarrays[dest], dest, MPI_TAG_MESH+10, comm)); MPI_Waitall (sendrequests.Size(), &sendrequests[0], MPI_STATUS_IGNORE); for (int dest = 1; dest < ntasks; dest++) @@ -168,7 +175,7 @@ { Array recvarray; - MyMPI_Recv (recvarray, 0, MPI_TAG_MESH+10); + MyMPI_Recv (recvarray, 0, MPI_TAG_MESH+10, comm); int ii = 0; @@ -206,6 +213,12 @@ // cout << "UpdateCoarseGrid" << endl; // if (is_updated) return; + NgMPI_Comm comm = mesh.GetCommunicator(); + int id = comm.Rank(); + int ntasks = comm.Size(); + + if (ntasks == 1) return; + Reset(); static int timer = NgProfiler::CreateTimer ("UpdateCoarseGrid"); NgProfiler::RegionTimer reg(timer); @@ -222,14 +235,14 @@ // MPI_Barrier (MPI_COMM_WORLD); - MPI_Group MPI_GROUP_WORLD; + MPI_Group MPI_GROUP_comm; MPI_Group MPI_LocalGroup; MPI_Comm MPI_LocalComm; int process_ranks[] = { 0 }; - MPI_Comm_group (MPI_COMM_WORLD, &MPI_GROUP_WORLD); - MPI_Group_excl (MPI_GROUP_WORLD, 1, process_ranks, &MPI_LocalGroup); - MPI_Comm_create (MPI_COMM_WORLD, MPI_LocalGroup, &MPI_LocalComm); + MPI_Comm_group (comm, &MPI_GROUP_comm); + MPI_Group_excl (MPI_GROUP_comm, 1, process_ranks, &MPI_LocalGroup); + MPI_Comm_create (comm, MPI_LocalGroup, &MPI_LocalComm); if (id == 0) return; diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/python_mesh.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/python_mesh.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/python_mesh.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/python_mesh.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -17,6 +17,24 @@ { extern bool netgen_executable_started; extern shared_ptr ng_geometry; + extern void Optimize2d (Mesh & mesh, MeshingParameters & mp); + +#ifdef PARALLEL + /** we need allreduce in python-wrapped communicators **/ + template + inline T MyMPI_AllReduceNG (T d, const MPI_Op & op /* = MPI_SUM */, MPI_Comm comm) + { + T global_d; + MPI_Allreduce ( &d, &global_d, 1, MyGetMPIType(), op, comm); + return global_d; + } +#else + // enum { MPI_SUM = 0, MPI_MIN = 1, MPI_MAX = 2 }; + // typedef int MPI_Op; + template + inline T MyMPI_AllReduceNG (T d, const MPI_Op & op /* = MPI_SUM */, MPI_Comm comm) + { return d; } +#endif } @@ -61,6 +79,48 @@ 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, "MPI_Comm") + .def_property_readonly ("rank", &NgMPI_Comm::Rank) + .def_property_readonly ("size", &NgMPI_Comm::Size) + .def("Barrier", &NgMPI_Comm::Barrier) + +#ifdef PARALLEL + .def("WTime", [](NgMPI_Comm & c) { return MPI_Wtime(); }) +#else + .def("WTime", [](NgMPI_Comm & c) { return -1.0; }) +#endif + .def("Sum", [](NgMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_SUM, c); }) + .def("Min", [](NgMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_MIN, c); }) + .def("Max", [](NgMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_MAX, c); }) + .def("Sum", [](NgMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_SUM, c); }) + .def("Min", [](NgMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_MIN, c); }) + .def("Max", [](NgMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_MAX, c); }) + .def("Sum", [](NgMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_SUM, c); }) + .def("Min", [](NgMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MIN, c); }) + .def("Max", [](NgMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MAX, c); }) + .def("SubComm", [](NgMPI_Comm & c, std::vector proc_list) { + Array procs(proc_list.size()); + for (int i = 0; i < procs.Size(); i++) + procs[i] = proc_list[i]; + if (!procs.Contains(c.Rank())) + throw Exception("rank "+ToString(c.Rank())+" not in subcomm"); + MPI_Comm subcomm = MyMPI_SubCommunicator(c, procs); + return NgMPI_Comm(subcomm, true); + }, py::arg("procs")); + ; + + + + py::class_(m, "NGDummyArgument") .def("__bool__", []( NGDummyArgument &self ) { return false; } ) ; @@ -71,6 +131,7 @@ .def(py::self-py::self) .def(py::self+Vec<2>()) .def(py::self-Vec<2>()) + .def("__getitem__", [](Point<2>& self, int index) { return self[index]; }) ; py::class_> (m, "Point3d") @@ -79,6 +140,7 @@ .def(py::self-py::self) .def(py::self+Vec<3>()) .def(py::self-Vec<3>()) + .def("__getitem__", [](Point<2>& self, int index) { return self[index]; }) ; m.def ("Pnt", FunctionPointer @@ -102,6 +164,8 @@ .def(-py::self) .def(double()*py::self) .def("Norm", &Vec<2>::Length) + .def("__getitem__", [](Vec<2>& vec, int index) { return vec[index]; }) + .def("__len__", [](Vec<2>& /*unused*/) { return 2; }) ; py::class_> (m, "Vec3d") @@ -112,6 +176,8 @@ .def(-py::self) .def(double()*py::self) .def("Norm", &Vec<3>::Length) + .def("__getitem__", [](Vec<3>& vec, int index) { return vec[index]; }) + .def("__len__", [](Vec<3>& /*unused*/) { return 3; }) ; m.def ("Vec", FunctionPointer @@ -120,19 +186,35 @@ ([] (double x, double y) { return Vec<2>(x,y); })); py::class_> (m, "Trafo") - .def(py::init>()) + .def(py::init>(), "a translation") + .def(py::init,Vec<3>,double>(), "a rotation given by point on axes, direction of axes, angle") + .def("__mul__", [](Transformation<3> a, Transformation<3> b)->Transformation<3> + { Transformation<3> res; res.Combine(a,b); return res; }) .def("__call__", [] (Transformation<3> trafo, Point<3> p) { return trafo(p); }) ; - m.def ("SetTransformation", FunctionPointer - ([](int dir, double angle) - { - if (dir > 0) - global_trafo.SetAxisRotation (dir, angle*M_PI/180); - else - global_trafo = Transformation<3> (Vec<3>(0,0,0)); - }), + m.def ("GetTransformation", [] () { return global_trafo; }); + m.def ("SetTransformation", [] (Transformation<3> trafo) { global_trafo = trafo; }); + m.def ("SetTransformation", + [](int dir, double angle) + { + if (dir > 0) + global_trafo.SetAxisRotation (dir, angle*M_PI/180); + else + global_trafo = Transformation<3> (Vec<3>(0,0,0)); + }, py::arg("dir")=int(0), py::arg("angle")=int(0)); + m.def ("SetTransformation", + [](Point<3> p0, Vec<3> ex, Vec<3> ey, Vec<3> ez) + { + Point<3> pnts[4]; + pnts[0] = p0; + pnts[1] = p0 + ex; + pnts[2] = p0 + ey; + pnts[3] = p0 + ez; + global_trafo = Transformation<3> (pnts); + }, + py::arg("p0"), py::arg("ex"), py::arg("ey"), py::arg("ez")); @@ -208,41 +290,31 @@ self(index) = val; })) ; - + py::class_(m, "Element3D") - .def(py::init([](int index, py::list vertices) + .def(py::init([](int index, std::vector vertices) { - Element * newel = nullptr; - if (py::len(vertices) == 4) + int np = vertices.size(); + ELEMENT_TYPE et; + switch (np) { - newel = new Element(TET); - for (int i = 0; i < 4; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); + case 4: et = TET; break; + case 5: et = PYRAMID; break; + case 6: et = PRISM; break; + case 8: et = HEX; break; + case 10: et = TET10; break; + case 13: et = PYRAMID13; break; + case 15: et = PRISM15; break; + case 20: et = HEX20; break; + default: + throw Exception ("no Element3D with " + ToString(np) + + " points"); } - else if (py::len(vertices) == 5) - { - newel = new Element(PYRAMID); - for (int i = 0; i < 5; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); - } - else if (py::len(vertices) == 6) - { - newel = new Element(PRISM); - for (int i = 0; i < 6; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); - } - else if (py::len(vertices) == 8) - { - newel = new Element(HEX); - for (int i = 0; i < 8; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); - } - else - throw NgException ("cannot create element"); + + auto newel = new Element(et); + for(int i=0; iSetIndex(index); return newel; }), py::arg("index")=1,py::arg("vertices"), @@ -250,6 +322,7 @@ ) .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 { @@ -293,6 +366,13 @@ (*newel)[i] = py::extract(vertices[i])(); newel->SetIndex(index); } + else if (py::len(vertices) == 8) + { + newel = new Element2d(QUAD8); + for(int i = 0; i<8; i++) + (*newel)[i] = py::extract(vertices[i])(); + newel->SetIndex(index); + } else throw NgException("Inconsistent number of vertices in Element2D"); return newel; @@ -301,6 +381,7 @@ "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 { @@ -459,17 +540,21 @@ py::class_>(m, "Mesh") // .def(py::init<>("create empty mesh")) - .def(py::init( [] (int dim) + .def(py::init( [] (int dim, NgMPI_Comm comm) { auto mesh = make_shared(); + mesh->SetCommunicator(comm); mesh -> SetDimension(dim); SetGlobalMesh(mesh); // for visualization - mesh -> SetGeometry (make_shared()); + mesh -> SetGeometry (nullptr); return mesh; } ), - py::arg("dim")=3 + py::arg("dim")=3, py::arg("comm")=NgMPI_Comm{} ) - + .def(NGSPickle()) + .def_property_readonly("comm", [](const Mesh & amesh) -> NgMPI_Comm + { return amesh.GetCommunicator(); }, + "MPI-communicator the Mesh lives in") /* .def("__init__", [](Mesh *instance, int dim) @@ -481,69 +566,156 @@ ) */ - .def("__str__", &ToString) + .def_property_readonly("_timestamp", &Mesh::GetTimeStamp) + .def("Distribute", [](shared_ptr self, NgMPI_Comm comm) { + self->SetCommunicator(comm); + if(comm.Size()==1) return self; + // if(MyMPI_GetNTasks(comm)==2) throw NgException("Sorry, cannot handle communicators with NP=2!"); + // cout << " rank " << MyMPI_GetId(comm) << " of " << MyMPI_GetNTasks(comm) << " called Distribute " << endl; + if(comm.Rank()==0) self->Distribute(); + else self->SendRecvMesh(); + return self; + }, py::arg("comm")) + .def_static("Receive", [](NgMPI_Comm comm) -> shared_ptr { + auto mesh = make_shared(); + mesh->SetCommunicator(comm); + mesh->SendRecvMesh(); + return mesh; + }, py::arg("comm")) .def("Load", FunctionPointer - ([](Mesh & self, const string & filename) + ([](shared_ptr self, const string & filename) { - istream * infile; -#ifdef PARALLEL - MPI_Comm_rank(MPI_COMM_WORLD, &id); - MPI_Comm_size(MPI_COMM_WORLD, &ntasks); - - char* buf = nullptr; - int strs = 0; - if(id==0) { -#endif - if (filename.find(".vol.gz") != string::npos) - infile = new igzstream (filename.c_str()); - else - infile = new ifstream (filename.c_str()); - // ifstream input(filename); -#ifdef PARALLEL - //still inside id==0-bracket... - self.Load(*infile); - self.Distribute(); - - /** Copy the rest of the file into a string (for geometry) **/ - stringstream geom_part; - geom_part << infile->rdbuf(); - string geom_part_string = geom_part.str(); - strs = geom_part_string.size(); - buf = new char[strs]; - memcpy(buf, geom_part_string.c_str(), strs*sizeof(char)); + auto comm = self->GetCommunicator(); + int id = comm.Rank(); + int ntasks = comm.Size(); + auto & mesh = self; + + { + ifstream infile(filename.c_str()); + if(!infile.good()) + throw NgException(string("Error opening file ") + filename); + } + + if ( filename.find(".vol") == string::npos ) + { + if(ntasks>1) + throw NgException("Not sure what to do with this?? Does this work with MPI??"); + mesh->SetCommunicator(comm); + ReadFile(*mesh,filename.c_str()); + //mesh->SetGlobalH (mparam.maxh); + //mesh->CalcLocalH(); + return; } + + istream * infile; + Array buf; // for distributing geometry! + int strs; + + if( id == 0) { + + if (filename.substr (filename.length()-3, 3) == ".gz") + infile = new igzstream (filename.c_str()); + else + infile = new ifstream (filename.c_str()); + mesh -> Load(*infile); + + // make string from rest of file (for geometry info!) + // (this might be empty, in which case we take the global ng_geometry) + stringstream geom_part; + geom_part << infile->rdbuf(); + string geom_part_string = geom_part.str(); + strs = geom_part_string.size(); + // buf = new char[strs]; + buf.SetSize(strs); + memcpy(&buf[0], geom_part_string.c_str(), strs*sizeof(char)); + + delete infile; + + if (ntasks > 1) + { + + char * weightsfilename = new char [filename.size()+1]; + strcpy (weightsfilename, filename.c_str()); + weightsfilename[strlen (weightsfilename)-3] = 'w'; + weightsfilename[strlen (weightsfilename)-2] = 'e'; + weightsfilename[strlen (weightsfilename)-1] = 'i'; + + ifstream weightsfile(weightsfilename); + delete [] weightsfilename; + + if (!(weightsfile.good())) + { + // cout << "regular distribute" << endl; + mesh -> Distribute(); + } + else + { + char str[20]; + bool endfile = false; + int n, dummy; + + Array segment_weights; + Array surface_weights; + Array volume_weights; + + while (weightsfile.good() && !endfile) + { + weightsfile >> str; + + if (strcmp (str, "edgeweights") == 0) + { + weightsfile >> n; + segment_weights.SetSize(n); + for (int i = 0; i < n; i++) + weightsfile >> dummy >> segment_weights[i]; + } + + if (strcmp (str, "surfaceweights") == 0) + { + weightsfile >> n; + surface_weights.SetSize(n); + for (int i=0; i> dummy >> surface_weights[i]; + } + + if (strcmp (str, "volumeweights") == 0) + { + weightsfile >> n; + volume_weights.SetSize(n); + for (int i=0; i> dummy >> volume_weights[i]; + } + + if (strcmp (str, "endfile") == 0) + endfile = true; + } + + mesh -> Distribute(volume_weights, surface_weights, segment_weights); + } + } // ntasks>1 end + } // id==0 end else { - self.SendRecvMesh(); + mesh->SendRecvMesh(); } - /** Scatter the geometry-string **/ - MPI_Bcast(&strs, 1, MPI_INT, 0, MPI_COMM_WORLD); - if(id!=0) - buf = new char[strs]; - MPI_Bcast(buf, strs, MPI_CHAR, 0, MPI_COMM_WORLD); - if(id==0) - delete infile; - infile = new istringstream(string((const char*)buf, (size_t)strs)); - delete[] buf; - -#else - self.Load(*infile); + if(ntasks>1) { +#ifdef PARALLEL + /** Scatter the geometry-string (no dummy-implementation in mpi_interface) **/ + int strs = buf.Size(); + MyMPI_Bcast(strs, comm); + if(strs>0) + MyMPI_Bcast(buf, comm); #endif - for (int i = 0; i < geometryregister.Size(); i++) - { - NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (*infile); - if (hgeom) - { - ng_geometry.reset (hgeom); - self.SetGeometry(ng_geometry); - break; - } - } - if (!ng_geometry) - ng_geometry = make_shared(); - self.SetGeometry(ng_geometry); - delete infile; + } + + shared_ptr geo; + if(buf.Size()) { // if we had geom-info in the file, take it + istringstream geom_infile(string((const char*)&buf[0], buf.Size())); + geo = geometryregister.LoadFromMeshFile(geom_infile); + } + if(geo!=nullptr) mesh->SetGeometry(geo); + else if(ng_geometry!=nullptr) mesh->SetGeometry(ng_geometry); }),py::call_guard()) // static_cast(&Mesh::Load)) .def("Save", static_cast(&Mesh::Save),py::call_guard()) @@ -591,6 +763,13 @@ py::return_value_policy::reference) .def("GetNFaceDescriptors", &Mesh::GetNFD) + .def("GetVolumeNeighboursOfSurfaceElement", [](Mesh & self, size_t sel) + { + int elnr1, elnr2; + self.GetTopology().GetSurface2VolumeElement(sel+1, elnr1, elnr2); + return py::make_tuple(elnr1, elnr2); + }, "Returns element nrs of volume element connected to surface element, -1 if no volume element") + .def("GetNCD2Names", &Mesh::GetNCD2Names) @@ -649,7 +828,10 @@ { return string(self.GetMaterial(domnr)); })) .def ("GetCD2Name", &Mesh::GetCD2Name) - .def("SetCD2Name", &Mesh::SetCD2Name) + .def ("SetCD2Name", &Mesh::SetCD2Name) + + .def ("GetCD3Name", &Mesh::GetCD3Name) + .def ("SetCD3Name", &Mesh::SetCD3Name) .def ("AddPointIdentification", [](Mesh & self, py::object pindex1, py::object pindex2, int identnr, int type) { @@ -692,14 +874,21 @@ }, py::arg("mp")=NGDummyArgument(),py::call_guard()) - .def ("OptimizeVolumeMesh", FunctionPointer - ([](Mesh & self) + .def ("OptimizeVolumeMesh", [](Mesh & self) { MeshingParameters mp; mp.optsteps3d = 5; OptimizeVolume (mp, self); - }),py::call_guard()) + },py::call_guard()) + .def ("OptimizeMesh2d", [](Mesh & self) + { + self.CalcLocalH(0.5); + MeshingParameters mp; + mp.optsteps2d = 5; + Optimize2d (self, mp); + },py::call_guard()) + .def ("Refine", FunctionPointer ([](Mesh & self) { @@ -707,6 +896,7 @@ self.GetGeometry()->GetRefinement().Refine(self); else Refinement().Refine(self); + self.UpdateTopology(); }),py::call_guard()) .def ("SecondOrder", FunctionPointer @@ -801,15 +991,33 @@ }, py::arg("name"), py::arg("set")=true) - .def ("Scale", FunctionPointer([](Mesh & self, double factor) - { - for(auto i = 0; i (); + *m2 = self; + return m2; + }) ; - + m.def("ImportMesh", [](const string& filename) + { + auto mesh = make_shared(); + ReadFile(*mesh, filename); + return mesh; + }, py::arg("filename"), + R"delimiter(Import mesh from other file format, supported file formats are: + Neutral format (*.mesh, *.emt) + Surface file (*.surf) + Universal format (*.unv) + Olaf format (*.emt) + Tet format (*.tet) + Pro/ENGINEER format (*.fnf) +)delimiter"); py::enum_(m,"MeshingStep") .value("MESHEDGES",MESHCONST_MESHEDGES) .value("MESHSURFACE",MESHCONST_OPTSURFACE) @@ -874,6 +1082,8 @@ printmessage_importance = importance; return old; })); + + } PYBIND11_MODULE(libmesh, m) { diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/refine.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/refine.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/refine.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/refine.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -15,6 +15,8 @@ { PrintMessage (3, "Refine mesh"); + mesh.SetNextMajorTimeStamp(); + if (ntasks > 1 && id == 0) return; diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/ruler3.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/ruler3.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/ruler3.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/ruler3.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -63,8 +63,11 @@ ) { - NgProfiler::RegionTimer regtot(97); + static Timer t("ruler3 - all"); RegionTimer reg(t); + static Timer tstart("ruler3 - rule start"); + static Timer tloop("ruler3 - rule loop"); + tstart.Start(); float err, minerr, teterr, minteterr; char ok, found, hc; // vnetrule * rule; @@ -76,19 +79,19 @@ Array pused; // point is already mapped, number of uses - Array fused; // face is already mapped - Array pmap; // map of reference point to local point - Array pfixed; // point mapped by face-map - Array fmapi; // face in reference is mapped to face nr ... - Array fmapr; // face in reference is rotated to map - Array transfreezone; // transformed free-zone + ArrayMem fused; // face is already mapped + ArrayMem pmap; // map of reference point to local point + ArrayMem pfixed; // point mapped by face-map + ArrayMem fmapi; // face in reference is mapped to face nr ... + ArrayMem fmapr; // face in reference is rotated to map + ArrayMem transfreezone; // transformed free-zone INDEX_2_CLOSED_HASHTABLE ledges(100); // edges in local environment - Array tempnewpoints; + ArrayMem tempnewpoints; Array tempnewfaces; - Array tempdelfaces; + ArrayMem tempdelfaces; Array tempelements; - Array triboxes; // bounding boxes of local faces + ArrayMem triboxes; // bounding boxes of local faces Array pnearness; Array fnearness; @@ -221,7 +224,8 @@ // check each rule: - + tstart.Stop(); + tloop.Start(); for (int ri = 1; ri <= rules.Size(); ri++) { int base = (lfaces[0].GetNP() == 3) ? 100 : 200; @@ -1111,7 +1115,8 @@ if (loktestmode) (*testout) << "end rule" << endl; } - + tloop.Stop(); + if (found) { /* diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/secondorder.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/secondorder.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/secondorder.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/secondorder.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -23,6 +23,14 @@ INDEX_2_HASHTABLE between(mesh.GetNP() + 5); + for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++) + { + auto & seg = mesh[si]; + if (seg.GetType() == SEGMENT3) + between.Set(INDEX_2::Sort(seg[0],seg[1]), seg[2]); + } + + for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++) { const Element2d & el = mesh[sei]; @@ -223,6 +231,45 @@ { 3, 4, 10 }, { 4, 5, 11 }, }; + static int betw_prism15[9][3] = + { + { 0, 1, 6 }, + { 0, 2, 7 }, + { 1, 2, 8 }, + { 0, 3, 9 }, + { 1, 4, 10 }, + { 2, 5, 11 }, + { 3, 4, 12 }, + { 3, 5, 13 }, + { 4, 5, 14 } + }; + static int betw_pyramid[8][3] = + { + { 0, 1, 5 }, + { 3, 2, 6 }, + { 3, 0, 7 }, + { 1, 2, 8 }, + { 0, 4, 9 }, + { 1, 4, 10 }, + { 2, 4, 11 }, + { 3, 4, 12 } + }; + static int betw_hex[12][3] = + { + { 0, 1, 8 }, + { 2, 3, 9 }, + { 3, 0, 10 }, + { 1, 2, 11 }, + { 4, 5, 12 }, + { 6, 7, 13 }, + { 7, 4, 14 }, + { 5, 6, 15 }, + { 0, 4, 16 }, + { 1, 5, 17 }, + { 2, 6, 18 }, + { 3, 7, 19 }, + }; + int (*betw)[3] = NULL; switch (el.GetType()) @@ -243,6 +290,29 @@ onp = 6; break; } + case PRISM15: + { + betw = betw_prism15; + newel.SetType(PRISM15); + onp = 6; + break; + } + case PYRAMID: + case PYRAMID13: + { + betw = betw_pyramid; + newel.SetType(PYRAMID13); + onp = 5; + break; + } + case HEX: + case HEX20: + { + betw = betw_hex; + newel.SetType (HEX20); + onp = 8; + break; + } default: PrintSysError ("MakeSecondOrder, illegal vol type ", int(el.GetType())); } diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/smoothing2.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/smoothing2.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/smoothing2.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/smoothing2.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -729,11 +729,11 @@ return; } - static int timer = NgProfiler::CreateTimer ("MeshSmoothing 2D"); + static Timer timer("MeshSmoothing 2D"); static int timer1 = NgProfiler::CreateTimer ("MeshSmoothing 2D start"); static int timer2 = NgProfiler::CreateTimer ("MeshSmoothing 2D - BFGS"); - NgProfiler::RegionTimer reg (timer); + RegionTimer reg (timer); NgProfiler::StartTimer (timer1); CheckMeshApproximation (mesh); diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/smoothing3.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/smoothing3.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/smoothing3.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/smoothing3.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -923,6 +923,8 @@ const Mesh::T_VOLELEMENTS & elements, const MeshingParameters & mp) { + static Timer t("CalcTotalBad"); RegionTimer reg(t); + double sum = 0; double elbad; @@ -1353,6 +1355,8 @@ void Mesh :: ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal) { + static Timer t("Mesh::ImproveMesh"); RegionTimer reg(t); + int typ = 1; (*testout) << "Improve Mesh" << "\n"; diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/topology.cpp netgen-6.2.1905+dfsg1/libsrc/meshing/topology.cpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/topology.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/topology.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -51,6 +51,9 @@ MeshTopology :: ~MeshTopology () { ; } + bool MeshTopology :: NeedsUpdate() const + { return (timestamp <= mesh->GetTimeStamp()); } + template void LoopOverEdges (const Mesh & mesh, MeshTopology & top, PointIndex v, FUNC func) @@ -338,6 +341,8 @@ // ParallelMeshTopology & paralleltop = mesh.GetParallelTopology(); #endif + auto id = this->mesh->GetCommunicator().Rank(); + auto ntasks = this->mesh->GetCommunicator().Size(); if (timestamp > mesh->GetTimeStamp()) return; @@ -525,7 +530,7 @@ for (int i = mesh->mlbetweennodes.Begin(); i < mesh->mlbetweennodes.End(); i++) { INDEX_2 parents = Sort (mesh->mlbetweennodes[i]); - if (parents[0] > PointIndex::BASE) vert2vertcoarse.AddSave (parents[0], parents[1]); + if (parents[0] >= PointIndex::BASE) vert2vertcoarse.AddSave (parents[0], parents[1]); } @@ -543,7 +548,7 @@ cnt = 0; ParallelForRange - (tm, mesh->Points().Size(), + (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_CLOSED_HASHTABLE v2eht(2*max_edge_on_vertex+10); @@ -581,7 +586,9 @@ // accumulate number of edges int ned = edge2vert.Size(); - for (auto v : mesh->Points().Range()) + + // for (size_t v = 0; v < mesh->GetNV(); v++) + for (size_t v : cnt.Range()) { auto hv = cnt[v]; cnt[v] = ned; @@ -595,7 +602,7 @@ // for (PointIndex v = PointIndex::BASE; v < nv+PointIndex::BASE; v++) ParallelForRange - (tm, mesh->Points().Size(), + (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_CLOSED_HASHTABLE v2eht(2*max_edge_on_vertex+10); @@ -669,16 +676,16 @@ if (buildfaces) { static int timer2 = NgProfiler::CreateTimer ("topology::buildfaces"); - static int timer2a = NgProfiler::CreateTimer ("topology::buildfacesa"); - static int timer2b = NgProfiler::CreateTimer ("topology::buildfacesb"); - static int timer2b1 = NgProfiler::CreateTimer ("topology::buildfacesb1"); - static int timer2c = NgProfiler::CreateTimer ("topology::buildfacesc"); + // static int timer2a = NgProfiler::CreateTimer ("topology::buildfacesa"); + // static int timer2b = NgProfiler::CreateTimer ("topology::buildfacesb"); + // static int timer2b1 = NgProfiler::CreateTimer ("topology::buildfacesb1"); + // static int timer2c = NgProfiler::CreateTimer ("topology::buildfacesc"); NgProfiler::RegionTimer reg2 (timer2); if (id == 0) PrintMessage (5, "Update faces "); - NgProfiler::StartTimer (timer2a); + // NgProfiler::StartTimer (timer2a); faces.SetSize(ne); surffaces.SetSize(nse); @@ -707,8 +714,8 @@ - NgProfiler::StopTimer (timer2a); - NgProfiler::StartTimer (timer2b); + // NgProfiler::StopTimer (timer2a); + // NgProfiler::StartTimer (timer2b); INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); @@ -717,9 +724,9 @@ // count faces associated with vertices cnt = 0; // for (auto v : mesh.Points().Range()) - NgProfiler::StartTimer (timer2b1); + // NgProfiler::StartTimer (timer2b1); ParallelForRange - (tm, mesh->Points().Size(), + (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); @@ -750,11 +757,13 @@ cnt[v] = cnti; } } ); - NgProfiler::StopTimer (timer2b1); + // NgProfiler::StopTimer (timer2b1); // accumulate number of faces int nfa = oldnfa; - for (auto v : mesh->Points().Range()) + // for (auto v : Range(mesh->GetNV())) // Points().Range()) + // for (size_t v = 0; v < mesh->GetNV(); v++) + for (auto v : cnt.Range()) { auto hv = cnt[v]; cnt[v] = nfa; @@ -765,7 +774,7 @@ // for (auto v : mesh.Points().Range()) ParallelForRange - (tm, mesh->Points().Size(), + (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); @@ -1084,8 +1093,8 @@ // *testout << "face2vert = " << endl << face2vert << endl; - NgProfiler::StopTimer (timer2b); - NgProfiler::StartTimer (timer2c); + // NgProfiler::StopTimer (timer2b); + // NgProfiler::StartTimer (timer2c); face2surfel.SetSize (nfa); @@ -1222,7 +1231,7 @@ if (cnt_err && ntasks == 1) cout << cnt_err << " elements are not matching !!!" << endl; } - NgProfiler::StopTimer (timer2c); + // NgProfiler::StopTimer (timer2c); } diff -Nru netgen-6.2.1804+dfsg1/libsrc/meshing/topology.hpp netgen-6.2.1905+dfsg1/libsrc/meshing/topology.hpp --- netgen-6.2.1804+dfsg1/libsrc/meshing/topology.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/meshing/topology.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -66,11 +66,9 @@ int GetNSurfedges() const {return surfedges.Size();} MeshTopology () = default; - MeshTopology (const MeshTopology & top) = default; MeshTopology (MeshTopology && top) = default; MeshTopology (const Mesh & amesh); ~MeshTopology (); - MeshTopology & operator= (const MeshTopology & top) = default; MeshTopology & operator= (MeshTopology && top) = default; void SetBuildEdges (bool be) @@ -84,6 +82,7 @@ { return buildfaces; } void Update(TaskManager tm = &DummyTaskManager, Tracer tracer = &DummyTracer); + bool NeedsUpdate() const; int GetNEdges () const { return edge2vert.Size(); } @@ -212,13 +211,16 @@ return 4; case PYRAMID: + case PYRAMID13: return 5; case PRISM: case PRISM12: + case PRISM15: return 6; case HEX: + case HEX20: return 8; // default: @@ -244,9 +246,11 @@ case QUAD: case QUAD6: - case QUAD8: return 4; + case QUAD8: + return 8; + case TET: return 4; case TET10: @@ -254,14 +258,21 @@ case PYRAMID: return 5; + case PYRAMID13: + return 13; case PRISM: - case PRISM12: return 6; + case PRISM12: + return 12; + case PRISM15: + return 15; case HEX: return 8; + case HEX20: + return 20; // default: // cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; } @@ -272,7 +283,7 @@ inline short int MeshTopology :: GetNEdges (ELEMENT_TYPE et) { - __assume(et >= SEGMENT && et <= HEX); + __assume(et >= SEGMENT && et <= PYRAMID13); switch (et) { case SEGMENT: @@ -293,13 +304,16 @@ return 6; case PYRAMID: + case PYRAMID13: return 8; case PRISM: case PRISM12: + case PRISM15: return 9; case HEX: + case HEX20: return 12; default: return 0; @@ -312,7 +326,7 @@ inline short int MeshTopology :: GetNFaces (ELEMENT_TYPE et) { - __assume(et >= SEGMENT && et <= HEX); + __assume(et >= SEGMENT && et <= PYRAMID13); switch (et) { case SEGMENT: @@ -333,13 +347,16 @@ return 4; case PYRAMID: + case PYRAMID13: return 5; case PRISM: case PRISM12: + case PRISM15: return 5; case HEX: + case HEX20: return 6; default: @@ -436,13 +453,16 @@ return tet_edges; case PYRAMID: + case PYRAMID13: return pyramid_edges; case PRISM: case PRISM12: + case PRISM15: return prism_edges; case HEX: + case HEX20: return hex_edges; // default: // cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; @@ -513,7 +533,7 @@ { 2, 6 }, { 3, 7 }, }; - + switch (et) { case SEGMENT: @@ -534,13 +554,16 @@ return tet_edges; case PYRAMID: + case PYRAMID13: return pyramid_edges; case PRISM: case PRISM12: + case PRISM15: return prism_edges; case HEX: + case HEX20: return hex_edges; // default: // cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; @@ -618,15 +641,18 @@ case PRISM: case PRISM12: + case PRISM15: return prism_faces; case PYRAMID: + case PYRAMID13: return pyramid_faces; case SEGMENT: case SEGMENT3: case HEX: + case HEX20: return hex_faces; // default: @@ -700,15 +726,18 @@ case PRISM: case PRISM12: + case PRISM15: return prism_faces; case PYRAMID: + case PYRAMID13: return pyramid_faces; case SEGMENT: case SEGMENT3: case HEX: + case HEX20: return hex_faces; // default: diff -Nru netgen-6.2.1804+dfsg1/libsrc/occ/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/occ/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/occ/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/occ/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -4,13 +4,19 @@ Partition_Loop.cxx Partition_Loop2d.cxx Partition_Loop3d.cxx Partition_Spliter.cxx occconstruction.cpp occgenmesh.cpp occgeom.cpp occmeshsurf.cpp python_occ.cpp ) +if(USE_GUI) + add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) +endif(USE_GUI) -add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) +target_link_libraries(occ PUBLIC ngcore) if(NOT WIN32) - target_link_libraries( occ ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) - target_link_libraries( occvis occ ) - install( TARGETS occ occvis ${NG_INSTALL_DIR}) + target_link_libraries( occ PUBLIC ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) + install( TARGETS occ ${NG_INSTALL_DIR}) + if (USE_GUI) + target_link_libraries( occvis PUBLIC occ ) + install( TARGETS occvis ${NG_INSTALL_DIR}) + endif(USE_GUI) endif(NOT WIN32) install(FILES diff -Nru netgen-6.2.1804+dfsg1/libsrc/occ/occgenmesh.cpp netgen-6.2.1905+dfsg1/libsrc/occ/occgenmesh.cpp --- netgen-6.2.1804+dfsg1/libsrc/occ/occgenmesh.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/occ/occgenmesh.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -899,8 +899,8 @@ multithread.task = "Optimizing surface"; - static int timer_opt2d = NgProfiler::CreateTimer ("Optimization 2D"); - NgProfiler::StartTimer (timer_opt2d); + static Timer timer_opt2d("Optimization 2D"); + timer_opt2d.Start(); for (k = 1; k <= mesh.GetNFD(); k++) { @@ -974,8 +974,7 @@ mesh.CalcSurfacesOfNode(); mesh.Compress(); - - NgProfiler::StopTimer (timer_opt2d); + timer_opt2d.Stop(); multithread.task = savetask; diff -Nru netgen-6.2.1804+dfsg1/libsrc/occ/occgeom.cpp netgen-6.2.1905+dfsg1/libsrc/occ/occgeom.cpp --- netgen-6.2.1804+dfsg1/libsrc/occ/occgeom.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/occ/occgeom.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -3,6 +3,7 @@ #include #include +#include #include "ShapeAnalysis_ShapeTolerance.hxx" #include "ShapeAnalysis_ShapeContents.hxx" #include "ShapeAnalysis_CheckSmallFace.hxx" @@ -1106,94 +1107,8 @@ // } - - // 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 @@ if(stat != IFSelect_RetDone) { - delete occgeo; - return NULL; + throw NgException("Couldn't load OCC geometry"); } reader.Transfer(step_doc); @@ -1255,7 +1169,7 @@ occgeo->CalcBoundingBox(); PrintContents (occgeo); - char * name = new char(50); + char * name = new char[50]; //string name; STEP_GetEntityName(occgeo->shape,&reader,name); occgeo->snames.Append(name); @@ -1265,6 +1179,8 @@ { TopoDS_Face face = TopoDS::Face(exp0.Current()); STEP_GetEntityName(face,&reader,name); + if (name == string("")) + snprintf(name, 50, "bc_%zu", occgeo->fnames.Size()); occgeo->fnames.Append(name); for (exp1.Init(face, TopAbs_EDGE); exp1.More(); exp1.Next()) { @@ -1287,6 +1203,94 @@ // 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 +1359,34 @@ } } - - + 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 -Nru netgen-6.2.1804+dfsg1/libsrc/occ/occgeom.hpp netgen-6.2.1905+dfsg1/libsrc/occ/occgeom.hpp --- netgen-6.2.1804+dfsg1/libsrc/occ/occgeom.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/occ/occgeom.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -246,6 +246,7 @@ DLL_HEADER virtual void Save (string filename) const; + void DoArchive(Archive& ar); DLL_HEADER void BuildFMap(); diff -Nru netgen-6.2.1804+dfsg1/libsrc/occ/occmeshsurf.cpp netgen-6.2.1905+dfsg1/libsrc/occ/occmeshsurf.cpp --- netgen-6.2.1804+dfsg1/libsrc/occ/occmeshsurf.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/occ/occmeshsurf.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -673,13 +673,14 @@ if (surfi > 0) { - double u = gi1.u+secpoint*(gi2.u-gi1.u); double v = gi1.v+secpoint*(gi2.v-gi1.v); - - if (!geometry.FastProject (surfi, hnewp, u, v)) + + auto savept = hnewp; + if (!geometry.FastProject (surfi, hnewp, u, v) || Dist(hnewp, savept) > Dist(p1,p2)) { - // cout << "Fast projection to surface fails! Using OCC projection" << endl; + // cout << "Fast projection to surface fails! Using OCC projection" << endl; + hnewp = savept; geometry.Project (surfi, hnewp); } diff -Nru netgen-6.2.1804+dfsg1/libsrc/occ/occmeshsurf.hpp netgen-6.2.1905+dfsg1/libsrc/occ/occmeshsurf.hpp --- netgen-6.2.1804+dfsg1/libsrc/occ/occmeshsurf.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/occ/occmeshsurf.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -182,17 +182,17 @@ int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, - Point<3> & newp, PointGeomInfo & newgi) const; + Point<3> & newp, PointGeomInfo & newgi) const override; virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, - Point<3> & newp, EdgePointGeomInfo & newgi) const; + Point<3> & newp, EdgePointGeomInfo & newgi) const override; - virtual void ProjectToSurface (Point<3> & p, int surfi) const; + virtual void ProjectToSurface (Point<3> & p, int surfi) const override; - virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const; + virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const override; }; diff -Nru netgen-6.2.1804+dfsg1/libsrc/occ/python_occ.cpp netgen-6.2.1905+dfsg1/libsrc/occ/python_occ.cpp --- netgen-6.2.1804+dfsg1/libsrc/occ/python_occ.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/occ/python_occ.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -18,6 +18,7 @@ { 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; @@ -30,6 +31,82 @@ self.HealGeometry(); self.BuildFMap(); },py::arg("tolerance")=1e-3, py::arg("fixsmalledges")=true, py::arg("fixspotstripfaces")=true, py::arg("sewfaces")=true, py::arg("makesolids")=true, py::arg("splitpartitions")=false,R"raw_string(Heal the OCCGeometry.)raw_string",py::call_guard()) + .def("_visualizationData", [] (shared_ptr occ_geo) + { + std::vector vertices; + std::vector trigs; + std::vector normals; + std::vector min = {std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()}; + std::vector max = {std::numeric_limits::lowest(), + std::numeric_limits::lowest(), + std::numeric_limits::lowest()}; + std::vector surfnames; + auto box = occ_geo->GetBoundingBox(); + for(int i = 0; i < 3; i++) + { + min[i] = box.PMin()[i]; + max[i] = box.PMax()[i]; + } + occ_geo->BuildVisualizationMesh(0.01); + gp_Pnt2d uv; + gp_Pnt pnt; + gp_Vec n; + gp_Pnt p[3]; + int count = 0; + for (int i = 1; i <= occ_geo->fmap.Extent(); i++) + { + surfnames.push_back("occ_surface" + to_string(i)); + auto face = TopoDS::Face(occ_geo->fmap(i)); + auto surf = BRep_Tool::Surface(face); + TopLoc_Location loc; + BRepAdaptor_Surface sf(face, Standard_False); + BRepLProp_SLProps prop(sf, 1, 1e-5); + Handle(Poly_Triangulation) triangulation = BRep_Tool::Triangulation (face, loc); + if (triangulation.IsNull()) + cout << "cannot visualize face " << i << endl; + trigs.reserve(trigs.size() + triangulation->NbTriangles()*4); + vertices.reserve(vertices.size() + triangulation->NbTriangles()*3*3); + normals.reserve(normals.size() + triangulation->NbTriangles()*3*3); + for (int j = 1; j < triangulation->NbTriangles()+1; j++) + { + auto triangle = (triangulation->Triangles())(j); + for (int k = 1; k < 4; k++) + p[k-1] = (triangulation->Nodes())(triangle(k)).Transformed(loc); + for (int k = 1; k < 4; k++) + { + vertices.insert(vertices.end(),{float(p[k-1].X()), float(p[k-1].Y()), float(p[k-1].Z())}); + trigs.insert(trigs.end(),{count, count+1, count+2,i}); + count += 3; + uv = (triangulation->UVNodes())(triangle(k)); + prop.SetParameters(uv.X(), uv.Y()); + if (prop.IsNormalDefined()) + n = prop.Normal(); + else + { + gp_Vec a(p[0], p[1]); + gp_Vec b(p[0], p[2]); + n = b^a; + } + if (face.Orientation() == TopAbs_REVERSED) n*= -1; + normals.insert(normals.end(),{float(n.X()), float(n.Y()), float(n.Z())}); + } + } + } + py::gil_scoped_acquire ac; + py::dict res; + py::list snames; + for(auto name : surfnames) + snames.append(py::cast(name)); + res["vertices"] = MoveToNumpy(vertices); + res["triangles"] = MoveToNumpy(trigs); + res["normals"] = MoveToNumpy(normals); + res["surfnames"] = snames; + res["min"] = MoveToNumpy(min); + res["max"] = MoveToNumpy(max); + return res; + }, py::call_guard()) ; m.def("LoadOCCGeometry",FunctionPointer([] (const string & filename) { @@ -37,7 +114,8 @@ ifstream ist(filename); OCCGeometry * instance = new OCCGeometry(); instance = LoadOCC_STEP(filename.c_str()); - return shared_ptr(instance, NOOP_Deleter); + ng_geometry = shared_ptr(instance, NOOP_Deleter); + return ng_geometry; }),py::call_guard()); m.def("GenerateMesh", FunctionPointer([] (shared_ptr geo, MeshingParameters ¶m) { diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/stlgeom/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -4,11 +4,13 @@ ) if(NOT WIN32) - target_link_libraries( stl mesh ${PYTHON_LIBRARIES}) - target_link_libraries( stl ${PYTHON_LIBRARIES}) + target_link_libraries( stl mesh ${PYTHON_LIBRARIES}) install( TARGETS stl ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries( stl ngcore ) + + if(USE_GUI) add_library(stlvis ${NG_LIB_TYPE} vsstl.cpp diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/meshstlsurface.cpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/meshstlsurface.cpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/meshstlsurface.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/meshstlsurface.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -598,7 +598,6 @@ for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++) { - if (fnr == 100) NgProfiler::ClearTimers(); if (!opensegsperface[fnr]) continue; if (multithread.terminate) return; diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/meshstlsurface.hpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/meshstlsurface.hpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/meshstlsurface.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/meshstlsurface.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -103,16 +103,16 @@ int surfi, const PointGeomInfo & gi1, const PointGeomInfo & gi2, - Point<3> & newp, PointGeomInfo & newgi) const; + Point<3> & newp, PointGeomInfo & newgi) const override; virtual void PointBetween (const Point<3> & p1, const Point<3> & p2, double secpoint, int surfi1, int surfi2, const EdgePointGeomInfo & ap1, const EdgePointGeomInfo & ap2, - Point<3> & newp, EdgePointGeomInfo & newgi) const; + Point<3> & newp, EdgePointGeomInfo & newgi) const override; - virtual void ProjectToSurface (Point<3> & p, int surfi) const; - virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const; + virtual void ProjectToSurface (Point<3> & p, int surfi) const override; + virtual void ProjectToSurface (Point<3> & p, int surfi, PointGeomInfo & gi) const override; }; diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/python_stl.cpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/python_stl.cpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/python_stl.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/python_stl.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -20,6 +20,56 @@ { py::class_, NetgenGeometry> (m,"STLGeometry") .def(py::init<>()) + .def(NGSPickle()) + .def("_visualizationData", [](shared_ptr stl_geo) + { + std::vector vertices; + std::vector trigs; + std::vector normals; + std::vector min = {std::numeric_limits::max(), + std::numeric_limits::max(), + std::numeric_limits::max()}; + std::vector max = {std::numeric_limits::lowest(), + std::numeric_limits::lowest(), + std::numeric_limits::lowest()}; + std::vector surfnames; + + surfnames.push_back("stl"); + vertices.reserve(stl_geo->GetNT()*3*3); + trigs.reserve(stl_geo->GetNT()*4); + normals.reserve(stl_geo->GetNT()*3*3); + size_t ii = 0; + for(int i = 0; i < stl_geo->GetNT(); i++) + { + auto& trig = stl_geo->GetTriangle(i+1); + for(int k = 0; k < 3; k++) + { + trigs.push_back(ii++); + auto& pnt = stl_geo->GetPoint(trig[k]); + for (int l = 0; l < 3; l++) + { + float val = pnt[l]; + vertices.push_back(val); + min[l] = min2(min[l], val); + max[l] = max2(max[l], val); + normals.push_back(trig.Normal()[l]); + } + } + trigs.push_back(0); + } + py::gil_scoped_acquire ac; + py::dict res; + py::list snames; + for(auto name : surfnames) + snames.append(py::cast(name)); + res["vertices"] = MoveToNumpy(vertices); + res["triangles"] = MoveToNumpy(trigs); + res["normals"] = MoveToNumpy(normals); + res["surfnames"] = snames; + res["min"] = MoveToNumpy(min); + res["max"] = MoveToNumpy(max); + return res; + }, py::call_guard()) ; m.def("LoadSTLGeometry", FunctionPointer([] (const string & filename) { diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/stlgeomchart.cpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/stlgeomchart.cpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/stlgeomchart.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/stlgeomchart.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -818,7 +818,8 @@ if (GetChartNr(tn2) != chartnum && outercharttrigs.Get(tn2) != chartnum) {problem = 1;} } - if (problem && !IsInArray(j,dirtytrigs)) + // if (problem && !IsInArray(j,dirtytrigs)) + if (problem && !dirtytrigs.Contains(j)) { dirtytrigs.Append(j); cnt++; diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/stlgeom.cpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/stlgeom.cpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/stlgeom.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/stlgeom.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -62,6 +62,7 @@ STLGeometry :: ~STLGeometry() { + for (auto p : atlas) delete p; delete edgedata; delete ref; } @@ -3578,5 +3579,5 @@ STLInit stlinit; - +static RegisterClassForArchive stlgeo; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/stlgeom.hpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/stlgeom.hpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/stlgeom.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/stlgeom.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -26,6 +26,7 @@ namespace netgen { + /* inline int IsInArray(int n, const Array& ia) { return ia.Contains(n); @@ -37,6 +38,7 @@ list.Append(x); return true; } + */ extern DLL_HEADER MeshingParameters mparam; @@ -182,6 +184,10 @@ STLGeometry(); virtual ~STLGeometry(); + void DoArchive(Archive& ar) + { + STLTopology::DoArchive(ar); + } void Clear(); diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/stlgeommesh.cpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/stlgeommesh.cpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/stlgeommesh.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/stlgeommesh.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -1174,14 +1174,18 @@ { Point3d p3p1 = GetPoint(np1); Point3d p3p2 = GetPoint(np2); - if (AddIfNotExists(limes1,np1)) + // if (AddIfNotExists(limes1,np1)) + if (!limes1.Contains(np1)) { + limes1.Append(np1); plimes1.Append(p3p1); plimes1trigs.Append(t); plimes1origin.Append(np1); } - if (AddIfNotExists(limes1,np2)) + // if (AddIfNotExists(limes1,np2)) + if (!limes1.Contains(np2)) { + limes1.Append(np2); plimes1.Append(p3p2); plimes1trigs.Append(t); plimes1origin.Append(np2); @@ -1226,8 +1230,20 @@ Point3d p3p1 = GetPoint(np1); Point3d p3p2 = GetPoint(np2); - if (AddIfNotExists(limes2,np1)) {plimes2.Append(p3p1); plimes2trigs.Append(t);} - if (AddIfNotExists(limes2,np2)) {plimes2.Append(p3p2); plimes2trigs.Append(t);} + // if (AddIfNotExists(limes2,np1)) {plimes2.Append(p3p1); plimes2trigs.Append(t);} + // if (AddIfNotExists(limes2,np2)) {plimes2.Append(p3p2); plimes2trigs.Append(t);} + if (!limes2.Contains(np1)) + { + limes2.Append(np1); + plimes2.Append(p3p1); + plimes2trigs.Append(t); + } + if (!limes2.Contains(np2)) + { + limes2.Append(np2); + plimes2.Append(p3p2); + plimes2trigs.Append(t); + } chart.AddOLimit(twoint(np1,np2)); for (int di = 1; di <= divisions; di++) diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/stltool.cpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/stltool.cpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/stltool.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/stltool.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -609,40 +609,62 @@ STLChart :: STLChart(STLGeometry * ageometry) { - charttrigs = new Array (0,0); - outertrigs = new Array (0,0); - ilimit = new Array (0,0); - olimit = new Array (0,0); + // charttrigs = new Array (0,0); + // outertrigs = new Array (0,0); + // ilimit = new Array (0,0); + // olimit = new Array (0,0); geometry = ageometry; if ( stlparam.usesearchtree == 1) - searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1), - geometry->GetBoundingBox().PMax() + Vec3d(1,1,1)); + { + Box<3> box = geometry->GetBoundingBox(); + box.Increase (0.2*box.Diam()+1e-12); + searchtree = new BoxTree<3> (box); + /* + searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1), + geometry->GetBoundingBox().PMax() + Vec3d(1,1,1)); + */ + } else searchtree = NULL; } +STLChart :: ~STLChart() +{ + delete searchtree; +} + void STLChart :: AddChartTrig(int i) { // static int timer = NgProfiler::CreateTimer ("STLChart::AddChartTrig"); // NgProfiler::RegionTimer reg(timer); - charttrigs->Append(i); + charttrigs.Append(i); const STLTriangle & trig = geometry->GetTriangle(i); - const Point3d & p1 = geometry->GetPoint (trig.PNum(1)); - const Point3d & p2 = geometry->GetPoint (trig.PNum(2)); - const Point3d & p3 = geometry->GetPoint (trig.PNum(3)); + const Point<3> & p1 = geometry->GetPoint (trig.PNum(1)); + const Point<3> & p2 = geometry->GetPoint (trig.PNum(2)); + const Point<3> & p3 = geometry->GetPoint (trig.PNum(3)); + /* Point3d pmin(p1), pmax(p1); pmin.SetToMin (p2); pmin.SetToMin (p3); pmax.SetToMax (p2); pmax.SetToMax (p3); - + */ + /* + Box<3> box(p1); + box.Add(p2); + box.Add(p3); + */ + Box<3> box(p1,p2,p3); if (!geomsearchtreeon && (stlparam.usesearchtree == 1)) - {searchtree->Insert (pmin, pmax, i);} + // {searchtree->Insert (pmin, pmax, i);} + { + searchtree->Insert (box, i); + } } void STLChart :: AddOuterTrig(int i) @@ -650,7 +672,7 @@ // static int timer = NgProfiler::CreateTimer ("STLChart::AddOuterTrig"); // NgProfiler::RegionTimer reg(timer); - outertrigs->Append(i); + outertrigs.Append(i); const STLTriangle & trig = geometry->GetTriangle(i); const Point3d & p1 = geometry->GetPoint (trig.PNum(1)); @@ -669,11 +691,11 @@ int STLChart :: IsInWholeChart(int nr) const { - for (int i = 1; i <= charttrigs->Size(); i++) - if (charttrigs->Get(i) == nr) return 1; + for (int i = 1; i <= charttrigs.Size(); i++) + if (charttrigs.Get(i) == nr) return 1; - for (int i = 1; i <= outertrigs->Size(); i++) - if (outertrigs->Get(i) == nr) return 1; + for (int i = 1; i <= outertrigs.Size(); i++) + if (outertrigs.Get(i) == nr) return 1; return 0; } @@ -688,9 +710,8 @@ searchtree -> GetIntersecting (pmin, pmax, trias); else { - Box3d box1(pmin, pmax); - box1.Increase (1e-4); - Box3d box2; + Box<3> box1(pmin, pmax); + box1.Increase (1e-2*box1.Diam()); trias.SetSize(0); @@ -699,9 +720,9 @@ { int trignum = GetTrig(i); const STLTriangle & trig = geometry->GetTriangle(trignum); - box2.SetPoint (geometry->GetPoint (trig.PNum(1))); - box2.AddPoint (geometry->GetPoint (trig.PNum(2))); - box2.AddPoint (geometry->GetPoint (trig.PNum(3))); + Box<3> box2(geometry->GetPoint (trig.PNum(1)), + geometry->GetPoint (trig.PNum(2)), + geometry->GetPoint (trig.PNum(3))); if (box1.Intersect (box2)) trias.Append (trignum); @@ -712,12 +733,12 @@ //trigs may contain the same triangle double void STLChart :: MoveToOuterChart(const Array& trigs) { - if (!trigs.Size()) {return;} + if (!trigs.Size()) return; for (int i = 1; i <= trigs.Size(); i++) { - if (charttrigs->Get(trigs.Get(i)) != -1) - {AddOuterTrig(charttrigs->Get(trigs.Get(i)));} - charttrigs->Elem(trigs.Get(i)) = -1; + if (charttrigs.Get(trigs.Get(i)) != -1) + {AddOuterTrig(charttrigs.Get(trigs.Get(i)));} + charttrigs.Elem(trigs.Get(i)) = -1; } DelChartTrigs(trigs); } @@ -725,27 +746,22 @@ //trigs may contain the same triangle double void STLChart :: DelChartTrigs(const Array& trigs) { - if (!trigs.Size()) {return;} + if (!trigs.Size()) return; for (int i = 1; i <= trigs.Size(); i++) - { - charttrigs->Elem(trigs.Get(i)) = -1; - } + charttrigs.Elem(trigs.Get(i)) = -1; int cnt = 0; - for (int i = 1; i <= charttrigs->Size(); i++) + for (int i = 1; i <= charttrigs.Size(); i++) { - if (charttrigs->Elem(i) == -1) - { - cnt++; - } - if (cnt != 0 && i < charttrigs->Size()) - { - charttrigs->Elem(i-cnt+1) = charttrigs->Get(i+1); - } + if (charttrigs.Elem(i) == -1) + cnt++; + if (cnt != 0 && i < charttrigs.Size()) + charttrigs.Elem(i-cnt+1) = charttrigs.Get(i+1); } - int i = charttrigs->Size() - trigs.Size(); - charttrigs->SetSize(i); + + int i = charttrigs.Size() - trigs.Size(); + charttrigs.SetSize(i); if (!geomsearchtreeon && stlparam.usesearchtree == 1) { @@ -754,7 +770,7 @@ searchtree = new BoxTree<3> (geometry->GetBoundingBox().PMin() - Vec3d(1,1,1), geometry->GetBoundingBox().PMax() + Vec3d(1,1,1)); - for (int i = 1; i <= charttrigs->Size(); i++) + for (int i = 1; i <= charttrigs.Size(); i++) { const STLTriangle & trig = geometry->GetTriangle(i); const Point3d & p1 = geometry->GetPoint (trig.PNum(1)); @@ -767,7 +783,7 @@ pmax.SetToMax (p2); pmax.SetToMax (p3); - searchtree->Insert (pmin, pmax, i); + searchtree->Insert (pmin, pmax, i); } } } @@ -831,21 +847,17 @@ STLBoundary :: STLBoundary (STLGeometry * ageometry) - : // boundary(), - geometry(ageometry) -{ - ; -} + : geometry(ageometry) +{ ; } void STLBoundary :: AddOrDelSegment(const STLBoundarySeg & seg) { - int i; - int found = 0; - for (i = 1; i <= boundary.Size(); i++) + bool found = false; + for (int i = 1; i <= boundary.Size(); i++) { - if (found) {boundary.Elem(i-1) = boundary.Get(i);} - if (boundary.Get(i) == seg) {found = 1;} + if (found) { boundary.Elem(i-1) = boundary.Get(i); } + if (boundary.Get(i) == seg) { found = true; } } if (!found) { diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/stltool.hpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/stltool.hpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/stltool.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/stltool.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -43,49 +43,50 @@ { private: STLGeometry * geometry; - Array* charttrigs; // trigs which only belong to this chart - Array* outertrigs; // trigs which belong to other charts + Array charttrigs; // trigs which only belong to this chart + Array outertrigs; // trigs which belong to other charts BoxTree<3> * searchtree; // ADT containing outer trigs - Array* olimit; //outer limit of outer chart - Array* ilimit; //outer limit of inner chart + Array olimit; //outer limit of outer chart + Array ilimit; //outer limit of inner chart public: STLChart(STLGeometry * ageometry); + ~STLChart(); void AddChartTrig(int i); void AddOuterTrig(int i); int IsInWholeChart(int nr) const; - int GetChartTrig(int i) const {return charttrigs->Get(i);} - int GetOuterTrig(int i) const {return outertrigs->Get(i);} + int GetChartTrig(int i) const {return charttrigs.Get(i);} + int GetOuterTrig(int i) const {return outertrigs.Get(i);} //get all trigs: int GetTrig(int i) const { - if (i <= charttrigs->Size()) {return charttrigs->Get(i);} - else {return outertrigs->Get(i-charttrigs->Size());} + if (i <= charttrigs.Size()) {return charttrigs.Get(i);} + else {return outertrigs.Get(i-charttrigs.Size());} } - int GetNChartT() const {return charttrigs->Size();} - int GetNOuterT() const {return outertrigs->Size();} - int GetNT() const {return charttrigs->Size()+outertrigs->Size(); } + int GetNChartT() const {return charttrigs.Size();} + int GetNOuterT() const {return outertrigs.Size();} + int GetNT() const {return charttrigs.Size()+outertrigs.Size(); } void GetTrianglesInBox (const Point3d & pmin, const Point3d & pmax, Array & trias) const; - void AddOLimit(twoint l) {olimit->Append(l);} - void AddILimit(twoint l) {ilimit->Append(l);} + void AddOLimit(twoint l) {olimit.Append(l);} + void AddILimit(twoint l) {ilimit.Append(l);} - void ClearOLimit() {olimit->SetSize(0);} - void ClearILimit() {ilimit->SetSize(0);} + void ClearOLimit() {olimit.SetSize(0);} + void ClearILimit() {ilimit.SetSize(0);} - int GetNOLimit() const {return olimit->Size();} - int GetNILimit() const {return ilimit->Size();} + int GetNOLimit() const {return olimit.Size();} + int GetNILimit() const {return ilimit.Size();} - twoint GetOLimit(int i) const {return olimit->Get(i);} - twoint GetILimit(int i) const {return ilimit->Get(i);} + twoint GetOLimit(int i) const {return olimit.Get(i);} + twoint GetILimit(int i) const {return ilimit.Get(i);} //move triangles trigs (local chart-trig numbers) to outer chart void MoveToOuterChart(const Array& trigs); diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/stltopology.cpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/stltopology.cpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/stltopology.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/stltopology.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -1074,5 +1074,5 @@ } } - +static RegisterClassForArchive stltop; } diff -Nru netgen-6.2.1804+dfsg1/libsrc/stlgeom/stltopology.hpp netgen-6.2.1905+dfsg1/libsrc/stlgeom/stltopology.hpp --- netgen-6.2.1804+dfsg1/libsrc/stlgeom/stltopology.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/stlgeom/stltopology.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -96,6 +96,17 @@ 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 @@ 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 -Nru netgen-6.2.1804+dfsg1/libsrc/visualization/CMakeLists.txt netgen-6.2.1905+dfsg1/libsrc/visualization/CMakeLists.txt --- netgen-6.2.1804+dfsg1/libsrc/visualization/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/visualization/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -9,10 +9,8 @@ add_library(visual ${NG_LIB_TYPE} ${LIB_VISUAL_SOURCES}) -if(NOT WIN32) - target_link_libraries( visual ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ) - install( TARGETS visual ${NG_INSTALL_DIR}) -endif(NOT WIN32) +target_link_libraries( visual ngcore ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ) +install( TARGETS visual ${NG_INSTALL_DIR}) install(FILES meshdoc.hpp mvdraw.hpp diff -Nru netgen-6.2.1804+dfsg1/libsrc/visualization/soldata.hpp netgen-6.2.1905+dfsg1/libsrc/visualization/soldata.hpp --- netgen-6.2.1804+dfsg1/libsrc/visualization/soldata.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/visualization/soldata.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -1,7 +1,7 @@ #ifndef FILE_SOLDATA #define FILE_SOLDATA - +#include // for tAVX namespace netgen { @@ -103,10 +103,10 @@ #ifdef __SSE__ virtual bool GetMultiSurfValue (size_t selnr, size_t facetnr, size_t npts, - const tAVXd * xref, - const tAVXd * x, - const tAVXd * dxdxref, - tAVXd * values) + const ngsimd::tAVXd * xref, + const ngsimd::tAVXd * x, + const ngsimd::tAVXd * dxdxref, + ngsimd::tAVXd * values) { cerr << "GetMultiSurfVaue not overloaded for SIMD" << endl; return false; diff -Nru netgen-6.2.1804+dfsg1/libsrc/visualization/visual.hpp netgen-6.2.1905+dfsg1/libsrc/visualization/visual.hpp --- netgen-6.2.1804+dfsg1/libsrc/visualization/visual.hpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/visualization/visual.hpp 2019-06-26 11:04:55.000000000 +0000 @@ -13,9 +13,9 @@ */ -#ifdef PARALLEL -#define PARALLELGL -#endif +// #ifdef PARALLEL +// #define PARALLELGL +// #endif #include "../include/incopengl.hpp" diff -Nru netgen-6.2.1804+dfsg1/libsrc/visualization/vsmesh.cpp netgen-6.2.1905+dfsg1/libsrc/visualization/vsmesh.cpp --- netgen-6.2.1804+dfsg1/libsrc/visualization/vsmesh.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/visualization/vsmesh.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -1618,12 +1618,15 @@ { const Segment & seg = mesh->LineSegment(i); + /* #ifdef PARALLEL if (ntasks > 1 && vispar.drawtetsdomain && - (vispar.drawtetsdomain != seg.GetPartition())) continue; + // (vispar.drawtetsdomain != seg.GetPartition())) continue; + (vispar.drawtetsdomain != mesh->seg_partition[i-1]) continue; #endif - + */ + const Point3d & p1 = (*mesh)[seg[0]]; const Point3d & p2 = (*mesh)[seg[1]]; @@ -1865,9 +1868,11 @@ { if (vispar.drawtetsdomain > 0) { + /* int tetid = vispar.drawmetispartition ? - (*mesh)[ei].GetPartition() : (*mesh)[ei].GetIndex(); - + (*mesh)[ei].GetPartition() : (*mesh)[ei].GetIndex(); + */ + int tetid = (*mesh)[ei].GetIndex(); if (vispar.drawtetsdomain != tetid) continue; } @@ -1884,8 +1889,8 @@ int ind = el.GetIndex() % 4; - if (vispar.drawmetispartition && el.GetPartition()!=-1) - ind = el.GetPartition() % 4; + // if (vispar.drawmetispartition && el.GetPartition()!=-1) + // ind = el.GetPartition() % 4; glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, tetcols[ind]); @@ -2682,7 +2687,7 @@ for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; - if (el.GetType() == PYRAMID && !el.IsDeleted()) + if ((el.GetType() == PYRAMID || el.GetType() == PYRAMID13) && !el.IsDeleted()) { int i = ei + 1; diff -Nru netgen-6.2.1804+dfsg1/libsrc/visualization/vssolution.cpp netgen-6.2.1905+dfsg1/libsrc/visualization/vssolution.cpp --- netgen-6.2.1804+dfsg1/libsrc/visualization/vssolution.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/libsrc/visualization/vssolution.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -451,8 +451,8 @@ glCallList (surfellist); #ifdef USE_BUFFERS - static int timer = NgProfiler::CreateTimer ("Solution::drawing - DrawSurfaceElements VBO"); - NgProfiler::StartTimer(timer); + // static int timer = NgProfiler::CreateTimer ("Solution::drawing - DrawSurfaceElements VBO"); + // NgProfiler::StartTimer(timer); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); @@ -460,7 +460,7 @@ glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); - NgProfiler::StopTimer(timer); + // NgProfiler::StopTimer(timer); #endif glDisable(GL_BLEND); @@ -1101,7 +1101,7 @@ glEndList (); if (clipplane_isolinelist) glDeleteLists (clipplane_isolinelist, 1); - + if (vispar.clipping.enable && clipsolution == 1 && sol) { clipplane_isolinelist = glGenLists (1); @@ -1113,7 +1113,8 @@ bool drawelem; glNormal3d (-clipplane[0], -clipplane[1], -clipplane[2]); - + glBegin (GL_LINES); + if (numisolines) for (int i = 0; i < cpt.Size(); i++) { @@ -1129,13 +1130,11 @@ DrawIsoLines (pts[trig.points[0].pnr].p, pts[trig.points[1].pnr].p, pts[trig.points[2].pnr].p, - // trig.points[1].p, - // trig.points[2].p, vali[0], vali[1], vali[2]); } + glEnd(); glEndList (); } - glEnd(); } clipplanetimestamp = max2 (vispar.clipping.timestamp, solutiontimestamp); @@ -1175,7 +1174,7 @@ for (int i = 0; i < npt; i++) pref[i] = double(i) / (npt-1); - + int meshdim = mesh->GetDimension(); for (SegmentIndex i = 0; i < mesh -> GetNSeg(); i++) { // mesh->GetCurvedElements(). @@ -1190,8 +1189,10 @@ { vsol->solclass->GetSegmentValue (i, pref[j], &mvalues[0]); // values[j] = ExtractValue (sol, scalcomp, &mvalues[0]); - points[j](0) += scaledeform * mvalues[0]; - points[j](1) += scaledeform * mvalues[1]; + for (int k = 0; k < min(ncomp, 3); k++) + points[j](k) += scaledeform * mvalues[k]; + // points[j](0) += scaledeform * mvalues[0]; + // points[j](1) += scaledeform * mvalues[1]; } } else if (sol) @@ -1200,7 +1201,8 @@ { sol->solclass->GetSegmentValue (i, pref[j], &mvalues[0]); values[j] = ExtractValue (sol, scalcomp, &mvalues[0]); - points[j](1) += scaledeform * values[j]; + if (meshdim <= 2) + points[j](meshdim) += scaledeform * values[j]; } } @@ -1218,6 +1220,7 @@ shared_ptr mesh = GetMesh(); static int timer = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements"); + /* static int timerstart = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements start"); static int timerloops = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements loops"); static int timerlist = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements list"); @@ -1229,6 +1232,7 @@ static int timer2 = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2"); static int timer2a = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2a"); static int timer2b = NgProfiler::CreateTimer ("Solution::DrawSurfaceElements 2b"); + */ NgProfiler::RegionTimer reg (timer); @@ -1260,7 +1264,7 @@ } #endif - NgProfiler::StartTimer(timerstart); + // NgProfiler::StartTimer(timerstart); if (surfellist) glDeleteLists (surfellist, 1); @@ -1351,7 +1355,7 @@ #endif - NgProfiler::StopTimer(timerstart); + // NgProfiler::StopTimer(timerstart); for (SurfaceElementIndex sei = 0; sei < nse; sei++) { @@ -1373,7 +1377,7 @@ - if ( el.GetType() == QUAD || el.GetType() == QUAD6 ) + if ( el.GetType() == QUAD || el.GetType() == QUAD6 || el.GetType() == QUAD8 ) { bool curved = curv.IsSurfaceElementCurved (sei); @@ -1506,7 +1510,7 @@ n = 1 << subdivisions; double invn = 1.0 / n; npt = (n+1)*(n+2)/2; - NgProfiler::StartTimer(timerloops); + // NgProfiler::StartTimer(timerloops); size_t base_pi = 0; for (int iy = 0, ii = 0; iy <= n; iy++) @@ -1558,7 +1562,7 @@ if ( el.GetType() == TRIG || el.GetType() == TRIG6 ) { - NgProfiler::StartTimer(timer1); + // NgProfiler::StartTimer(timer1); #ifdef __AVX_try_it_out__ // NgProfiler::StartTimer(timer1a); bool curved = curv.IsSurfaceElementCurved(sei); @@ -1699,7 +1703,7 @@ for (int ii = 0; ii < npt; ii++) points[ii] += GetSurfDeformation (sei, -1, pref[ii](0), pref[ii](1)); #endif - NgProfiler::StopTimer(timer1); + // NgProfiler::StopTimer(timer1); int save_usetexture = usetexture; if (!drawelem) @@ -1708,7 +1712,7 @@ SetTextureMode (usetexture); } - NgProfiler::StartTimer(timer2); + // NgProfiler::StartTimer(timer2); #ifdef USE_BUFFERS if (drawelem && usetexture == 1 && !logscale) @@ -1759,7 +1763,7 @@ glEnd(); } - NgProfiler::StopTimer(timer2); + // NgProfiler::StopTimer(timer2); @@ -1771,15 +1775,15 @@ } } } - NgProfiler::StopTimer(timerloops); + // NgProfiler::StopTimer(timerloops); - NgProfiler::StartTimer(timerbuffer); + // NgProfiler::StartTimer(timerbuffer); // glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, surfel_vbo[3]); // glBufferData(GL_ELEMENT_ARRAY_BUFFER, glob_ind.Size()*sizeof(int), &glob_ind[0], GL_STATIC_DRAW); // surfel_vbo_size = glob_ind.Size(); - NgProfiler::StopTimer(timerbuffer); + // NgProfiler::StopTimer(timerbuffer); // glDrawElements(GL_TRIANGLES, surfel_vbo_size, GL_UNSIGNED_INT, 0); @@ -1793,9 +1797,9 @@ // glDeleteBuffers (4, &vboId[0]); - NgProfiler::StartTimer(timerlist); + // NgProfiler::StartTimer(timerlist); glEndList (); - NgProfiler::StopTimer(timerlist); + // NgProfiler::StopTimer(timerlist); #ifdef PARALLELGL glFinish(); @@ -2646,17 +2650,21 @@ { shared_ptr mesh = GetMesh(); - static int timer1 = NgProfiler::CreateTimer ("getminmax, vol"); - static int timer2 = NgProfiler::CreateTimer ("getminmax, surf"); + // static int timer1 = NgProfiler::CreateTimer ("getminmax, vol"); + // static int timer2 = NgProfiler::CreateTimer ("getminmax, surf"); #ifdef PARALLEL - if (id == 0) + auto comm = mesh->GetCommunicator(); + if (comm.Size() > 1) { - MyMPI_SendCmd ("redraw"); - MyMPI_SendCmd ("getminmax"); + if (id == 0) + { + MyMPI_SendCmd ("redraw"); + MyMPI_SendCmd ("getminmax"); + } + MyMPI_Bcast (funcnr, mesh->GetCommunicator()); + MyMPI_Bcast (comp, mesh->GetCommunicator()); } - MyMPI_Bcast (funcnr); - MyMPI_Bcast (comp); #endif // double val; @@ -2676,7 +2684,7 @@ if (sol->draw_volume) { - NgProfiler::RegionTimer reg1 (timer1); + // NgProfiler::RegionTimer reg1 (timer1); int ne = mesh->GetNE(); @@ -2715,7 +2723,7 @@ if (sol->draw_surface) { - NgProfiler::RegionTimer reg2 (timer2); + // NgProfiler::RegionTimer reg2 (timer2); int nse = mesh->GetNSE(); for (int i = 0; i < nse; i++) @@ -2744,11 +2752,14 @@ minv = 1e99; maxv = -1e99; } - double hmin, hmax; - MPI_Reduce (&minv, &hmin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); - MPI_Reduce (&maxv, &hmax, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); - minv = hmin; - maxv = hmax; + if (ntasks > 1) + { + double hmin, hmax; + MPI_Reduce (&minv, &hmin, 1, MPI_DOUBLE, MPI_MIN, 0, MPI_COMM_WORLD); + MPI_Reduce (&maxv, &hmax, 1, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD); + minv = hmin; + maxv = hmax; + } #endif } @@ -2857,6 +2868,7 @@ } case PRISM: case PRISM12: + case PRISM15: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; @@ -2907,6 +2919,7 @@ } case PRISM: case PRISM12: + case PRISM15: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; @@ -2918,6 +2931,7 @@ break; } case PYRAMID: + case PYRAMID13: { if (lam3 > 1-1e-5) { @@ -3482,6 +3496,7 @@ case QUAD: case QUAD6: + case QUAD8: lami[0] = (1-lam1)*(1-lam2); lami[1] = lam1 * (1-lam2); lami[2] = lam1 * lam2; @@ -3723,6 +3738,7 @@ case QUAD: case QUAD6: + case QUAD8: lami[0] = (1-lam1)*(1-lam2); lami[1] = lam1 * (1-lam2); lami[2] = lam1 * lam2; @@ -3950,13 +3966,13 @@ { shared_ptr mesh = GetMesh(); - static int timer_vals = NgProfiler::CreateTimer ("ClipPlaneTrigs - vertex values"); + // static int timer_vals = NgProfiler::CreateTimer ("ClipPlaneTrigs - vertex values"); static int timer1 = NgProfiler::CreateTimer ("ClipPlaneTrigs1"); // static int timer1a = NgProfiler::CreateTimer ("ClipPlaneTrigs1a"); // static int timer2 = NgProfiler::CreateTimer ("ClipPlaneTrigs2"); - static int timer3 = NgProfiler::CreateTimer ("ClipPlaneTrigs3"); - static int timer4 = NgProfiler::CreateTimer ("ClipPlaneTrigs4"); - static int timer4b = NgProfiler::CreateTimer ("ClipPlaneTrigs4b"); + // static int timer3 = NgProfiler::CreateTimer ("ClipPlaneTrigs3"); + // static int timer4 = NgProfiler::CreateTimer ("ClipPlaneTrigs4"); + // static int timer4b = NgProfiler::CreateTimer ("ClipPlaneTrigs4b"); NgProfiler::RegionTimer reg1 (timer1); @@ -3989,9 +4005,9 @@ Array locposval(n3); Array compress(n3); - NgProfiler::StartTimer (timer_vals); - Array vertval(mesh->GetNV()); - Array posval(mesh->GetNV()); + // NgProfiler::StartTimer (timer_vals); + Array vertval(mesh->GetNP()); + Array posval(mesh->GetNP()); for (PointIndex pi = vertval.Begin(); pi < vertval.End(); pi++) { Point<3> vert = (*mesh)[pi]; @@ -4002,7 +4018,7 @@ clipplane[3]; posval[pi] = vertval[pi] > 0; } - NgProfiler::StopTimer (timer_vals); + // NgProfiler::StopTimer (timer_vals); INDEX_2_CLOSED_HASHTABLE edges(8*n3); // point nr of edge @@ -4017,7 +4033,7 @@ if(vispar.donotclipdomain > 0 && vispar.donotclipdomain == (*mesh)[ei].GetIndex()) continue; ELEMENT_TYPE type = (*mesh)[ei].GetType(); - if (type == HEX || type == PRISM || type == TET || type == TET10 || type == PYRAMID) + if (type == HEX || type == PRISM || type == TET || type == TET10 || type == PYRAMID || type == PYRAMID13 || type == PRISM15 || type == HEX20) { const Element & el = (*mesh)[ei]; @@ -4076,6 +4092,8 @@ switch (type) { case PRISM: + case PRISM12: + case PRISM15: if (ix+iy <= n) { ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); @@ -4086,9 +4104,11 @@ compress[ii] = -1; break; case HEX: + case HEX20: ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); break; case PYRAMID: + case PYRAMID13: ploc = Point<3> (double(ix) / n * (1-double(iz)/n), double(iy) / n * (1-double(iz)/n), double(iz)/n); @@ -4102,7 +4122,7 @@ locgrid[compress[ii]] = ploc; } - if (type != TET && type != TET10 && type != PRISM) cnt_valid = n3; + if (type != TET && type != TET10 && type != PRISM && type != PRISM12 && type != PRISM15) cnt_valid = n3; locgrid.SetSize(cnt_valid); @@ -4111,13 +4131,13 @@ if (mesh->GetCurvedElements().IsHighOrder()) { - NgProfiler::RegionTimer reg4(timer4); + // NgProfiler::RegionTimer reg4(timer4); mesh->GetCurvedElements(). CalcMultiPointElementTransformation (&locgrid, ei, &grid, 0); } else { - NgProfiler::RegionTimer reg4(timer4b); + // NgProfiler::RegionTimer reg4(timer4b); Vector shape(el.GetNP()); MatrixFixWidth<3> pointmat(el.GetNP()); @@ -4139,7 +4159,7 @@ } } - NgProfiler::RegionTimer reg3(timer3); + // NgProfiler::RegionTimer reg3(timer3); bool has_pos = false, all_pos = true; diff -Nru netgen-6.2.1804+dfsg1/ng/CMakeLists.txt netgen-6.2.1905+dfsg1/ng/CMakeLists.txt --- netgen-6.2.1804+dfsg1/ng/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/ng/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -24,19 +24,13 @@ 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} ${PYTHON_LIBRARIES}) if(NOT WIN32) target_link_libraries( netgen mesh stlvis stl geom2dvis interface geom2d csg stl visual csgvis ) @@ -52,12 +46,13 @@ if(WIN32) set_target_properties( gui PROPERTIES OUTPUT_NAME libgui ) endif(WIN32) + target_link_libraries( gui PRIVATE ${PYTHON_LIBRARIES}) 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 -Nru netgen-6.2.1804+dfsg1/ng/dialog.tcl netgen-6.2.1905+dfsg1/ng/dialog.tcl --- netgen-6.2.1804+dfsg1/ng/dialog.tcl 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/ng/dialog.tcl 2019-06-26 11:04:55.000000000 +0000 @@ -2009,7 +2009,7 @@ 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 -Nru netgen-6.2.1804+dfsg1/ng/ngappinit.cpp netgen-6.2.1905+dfsg1/ng/ngappinit.cpp --- netgen-6.2.1804+dfsg1/ng/ngappinit.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/ng/ngappinit.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -73,8 +73,12 @@ MPI_Comm_size(MPI_COMM_WORLD, &netgen::ntasks); MPI_Comm_rank(MPI_COMM_WORLD, &netgen::id); + if(netgen::ntasks!=1) + throw ngcore::Exception("Netgen GUI cannot run MPI-parallel"); + + // MPI_COMM_WORLD is just a local communicator + // netgen::ng_comm = ngcore::NgMPI_Comm{MPI_COMM_WORLD, false}; - MPI_Comm_dup ( MPI_COMM_WORLD, &netgen::mesh_comm); #endif if ( netgen::id == 0 ) @@ -106,21 +110,7 @@ #ifdef PARALLEL - if (netgen::ntasks == 1) - { - cout << "Run parallel Netgen with 'mpirun -np xy netgen'" << endl; - } - else - { - cout << "Running MPI - parallel using " - << netgen::ntasks << " processor" - << ((netgen::ntasks > 1) ? "s " : " ") << endl; - - cout << "MPI-version = " << MPI_VERSION << '.' << MPI_SUBVERSION << endl; - - if (mpi_provided == MPI_THREAD_MULTIPLE) - cout << "multithreaded MPI is supported" << endl; - } + cout << "Including MPI version " << MPI_VERSION << '.' << MPI_SUBVERSION << endl; #endif } @@ -156,8 +146,11 @@ if ( netgen::id == 0 ) { - if (parameters.StringFlagDefined ("testout")) - netgen::testout = new ofstream (parameters.GetStringFlag ("testout", "test.out")); + if (parameters.StringFlagDefined ("testout")) + { + delete ngcore::testout; + ngcore::testout = new ofstream (parameters.GetStringFlag ("testout", "test.out")); + } #ifdef SOCKETS diff -Nru netgen-6.2.1804+dfsg1/ng/ngpkg.cpp netgen-6.2.1905+dfsg1/ng/ngpkg.cpp --- netgen-6.2.1804+dfsg1/ng/ngpkg.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/ng/ngpkg.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -25,6 +25,8 @@ // to be sure to include the 'right' togl-version #include "Togl2.1/togl.h" +// EXTERN int Togl_PixelScale (const Togl * togl); + #include "fonts.hpp" extern bool nodisplay; @@ -664,11 +666,11 @@ char buf[20], lstring[200]; if (mesh) { - sprintf (buf, "%d", mesh->GetNP()); + sprintf (buf, "%u", unsigned(mesh->GetNP())); Tcl_SetVar (interp, "::status_np", buf, 0); - sprintf (buf, "%d", mesh->GetNE()); + sprintf (buf, "%u", unsigned(mesh->GetNE())); Tcl_SetVar (interp, "::status_ne", buf, 0); - sprintf (buf, "%d", mesh->GetNSE()); + sprintf (buf, "%u", unsigned(mesh->GetNSE())); Tcl_SetVar (interp, "::status_nse", buf, 0); } else @@ -1215,9 +1217,9 @@ mesh->SetMinimalH (mparam.minh); } -#ifdef PARALLEL +#ifdef PARALLELGL MyMPI_SendCmd ("bcastparthread"); - MyMPI_Bcast (mparam.parthread); + MyMPI_Bcast (mparam.parthread, MPI_COMM_WORLD); #endif return TCL_OK; @@ -1838,9 +1840,9 @@ - SYMBOLTABLE & GetVisualizationScenes () + SymbolTable & GetVisualizationScenes () { - static SYMBOLTABLE vss; + static SymbolTable vss; return vss; } @@ -1858,7 +1860,7 @@ vs = &vscross; if (GetVisualizationScenes().Used(vismode)) { - vs = GetVisualizationScenes().Get(vismode); + vs = GetVisualizationScenes()[vismode]; } else if (vismode) { @@ -1994,7 +1996,6 @@ return TCL_OK; } - static int Ng_SnapShot(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const *argv) { struct Togl *togl; @@ -2003,9 +2004,8 @@ const char * filename = Tcl_GetString(argv[2]); int len = strlen(filename); - - int w = Togl_Width (togl); - int h = Togl_Height (togl); + int w = Togl_PixelScale(togl)*Togl_Width (togl); + int h = Togl_PixelScale(togl)*Togl_Height (togl); Array buffer(w*h*3); glPixelStorei(GL_UNPACK_ALIGNMENT,1); @@ -2064,8 +2064,8 @@ cout << "Snapshot to file '" << filename << endl; - int w = Togl_Width (togl); - int h = Togl_Height (togl); + // int w = Togl_Width (togl); + // int h = Togl_Height (togl); ofstream outfile(filename2); outfile << "P6" << endl @@ -2184,10 +2184,8 @@ Tcl_Interp * interp, int argc, tcl_const char *argv[]) { - int px, py; - - px = atoi (argv[1]); - py = atoi (argv[2]); + int px = Togl_PixelScale(togl)*atoi (argv[1]); + int py = Togl_PixelScale(togl)*atoi (argv[2]); SetVisualScene(interp); vs->MouseDblClick (px, py); @@ -2266,8 +2264,9 @@ mesh->ParallelMetis(); cout << "done" << endl; ntasks = 1; - for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) - (*mesh)[ei].SetIndex ( (*mesh)[ei].GetPartition() ); + + // for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) + // (*mesh)[ei].SetIndex ( (*mesh)[ei].GetPartition() ); return TCL_OK; @@ -2704,7 +2703,7 @@ //cout << "stopped acis, outcome = " << res.ok() << endl; #endif -#ifdef PARALLEL +#ifdef PARALLELGL if (id == 0) MyMPI_SendCmd ("end"); MPI_Finalize(); #endif diff -Nru netgen-6.2.1804+dfsg1/ng/onetcl.cpp netgen-6.2.1905+dfsg1/ng/onetcl.cpp --- netgen-6.2.1804+dfsg1/ng/onetcl.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/ng/onetcl.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -2687,7 +2687,7 @@ ,"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 -Nru netgen-6.2.1804+dfsg1/ng/parallelfunc.cpp netgen-6.2.1905+dfsg1/ng/parallelfunc.cpp --- netgen-6.2.1804+dfsg1/ng/parallelfunc.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/ng/parallelfunc.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -71,8 +71,11 @@ MPI_Comm_size(MPI_COMM_WORLD, &ntasks); MPI_Comm_rank(MPI_COMM_WORLD, &id); - if (parameters.StringFlagDefined ("testout")) - testout = new ofstream (string("testout_proc") + id ); + if (parameters.StringFlagDefined ("testout")) + { + delete testout; + testout = new ofstream (string("testout_proc") + id ); + } @@ -125,7 +128,7 @@ else if ( message == "bcastparthread" ) { - MyMPI_Bcast (mparam.parthread); + MyMPI_Bcast (mparam.parthread, MPI_COMM_WORLD); } diff -Nru netgen-6.2.1804+dfsg1/ng/Togl2.1/toglDecls.h netgen-6.2.1905+dfsg1/ng/Togl2.1/toglDecls.h --- netgen-6.2.1804+dfsg1/ng/Togl2.1/toglDecls.h 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/ng/Togl2.1/toglDecls.h 2019-06-26 11:04:55.000000000 +0000 @@ -50,6 +50,11 @@ /* 6 */ EXTERN int Togl_Height(const Togl *togl); #endif +#ifndef Togl_PixelScale_TCL_DECLARED +#define Togl_PixelScale_TCL_DECLARED +/* 6 */ +EXTERN int Togl_PixelScale(const Togl *togl); +#endif #ifndef Togl_Interp_TCL_DECLARED #define Togl_Interp_TCL_DECLARED /* 7 */ diff -Nru netgen-6.2.1804+dfsg1/nglib/CMakeLists.txt netgen-6.2.1905+dfsg1/nglib/CMakeLists.txt --- netgen-6.2.1804+dfsg1/nglib/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/nglib/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -8,9 +8,6 @@ $ $ $ - $ - $ - $ $ $ @@ -26,20 +23,23 @@ 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 PRIVATE gen la gprim PUBLIC ngcore) +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 -Nru netgen-6.2.1804+dfsg1/nglib/nglib.cpp netgen-6.2.1905+dfsg1/nglib/nglib.cpp --- netgen-6.2.1804+dfsg1/nglib/nglib.cpp 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/nglib/nglib.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -82,7 +82,7 @@ mycout = &cout; myerr = &cerr; // netgen::testout->SetOutStream (new ofstream ("test.out")); - testout = new ofstream ("test.out"); + // testout = new ofstream ("test.out"); } @@ -1211,14 +1211,14 @@ } */ - + /* #ifndef WIN32 void ResetTime () { ; } #endif - + */ void MyBeep (int i) diff -Nru netgen-6.2.1804+dfsg1/python/geom2d.py netgen-6.2.1905+dfsg1/python/geom2d.py --- netgen-6.2.1804+dfsg1/python/geom2d.py 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/python/geom2d.py 2019-06-26 11:04:55.000000000 +0000 @@ -39,11 +39,107 @@ geo.Append( ["spline3", pts[p1], pts[p2], pts[p3]], **args) + +def CreatePML(geo, pml_size, tol=1e-12): + """Create a pml layer around the geometry. This function works only on convex geometries and +the highest existing domain number must be named by using the function geo.SetMaterial(domnr, name). +Points in the geometry are assumed to be the same if (pt1 - pt2).Norm() < tol. +Returned is a dict with information to create the pml layer: + normals: A dict from the names of the linear pml domains to the normal vectors pointing inside the pml.""" + + def Start(spline): + if spline.rightdom == 0: + return spline.StartPoint() + return spline.EndPoint() + def End(spline): + if spline.rightdom == 0: + return spline.EndPoint() + return spline.StartPoint() + + splines = [] + for i in range(geo.GetNSplines()): + splines.append(geo.GetSpline(i)) + border = [] + is_closed = False + current_endpoint = None + while not is_closed: + for spline in splines: + if spline.leftdom == 0 or spline.rightdom == 0: + if current_endpoint is not None: + if (Start(spline)-current_endpoint).Norm() < tol: + border.append(spline) + current_endpoint = End(spline) + if (current_endpoint - startpoint).Norm() < tol: + is_closed = True + break + else: + startpoint = Start(spline) + current_endpoint = End(spline) + border.append(spline) + break + else: + raise Exception("Couldn't find closed spline around domain") + endpointindex_map = [] + for spline in border: + pnt = End(spline) + for i in range(geo.GetNPoints()): + if (pnt - geo.GetPoint(i)).Norm() < tol: + endpointindex_map.append(i) + break + else: + raise Exception("Couldn't find endpoint of spline in geometry") + start_ndoms = ndoms = geo.GetNDomains() + 1 + new_spline_domains = [] + normals = {} + for i, spline in enumerate(border): + if i == 0: + global_start = Start(spline) + pml_size * spline.GetNormal(0) + global_start_pnt = current_start = geo.AppendPoint(global_start[0], global_start[1]) + next_spline = border[(i+1)%len(border)] + new_end = End(spline) + pml_size * spline.GetNormal(1) + spline_name = geo.GetBCName(spline.bc) + if (new_end - global_start).Norm() < tol: + new_spline_domains.append(ndoms) + geo.Append(["line", current_start, global_start_pnt], bc="outer_" + spline_name, leftdomain = ndoms) + geo.Append(["line", global_start_pnt, endpointindex_map[i]], leftdomain=ndoms, rightdomain=start_ndoms) + geo.SetMaterial(ndoms, "pml_" + spline_name) + normals["pml_" + spline_name] = spline.GetNormal(0) + ndoms += 1 + break + end = geo.AppendPoint(new_end[0], new_end[1]) + new_spline_domains.append(ndoms) + geo.Append(["line", current_start, end], bc="outer_" + spline_name, leftdomain = ndoms) + geo.Append(["line", end, endpointindex_map[i]], leftdomain=ndoms, rightdomain=ndoms+1) + geo.SetMaterial(ndoms, "pml_" + spline_name) + normals["pml_" + spline_name] = spline.GetNormal(0) + ndoms += 1 + new_start = Start(next_spline) + pml_size * next_spline.GetNormal(0) + if (new_start - global_start).Norm() < tol: + geo.Append(["line", end, global_start_pnt], bc="outer", leftdomain = ndoms) + geo.Append(["line", global_start_pnt, endpointindex_map[i]], leftdomain=ndoms, rightdomain=start_ndoms) + geo.SetMaterial(ndoms, "pml_corner") + ndoms += 1 + break + if (new_end - new_start).Norm() < tol: + current_start = end + else: + current_start = geo.AppendPoint(new_start[0], new_start[1]) + geo.Append(["line", end, current_start], bc="outer", leftdomain = ndoms) + geo.Append(["line", current_start, endpointindex_map[i]], leftdomain=ndoms, rightdomain=ndoms+1) + geo.SetMaterial(ndoms, "pml_corner") + ndoms += 1 + for spline, domnr in zip(border, new_spline_domains): + if spline.leftdom == 0: + spline.leftdom = domnr + else: + spline.rightdom = domnr + return {"normals" : normals} + SplineGeometry.AddCircle = lambda geo, c, r, **args : MakeCircle(geo, c, r, **args) SplineGeometry.AddRectangle = lambda geo, p1, p2, **args : MakeRectangle(geo, p1, p2, **args) SplineGeometry.AddSegment = lambda *args, **kwargs : SplineGeometry.Append(*args, **kwargs) SplineGeometry.AddPoint = lambda *args, **kwargs : SplineGeometry.AppendPoint(*args, **kwargs) - +SplineGeometry.CreatePML = CreatePML __all__ = ['SplineGeometry', 'unit_square'] diff -Nru netgen-6.2.1804+dfsg1/python/gui.py netgen-6.2.1905+dfsg1/python/gui.py --- netgen-6.2.1804+dfsg1/python/gui.py 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/python/gui.py 2019-06-26 11:04:55.000000000 +0000 @@ -11,5 +11,12 @@ 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 -Nru netgen-6.2.1804+dfsg1/python/read_gmsh.py netgen-6.2.1905+dfsg1/python/read_gmsh.py --- netgen-6.2.1804+dfsg1/python/read_gmsh.py 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/python/read_gmsh.py 2019-06-26 11:04:55.000000000 +0000 @@ -1,9 +1,10 @@ from netgen.meshing import * - def ReadGmsh(filename): + if not filename.endswith(".msh"): + filename += ".msh" meshdim = 1 - with open(filename + ".msh", 'r') as f: + with open(filename, 'r') as f: while f.readline().split()[0] != "$Elements": pass nelem = int(f.readline()) @@ -16,15 +17,58 @@ meshdim = 3 break - f = open(filename + ".msh", 'r') + f = open(filename, 'r') mesh = Mesh(dim=meshdim) pointmap = {} facedescriptormap = {} - namemap = {} + namemap = { 0 : "default" } materialmap = {} bbcmap = {} + segm = 1 + trig = 2 + quad = 3 + tet = 4 + hex = 5 + prism = 6 + pyramid = 7 + segm3 = 8 # 2nd order line + trig6 = 9 # 2nd order trig + tet10 = 11 # 2nd order tet + point = 15 + quad8 = 16 # 2nd order quad + hex20 = 17 # 2nd order hex + prism15 = 18 # 2nd order prism + pyramid13 = 19 # 2nd order pyramid + segms = [segm, segm3] + trigs = [trig, trig6] + quads = [quad, quad8] + tets = [tet, tet10] + hexes = [hex, hex20] + prisms = [prism, prism15] + pyramids = [pyramid, pyramid13] + elem0d = [point] + elem1d = segms + elem2d = trigs + quads + elem3d = tets + hexes + prisms + pyramids + + num_nodes_map = { segm : 2, + trig : 3, + quad : 4, + tet : 4, + hex : 8, + prism : 6, + pyramid : 5, + segm3 : 3, + trig6 : 6, + tet10 : 10, + point : 1, + quad8 : 8, + hex20 : 20, + prism15 : 18, + pyramid13 : 19 } + while True: line = f.readline() if line == "": @@ -57,29 +101,14 @@ # the first tag is the physical group nr, the second tag is the group nr of the dim tags = [int(line[3 + k]) for k in range(numtags)] - if elmtype == 1: # 2-node line - num_nodes = 2 - elif elmtype == 2: # 3-node trig - num_nodes = 3 - elif elmtype == 3: # 4-node quad - num_nodes = 4 - elif elmtype == 4: # 4-node tet - num_nodes = 4 - elif elmtype == 5: # 8-node hex - num_nodes = 8 - elif elmtype == 6: # 6-node prism - num_nodes = 6 - elif elmtype == 7: # 5-node pyramid - num_nodes = 5 - elif elmtype == 15: # 1-node point - num_nodes = 1 - else: + if elmtype not in num_nodes_map: raise Exception("element type", elmtype, "not implemented") + num_nodes = num_nodes_map[elmtype] nodenums = line[3 + numtags:3 + numtags + num_nodes] nodenums2 = [pointmap[int(nn)] for nn in nodenums] - if elmtype == 1: + if elmtype in elem1d: if meshdim == 3: if tags[1] in bbcmap: index = bbcmap[tags[1]] @@ -117,7 +146,7 @@ mesh.Add(Element1D(index=index, vertices=nodenums2)) - if elmtype in [2, 3]: # 2d elements + if elmtype in elem2d: # 2d elements if meshdim == 3: if tags[1] in facedescriptormap.keys(): index = facedescriptormap[tags[1]] @@ -142,9 +171,17 @@ mesh.SetMaterial(index, "surf" + str(tags[1])) materialmap[tags[1]] = index - mesh.Add(Element2D(index, nodenums2)) + if elmtype in trigs: + ordering = [i for i in range(3)] + if elmtype == trig6: + ordering += [4,5,3] + if elmtype in quads: + ordering = [i for i in range(4)] + if elmtype == quad8: + ordering += [4, 6, 7, 5] + mesh.Add(Element2D(index, [nodenums2[i] for i in ordering])) - if elmtype in [4, 5, 6, 7]: # volume elements + if elmtype in elem3d: # volume elements if tags[1] in materialmap: index = materialmap[tags[1]] else: @@ -157,9 +194,22 @@ nodenums2 = [pointmap[int(nn)] for nn in nodenums] - if elmtype == 4: - mesh.Add(Element3D(index, [nodenums2[0], nodenums2[1], nodenums2[3], nodenums2[2]])) - elif elmtype in [5, 6, 7]: - mesh.Add(Element3D(index, nodenums2)) + if elmtype in tets: + ordering = [0,1,2,3] + if elmtype == tet10: + ordering += [4,6,7,5,9,8] + elif elmtype in hexes: + ordering = [0,1,5,4,3,2,6,7] + if elmtype == hex20: + ordering += [8,16,10,12,13,19,15,14,9,11,18,17] + elif elmtype in prisms: + ordering = [0,2,1,3,5,4] + if elmtype == prism15: + ordering += [7,6,9,8,11,10,13,12,14] + elif elmtype in pyramids: + ordering = [3,2,1,0,4] + if elmtype == pyramid13: + ordering += [10,5,6,8,12,11,9,7] + mesh.Add(Element3D(index, [nodenums2[i] for i in ordering])) return mesh diff -Nru netgen-6.2.1804+dfsg1/tests/build_guidelines.sh netgen-6.2.1905+dfsg1/tests/build_guidelines.sh --- netgen-6.2.1804+dfsg1/tests/build_guidelines.sh 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/build_guidelines.sh 2019-06-26 11:04:55.000000000 +0000 @@ -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 -Nru netgen-6.2.1804+dfsg1/tests/build_mpi.sh netgen-6.2.1905+dfsg1/tests/build_mpi.sh --- netgen-6.2.1804+dfsg1/tests/build_mpi.sh 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/build_mpi.sh 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,6 @@ +cd +mkdir -p build/netgen +cd build/netgen +cmake ../../src/netgen -DUSE_CCACHE=ON -DUSE_MPI=ON +make -j12 +make install diff -Nru netgen-6.2.1804+dfsg1/tests/build_ngsolve.sh netgen-6.2.1905+dfsg1/tests/build_ngsolve.sh --- netgen-6.2.1804+dfsg1/tests/build_ngsolve.sh 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/build_ngsolve.sh 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,12 @@ +cd ~/src +git clone https://github.com/NGSolve/ngsolve.git +mkdir -p ~/build/ngsolve +cd ~/build/ngsolve +cmake \ + -DUSE_MKL=ON \ + -DUSE_CCACHE=ON \ + -DNETGEN_DIR=/opt/netgen \ + -DCMAKE_BUILD_TYPE=RelWithDebInfo \ + ~/src/ngsolve +make -j12 +make install diff -Nru netgen-6.2.1804+dfsg1/tests/build_nospdlog.sh netgen-6.2.1905+dfsg1/tests/build_nospdlog.sh --- netgen-6.2.1804+dfsg1/tests/build_nospdlog.sh 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/build_nospdlog.sh 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,8 @@ +cd +mkdir -p build/netgen +cd build/netgen +cmake ../../src/netgen -DUSE_CCACHE=ON -DUSE_SPDLOG=OFF -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang +make -j12 +make install + diff -Nru netgen-6.2.1804+dfsg1/tests/catch/archive.cpp netgen-6.2.1905+dfsg1/tests/catch/archive.cpp --- netgen-6.2.1804+dfsg1/tests/catch/archive.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/catch/archive.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,340 @@ + +#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 testMap(Archive& in, Archive& out) +{ + map map1; + map1["netgen"] = "v6.2.1901"; + out & map1; + out.FlushBuffer(); + map map2; + in & map2; + CHECK(map2.size() == 1); + CHECK(map2["netgen"] == "v6.2.1901"); +} + +enum MyEnum + { + CASE1, + CASE2 + }; + +void testEnum(Archive& in, Archive& out) + { + MyEnum en = CASE2; + out & en; + out.FlushBuffer(); + MyEnum enin; + in & enin; + CHECK(enin == CASE2); + } + +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); + } + SECTION("map") + { + testMap(in, out); + } + SECTION("enum") + { + testEnum(in, out); + } +} + +TEST_CASE("BinaryArchive") +{ + auto stream = make_shared(); + BinaryOutArchive out(stream); + BinaryInArchive in(stream); + testArchive(in, out); +} + +TEST_CASE("TextArchive") +{ + auto stream = make_shared(); + TextOutArchive out(stream); + TextInArchive in(stream); + testArchive(in, out); +} diff -Nru netgen-6.2.1804+dfsg1/tests/catch/CMakeLists.txt netgen-6.2.1905+dfsg1/tests/catch/CMakeLists.txt --- netgen-6.2.1804+dfsg1/tests/catch/CMakeLists.txt 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/catch/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,32 @@ + +if(ENABLE_UNIT_TESTS) +add_custom_target(unit_tests) + +# Build catch_main test object +include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include ${SPDLOG_INCLUDE_DIR}) +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} ) + target_link_libraries(test_${name} ngcore catch_main ${PYTHON_LIBRARIES}) + + add_dependencies(unit_tests test_${name}) + add_test(NAME unit_${name} COMMAND test_${name}) + set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built) + + if(ENABLE_CPP_CORE_GUIDELINES_CHECK) + set_target_properties(test_${name} PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") + endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) +endmacro() + +add_unit_test(archive archive.cpp) +add_unit_test(symboltable symboltable.cpp) +add_unit_test(version version.cpp) + +endif(ENABLE_UNIT_TESTS) diff -Nru netgen-6.2.1804+dfsg1/tests/catch/main.cpp netgen-6.2.1905+dfsg1/tests/catch/main.cpp --- netgen-6.2.1804+dfsg1/tests/catch/main.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/catch/main.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,3 @@ + +#define CATCH_CONFIG_MAIN +#include diff -Nru netgen-6.2.1804+dfsg1/tests/catch/symboltable.cpp netgen-6.2.1905+dfsg1/tests/catch/symboltable.cpp --- netgen-6.2.1804+dfsg1/tests/catch/symboltable.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/catch/symboltable.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,64 @@ + +#include "catch.hpp" +#include <../core/ngcore.hpp> +using namespace ngcore; +using namespace std; + +TEST_CASE("Symboltable") +{ + SymbolTable table; + CHECK_THROWS_AS(table["test"], RangeException); + table.Set("first", 1); + CHECK(table["first"] == 1); + table["first"] = 2; + CHECK(table["first"] == 2); + auto index = table.Index("first"); + CHECK(index == 0); + CHECK(table[index] == 2); + table[index] = 3; + CHECK(table["first"] == 3); +#ifndef NDEBUG + int a; + CHECK_THROWS_AS(a = table[5], RangeException); + CHECK_THROWS_AS(table.GetName(5), RangeException); +#endif + CHECK(table.Used("first")); + CHECK(!table.Used("second")); + SymbolTable another; + another.Set("first", 1); + another.Set("second", 2); + table.Update(another); + CHECK(table["first"] == 1); + CHECK(table["second"] == 2); + std::stringstream s; + s << table; + CHECK(s.str() == "first : 1\nsecond : 2\n"); + auto ss = std::make_shared(); + BinaryOutArchive ao(ss); + ao & table; + ao.FlushBuffer(); + BinaryInArchive ai(ss); + SymbolTable read; + ai & read; + for(size_t i = 0; i is special because of vector is special... + SymbolTable btable; + btable.Set("true", true); + btable.Set("false", false); + CHECK(btable[0]); + CHECK(!btable[1]); + CHECK(btable["true"]); + CHECK(!btable["false"]); + ao & btable; + ao.FlushBuffer(); + SymbolTable bread; + ai & bread; + CHECK(bread["true"]); + CHECK(!bread["false"]); +} diff -Nru netgen-6.2.1804+dfsg1/tests/catch/version.cpp netgen-6.2.1905+dfsg1/tests/catch/version.cpp --- netgen-6.2.1804+dfsg1/tests/catch/version.cpp 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/catch/version.cpp 2019-06-26 11:04:55.000000000 +0000 @@ -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 -Nru netgen-6.2.1804+dfsg1/tests/CMakeLists.txt netgen-6.2.1905+dfsg1/tests/CMakeLists.txt --- netgen-6.2.1804+dfsg1/tests/CMakeLists.txt 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/CMakeLists.txt 2019-06-26 11:04:55.000000000 +0000 @@ -1 +1,2 @@ +add_subdirectory(catch) add_subdirectory(pytest) diff -Nru netgen-6.2.1804+dfsg1/tests/docker_15.10 netgen-6.2.1905+dfsg1/tests/docker_15.10 --- netgen-6.2.1804+dfsg1/tests/docker_15.10 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/docker_15.10 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -FROM ubuntu:15.10 -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 -Nru netgen-6.2.1804+dfsg1/tests/docker_16.04 netgen-6.2.1905+dfsg1/tests/docker_16.04 --- netgen-6.2.1804+dfsg1/tests/docker_16.04 2018-05-01 19:26:47.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/docker_16.04 1970-01-01 00:00:00.000000000 +0000 @@ -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 -Nru netgen-6.2.1804+dfsg1/tests/dockerfile netgen-6.2.1905+dfsg1/tests/dockerfile --- netgen-6.2.1804+dfsg1/tests/dockerfile 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/dockerfile 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,5 @@ +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 clang-tidy python3-distutils clang +ADD . /root/src/netgen diff -Nru netgen-6.2.1804+dfsg1/tests/dockerfile_mpi netgen-6.2.1905+dfsg1/tests/dockerfile_mpi --- netgen-6.2.1804+dfsg1/tests/dockerfile_mpi 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/dockerfile_mpi 2019-06-26 11:04:55.000000000 +0000 @@ -0,0 +1,5 @@ +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 clang-tidy python3-distutils clang libopenmpi-dev openmpi-bin gfortran +ADD . /root/src/netgen diff -Nru netgen-6.2.1804+dfsg1/tests/pytest/test_pickling.py netgen-6.2.1905+dfsg1/tests/pytest/test_pickling.py --- netgen-6.2.1804+dfsg1/tests/pytest/test_pickling.py 1970-01-01 00:00:00.000000000 +0000 +++ netgen-6.2.1905+dfsg1/tests/pytest/test_pickling.py 2019-06-26 11:04:55.000000000 +0000 @@ -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()