Merge branch 'ngcore' into curved_splinesurface

This commit is contained in:
Christopher Lackner 2018-12-13 14:01:26 +01:00
commit 8fc1420d03
69 changed files with 1978 additions and 512 deletions

View File

@ -45,16 +45,8 @@ stages:
- pwd
- ls
- docker info
.template_ubuntu_1510: &ubuntu_1510
<<: *ubuntu
variables:
UBUNTU_VERSION: "15.10"
.template_ubuntu_1604: &ubuntu_1604
<<: *ubuntu
variables:
UBUNTU_VERSION: "16.04"
UBUNTU_VERSION: "18.04"
############################################
# Build stage
@ -98,18 +90,14 @@ build_netgen_win64:
.template_build_linux: &build_linux
stage: build
script:
- docker build -t netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} -f tests/docker_${UBUNTU_VERSION} .
- docker build -t netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} -f tests/dockerfile .
- rm -f netgen_${CI_BUILD_REF_NAME}_$UBUNTU_VERSION.id
- docker run --cidfile netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build.sh
- docker commit `cat netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id` netgen_${CI_BUILD_REF_NAME}_installed:${UBUNTU_VERSION}
- rm netgen_${CI_BUILD_REF_NAME}_${UBUNTU_VERSION}.id
.build_ubuntu_1510:
<<: *ubuntu_1510
<<: *build_linux
build_ubuntu_1604:
<<: *ubuntu_1604
build_ubuntu:
<<: *ubuntu
<<: *build_linux
@ -145,13 +133,17 @@ test_win64:
netgen_${CI_BUILD_REF_NAME}_installed:${UBUNTU_VERSION}
bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V"'
.test_ubuntu_1510:
<<: *ubuntu_1510
<<: *test_linux
test_ubuntu_1604:
<<: *ubuntu_1604
test_ubuntu:
<<: *ubuntu
<<: *test_linux
# cpp guideline checks
test_guidelines:
<<: *ubuntu
stage: test
script:
- docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh
when: always
############################################
# Deploy stage
############################################

View File

@ -17,6 +17,8 @@ option( INTEL_MIC "cross compile for intel xeon phi")
option( INSTALL_PROFILES "install environment variable settings to /etc/profile.d" OFF )
option( USE_CCACHE "use ccache")
option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON)
option( ENABLE_UNIT_TESTS "Enable Catch unit tests")
option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF)
option( USE_SUPERBUILD "use ccache" ON)
@ -341,8 +343,27 @@ execute_process(COMMAND hdiutil create -volname Netgen -srcfolder ${CMAKE_INSTAL
enable_testing()
include(CTest)
if(ENABLE_UNIT_TESTS)
include(${CMAKE_CURRENT_LIST_DIR}/cmake/external_projects/catch.cmake)
endif(ENABLE_UNIT_TESTS)
#######################################################################
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
find_program(
CLANG_TIDY_EXE
NAMES "clang-tidy"
DOC "Path to clang-tidy executable"
)
if(NOT CLANG_TIDY_EXE)
message(WARNING "clang-tidy not found.")
else()
message(STATUS "clang-tidy found: ${CLANG_TIDY_EXE}")
set(DO_CLANG_TIDY "${CLANG_TIDY_EXE}" "-header-filter=libsrc/core/")
endif()
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
add_subdirectory(libsrc)
add_subdirectory(ng)
add_subdirectory(tutorials)

View File

@ -140,6 +140,8 @@ set_vars( NETGEN_CMAKE_ARGS
INTEL_MIC
CMAKE_PREFIX_PATH
CMAKE_INSTALL_PREFIX
ENABLE_UNIT_TESTS
ENABLE_CPP_CORE_GUIDELINES_CHECK
)
# propagate all variables set on the command line using cmake -DFOO=BAR

View File

@ -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")

View File

@ -27,85 +27,35 @@ if(APPLE)
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)
find_package(TCL 8.6 REQUIRED)
list(APPEND NETGEN_DEPENDENCIES project_tcl 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 ";" "$<SEMICOLON>" TCL_INC "${TCL_INCLUDE_PATH}")
string(REPLACE ";" "$<SEMICOLON>" 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
DEPENDS project_tcl project_tk
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
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()
# 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)
#
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
)
list(APPEND NETGEN_DEPENDENCIES project_tkdnd)
elseif(WIN32)

View File

@ -1,35 +1,36 @@
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 <tcl.h>
#import <tk.h>
#import <tkInt.h>
+#undef panic
#import <tkMacOSXInt.h>
#import <Cocoa/Cocoa.h>
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4eb497c..c6424fc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -43,17 +43,17 @@ IF ( WIN32 )
ELSE ( WIN32 )
## Unix and OS X...
IF ( APPLE )
- SET ( CMAKE_OSX_ARCHITECTURES "x86_64;i386" )
+ SET ( CMAKE_OSX_ARCHITECTURES "x86_64")
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 ( /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 )
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,7 +125,7 @@ SET ( CP ${CMAKE_COMMAND} -E copy )
## Locate Tcl/Tk
## ===========================================================================
MESSAGE ( STATUS "Searching for Tcl/Tk..." )
-FIND_PACKAGE ( TCL REQUIRED )
+#FIND_PACKAGE ( TCL REQUIRED )
FIND_PACKAGE ( TclStub REQUIRED )
## Tcl/Tk info (useful for debug purposes)...

@ -1 +1 @@
Subproject commit 2a150736601bb3113877bb673fb934bb60d46ec5
Subproject commit e2b884c33bcde70b2ea562ffa52dd7ebee276d50

View File

@ -1,3 +1,4 @@
add_subdirectory(core)
add_subdirectory(general)
add_subdirectory(gprim)
add_subdirectory(linalg)

5
libsrc/core/.clang-tidy Normal file
View File

@ -0,0 +1,5 @@
Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard'
CheckOptions:
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
value: 1
WarningsAsErrors: '*'

View File

@ -0,0 +1,12 @@
add_library(ngcore SHARED archive.cpp)
target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS)
install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen)
install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)

52
libsrc/core/archive.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "archive.hpp"
#ifndef WIN32
#include <cxxabi.h>
#endif
namespace ngcore
{
// clang-tidy should ignore this static object
static std::map<std::string, VersionInfo> library_versions; // NOLINT
std::map<std::string, VersionInfo>& Archive :: GetLibraryVersions()
{
return library_versions;
}
const VersionInfo& GetLibraryVersion(const std::string& library)
{ return library_versions[library]; }
void SetLibraryVersion(const std::string& library, const VersionInfo& version)
{ library_versions[library] = version; }
#ifdef WIN32
// windows does demangling in typeid(T).name()
std::string Demangle(const char* typeinfo) { return typeinfo; }
#else
std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo,
nullptr,
nullptr,
&status); }
#endif
// clang-tidy should ignore this static object
static std::unique_ptr<std::map<std::string, detail::ClassArchiveInfo>> type_register; // NOLINT
const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname)
{
if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return (*type_register)[classname];
}
void Archive :: SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info)
{
if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
(*type_register)[classname] = info;
}
bool Archive :: IsRegistered(const std::string& classname)
{
if(type_register == nullptr) type_register =
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
return type_register->count(classname) != 0;
}
} // namespace ngcore

796
libsrc/core/archive.hpp Normal file
View File

@ -0,0 +1,796 @@
#ifndef NETGEN_CORE_ARCHIVE_HPP
#define NETGEN_CORE_ARCHIVE_HPP
#include <complex> // for complex
#include <cstring> // for size_t, strlen
#include <fstream> // for operator<<, ifstream, ofstream, basic...
#include <functional> // for function
#include <map> // for map, _Rb_tree_iterator
#include <memory> // for __shared_ptr_access, __shared_ptr_acc...
#include <stdexcept> // for runtime_error
#include <string> // for string, operator+
#include <type_traits> // for declval, enable_if, false_type, is_co...
#include <typeinfo> // for type_info
#include <utility> // for move, swap, pair
#include <vector> // for vector
#include "ngcore_api.hpp" // for NGCORE_API, unlikely
#include "type_traits.hpp" // for all_of_tmpl
#include "version.hpp" // for VersionInfo
namespace ngcore
{
// Libraries using this archive can store their version here to implement backwards compatibility
NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library);
NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version);
NGCORE_API std::string Demangle(const char* typeinfo);
class NGCORE_API Archive;
namespace detail
{
// create new pointer of type T if it is default constructible, else throw
template<typename T, typename ...Rest>
T* constructIfPossible_impl(Rest... /*unused*/)
{ throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); }
template<typename T, typename= typename std::enable_if<std::is_constructible<T>::value>::type>
T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT
template<typename T>
T* constructIfPossible() { return constructIfPossible_impl<T>(int{}); }
//Type trait to check if a class implements a 'void DoArchive(Archive&)' function
template<typename T>
struct has_DoArchive
{
private:
template<typename T2>
static constexpr auto check(T2*) ->
typename std::is_same<decltype(std::declval<T2>().DoArchive(std::declval<Archive&>())),void>::type;
template<typename>
static constexpr std::false_type check(...);
using type = decltype(check<T>(nullptr)); // NOLINT
public:
NGCORE_API static constexpr bool value = type::value;
};
// Check if class is archivable
template<typename T>
struct is_Archivable_struct
{
private:
template<typename T2>
static constexpr auto check(T2*) ->
typename std::is_same<decltype(std::declval<Archive>() & std::declval<T2&>()),Archive&>::type;
template<typename>
static constexpr std::false_type check(...);
using type = decltype(check<T>(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<void*(const std::type_info&)> 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<void*(const std::type_info&, void*)> 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<void*(const std::type_info&, void*)> downcaster;
};
} // namespace detail
template<typename T>
constexpr bool is_archivable = detail::is_Archivable_struct<T>::value;
// Base Archive class
class NGCORE_API Archive
{
const bool is_output;
// how many different shared_ptr/pointer have been (un)archived
int shared_ptr_count, ptr_count;
// maps for archived shared pointers and pointers
std::map<void*, int> shared_ptr2nr, ptr2nr;
// vectors for storing the unarchived (shared) pointers
std::vector<std::shared_ptr<void>> nr2shared_ptr;
std::vector<void*> nr2ptr;
public:
Archive() = delete;
Archive(const Archive&) = delete;
Archive(Archive&&) = delete;
Archive (bool ais_output) :
is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; }
virtual ~Archive() { ; }
Archive& operator=(const Archive&) = delete;
Archive& operator=(Archive&&) = delete;
bool Output () const { return is_output; }
bool Input () const { return !is_output; }
virtual const VersionInfo& GetVersion(const std::string& library) = 0;
// Pure virtual functions that have to be implemented by In-/OutArchive
virtual Archive & operator & (double & d) = 0;
virtual Archive & operator & (int & i) = 0;
virtual Archive & operator & (long & i) = 0;
virtual Archive & operator & (size_t & i) = 0;
virtual Archive & operator & (short & i) = 0;
virtual Archive & operator & (unsigned char & i) = 0;
virtual Archive & operator & (bool & b) = 0;
virtual Archive & operator & (std::string & str) = 0;
virtual Archive & operator & (char *& str) = 0;
virtual Archive & operator & (VersionInfo & version)
{
if(Output())
(*this) << version.to_string();
else
{
std::string s;
(*this) & s;
version = VersionInfo(s);
}
return *this;
}
// Archive std classes ================================================
template<typename T>
Archive& operator & (std::complex<T>& c)
{
if(Output())
(*this) << c.real() << c.imag();
else
{
T tmp;
(*this) & tmp;
c.real(tmp);
(*this) & tmp;
c.imag(tmp);
}
return (*this);
}
template<typename T>
Archive& operator & (std::vector<T>& v)
{
size_t size;
if(Output())
size = v.size();
(*this) & size;
if(Input())
v.resize(size);
Do(&v[0], size);
return (*this);
}
template<typename T1, typename T2>
Archive& operator& (std::map<T1, T2>& 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 <typename T, typename = typename std::enable_if<is_archivable<T>>::type>
Archive & Do (T * data, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & data[j]; }; return *this; }; // NOLINT
virtual Archive & Do (double * d, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & d[j]; }; return *this; }; // NOLINT
virtual Archive & Do (int * i, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT
virtual Archive & Do (long * i, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT
virtual Archive & Do (size_t * i, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT
virtual Archive & Do (short * i, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT
virtual Archive & Do (unsigned char * i, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & i[j]; }; return *this; }; // NOLINT
virtual Archive & Do (bool * b, size_t n)
{ for (size_t j = 0; j < n; j++) { (*this) & b[j]; }; return *this; }; // NOLINT
// Archive a class implementing a (void DoArchive(Archive&)) method =======
template<typename T, typename=std::enable_if_t<detail::has_DoArchive<T>::value>>
Archive& operator & (T& val)
{
val.DoArchive(*this); return *this;
}
// Archive shared_ptrs =================================================
template <typename T>
Archive& operator & (std::shared_ptr<T>& ptr)
{
if(Output())
{
// save -2 for nullptr
if(!ptr)
return (*this) << -2;
void* reg_ptr = ptr.get();
bool neededDowncast = false;
// Downcasting is only possible for our registered classes
if(typeid(T) != typeid(*ptr))
{
if(!IsRegistered(Demangle(typeid(*ptr).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*ptr).name())
+ " not registered for archive");
reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get());
// if there was a true downcast we have to store more information
if(reg_ptr != static_cast<void*>(ptr.get()) )
neededDowncast = true;
}
auto pos = shared_ptr2nr.find(reg_ptr);
// if not found store -1 and the pointer
if(pos == shared_ptr2nr.end())
{
auto p = ptr.get();
(*this) << -1;
(*this) & neededDowncast & p;
// if we did downcast we store the true type as well
if(neededDowncast)
(*this) << Demangle(typeid(*ptr).name());
shared_ptr2nr[reg_ptr] = shared_ptr_count++;
return *this;
}
// if found store the position and if it has to be downcasted and how
(*this) << pos->second << neededDowncast;
if(neededDowncast)
(*this) << Demangle(typeid(*ptr).name());
}
else // Input
{
int nr;
(*this) & nr;
// -2 restores a nullptr
if(nr == -2)
{
ptr = nullptr;
return *this;
}
// -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it
if (nr == -1)
{
T* p = nullptr;
bool neededDowncast;
(*this) & neededDowncast & p;
ptr = std::shared_ptr<T>(p);
// if we did downcast we need to store a shared_ptr<void> to the true object
if(neededDowncast)
{
std::string name;
(*this) & name;
auto info = GetArchiveRegister(name);
// for this we use an aliasing constructor to create a shared pointer sharing lifetime
// with our shared ptr, but pointing to the true object
nr2shared_ptr.push_back(std::shared_ptr<void>(std::static_pointer_cast<void>(ptr),
info.downcaster(typeid(T),
ptr.get())));
}
else
nr2shared_ptr.push_back(ptr);
}
else
{
auto other = nr2shared_ptr[nr];
bool neededDowncast;
(*this) & neededDowncast;
if(neededDowncast)
{
// if there was a downcast we can expect the class to be registered (since archiving
// wouldn't have worked else)
std::string name;
(*this) & name;
auto info = GetArchiveRegister(name);
// same trick as above, create a shared ptr sharing lifetime with
// the shared_ptr<void> in the register, but pointing to our object
ptr = std::static_pointer_cast<T>(std::shared_ptr<void>(other,
info.upcaster(typeid(T),
other.get())));
}
else
ptr = std::static_pointer_cast<T>(other);
}
}
return *this;
}
// Archive pointers =======================================================
template <typename T>
Archive & operator& (T *& p)
{
if (Output())
{
// if the pointer is null store -2
if (!p)
return (*this) << -2;
auto reg_ptr = static_cast<void*>(p);
if(typeid(T) != typeid(*p))
{
if(!IsRegistered(Demangle(typeid(*p).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*p).name())
+ " not registered for archive");
reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p));
}
auto pos = ptr2nr.find(reg_ptr);
// if the pointer is not found in the map create a new entry
if (pos == ptr2nr.end())
{
ptr2nr[reg_ptr] = ptr_count++;
if(typeid(*p) == typeid(T))
if (std::is_constructible<T>::value)
{
return (*this) << -1 & (*p);
}
else
throw std::runtime_error(std::string("Archive error: Class ") +
Demangle(typeid(*p).name()) + " does not provide a default constructor!");
else
{
// if a pointer to a base class is archived, the class hierarchy must be registered
// to avoid compile time issues we allow this behaviour only for "our" classes that
// implement a void DoArchive(Archive&) member function
// To recreate the object we need to store the true type of it
if(!IsRegistered(Demangle(typeid(*p).name())))
throw std::runtime_error(std::string("Archive error: Polymorphic type ")
+ Demangle(typeid(*p).name())
+ " not registered for archive");
return (*this) << -3 << Demangle(typeid(*p).name()) & (*p);
}
}
else
{
(*this) & pos->second;
bool downcasted = !(reg_ptr == static_cast<void*>(p) );
// store if the class has been downcasted and the name
(*this) << downcasted << Demangle(typeid(*p).name());
}
}
else
{
int nr;
(*this) & nr;
if (nr == -2) // restore a nullptr
p = nullptr;
else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...)
{
p = detail::constructIfPossible<T>();
nr2ptr.push_back(p);
(*this) & *p;
}
else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,...
{
// As stated above, we want this special behaviour only for our classes that implement DoArchive
std::string name;
(*this) & name;
auto info = GetArchiveRegister(name);
// the creator creates a new object of type name, and returns a void* pointing
// to T (which may have an offset)
p = static_cast<T*>(info.creator(typeid(T)));
// we store the downcasted pointer (to be able to find it again from
// another class in a multiple inheritance tree)
nr2ptr.push_back(info.downcaster(typeid(T),p));
(*this) & *p;
}
else
{
bool downcasted;
std::string name;
(*this) & downcasted & name;
if(downcasted)
{
// if the class has been downcasted we can assume it is in the register
auto info = GetArchiveRegister(name);
p = static_cast<T*>(info.upcaster(typeid(T), nr2ptr[nr]));
}
else
p = static_cast<T*>(nr2ptr[nr]);
}
}
return *this;
}
// const ptr
template<typename T>
Archive& operator &(const T*& t)
{
return (*this) & const_cast<T*&>(t); // NOLINT
}
// Write a read only variable
template <typename T>
Archive & operator << (const T & t)
{
T ht(t);
(*this) & ht;
return *this;
}
virtual void FlushBuffer() {}
protected:
static std::map<std::string, VersionInfo>& GetLibraryVersions();
private:
template<typename T, typename ... Bases>
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<type, bases...>
static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info);
static bool IsRegistered(const std::string& classname);
// Helper class for up-/downcasting
template<typename T, typename ... Bases>
struct Caster{};
template<typename T>
struct Caster<T>
{
static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/)
{
throw std::runtime_error("Upcast not successful, some classes are not registered properly for archiving!");
}
static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/)
{
throw std::runtime_error("Downcast not successful, some classes are not registered properly for archiving!");
}
};
template<typename T, typename B1, typename ... Brest>
struct Caster<T,B1,Brest...>
{
static void* tryUpcast(const std::type_info& ti, T* p)
{
try
{ return GetArchiveRegister(Demangle(typeid(B1).name())).
upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); }
catch(std::exception&)
{ return Caster<T, Brest...>::tryUpcast(ti, p); }
}
static void* tryDowncast(const std::type_info& ti, void* p)
{
if(typeid(B1) == ti)
return dynamic_cast<T*>(static_cast<B1*>(p));
try
{
return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())).
downcaster(ti, p)));
}
catch(std::exception&)
{
return Caster<T, Brest...>::tryDowncast(ti, p);
}
}
};
};
template<typename T, typename ... Bases>
class RegisterClassForArchive
{
public:
RegisterClassForArchive()
{
static_assert(detail::all_of_tmpl<std::is_base_of<Bases,T>::value...>,
"Variadic template arguments must be base classes of T");
detail::ClassArchiveInfo info;
info.creator = [this,&info](const std::type_info& ti) -> void*
{ return typeid(T) == ti ? detail::constructIfPossible<T>()
: Archive::Caster<T, Bases...>::tryUpcast(ti, detail::constructIfPossible<T>()); };
info.upcaster = [this](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryUpcast(ti, static_cast<T*>(p)); };
info.downcaster = [this](const std::type_info& ti, void* p) -> void*
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryDowncast(ti, p); };
Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info);
}
};
// BinaryOutArchive ======================================================================
class NGCORE_API BinaryOutArchive : public Archive
{
size_t ptr = 0;
static constexpr size_t BUFFERSIZE = 1024;
alignas(64) char buffer[BUFFERSIZE] = {};
std::shared_ptr<std::ostream> fout;
public:
BinaryOutArchive() = delete;
BinaryOutArchive(const BinaryOutArchive&) = delete;
BinaryOutArchive(BinaryOutArchive&&) = delete;
BinaryOutArchive(std::shared_ptr<std::ostream>&& afout)
: Archive(true), fout(std::move(afout))
{
(*this) & GetLibraryVersions();
}
BinaryOutArchive(const std::string& filename)
: BinaryOutArchive(std::make_shared<std::ofstream>(filename)) {}
~BinaryOutArchive () override { FlushBuffer(); }
BinaryOutArchive& operator=(const BinaryOutArchive&) = delete;
BinaryOutArchive& operator=(BinaryOutArchive&&) = delete;
const VersionInfo& GetVersion(const std::string& library) override
{ return GetLibraryVersions()[library]; }
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)
fout->write (&str[0], len);
return *this;
}
Archive & operator & (char *& str) override
{
long len = str ? strlen (str) : -1;
(*this) & len;
FlushBuffer();
if(len > 0)
fout->write (&str[0], len); // NOLINT
return *this;
}
void FlushBuffer() override
{
if (ptr > 0)
{
fout->write(&buffer[0], ptr);
ptr = 0;
}
}
private:
template <typename T>
Archive & Write (T x)
{
if (unlikely(ptr > BUFFERSIZE-sizeof(T)))
{
fout->write(&buffer[0], ptr);
*reinterpret_cast<T*>(&buffer[0]) = x; // NOLINT
ptr = sizeof(T);
return *this;
}
*reinterpret_cast<T*>(&buffer[ptr]) = x; // NOLINT
ptr += sizeof(T);
return *this;
}
};
// BinaryInArchive ======================================================================
class NGCORE_API BinaryInArchive : public Archive
{
std::map<std::string, VersionInfo> vinfo{};
std::shared_ptr<std::istream> fin;
public:
BinaryInArchive (std::shared_ptr<std::istream>&& afin)
: Archive(false), fin(std::move(afin))
{
(*this) & vinfo;
}
BinaryInArchive (const std::string& filename)
: BinaryInArchive(std::make_shared<std::ifstream>(filename)) { ; }
const VersionInfo& GetVersion(const std::string& library) override
{ return vinfo[library]; }
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)
fin->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
fin->read(&str[0], len); // NOLINT
str[len] = '\0'; // NOLINT
}
return *this;
}
Archive & Do (double * d, size_t n) override
{ fin->read(reinterpret_cast<char*>(d), n*sizeof(double)); return *this; } // NOLINT
Archive & Do (int * i, size_t n) override
{ fin->read(reinterpret_cast<char*>(i), n*sizeof(int)); return *this; } // NOLINT
Archive & Do (size_t * i, size_t n) override
{ fin->read(reinterpret_cast<char*>(i), n*sizeof(size_t)); return *this; } // NOLINT
private:
template<typename T>
inline void Read(T& val)
{ fin->read(reinterpret_cast<char*>(&val), sizeof(T)); } // NOLINT
};
// TextOutArchive ======================================================================
class NGCORE_API TextOutArchive : public Archive
{
std::shared_ptr<std::ostream> fout;
public:
TextOutArchive (std::shared_ptr<std::ostream>&& afout)
: Archive(true), fout(std::move(afout))
{
(*this) & GetLibraryVersions();
}
TextOutArchive (const std::string& filename) :
TextOutArchive(std::make_shared<std::ofstream>(filename)) { }
const VersionInfo& GetVersion(const std::string& library) override
{ return GetLibraryVersions()[library]; }
using Archive::operator&;
Archive & operator & (double & d) override
{ *fout << d << '\n'; return *this; }
Archive & operator & (int & i) override
{ *fout << i << '\n'; return *this; }
Archive & operator & (short & i) override
{ *fout << i << '\n'; return *this; }
Archive & operator & (long & i) override
{ *fout << i << '\n'; return *this; }
Archive & operator & (size_t & i) override
{ *fout << i << '\n'; return *this; }
Archive & operator & (unsigned char & i) override
{ *fout << int(i) << '\n'; return *this; }
Archive & operator & (bool & b) override
{ *fout << (b ? 't' : 'f') << '\n'; return *this; }
Archive & operator & (std::string & str) override
{
int len = str.length();
*fout << len << '\n';
if(len)
{
fout->write(&str[0], len); // NOLINT
*fout << '\n';
}
return *this;
}
Archive & operator & (char *& str) override
{
long len = str ? strlen (str) : -1;
*this & len;
if(len > 0)
{
fout->write (&str[0], len); // NOLINT
*fout << '\n';
}
return *this;
}
};
// TextInArchive ======================================================================
class NGCORE_API TextInArchive : public Archive
{
std::map<std::string, VersionInfo> vinfo{};
std::shared_ptr<std::istream> fin;
public:
TextInArchive (std::shared_ptr<std::istream>&& afin) :
Archive(false), fin(std::move(afin))
{
(*this) & vinfo;
}
TextInArchive (const std::string& filename)
: TextInArchive(std::make_shared<std::ifstream>(filename)) {}
const VersionInfo& GetVersion(const std::string& library) override
{ return vinfo[library]; }
using Archive::operator&;
Archive & operator & (double & d) override
{ *fin >> d; return *this; }
Archive & operator & (int & i) override
{ *fin >> i; return *this; }
Archive & operator & (short & i) override
{ *fin >> i; return *this; }
Archive & operator & (long & i) override
{ *fin >> i; return *this; }
Archive & operator & (size_t & i) override
{ *fin >> i; return *this; }
Archive & operator & (unsigned char & i) override
{ int _i; *fin >> _i; i = _i; return *this; }
Archive & operator & (bool & b) override
{ char c; *fin >> c; b = (c=='t'); return *this; }
Archive & operator & (std::string & str) override
{
int len;
*fin >> len;
char ch;
fin->get(ch); // '\n'
str.resize(len);
if(len)
fin->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)
{
fin->get(ch); // \n
fin->get(&str[0], len+1, '\0'); // NOLINT
}
str[len] = '\0'; // NOLINT
return *this;
}
};
} // namespace ngcore
#endif // NETGEN_CORE_ARCHIVE_HPP

7
libsrc/core/ngcore.hpp Normal file
View File

@ -0,0 +1,7 @@
#ifndef NETGEN_CORE_NGCORE_HPP
#define NETGEN_CORE_NGCORE_HPP
#include "archive.hpp"
#include "version.hpp"
#endif // NETGEN_CORE_NGCORE_HPP

View File

@ -0,0 +1,29 @@
#ifndef NETGEN_CORE_NGCORE_API_HPP
#define NETGEN_CORE_NGCORE_API_HPP
#ifdef WIN32
#define NGCORE_API_EXPORT __declspec(dllexport)
#define NGCORE_API_IMPORT __declspec(dllimport)
#else
#define NGCORE_API_EXPORT
#define NGCORE_API_IMPORT
#endif
#ifdef NGCORE_EXPORTS
#define NGCORE_API NGCORE_API_EXPORT
#else
#define NGCORE_API NGCORE_API_IMPORT
#endif
namespace ngcore
{
#if defined(__GNUC__)
inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); }
inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); }
#else
inline bool likely (bool x) { return x; }
inline bool unlikely (bool x) { return x; }
#endif
} // namespace ngcore
#endif // NETGEN_CORE_NGCORE_API_HPP

View File

@ -0,0 +1,17 @@
#ifndef NETGEN_CORE_TYPE_TRAITS_HPP
#define NETGEN_CORE_TYPE_TRAITS_HPP
#include <type_traits>
namespace ngcore
{
namespace detail
{
template<bool... b> struct _BoolArray{};
template<bool ... vals>
constexpr bool all_of_tmpl = std::is_same<_BoolArray<vals...>, _BoolArray<(vals || true)...>>::value; // NOLINT
} // namespace detail
} // namespace ngcore
#endif // NETGEN_CORE_TYPE_TRAITS_HPP

88
libsrc/core/version.hpp Normal file
View File

@ -0,0 +1,88 @@
#ifndef NETGEN_CORE_VERSION_HPP
#define NETGEN_CORE_VERSION_HPP
#include <string>
#include <tuple>
#include "ngcore_api.hpp"
namespace ngcore
{
class VersionInfo
{
private:
size_t mayor_{}, minor_{}, release{}, patch{};
std::string git_hash{};
public:
VersionInfo() = default;
VersionInfo(std::string vstring)
{
minor_ = release = patch = 0;
git_hash = "";
if(vstring.substr(0,1) == "v")
vstring = vstring.substr(1,vstring.size()-1);
auto dot = vstring.find('.');
mayor_ = std::stoi(vstring.substr(0,dot));
if(dot == size_t(-1)) vstring = "";
else vstring = vstring.substr(dot+1, vstring.size()-dot-1);
if(!vstring.empty())
{
dot = vstring.find('.');
minor_ = std::stoi(vstring.substr(0,dot));
if (dot == size_t(-1)) vstring = "";
else vstring = vstring.substr(dot+1, vstring.size()-dot-1);
if(!vstring.empty())
{
dot = vstring.find('-');
release = std::stoi(vstring.substr(0,dot));
if(dot == size_t(-1)) vstring = "";
else vstring = vstring.substr(dot+1,vstring.size()-dot-1);
if(!vstring.empty())
{
dot = vstring.find('-');
patch = std::stoi(vstring.substr(0,dot));
if(dot == size_t(-1)) vstring = "";
else vstring = vstring.substr(dot+1, vstring.size()-dot-1);
if(!vstring.empty())
git_hash = vstring;
}
}
}
}
VersionInfo(const char* cstr) : VersionInfo(std::string(cstr)) { }
std::string to_string() const
{ std::string vstring = "v" + std::to_string(mayor_);
if(minor_ || release || patch || !git_hash.empty())
{
vstring += "." + std::to_string(minor_);
if(release || patch || !git_hash.empty())
{
vstring += "." + std::to_string(release);
if(patch || !git_hash.empty())
{
vstring += "-" + std::to_string(patch);
if(!git_hash.empty())
vstring += "-" + git_hash;
}
}
}
return vstring;
}
bool operator <(const VersionInfo& other) const
{
return std::tie(mayor_, minor_, release, patch) <
std::tie(other.mayor_, other.minor_, other.release, other.patch);
}
bool operator ==(const VersionInfo& other) const
{
return mayor_ == other.mayor_ && minor_ == other.minor_ && release == other.release
&& patch == other.patch;
}
bool operator >(const VersionInfo& other) const { return other < (*this); }
bool operator <=(const VersionInfo& other) const { return !((*this) > other); }
bool operator >=(const VersionInfo& other) const { return !((*this) < other); }
};
} // namespace ngcore
#endif // NETGEN_CORE_VERSION_HPP

View File

@ -1949,6 +1949,13 @@ void EllipticCone :: GetTriangleApproximation
<< R << " " << r << endl;
}
RegisterClassForArchive<QuadraticSurface, OneSurfacePrimitive> regqs;
RegisterClassForArchive<Plane, QuadraticSurface> regpl;
RegisterClassForArchive<Sphere, QuadraticSurface> regsph;
RegisterClassForArchive<Cylinder, QuadraticSurface> regcyl;
RegisterClassForArchive<EllipticCylinder, QuadraticSurface> regelcyl;
RegisterClassForArchive<Ellipsoid, QuadraticSurface> regell;
RegisterClassForArchive<Cone, QuadraticSurface> regcone;
RegisterClassForArchive<EllipticCone, QuadraticSurface> regellcone;
RegisterClassForArchive<Torus, OneSurfacePrimitive> regtorus;
}

View File

@ -47,6 +47,11 @@ namespace netgen
virtual void Print (ostream & str) const;
virtual void Read (istream & ist);
void PrintCoeff (ostream & ost) const;
virtual void DoArchive(Archive& ar)
{
OneSurfacePrimitive::DoArchive(ar);
ar & cxx & cyy & czz & cxy & cxz & cyz & cx & cy & cz & c1;
}
};
@ -64,6 +69,14 @@ namespace netgen
public:
///
Plane (const Point<3> & ap, Vec<3> an);
// default constructor for archive
Plane() {}
virtual void DoArchive(Archive& ar)
{
QuadraticSurface::DoArchive(ar);
ar & p & n & eps_base;
}
Point<3> P() const { return p; }
Vec<3> N() const { return n; }
virtual void GetPrimitiveData (const char *& classname,
@ -130,6 +143,14 @@ namespace netgen
public:
///
Sphere (const Point<3> & ac, double ar);
// default constructor for archive
Sphere() {}
virtual void DoArchive(Archive& ar)
{
QuadraticSurface::DoArchive(ar);
ar & c & r & invr;
}
virtual void GetPrimitiveData (const char *& classname,
Array<double> & coeffs) const;
@ -188,6 +209,14 @@ namespace netgen
public:
Cylinder (const Point<3> & aa, const Point<3> & ab, double ar);
Cylinder (Array<double> & coeffs);
// default constructor for archive
Cylinder() {}
virtual void DoArchive(Archive& ar)
{
QuadraticSurface::DoArchive(ar);
ar & a & b & r & vab;
}
Point<3> A() const { return a; }
Point<3> B() const { return b; }
double R() const { return r; }
@ -250,7 +279,14 @@ namespace netgen
EllipticCylinder (const Point<3> & aa,
const Vec<3> & avl, const Vec<3> & avs);
EllipticCylinder (Array<double> & 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<double> & coeffs) const;
@ -300,6 +336,14 @@ namespace netgen
const Vec<3> & av1,
const Vec<3> & av2,
const Vec<3> & av3);
// default constructor for archive
Ellipsoid() {}
virtual void DoArchive(Archive& ar)
{
QuadraticSurface::DoArchive(ar);
ar & a & v1 & v2 & v3 & rmin;
}
///
virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;
///
@ -340,6 +384,14 @@ namespace netgen
///
Cone (const Point<3> & aa, const Point<3> & ab, double ara, double arb);
///
// default constructor for archive
Cone() {}
virtual void DoArchive(Archive& ar)
{
QuadraticSurface::DoArchive(ar);
ar & a & b & ra & rb & minr & vab & t0vec & t1vec & vabl & t0 & t1 & cosphi;
}
static Primitive * CreateDefault ();
virtual void GetPrimitiveData (const char *& classname, Array<double> & coeffs) const;
virtual void SetPrimitiveData (Array<double> & coeffs);
@ -384,7 +436,14 @@ namespace netgen
///
EllipticCone (const Point<3> & aa, const Vec<3> & avl,
const Vec<3> & avs, double ah, double avlr);
// default constructor for archive
EllipticCone() {}
virtual void DoArchive(Archive& ar)
{
QuadraticSurface::DoArchive(ar);
ar & a & vl & vs & h & vlr;
}
static Primitive * CreateDefault ();
virtual void GetPrimitiveData (const char *& classname, Array<double> & coeffs) const;
virtual void SetPrimitiveData (Array<double> & coeffs);
@ -426,6 +485,14 @@ namespace netgen
public:
/// OK
Torus (const Point<3> & ac, const Vec<3> & an, double aR, double ar);
// default constructor for archive
Torus() {}
virtual void DoArchive(Archive& ar)
{
OneSurfacePrimitive::DoArchive(ar);
ar & c & n & R & r;
}
/// OK
const Point<3> & Center () const { return c; }
/// OK

View File

@ -523,4 +523,8 @@ void OrthoBrick :: Reduce (const BoxSphere<3> & box)
surfaceactive.Elem(6) =
(box.PMin()(0) < pmax(0)) && (pmax(0) < box.PMax()(0));
}
RegisterClassForArchive<Parallelogram3d, Surface> regpar;
RegisterClassForArchive<Brick, Primitive> regbrick;
RegisterClassForArchive<OrthoBrick, Brick> regob;
}

View File

@ -28,8 +28,16 @@ namespace netgen
public:
Parallelogram3d (Point<3> ap1, Point<3> ap2, Point<3> ap3);
// default constructor for archive
Parallelogram3d() {}
virtual ~Parallelogram3d ();
virtual void DoArchive(Archive& ar)
{
Surface::DoArchive(ar);
ar & p1 & p2 & p3 & p4 & v12 & v13 & n;
}
void SetPoints (Point<3> ap1, Point<3> ap2, Point<3> ap3);
virtual int IsIdentic (const Surface & s2, int & inv, double eps) const;
@ -60,7 +68,15 @@ namespace netgen
public:
Brick (Point<3> ap1, Point<3> ap2, Point<3> ap3, Point<3> ap4);
// default constructor for archive
Brick() {}
virtual ~Brick ();
virtual void DoArchive(Archive& ar)
{
Primitive::DoArchive(ar);
ar & p1 & p2 & p3 & p4 & v12 & v13 & v14 & faces;
}
static Primitive * CreateDefault ();
virtual Primitive * Copy () const;
@ -116,6 +132,14 @@ namespace netgen
Point<3> pmin, pmax;
public:
OrthoBrick (const Point<3> & ap1, const Point<3> & ap2);
// default constructor for archive
OrthoBrick() {}
virtual void DoArchive(Archive& ar)
{
Brick::DoArchive(ar);
ar & pmin & pmax;
}
virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;
virtual void Reduce (const BoxSphere<3> & box);

View File

@ -324,6 +324,14 @@ namespace netgen
}
void CSGeometry :: DoArchive(Archive& archive)
{
archive & surfaces & solids & toplevelobjects & userpoints & userpoints_ref_factor
& identpoints & boundingbox & isidenticto & ideps
& filename & spline_surfaces & splinecurves2d & splinecurves3d & surf2prim;
if(archive.Input())
FindIdenticSurfaces(1e-6);
}
void CSGeometry :: SaveSurfaces (ostream & out) const
{

View File

@ -39,7 +39,14 @@ namespace netgen
public:
TopLevelObject (Solid * asolid,
Surface * asurface = NULL);
// default constructor for archive
TopLevelObject() {}
void DoArchive(Archive& archive)
{
archive & solid & surface & red & blue & green & visible & transp & maxh
& material & layer & bc & bcname;
}
const Solid * GetSolid() const { return solid; }
Solid * GetSolid() { return solid; }
@ -124,6 +131,11 @@ namespace netgen
UserPoint() = default;
UserPoint (Point<3> p, int _index) : Point<3>(p), index(_index) { ; }
int GetIndex() const { return index; }
void DoArchive(Archive& archive)
{
archive & index;
Point<3>::DoArchive(archive);
}
};
private:
@ -199,6 +211,8 @@ namespace netgen
const SplineGeometry<2> * GetSplineCurve2d (const string & name) const;
const SplineGeometry<3> * GetSplineCurve3d (const string & name) const;
void DoArchive(Archive& archive);
void SetFlags (const char * solidname, const Flags & flags);

View File

@ -653,15 +653,15 @@ namespace netgen
Extrusion :: Extrusion(const SplineGeometry<3> & path_in,
const SplineGeometry<2> & profile_in,
const Vec<3> & z_dir) :
path(path_in), profile(profile_in), z_direction(z_dir)
path(&path_in), profile(&profile_in), z_direction(z_dir)
{
surfaceactive.SetSize(0);
surfaceids.SetSize(0);
for(int j=0; j<profile.GetNSplines(); j++)
for(int j=0; j<profile->GetNSplines(); j++)
{
ExtrusionFace * face = new ExtrusionFace(&(profile.GetSpline(j)),
&path,
ExtrusionFace * face = new ExtrusionFace(&((*profile).GetSpline(j)),
path,
z_direction);
faces.Append(face);
surfaceactive.Append(true);
@ -872,5 +872,6 @@ namespace netgen
surfaceactive[i] = true;
}
RegisterClassForArchive<ExtrusionFace, Surface> regexf;
RegisterClassForArchive<Extrusion, Primitive> regextr;
}

View File

@ -49,10 +49,19 @@ namespace netgen
const Vec<3> & z_direction);
ExtrusionFace(const Array<double> & 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;
virtual double CalcFunctionValue (const Point<3> & point) const;
@ -109,10 +118,10 @@ namespace netgen
class Extrusion : public Primitive
{
private:
const SplineGeometry<3> & path;
const SplineGeometry<2> & profile; // closed, clockwise oriented curve
const SplineGeometry<3>* path;
const SplineGeometry<2>* profile; // closed, clockwise oriented curve
const Vec<3> & z_direction;
Vec<3> z_direction;
Array<ExtrusionFace*> faces;
@ -122,7 +131,15 @@ namespace netgen
Extrusion(const SplineGeometry<3> & path_in,
const SplineGeometry<2> & profile_in,
const Vec<3> & z_dir);
// default constructor for archive
Extrusion() {}
~Extrusion();
virtual void DoArchive(Archive& ar)
{
Primitive::DoArchive(ar);
ar & path & profile & z_direction & faces & latestfacenum;
}
virtual INSOLID_TYPE BoxInSolid (const BoxSphere<3> & box) const;
virtual INSOLID_TYPE PointInSolid (const Point<3> & p,
double eps) const;

View File

@ -364,37 +364,31 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
py::class_<CSGeometry, NetgenGeometry, shared_ptr<CSGeometry>> (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<shared_ptr<SPSolid>> 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<CSGeometry>();
ParseCSG(ist, geo.get());
geo->FindIdenticSurfaces(1e-8 * geo->MaxSize());
return geo;
}), py::arg("filename"))
.def(py::pickle(
[](CSGeometry& self)
{
auto ss = make_shared<stringstream>();
BinaryOutArchive archive(ss);
archive & self;
archive.FlushBuffer();
return py::make_tuple(py::bytes(ss->str()));
},
[](py::tuple state)
{
auto geo = make_shared<CSGeometry>();
auto ss = make_shared<stringstream> (py::cast<py::bytes>(state[0]));
BinaryInArchive archive(ss);
archive & (*geo);
return geo;
}))
.def("Save", FunctionPointer([] (CSGeometry & self, string filename)
{
cout << "save geometry to file " << filename << endl;

View File

@ -640,9 +640,9 @@ namespace netgen
Revolution :: Revolution(const Point<3> & p0_in,
const Point<3> & p1_in,
const SplineGeometry<2> & spline_in) :
p0(p0_in), p1(p1_in), splinecurve(spline_in),
nsplines(spline_in.GetNSplines())
p0(p0_in), p1(p1_in)
{
auto nsplines = spline_in.GetNSplines();
surfaceactive.SetSize(0);
surfaceids.SetSize(0);
@ -650,21 +650,21 @@ namespace netgen
v_axis.Normalize();
if(splinecurve.GetSpline(0).StartPI()(1) <= 0. &&
splinecurve.GetSpline(nsplines-1).EndPI()(1) <= 0.)
if(spline_in.GetSpline(0).StartPI()(1) <= 0. &&
spline_in.GetSpline(nsplines-1).EndPI()(1) <= 0.)
type = 2;
else if (Dist(splinecurve.GetSpline(0).StartPI(),
splinecurve.GetSpline(nsplines-1).EndPI()) < 1e-7)
else if (Dist(spline_in.GetSpline(0).StartPI(),
spline_in.GetSpline(nsplines-1).EndPI()) < 1e-7)
type = 1;
else
cerr << "Surface of revolution cannot be constructed" << endl;
for(int i=0; i<splinecurve.GetNSplines(); i++)
for(int i=0; i<spline_in.GetNSplines(); i++)
{
RevolutionFace * face = new RevolutionFace(splinecurve.GetSpline(i),
RevolutionFace * face = new RevolutionFace(spline_in.GetSpline(i),
p0,v_axis,
type==2 && i==0,
type==2 && i==splinecurve.GetNSplines()-1);
type==2 && i==spline_in.GetNSplines()-1);
faces.Append(face);
surfaceactive.Append(1);
surfaceids.Append(0);
@ -959,4 +959,7 @@ namespace netgen
for(int i=0; i<faces.Size(); i++)
surfaceactive[i] = true;
}
RegisterClassForArchive<RevolutionFace, Surface> regrevf;
RegisterClassForArchive<Revolution, Primitive> regrev;
}

View File

@ -45,9 +45,18 @@ namespace netgen
const int id_in = 0);
RevolutionFace(const Array<double> & raw_data);
// default constructor for archive
RevolutionFace() {}
~RevolutionFace();
virtual void DoArchive(Archive& ar)
{
Surface::DoArchive(ar);
ar & isfirst & islast & spline & deletable & p0 & v_axis & id & spline_coefficient
& spline_coefficient_shifted & checklines_vec & checklines_start & checklines_normal;
}
virtual int IsIdentic (const Surface & s2, int & inv, double eps) const;
virtual double CalcFunctionValue (const Point<3> & point) const;
@ -96,8 +105,6 @@ namespace netgen
private:
Point<3> p0,p1;
Vec<3> v_axis;
const SplineGeometry<2> & splinecurve;
const int nsplines;
// 1 ... torus-like
// 2 ... sphere-like
@ -112,9 +119,16 @@ namespace netgen
Revolution(const Point<3> & p0_in,
const Point<3> & p1_in,
const SplineGeometry<2> & spline_in);
// default constructor for archive
Revolution() {}
~Revolution();
virtual void DoArchive(Archive& ar)
{
Primitive::DoArchive(ar);
ar & p0 & p1 & v_axis & type & faces & intersecting_face;
}
/*
Check, whether box intersects solid defined by surface.

View File

@ -55,8 +55,22 @@ namespace netgen
public:
Solid (Primitive * aprim);
Solid (optyp aop, Solid * as1, Solid * as2 = NULL);
// default constructor for archive
Solid () {}
~Solid ();
void DoArchive(Archive& archive)
{
archive & name & prim & s1 & s2 & visited & maxh & num_surfs;
if(archive.Output())
archive << int(op);
else
{
int iop;
archive & iop;
op = optyp(iop);
}
}
const char * Name () const { return name; }
void SetName (const char * aname);

View File

@ -566,4 +566,8 @@ void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp)
if (Abs2 (rs) < 1e-24 && i > 1) i = 1;
}
}
RegisterClassForArchive<Surface> regsurf;
RegisterClassForArchive<Primitive> regprim;
RegisterClassForArchive<OneSurfacePrimitive, Surface, Primitive> regosf;
}

View File

@ -63,6 +63,12 @@ namespace netgen
//@}
public:
virtual void DoArchive(Archive& archive)
{
archive & inverse & maxh & name & bcprop & bcname
& p1 & p2 & ex & ey & ez;
}
void SetName (const char * aname);
const char * Name () const { return name; }
@ -234,6 +240,9 @@ namespace netgen
class Primitive
{
protected:
Array<int> surfaceids;
Array<int> surfaceactive;
public:
@ -241,6 +250,10 @@ namespace netgen
virtual ~Primitive();
virtual void DoArchive(Archive& archive)
{
archive & surfaceids & surfaceactive;
}
/*
Check, whether box intersects solid defined by surface.
@ -299,9 +312,6 @@ namespace netgen
virtual Surface & GetSurface (int i = 0) = 0;
virtual const Surface & GetSurface (int i = 0) const = 0;
Array<int> surfaceids;
Array<int> surfaceactive;
int GetSurfaceId (int i = 0) const;
void SetSurfaceId (int i, int id);
int SurfaceActive (int i) const { return surfaceactive[i]; }
@ -329,6 +339,12 @@ namespace netgen
OneSurfacePrimitive();
~OneSurfacePrimitive();
virtual void DoArchive(Archive& archive)
{
Surface::DoArchive(archive);
Primitive::DoArchive(archive);
}
virtual INSOLID_TYPE PointInSolid (const Point<3> & p,
double eps) const;
virtual INSOLID_TYPE VecInSolid (const Point<3> & p,

View File

@ -11,7 +11,7 @@ set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON )
install( FILES ngexception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel )
install(FILES
archive_base.hpp array.hpp autodiff.hpp autoptr.hpp bitarray.hpp
array.hpp autodiff.hpp autoptr.hpp bitarray.hpp
dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp
ngsimd.hpp mystring.hpp netgenout.hpp ngexception.hpp ngpython.hpp
optmem.hpp parthreads.hpp profiler.hpp seti.hpp sort.hpp

View File

@ -1,144 +0,0 @@
#ifndef NGS_ARCHIVE_BASE
#define NGS_ARCHIVE_BASE
// copied from netgen
#include <vector>
#include <map>
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 <typename T>
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<void*,int> ptr2nr;
std::vector<void*> nr2ptr;
/*
// necessary for msvc ???
Archive & operator& (string* & ps)
{
return operator&<string> (ps);
}
*/
template <typename T>
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 <typename T>
Archive & operator << (const T & t)
{
T ht(t);
(*this) & ht;
return *this;
}
};
}
#endif

View File

@ -401,6 +401,21 @@ namespace netgen
return data;
}
// Only provide this function if T is archivable
template<typename T2=T>
auto DoArchive(Archive& archive) -> typename std::enable_if<is_archivable<T2>, void>::type
{
if(archive.Output())
archive << size;
else
{
size_t s;
archive & s;
SetSize(s);
}
archive.Do(data, size);
}
private:
/// resize array, at least to size minsize. copy contents
@ -778,30 +793,6 @@ namespace netgen
if(in2.Contains(in1[i]) && in3.Contains(in1[i]))
out.Append(in1[i]);
}
template <typename T, int BASE, typename TIND>
ngstd::Archive & operator & (ngstd::Archive & archive, Array<T,BASE,TIND> & 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

View File

@ -259,20 +259,13 @@ public:
const T & GetData (const Iterator & it) const
{ return cont[it.BagNr()][it.Pos()]; }
ngstd::Archive & DoArchive (ngstd::Archive & ar)
void DoArchive (Archive & ar)
{
ar & hash & cont;
return ar;
}
};
template <typename T>
inline ngstd::Archive & operator & (ngstd::Archive & archive, INDEX_2_HASHTABLE<T> & mp)
{ return mp.DoArchive(archive); }
template <typename T>
inline ostream & operator<< (ostream & ost, const INDEX_2_HASHTABLE<T> & ht)
{
@ -436,24 +429,15 @@ public:
{ return cont[it.BagNr()][it.Pos()]; }
ngstd::Archive & DoArchive (ngstd::Archive & ar)
void DoArchive (Archive & ar)
{
ar & hash & cont;
return ar;
}
};
template <typename T>
inline ngstd::Archive & operator & (ngstd::Archive & archive, INDEX_3_HASHTABLE<T> & mp)
{ return mp.DoArchive(archive); }
template <typename T>
inline ostream & operator<< (ostream & ost, const INDEX_3_HASHTABLE<T> & ht)
{

View File

@ -17,11 +17,15 @@
#include "../include/mydefs.hpp"
#include "../core/ngcore.hpp"
namespace netgen
{
using namespace ngcore;
}
#include "ngexception.hpp"
#include "parthreads.hpp"
// #include "moveablemem.hpp"
#include "dynamicmem.hpp"
#include "archive_base.hpp"
#include "template.hpp"
#include "array.hpp"

View File

@ -1,28 +1,5 @@
#ifdef NG_PYTHON
// BEGIN EVIL HACK: Patch PyThread_get_key_value/PyThread_tss_get inside pybind11 to avoid deadlocks
// see https://github.com/pybind/pybind11/pull/1211 (please merge!)
#if defined(__GNUG__) && !defined(__clang__)
# pragma GCC diagnostic ignored "-Wattributes"
#endif
#include <Python.h>
#include <pythread.h>
#include <pybind11/cast.h>
#undef PYBIND11_TLS_GET_VALUE
#if PY_VERSION_HEX >= 0x03070000
inline void * PYBIND11_TLS_GET_VALUE(Py_tss_t *state) {
PyThreadState *tstate = (PyThreadState *) PyThread_tss_get(state);
if (!tstate) tstate = PyGILState_GetThisThreadState();
return tstate;
}
#else
inline void * PYBIND11_TLS_GET_VALUE(int state) {
PyThreadState *tstate = (PyThreadState *) PyThread_get_key_value(state);
if (!tstate) tstate = PyGILState_GetThisThreadState();
return tstate;
}
#endif
// END EVIL HACK
#include <pybind11/pybind11.h>
#include <pybind11/operators.h>
#include <pybind11/numpy.h>

View File

@ -69,6 +69,8 @@ public:
/// Deletes symboltable
inline void DeleteAll ();
void DoArchive(Archive& archive) { archive & names & data;}
inline T & operator[] (int i)
{ return data[i]; }
inline const T & operator[] (int i) const

View File

@ -213,7 +213,7 @@ namespace netgen
ngstd::Archive & BASE_TABLE :: DoArchive (ngstd::Archive & ar, int elemsize)
void BASE_TABLE :: DoArchive (Archive & ar, int elemsize)
{
if (ar.Output())
{
@ -248,7 +248,6 @@ namespace netgen
cnt += data[i].size*elemsize;
}
}
return ar;
}

View File

@ -89,7 +89,7 @@ public:
void SetElementSizesToMaxSizes ();
ngstd::Archive & DoArchive (ngstd::Archive & ar, int elemsize);
void DoArchive (Archive & ar, int elemsize);
};
@ -238,21 +238,13 @@ public:
return FlatArray<T> (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 <typename T, int BASE>
inline ngstd::Archive & operator & (ngstd::Archive & archive, TABLE<T,BASE> & mp)
{ return mp.DoArchive(archive); }
template <class T, int BASE>
inline ostream & operator<< (ostream & ost, const TABLE<T,BASE> & table)
{

View File

@ -208,6 +208,9 @@ namespace netgen
// mesh size restrictions ...
for (auto & point : geompoints)
mesh2d.RestrictLocalH (Point<3> (point(0), point(1), 0), point.hmax);
for (int i = 0; i < splines.Size(); i++)
{
const SplineSegExt & spline = GetSpline(i);
@ -241,6 +244,20 @@ namespace netgen
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)
{
double diam2 = Dist2(pmin, pmax);
@ -584,7 +601,9 @@ namespace netgen
// not complete, use at own risk ...
// meshing.Delaunay(*mesh, domnr, mp);
mp.checkoverlap = 0;
meshing.GenerateMesh (*mesh, mp, h, domnr);
auto res = meshing.GenerateMesh (*mesh, mp, h, domnr);
if (res != 0)
throw NgException("meshing failed");
for (SurfaceElementIndex sei = oldnf; sei < mesh->GetNSE(); sei++)
(*mesh)[sei].SetIndex (domnr);

View File

@ -47,8 +47,8 @@ namespace netgen
auto ext = dynamic_cast<const SplineSegExt *>(spline);
if(ext)
{
ss3 = dynamic_cast<const SplineSeg3<2> *>(&ext->seg);
ls = dynamic_cast<const LineSeg<2> *>(&ext->seg);
ss3 = dynamic_cast<const SplineSeg3<2> *>(ext->seg);
ls = dynamic_cast<const LineSeg<2> *>(ext->seg);
}
else
{

View File

@ -21,7 +21,7 @@ namespace netgen
class SplineSegExt : public SplineSeg<2>
{
public:
const SplineSeg<2> & seg;
SplineSeg<2>* seg;
/// left domain
int leftdom;
@ -42,35 +42,43 @@ namespace netgen
///
int layer;
SplineSegExt (const SplineSeg<2> & hseg)
: seg(hseg)
SplineSegExt (SplineSeg<2> & hseg)
: seg(&hseg)
{
layer = 1;
}
// default constructor for archive
SplineSegExt() {}
~SplineSegExt ()
{
delete &seg;
delete seg;
}
virtual void DoArchive(Archive& ar)
{
ar & seg & leftdom & rightdom & reffak & hmax & bc & copyfrom
& hpref_left & hpref_right & layer;
}
virtual const GeomPoint<2> & StartPI () const
{
return seg.StartPI();
return seg->StartPI();
}
virtual const GeomPoint<2> & EndPI () const
{
return seg.EndPI();
return seg->EndPI();
}
virtual Point<2> GetPoint (double t) const
{
return seg.GetPoint(t);
return seg->GetPoint(t);
}
virtual Vec<2> GetTangent (const double t) const
{
return seg.GetTangent(t);
return seg->GetTangent(t);
}
virtual void GetDerivatives (const double t,
@ -78,27 +86,27 @@ namespace netgen
Vec<2> & first,
Vec<2> & second) const
{
seg.GetDerivatives (t, point, first, second);
seg->GetDerivatives (t, point, first, second);
}
virtual void GetCoeff (Vector & coeffs) const
{
seg.GetCoeff (coeffs);
seg->GetCoeff (coeffs);
}
virtual void GetPoints (int n, Array<Point<2> > & points) const
{
seg.GetPoints (n, points);
seg->GetPoints (n, points);
}
virtual double MaxCurvature () const
{
return seg.MaxCurvature();
return seg->MaxCurvature();
}
virtual string GetType () const
{
return seg.GetType();
return seg->GetType();
}
virtual double CalcCurvature (double t) const
@ -112,7 +120,7 @@ namespace netgen
virtual bool InConvexHull (Point<2> p, double eps) const
{
return seg.InConvexHull (p, eps);
return seg->InConvexHull (p, eps);
}
};

View File

@ -31,7 +31,7 @@ DLL_HEADER void ExportGeom2d(py::module &m)
.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 +39,11 @@ DLL_HEADER void ExportGeom2d(py::module &m)
GeomPoint<2> gp(p);
gp.hmax = maxh;
gp.hpref = hpref;
gp.name = name;
self.geompoints.Append(gp);
return self.geompoints.Size()-1;
}),
py::arg("x"), py::arg("y"), py::arg("maxh") = 1e99, py::arg("hpref")=0)
py::arg("x"), py::arg("y"), py::arg("maxh") = 1e99, py::arg("hpref")=0, py::arg("name")="")
.def("Append", FunctionPointer([](SplineGeometry2d &self, py::list segment, int leftdomain, int rightdomain,
py::object bc, py::object copy, double maxh, double hpref)
{

View File

@ -64,6 +64,12 @@ namespace netgen
const T & operator() (int i) const { return x[i]; }
operator const T* () const { return x; }
void DoArchive(Archive& archive)
{
for(int i=0; i<D; i++)
archive & x[i];
}
};
template <int D, typename T>
@ -117,6 +123,12 @@ namespace netgen
operator const T* () const { return x; }
void DoArchive(Archive& archive)
{
for(int i=0; i<D; i++)
archive & x[i];
}
T Length () const
{
T l = 0;
@ -324,6 +336,9 @@ namespace netgen
pmax(i) += dist;
}
}
void DoArchive(Archive& archive)
{ archive & pmin & pmax; }
};

View File

@ -99,7 +99,7 @@ namespace netgen
}
template<int D>
inline Point<D> SplineSeg3<D> :: GetPoint (double t) const
Point<D> SplineSeg3<D> :: GetPoint (double t) const
{
double b1, b2, b3;
@ -551,11 +551,10 @@ namespace netgen
template class SplineSeg3<2>;
template class SplineSeg3<3>;
RegisterClassForArchive<SplineSeg<2>> regss2;
RegisterClassForArchive<SplineSeg<3>> regss3;
RegisterClassForArchive<LineSeg<2>, SplineSeg<2>> regls2;
RegisterClassForArchive<LineSeg<3>, SplineSeg<3>> regls3;
RegisterClassForArchive<SplineSeg3<2>, SplineSeg<2>> regsss2;
RegisterClassForArchive<SplineSeg3<3>, SplineSeg<3>> regsss3;
}

View File

@ -28,13 +28,19 @@ namespace netgen
double hmax;
/// hp-refinement
double hpref;
///
string name;
///
GeomPoint () { ; }
///
GeomPoint (const Point<D> & ap, double aref = 1, double ahpref=0)
: Point<D>(ap), refatpoint(aref), hmax(1e99), hpref(ahpref) { ; }
void DoArchive(Archive& ar)
{
Point<D>::DoArchive(ar);
ar & refatpoint & hmax & hpref;
}
};
@ -72,6 +78,7 @@ namespace netgen
second = 1.0/sqr(eps) * ( (pr-point)+(pl-point));
}
virtual void DoArchive(Archive& ar) = 0;
/// returns initial point on curve
virtual const GeomPoint<D> & StartPI () const = 0;
@ -122,6 +129,12 @@ namespace netgen
///
LineSeg (const GeomPoint<D> & ap1, const GeomPoint<D> & ap2);
///
// default constructor for archive
LineSeg() {}
virtual void DoArchive(Archive& ar)
{
ar & p1 & p2;
}
virtual double Length () const;
///
inline virtual Point<D> GetPoint (double t) const;
@ -172,8 +185,14 @@ namespace netgen
SplineSeg3 (const GeomPoint<D> & ap1,
const GeomPoint<D> & ap2,
const GeomPoint<D> & ap3);
// default constructor for archive
SplineSeg3() {}
///
inline virtual Point<D> GetPoint (double t) const;
virtual void DoArchive(Archive& ar)
{
ar & p1 & p2 & p3 & weight & proj_latest_t;
}
virtual Point<D> GetPoint (double t) const;
///
virtual Vec<D> GetTangent (const double t) const;
@ -226,6 +245,12 @@ namespace netgen
CircleSeg (const GeomPoint<D> & ap1,
const GeomPoint<D> & ap2,
const GeomPoint<D> & ap3);
// default constructor for archive
CircleSeg() {}
virtual void DoArchive(Archive& ar)
{
ar & p1 & p2 & p3 & pm & radius & w1 & w3;
}
///
virtual Point<D> GetPoint (double t) const;
///
@ -270,6 +295,12 @@ namespace netgen
public:
///
DiscretePointsSeg (const Array<Point<D> > & apts);
// default constructor for archive
DiscretePointsSeg() {}
virtual void DoArchive(Archive& ar)
{
ar & pts & p1n & p2n;
}
///
virtual ~DiscretePointsSeg ();
///
@ -624,8 +655,14 @@ namespace netgen
///
BSplineSeg (const Array<Point<D> > & apts);
///
//default constructor for archive
BSplineSeg() {}
virtual ~BSplineSeg();
///
virtual void DoArchive(Archive& ar)
{
ar & pts & p1n & p2n & ti;
}
virtual Point<D> GetPoint (double t) const;
///
virtual const GeomPoint<D> & StartPI () const { return p1n; };

View File

@ -55,6 +55,10 @@ namespace netgen
// void SetGrading (const double grading);
DLL_HEADER void AppendPoint (const Point<D> & p, const double reffac = 1., const bool hpref = false);
void DoArchive(Archive& ar)
{
ar & geompoints & splines;
}
void AppendSegment(SplineSeg<D> * spline)
{

View File

@ -230,7 +230,7 @@ namespace netgen
void LoadMesh (istream & str);
void SaveMesh (ostream & str) const;
void UpdateTopology ();
void DoArchive (ngstd::Archive & archive);
void DoArchive (Archive & archive);
virtual ~Ngx_Mesh();

View File

@ -47,6 +47,7 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (size_t nr) const
Ng_Element ret;
ret.type = NG_PNT;
ret.index = el.index;
ret.mat = &el.name;
ret.points.num = 1;
ret.points.ptr = (int*)&el.pnum;

View File

@ -9,9 +9,7 @@ add_library(interface ${NG_LIB_TYPE}
if(NOT WIN32)
target_link_libraries(interface mesh csg geom2d)
if(USE_GUI)
target_link_libraries(interface visual)
endif(USE_GUI)
target_link_libraries(interface visual)
install( TARGETS interface ${NG_INSTALL_DIR})
endif(NOT WIN32)

View File

@ -69,7 +69,7 @@ namespace netgen
mesh -> Save (ost);
}
void Ngx_Mesh :: DoArchive (ngstd::Archive & archive)
void Ngx_Mesh :: DoArchive (Archive & archive)
{
if (archive.Input()) mesh = make_shared<Mesh>();
mesh->DoArchive(archive);

View File

@ -139,6 +139,14 @@ public:
~Vector ()
{ if (ownmem) delete [] data; }
virtual void DoArchive(Archive& ar)
{
auto size = s;
ar & ownmem & size;
if(!ar.Output())
SetSize(size);
ar.Do(data, size);
}
Vector & operator= (const FlatVector & v)
{ memcpy (data, &v(0), s*sizeof(double)); return *this; }

View File

@ -30,7 +30,7 @@ if(APPLE)
endif(APPLE)
if(NOT WIN32)
target_link_libraries( mesh ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY})
target_link_libraries( mesh ngcore ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY})
install( TARGETS mesh ${NG_INSTALL_DIR})
endif(NOT WIN32)

View File

@ -22,7 +22,7 @@ namespace netgen
mgi = new MultiPointGeomInfo (*amgi);
for (int i = 1; i <= mgi->GetNPGI(); i++)
if (mgi->GetPGI(i).trignum <= 0)
cout << "Add FrontPoint2, illegal geominfo = " << mgi->GetPGI(i).trignum << endl;
cout << "WARNING: Add FrontPoint2, illegal geominfo = " << mgi->GetPGI(i).trignum << endl;
}
else
mgi = NULL;
@ -136,7 +136,7 @@ namespace netgen
if (!gi1.trignum || !gi2.trignum)
{
cout << "ERROR: in AdFront::AddLine, illegal geominfo" << endl;
cout << "WARNING: in AdFront::AddLine, illegal geominfo" << endl;
}
lines[li].SetGeomInfo (gi1, gi2);

View File

@ -1304,7 +1304,7 @@ namespace netgen
}
void Mesh :: DoArchive (ngstd::Archive & archive)
void Mesh :: DoArchive (Archive & archive)
{
archive & dimension;
archive & points;

View File

@ -517,7 +517,7 @@ namespace netgen
DLL_HEADER void Merge (const string & filename, const int surfindex_offset = 0);
DLL_HEADER void DoArchive (ngstd::Archive & archive);
DLL_HEADER void DoArchive (Archive & archive);
///
DLL_HEADER void ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY);

View File

@ -148,9 +148,9 @@ namespace netgen
return *this;
}
ngstd::Archive & Segment :: DoArchive (ngstd::Archive & ar)
void Segment :: DoArchive (Archive & ar)
{
return ar & pnums[0] & pnums[1] & pnums[2]
ar & pnums[0] & pnums[1] & pnums[2]
& edgenr & singedge_left & singedge_right
& si & cd2i & domin & domout & tlosurf
& surfnr1 & surfnr2
@ -2427,9 +2427,9 @@ namespace netgen
bcn = &default_bcname;
}
ngstd::Archive & FaceDescriptor :: DoArchive (ngstd::Archive & ar)
void FaceDescriptor :: DoArchive (Archive & ar)
{
return ar & surfnr & domin & domout & tlosurf & bcprop
ar & surfnr & domin & domout & tlosurf & bcprop
& surfcolour.X() & surfcolour.Y() & surfcolour.Z()
& bcname
& domin_singular & domout_singular ;
@ -2482,7 +2482,7 @@ namespace netgen
maxidentnr = 0;
}
ngstd::Archive & Identifications :: DoArchive (ngstd::Archive & ar)
void Identifications :: DoArchive (Archive & ar)
{
ar & maxidentnr;
ar & identifiedpoints & identifiedpoints_nr;
@ -2503,7 +2503,6 @@ namespace netgen
for (auto & t : type)
ar & (unsigned char&)(t);
}
return ar;
}

View File

@ -171,13 +171,9 @@ namespace netgen
enum { BASE = 1 };
#endif
ngstd::Archive & DoArchive (ngstd::Archive & ar) { return ar & i; }
void DoArchive (Archive & ar) { ar & i; }
};
inline ngstd::Archive & operator & (ngstd::Archive & archive, PointIndex & mp)
{ return mp.DoArchive(archive); }
inline istream & operator>> (istream & ist, PointIndex & pi)
{
int i; ist >> i; pi = PointIndex(i); return ist;
@ -247,14 +243,9 @@ namespace netgen
SurfaceElementIndex & operator-- () { --i; return *this; }
SurfaceElementIndex & operator+= (int inc) { i+=inc; return *this; }
ngstd::Archive & DoArchive (ngstd::Archive & ar) { return ar & i; }
void DoArchive (Archive & ar) { ar & i; }
};
inline ngstd::Archive & operator & (ngstd::Archive & archive, SurfaceElementIndex & mp)
{ return mp.DoArchive(archive); }
inline istream & operator>> (istream & ist, SurfaceElementIndex & pi)
{
int i; ist >> i; pi = i; return ist;
@ -337,19 +328,13 @@ namespace netgen
static MPI_Datatype MyGetMPIType ( );
#endif
ngstd::Archive & DoArchive (ngstd::Archive & ar)
void DoArchive (Archive & ar)
{
ar & x[0] & x[1] & x[2] & layer & singular;
ar & (unsigned char&)(type);
return ar;
}
};
inline ngstd::Archive & operator & (ngstd::Archive & archive, MeshPoint & mp)
{ return mp.DoArchive(archive); }
inline ostream & operator<<(ostream & s, const MeshPoint & pt)
{
return (s << Point<3> (pt));
@ -497,7 +482,7 @@ namespace netgen
///
const PointGeomInfo & GeomInfoPiMod (int i) const { return geominfo[(i-1) % np]; }
ngstd::Archive & DoArchive (ngstd::Archive & ar)
void DoArchive (Archive & ar)
{
short _np, _typ;
bool _curved, _vis, _deleted;
@ -511,7 +496,6 @@ namespace netgen
visible = _vis; deleted = _deleted; }
for (size_t i = 0; i < np; i++)
ar & pnum[i];
return ar;
}
void SetIndex (int si) { index = si; }
@ -630,9 +614,6 @@ namespace netgen
#endif
};
inline ngstd::Archive & operator & (ngstd::Archive & archive, Element2d & mp)
{ return mp.DoArchive(archive); }
ostream & operator<<(ostream & s, const Element2d & el);
@ -774,7 +755,7 @@ namespace netgen
///
const PointIndex & PNumMod (int i) const { return pnum[(i-1) % np]; }
ngstd::Archive & DoArchive (ngstd::Archive & ar)
void DoArchive (Archive & ar)
{
short _np, _typ;
if (ar.Output())
@ -784,7 +765,6 @@ namespace netgen
{ np = _np; typ = ELEMENT_TYPE(_typ); }
for (size_t i = 0; i < np; i++)
ar & pnum[i];
return ar;
}
///
@ -928,9 +908,6 @@ namespace netgen
int hp_elnr;
};
inline ngstd::Archive & operator & (ngstd::Archive & archive, Element & mp)
{ return mp.DoArchive(archive); }
ostream & operator<<(ostream & s, const Element & el);
@ -1049,12 +1026,9 @@ namespace netgen
#else
int GetPartition () const { return 0; }
#endif
ngstd::Archive & DoArchive (ngstd::Archive & ar);
void DoArchive (Archive & ar);
};
inline ngstd::Archive & operator & (ngstd::Archive & archive, Segment & mp)
{ return mp.DoArchive(archive); }
ostream & operator<<(ostream & s, const Segment & seg);
@ -1062,6 +1036,7 @@ namespace netgen
{
public:
PointIndex pnum;
string name;
int index;
Element0d () = default;
Element0d (PointIndex _pnum, int _index)
@ -1142,13 +1117,9 @@ namespace netgen
// friend ostream & operator<<(ostream & s, const FaceDescriptor & fd);
friend class Mesh;
ngstd::Archive & DoArchive (ngstd::Archive & ar);
void DoArchive (Archive & ar);
};
inline ngstd::Archive & operator & (ngstd::Archive & archive, FaceDescriptor & mp)
{ return mp.DoArchive(archive); }
ostream & operator<< (ostream & s, const FaceDescriptor & fd);
@ -1516,12 +1487,8 @@ namespace netgen
DLL_HEADER void Print (ostream & ost) const;
ngstd::Archive & DoArchive (ngstd::Archive & ar);
void DoArchive (Archive & ar);
};
inline ngstd::Archive & operator & (ngstd::Archive & archive, Identifications & mp)
{ return mp.DoArchive(archive); }
}

View File

@ -4,13 +4,17 @@ add_library(occ ${NG_LIB_TYPE}
Partition_Loop.cxx Partition_Loop2d.cxx Partition_Loop3d.cxx Partition_Spliter.cxx
occconstruction.cpp occgenmesh.cpp occgeom.cpp occmeshsurf.cpp python_occ.cpp
)
add_library(occvis ${NG_LIB_TYPE} vsocc.cpp)
if(USE_GUI)
add_library(occvis ${NG_LIB_TYPE} vsocc.cpp)
endif(USE_GUI)
if(NOT WIN32)
target_link_libraries( occ ${OCC_LIBRARIES} ${PYTHON_LIBRARIES})
target_link_libraries( occvis occ )
install( TARGETS occ occvis ${NG_INSTALL_DIR})
install( TARGETS occ ${NG_INSTALL_DIR})
if (USE_GUI)
target_link_libraries( occvis occ )
install( TARGETS occvis ${NG_INSTALL_DIR})
endif(USE_GUI)
endif(NOT WIN32)
install(FILES

View File

@ -32,6 +32,8 @@ if(NOT WIN32)
endif(USE_GUI)
endif(NOT WIN32)
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)

View File

@ -1 +1,2 @@
add_subdirectory(catch)
add_subdirectory(pytest)

View File

@ -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

View File

@ -0,0 +1,37 @@
if(ENABLE_UNIT_TESTS)
add_custom_target(unit_tests)
# Build catch_main test object
message("netgen include dir = ${NETGEN_INCLUDE_DIR_ABSOLUTE} --------------------------------------")
include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include})
add_library(catch_main STATIC main.cpp)
set_target_properties(catch_main PROPERTIES CXX_STANDARD 17)
add_dependencies(unit_tests catch_main)
add_dependencies(catch_main project_catch)
# ensure the test targets are built before testing
add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_tests --config ${CMAKE_BUILD_TYPE} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/../.. )
macro(add_unit_test name sources)
add_executable(test_${name} ${sources} )
if (WIN32)
target_link_libraries(test_${name} ngcore catch_main)
else(WIN32)
target_link_libraries(test_${name} ngcore catch_main)
endif(WIN32)
add_dependencies(unit_tests test_${name})
add_test(NAME unit_${name} COMMAND test_${name})
set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built)
endmacro()
add_unit_test(archive archive.cpp)
add_unit_test(version version.cpp)
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
set_target_properties(test_archive PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
set_target_properties(test_version PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
endif(ENABLE_UNIT_TESTS)

317
tests/catch/archive.cpp Normal file
View File

@ -0,0 +1,317 @@
#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<shared_ptr<string>> names;
virtual ~SharedPtrHolder()
{ }
virtual void abstract() = 0;
virtual void DoArchive(Archive& archive)
{
CommonBase::DoArchive(archive);
archive & names;
}
};
class PtrHolder : virtual public CommonBase
{
public:
vector<int*> 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<CommonBase> regb;
static RegisterClassForArchive<SharedPtrHolder, CommonBase> regsp;
static RegisterClassForArchive<PtrHolder, CommonBase> regp;
static RegisterClassForArchive<SharedPtrAndPtrHolder, SharedPtrHolder, PtrHolder> regspp;
static RegisterClassForArchive<OneMoreDerivedClass, SharedPtrAndPtrHolder> regom;
void testNullPtr(Archive& in, Archive& out)
{
SharedPtrHolder* p = nullptr;
shared_ptr<string> sp = nullptr;
out & p & sp;
out.FlushBuffer();
SharedPtrHolder* pin = nullptr;
shared_ptr<string> 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<SharedPtrHolder>::value, "");
SharedPtrAndPtrHolder holder, holder2;
holder.names.push_back(make_shared<string>("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<SharedPtrHolder*>(p);
p2->names.push_back(make_shared<string>("test"));
auto sp1 = shared_ptr<PtrHolder>(p);
auto sp2 = dynamic_pointer_cast<SharedPtrHolder>(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<SharedPtrAndPtrHolder*>(pin) == dynamic_cast<SharedPtrAndPtrHolder*>(pin2));
CHECK(pin->a == pin2->a);
CHECK(pin->a == 5);
REQUIRE(dynamic_cast<SharedPtrAndPtrHolder*>(pin2) != nullptr);
CHECK(*dynamic_cast<SharedPtrAndPtrHolder*>(pin2)->numbers[0] == 2);
CHECK(*pin->numbers[0] == *dynamic_cast<SharedPtrAndPtrHolder*>(pin2)->numbers[0]);
REQUIRE(dynamic_cast<SharedPtrAndPtrHolder*>(pin) != nullptr);
CHECK(dynamic_cast<SharedPtrAndPtrHolder*>(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<PtrHolder> pin;
shared_ptr<SharedPtrHolder> pin2;
in & pin & pin2;
checkPtr(pin.get(), pin2.get());
}
SECTION("Virtual base class")
{
CommonBase* b = dynamic_cast<CommonBase*>(p);
out & b & p;
PtrHolder* pin;
CommonBase* bin;
in & bin & pin;
checkPtr(pin, dynamic_cast<SharedPtrHolder*>(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<SimpleClass>(a);
out & spa;
out.FlushBuffer();
shared_ptr<SimpleClass> spain;
in & spain;
CHECK(spain->a == 5);
CHECK(spain->d == 2.3);
}
}
}
void testLibraryVersion(Archive& in, Archive& out)
{
SetLibraryVersion("netgen","v6.2.1812");
CHECK(in.GetVersion("netgen") == "v6.2.1811");
CHECK(out.GetVersion("netgen") == "v6.2.1812");
}
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("Library Version")
{
testLibraryVersion(in,out);
}
}
TEST_CASE("BinaryArchive")
{
SetLibraryVersion("netgen","v6.2.1811");
auto stream = make_shared<stringstream>();
BinaryOutArchive out(stream);
BinaryInArchive in(stream);
testArchive(in, out);
}
TEST_CASE("TextArchive")
{
SetLibraryVersion("netgen","v6.2.1811");
auto stream = make_shared<stringstream>();
TextOutArchive out(stream);
TextInArchive in(stream);
testArchive(in, out);
}

3
tests/catch/main.cpp Normal file
View File

@ -0,0 +1,3 @@
#define CATCH_CONFIG_MAIN
#include <catch.hpp>

19
tests/catch/version.cpp Normal file
View File

@ -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");
}

View File

@ -1,4 +0,0 @@
FROM ubuntu:16.04
MAINTAINER Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at>
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

View File

@ -1,4 +1,5 @@
FROM ubuntu:15.10
FROM ubuntu:18.04
ENV DEBIAN_FRONTEND=noninteractive
MAINTAINER Matthias Hochsteger <matthias.hochsteger@tuwien.ac.at>
RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk
RUN apt-get update && apt-get -y install python3 libpython3-dev libxmu-dev tk-dev tcl-dev cmake git g++ libglu1-mesa-dev ccache python3-pytest python3-numpy python3-tk clang-tidy python3-distutils clang
ADD . /root/src/netgen

View File

@ -0,0 +1,39 @@
import netgen.csg as csg
import pickle, numpy
def test_pickle_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)
if __name__ == "__main__":
test_pickle_csg()