mirror of
https://github.com/NGSolve/netgen.git
synced 2025-04-12 16:17:29 +05:00
Merge branch 'ngcore' into 'master'
Ngcore See merge request jschoeberl/netgen!114
This commit is contained in:
commit
18044b8897
@ -101,6 +101,13 @@ test_guidelines:
|
|||||||
- 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
|
- 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
|
when: always
|
||||||
|
|
||||||
|
# check if it compiles without spdlog
|
||||||
|
test_noSpdlog:
|
||||||
|
<<: *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_nospdlog.sh
|
||||||
|
|
||||||
cleanup_ubuntu:
|
cleanup_ubuntu:
|
||||||
stage: cleanup
|
stage: cleanup
|
||||||
tags:
|
tags:
|
||||||
|
@ -2,7 +2,13 @@ if(NOT CMAKE_BUILD_TYPE)
|
|||||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING INTERNAL)
|
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING INTERNAL)
|
||||||
endif(NOT CMAKE_BUILD_TYPE)
|
endif(NOT CMAKE_BUILD_TYPE)
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.1.3)
|
if(WIN32)
|
||||||
|
# we are linking to object libraries on Windows
|
||||||
|
cmake_minimum_required(VERSION 3.12)
|
||||||
|
else(WIN32)
|
||||||
|
cmake_minimum_required(VERSION 3.1.3)
|
||||||
|
endif(WIN32)
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
option( USE_NATIVE_ARCH "build which -march=native" ON)
|
option( USE_NATIVE_ARCH "build which -march=native" ON)
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
@ -19,6 +25,9 @@ option( USE_CCACHE "use ccache")
|
|||||||
option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON)
|
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_UNIT_TESTS "Enable Catch unit tests")
|
||||||
option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF)
|
option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF)
|
||||||
|
option( USE_SPDLOG "Enable spd log logging" OFF)
|
||||||
|
option( DEBUG_LOG "Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON" OFF)
|
||||||
|
option( CHECK_RANGE "Check array range access, automatically enabled if built in debug mode" OFF)
|
||||||
|
|
||||||
option( USE_SUPERBUILD "use ccache" ON)
|
option( USE_SUPERBUILD "use ccache" ON)
|
||||||
|
|
||||||
@ -258,6 +267,7 @@ endif (USE_GUI)
|
|||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
if (USE_PYTHON)
|
if (USE_PYTHON)
|
||||||
|
add_subdirectory(external_dependencies/pybind11)
|
||||||
add_definitions(-DNG_PYTHON)
|
add_definitions(-DNG_PYTHON)
|
||||||
find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h HINTS ${PYTHON_INCLUDE_DIR})
|
find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h HINTS ${PYTHON_INCLUDE_DIR})
|
||||||
if( PYBIND_INCLUDE_DIR )
|
if( PYBIND_INCLUDE_DIR )
|
||||||
@ -350,6 +360,11 @@ endif(ENABLE_UNIT_TESTS)
|
|||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
|
|
||||||
|
if(USE_SPDLOG)
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/cmake/external_projects/spdlog.cmake)
|
||||||
|
include_directories(${SPDLOG_INCLUDE_DIR})
|
||||||
|
endif(USE_SPDLOG)
|
||||||
|
|
||||||
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
||||||
find_program(
|
find_program(
|
||||||
CLANG_TIDY_EXE
|
CLANG_TIDY_EXE
|
||||||
|
@ -142,6 +142,9 @@ set_vars( NETGEN_CMAKE_ARGS
|
|||||||
CMAKE_INSTALL_PREFIX
|
CMAKE_INSTALL_PREFIX
|
||||||
ENABLE_UNIT_TESTS
|
ENABLE_UNIT_TESTS
|
||||||
ENABLE_CPP_CORE_GUIDELINES_CHECK
|
ENABLE_CPP_CORE_GUIDELINES_CHECK
|
||||||
|
USE_SPDLOG
|
||||||
|
DEBUG_LOG
|
||||||
|
CHECK_RANGE
|
||||||
)
|
)
|
||||||
|
|
||||||
# propagate all variables set on the command line using cmake -DFOO=BAR
|
# propagate all variables set on the command line using cmake -DFOO=BAR
|
||||||
|
18
cmake/external_projects/spdlog.cmake
Normal file
18
cmake/external_projects/spdlog.cmake
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
include(ExternalProject)
|
||||||
|
find_program(GIT_EXECUTABLE git)
|
||||||
|
|
||||||
|
ExternalProject_Add(
|
||||||
|
project_spdlog
|
||||||
|
PREFIX ${CMAKE_BINARY_DIR}/spdlog
|
||||||
|
GIT_REPOSITORY https://github.com/gabime/spdlog.git
|
||||||
|
GIT_TAG v1.2.1
|
||||||
|
TIMEOUT 01
|
||||||
|
UPDATE_COMMAND ""
|
||||||
|
CONFIGURE_COMMAND ""
|
||||||
|
BUILD_COMMAND ""
|
||||||
|
INSTALL_COMMAND ""
|
||||||
|
LOG_DOWNLOAD ON
|
||||||
|
)
|
||||||
|
|
||||||
|
ExternalProject_Get_Property(project_spdlog source_dir)
|
||||||
|
set(SPDLOG_INCLUDE_DIR ${source_dir}/include)
|
@ -1,5 +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'
|
Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value'
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
|
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
|
||||||
value: 1
|
value: 1
|
||||||
WarningsAsErrors: '*'
|
WarningsAsErrors: '*'
|
||||||
|
@ -1,16 +1,49 @@
|
|||||||
add_library(ngcore SHARED archive.cpp)
|
|
||||||
|
|
||||||
target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS)
|
add_library(ngcore SHARED archive.cpp logging.cpp paje_trace.cpp utils.cpp profiler.cpp)
|
||||||
|
|
||||||
|
target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS)
|
||||||
|
if(NOT WIN32)
|
||||||
|
target_compile_options(ngcore PRIVATE -fvisibility=hidden)
|
||||||
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
target_compile_definitions(ngcore PUBLIC $<$<CONFIG:DEBUG>:NETGEN_ENABLE_CHECK_RANGE>)
|
||||||
|
|
||||||
|
if(CHECK_RANGE)
|
||||||
|
target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE)
|
||||||
|
endif(CHECK_RANGE)
|
||||||
|
|
||||||
|
if(USE_SPDLOG)
|
||||||
|
include_directories(${SPDLOG_INCLUDE_DIR})
|
||||||
|
install(DIRECTORY ${SPDLOG_INCLUDE_DIR}
|
||||||
|
DESTINATION ${NG_INSTALL_DIR_INCLUDE}
|
||||||
|
)
|
||||||
|
add_dependencies(ngcore project_spdlog)
|
||||||
|
target_compile_definitions(ngcore PUBLIC NETGEN_USE_SPDLOG)
|
||||||
|
if(DEBUG_LOG)
|
||||||
|
target_compile_definitions(ngcore PUBLIC NETGEN_LOG_DEBUG)
|
||||||
|
endif(DEBUG_LOG)
|
||||||
|
endif(USE_SPDLOG)
|
||||||
|
|
||||||
install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen)
|
install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen)
|
||||||
|
|
||||||
if(USE_PYTHON)
|
if(USE_PYTHON)
|
||||||
|
target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON)
|
||||||
target_include_directories(ngcore PUBLIC ${PYTHON_INCLUDE_DIRS})
|
target_include_directories(ngcore PUBLIC ${PYTHON_INCLUDE_DIRS})
|
||||||
|
target_link_libraries(ngcore PUBLIC ${PYTHON_LIBRARIES})
|
||||||
endif(USE_PYTHON)
|
endif(USE_PYTHON)
|
||||||
|
|
||||||
install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp
|
install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp
|
||||||
|
exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp
|
||||||
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)
|
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)
|
||||||
|
|
||||||
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
||||||
set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
|
set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
|
||||||
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
||||||
|
|
||||||
|
if(USE_PYTHON)
|
||||||
|
pybind11_add_module(pyngcore SHARED python_ngcore.cpp)
|
||||||
|
target_link_libraries(pyngcore PUBLIC ngcore ${PYTHON_LIBRARIES})
|
||||||
|
set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}")
|
||||||
|
install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen)
|
||||||
|
endif(USE_PYTHON)
|
||||||
|
|
||||||
|
@ -19,16 +19,6 @@ namespace ngcore
|
|||||||
void SetLibraryVersion(const std::string& library, const VersionInfo& version)
|
void SetLibraryVersion(const std::string& library, const VersionInfo& version)
|
||||||
{ library_versions[library] = 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
|
// clang-tidy should ignore this static object
|
||||||
static std::unique_ptr<std::map<std::string, detail::ClassArchiveInfo>> type_register; // NOLINT
|
static std::unique_ptr<std::map<std::string, detail::ClassArchiveInfo>> type_register; // NOLINT
|
||||||
const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname)
|
const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname)
|
||||||
|
@ -3,31 +3,32 @@
|
|||||||
|
|
||||||
#include <complex> // for complex
|
#include <complex> // for complex
|
||||||
#include <cstring> // for size_t, strlen
|
#include <cstring> // for size_t, strlen
|
||||||
#include <fstream> // for operator<<, ifstream, ofstream, basic...
|
#include <fstream> // for ifstream, ofstream
|
||||||
#include <functional> // for function
|
#include <functional> // for function
|
||||||
#include <map> // for map, _Rb_tree_iterator
|
#include <map> // for map
|
||||||
#include <memory> // for __shared_ptr_access, __shared_ptr_acc...
|
#include <memory> // for shared_ptr
|
||||||
#include <stdexcept> // for runtime_error
|
#include <string> // for string
|
||||||
#include <string> // for string, operator+
|
|
||||||
#include <type_traits> // for declval, enable_if, false_type, is_co...
|
#include <type_traits> // for declval, enable_if, false_type, is_co...
|
||||||
#include <typeinfo> // for type_info
|
#include <typeinfo> // for type_info
|
||||||
#include <utility> // for move, swap, pair
|
#include <utility> // for move, swap, pair
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ngcore_api.hpp" // for NGCORE_API, unlikely
|
#include "exception.hpp" // for UnreachableCodeException, Exception
|
||||||
|
#include "logging.hpp" // for logger
|
||||||
|
#include "ngcore_api.hpp" // for NGCORE_API
|
||||||
#include "type_traits.hpp" // for all_of_tmpl
|
#include "type_traits.hpp" // for all_of_tmpl
|
||||||
|
#include "utils.hpp" // for Demangle, unlikely
|
||||||
#include "version.hpp" // for VersionInfo
|
#include "version.hpp" // for VersionInfo
|
||||||
|
|
||||||
#ifdef NG_PYTHON
|
#ifdef NETGEN_PYTHON
|
||||||
#include <pybind11/pybind11.h>
|
#include <pybind11/pybind11.h>
|
||||||
#endif // NG_PYTHON
|
#endif // NETGEN_PYTHON
|
||||||
|
|
||||||
namespace ngcore
|
namespace ngcore
|
||||||
{
|
{
|
||||||
// Libraries using this archive can store their version here to implement backwards compatibility
|
// Libraries using this archive can store their version here to implement backwards compatibility
|
||||||
NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library);
|
NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library);
|
||||||
NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version);
|
NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version);
|
||||||
NGCORE_API std::string Demangle(const char* typeinfo);
|
|
||||||
|
|
||||||
class NGCORE_API Archive;
|
class NGCORE_API Archive;
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ namespace ngcore
|
|||||||
// create new pointer of type T if it is default constructible, else throw
|
// create new pointer of type T if it is default constructible, else throw
|
||||||
template<typename T, typename ...Rest>
|
template<typename T, typename ...Rest>
|
||||||
T* constructIfPossible_impl(Rest... /*unused*/)
|
T* constructIfPossible_impl(Rest... /*unused*/)
|
||||||
{ throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); }
|
{ throw Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); }
|
||||||
|
|
||||||
template<typename T, typename= typename std::enable_if<std::is_constructible<T>::value>::type>
|
template<typename T, typename= typename std::enable_if<std::is_constructible<T>::value>::type>
|
||||||
T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT
|
T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT
|
||||||
@ -96,28 +97,34 @@ namespace ngcore
|
|||||||
{
|
{
|
||||||
const bool is_output;
|
const bool is_output;
|
||||||
// how many different shared_ptr/pointer have been (un)archived
|
// how many different shared_ptr/pointer have been (un)archived
|
||||||
int shared_ptr_count, ptr_count;
|
int shared_ptr_count{0}, ptr_count{0};
|
||||||
// maps for archived shared pointers and pointers
|
// maps for archived shared pointers and pointers
|
||||||
std::map<void*, int> shared_ptr2nr, ptr2nr;
|
std::map<void*, int> shared_ptr2nr{}, ptr2nr{};
|
||||||
// vectors for storing the unarchived (shared) pointers
|
// vectors for storing the unarchived (shared) pointers
|
||||||
std::vector<std::shared_ptr<void>> nr2shared_ptr;
|
std::vector<std::shared_ptr<void>> nr2shared_ptr{};
|
||||||
std::vector<void*> nr2ptr;
|
std::vector<void*> nr2ptr{};
|
||||||
protected:
|
protected:
|
||||||
bool shallow_to_python = false;
|
bool shallow_to_python = false;
|
||||||
|
std::map<std::string, VersionInfo> version_map = GetLibraryVersions();
|
||||||
|
std::shared_ptr<spdlog::logger> logger = GetLogger("Archive");
|
||||||
public:
|
public:
|
||||||
Archive() = delete;
|
Archive() = delete;
|
||||||
Archive(const Archive&) = delete;
|
Archive(const Archive&) = delete;
|
||||||
Archive(Archive&&) = delete;
|
Archive(Archive&&) = delete;
|
||||||
Archive (bool ais_output) :
|
Archive (bool ais_output) : is_output(ais_output) { ; }
|
||||||
is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; }
|
|
||||||
|
|
||||||
virtual ~Archive() { ; }
|
virtual ~Archive() { ; }
|
||||||
|
|
||||||
|
// If the object is pickled, all shallow archived objects will be pickled as a list,
|
||||||
|
// instead of written as a binary archive. This allows pickle to serialize every object only
|
||||||
|
// once and put them together correctly afterwards. Therefore all objects that may live in
|
||||||
|
// Python should be archived using this Shallow function. If Shallow is called from C++ code
|
||||||
|
// it archives the object normally.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
Archive& Shallow(T& val)
|
Archive& Shallow(T& val)
|
||||||
{
|
{
|
||||||
static_assert(detail::is_any_pointer<T>, "ShallowArchive must be given pointer type!");
|
static_assert(detail::is_any_pointer<T>, "ShallowArchive must be given pointer type!");
|
||||||
#ifdef NG_PYTHON
|
#ifdef NETGEN_PYTHON
|
||||||
if(shallow_to_python)
|
if(shallow_to_python)
|
||||||
{
|
{
|
||||||
if(is_output)
|
if(is_output)
|
||||||
@ -126,25 +133,25 @@ namespace ngcore
|
|||||||
val = pybind11::cast<T>(ShallowInPython());
|
val = pybind11::cast<T>(ShallowInPython());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif // NG_PYTHON
|
#endif // NETGEN_PYTHON
|
||||||
*this & val;
|
*this & val;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NG_PYTHON
|
#ifdef NETGEN_PYTHON
|
||||||
virtual void ShallowOutPython(pybind11::object /*unused*/) // NOLINT (copy by val is ok for this virt func)
|
virtual void ShallowOutPython(const pybind11::object& /*unused*/)
|
||||||
{ throw std::runtime_error("Should not get in ShallowToPython base class implementation!"); }
|
{ throw UnreachableCodeException{}; }
|
||||||
virtual pybind11::object ShallowInPython()
|
virtual pybind11::object ShallowInPython()
|
||||||
{ throw std::runtime_error("Should not get in ShallowFromPython base class implementation!"); }
|
{ throw UnreachableCodeException{}; }
|
||||||
#endif // NG_PYTHON
|
#endif // NETGEN_PYTHON
|
||||||
|
|
||||||
Archive& operator=(const Archive&) = delete;
|
Archive& operator=(const Archive&) = delete;
|
||||||
Archive& operator=(Archive&&) = delete;
|
Archive& operator=(Archive&&) = delete;
|
||||||
|
|
||||||
bool Output () const { return is_output; }
|
bool Output () const { return is_output; }
|
||||||
bool Input () const { return !is_output; }
|
bool Input () const { return !is_output; }
|
||||||
virtual const VersionInfo& GetVersion(const std::string& library)
|
const VersionInfo& GetVersion(const std::string& library)
|
||||||
{ return GetLibraryVersions()[library]; }
|
{ return version_map[library]; }
|
||||||
|
|
||||||
// Pure virtual functions that have to be implemented by In-/OutArchive
|
// Pure virtual functions that have to be implemented by In-/OutArchive
|
||||||
virtual Archive & operator & (double & d) = 0;
|
virtual Archive & operator & (double & d) = 0;
|
||||||
@ -157,7 +164,7 @@ namespace ngcore
|
|||||||
virtual Archive & operator & (std::string & str) = 0;
|
virtual Archive & operator & (std::string & str) = 0;
|
||||||
virtual Archive & operator & (char *& str) = 0;
|
virtual Archive & operator & (char *& str) = 0;
|
||||||
|
|
||||||
virtual Archive & operator & (VersionInfo & version)
|
Archive & operator & (VersionInfo & version)
|
||||||
{
|
{
|
||||||
if(Output())
|
if(Output())
|
||||||
(*this) << version.to_string();
|
(*this) << version.to_string();
|
||||||
@ -198,6 +205,33 @@ namespace ngcore
|
|||||||
Do(&v[0], size);
|
Do(&v[0], size);
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// vector<bool> has special implementation (like a bitarray) therefore
|
||||||
|
// it needs a special overload (this could probably be more efficient, but we
|
||||||
|
// don't use it that often anyway)
|
||||||
|
Archive& operator& (std::vector<bool>& v)
|
||||||
|
{
|
||||||
|
size_t size;
|
||||||
|
if(Output())
|
||||||
|
size = v.size();
|
||||||
|
(*this) & size;
|
||||||
|
if(Input())
|
||||||
|
{
|
||||||
|
v.resize(size);
|
||||||
|
bool b;
|
||||||
|
for(size_t i=0; i<size; i++)
|
||||||
|
{
|
||||||
|
(*this) & b;
|
||||||
|
v[i] = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(bool b : v)
|
||||||
|
(*this) & b;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
Archive& operator& (std::map<T1, T2>& map)
|
Archive& operator& (std::map<T1, T2>& map)
|
||||||
{
|
{
|
||||||
@ -261,28 +295,39 @@ namespace ngcore
|
|||||||
{
|
{
|
||||||
if(Output())
|
if(Output())
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Store shared ptr of type " + Demangle(typeid(T).name()));
|
||||||
// save -2 for nullptr
|
// save -2 for nullptr
|
||||||
if(!ptr)
|
if(!ptr)
|
||||||
return (*this) << -2;
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Storing nullptr");
|
||||||
|
return (*this) << -2;
|
||||||
|
}
|
||||||
|
|
||||||
void* reg_ptr = ptr.get();
|
void* reg_ptr = ptr.get();
|
||||||
bool neededDowncast = false;
|
bool neededDowncast = false;
|
||||||
// Downcasting is only possible for our registered classes
|
// Downcasting is only possible for our registered classes
|
||||||
if(typeid(T) != typeid(*ptr))
|
if(typeid(T) != typeid(*ptr))
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " +
|
||||||
|
Demangle(typeid(*ptr).name()));
|
||||||
if(!IsRegistered(Demangle(typeid(*ptr).name())))
|
if(!IsRegistered(Demangle(typeid(*ptr).name())))
|
||||||
throw std::runtime_error(std::string("Archive error: Polymorphic type ")
|
throw Exception(std::string("Archive error: Polymorphic type ")
|
||||||
+ Demangle(typeid(*ptr).name())
|
+ Demangle(typeid(*ptr).name())
|
||||||
+ " not registered for archive");
|
+ " not registered for archive");
|
||||||
reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get());
|
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 there was a true downcast we have to store more information
|
||||||
if(reg_ptr != static_cast<void*>(ptr.get()) )
|
if(reg_ptr != static_cast<void*>(ptr.get()))
|
||||||
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer");
|
||||||
neededDowncast = true;
|
neededDowncast = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto pos = shared_ptr2nr.find(reg_ptr);
|
auto pos = shared_ptr2nr.find(reg_ptr);
|
||||||
// if not found store -1 and the pointer
|
// if not found store -1 and the pointer
|
||||||
if(pos == shared_ptr2nr.end())
|
if(pos == shared_ptr2nr.end())
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Didn't find the shared_ptr, create new registry entry at " +
|
||||||
|
std::to_string(shared_ptr_count));
|
||||||
auto p = ptr.get();
|
auto p = ptr.get();
|
||||||
(*this) << -1;
|
(*this) << -1;
|
||||||
(*this) & neededDowncast & p;
|
(*this) & neededDowncast & p;
|
||||||
@ -293,23 +338,27 @@ namespace ngcore
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
// if found store the position and if it has to be downcasted and how
|
// if found store the position and if it has to be downcasted and how
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Found shared_ptr at position " + std::to_string(pos->second));
|
||||||
(*this) << pos->second << neededDowncast;
|
(*this) << pos->second << neededDowncast;
|
||||||
if(neededDowncast)
|
if(neededDowncast)
|
||||||
(*this) << Demangle(typeid(*ptr).name());
|
(*this) << Demangle(typeid(*ptr).name());
|
||||||
}
|
}
|
||||||
else // Input
|
else // Input
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Reading shared_ptr of type " + Demangle(typeid(T).name()));
|
||||||
int nr;
|
int nr;
|
||||||
(*this) & nr;
|
(*this) & nr;
|
||||||
// -2 restores a nullptr
|
// -2 restores a nullptr
|
||||||
if(nr == -2)
|
if(nr == -2)
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Reading a nullptr");
|
||||||
ptr = nullptr;
|
ptr = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
// -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it
|
// -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it
|
||||||
if (nr == -1)
|
if (nr == -1)
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Createing new shared_ptr");
|
||||||
T* p = nullptr;
|
T* p = nullptr;
|
||||||
bool neededDowncast;
|
bool neededDowncast;
|
||||||
(*this) & neededDowncast & p;
|
(*this) & neededDowncast & p;
|
||||||
@ -317,6 +366,7 @@ namespace ngcore
|
|||||||
// if we did downcast we need to store a shared_ptr<void> to the true object
|
// if we did downcast we need to store a shared_ptr<void> to the true object
|
||||||
if(neededDowncast)
|
if(neededDowncast)
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Shared pointer needed downcasting");
|
||||||
std::string name;
|
std::string name;
|
||||||
(*this) & name;
|
(*this) & name;
|
||||||
auto info = GetArchiveRegister(name);
|
auto info = GetArchiveRegister(name);
|
||||||
@ -327,15 +377,20 @@ namespace ngcore
|
|||||||
ptr.get())));
|
ptr.get())));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
nr2shared_ptr.push_back(ptr);
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need downcasting");
|
||||||
|
nr2shared_ptr.push_back(ptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Reading already existing pointer at entry " + std::to_string(nr));
|
||||||
auto other = nr2shared_ptr[nr];
|
auto other = nr2shared_ptr[nr];
|
||||||
bool neededDowncast;
|
bool neededDowncast;
|
||||||
(*this) & neededDowncast;
|
(*this) & neededDowncast;
|
||||||
if(neededDowncast)
|
if(neededDowncast)
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Shared pointer needed pointer downcast");
|
||||||
// if there was a downcast we can expect the class to be registered (since archiving
|
// if there was a downcast we can expect the class to be registered (since archiving
|
||||||
// wouldn't have worked else)
|
// wouldn't have worked else)
|
||||||
std::string name;
|
std::string name;
|
||||||
@ -348,7 +403,10 @@ namespace ngcore
|
|||||||
other.get())));
|
other.get())));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ptr = std::static_pointer_cast<T>(other);
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need pointer casts");
|
||||||
|
ptr = std::static_pointer_cast<T>(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@ -360,31 +418,44 @@ namespace ngcore
|
|||||||
{
|
{
|
||||||
if (Output())
|
if (Output())
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Store pointer of type " + Demangle(typeid(T).name()));
|
||||||
// if the pointer is null store -2
|
// if the pointer is null store -2
|
||||||
if (!p)
|
if (!p)
|
||||||
return (*this) << -2;
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Storing nullptr");
|
||||||
|
return (*this) << -2;
|
||||||
|
}
|
||||||
auto reg_ptr = static_cast<void*>(p);
|
auto reg_ptr = static_cast<void*>(p);
|
||||||
if(typeid(T) != typeid(*p))
|
if(typeid(T) != typeid(*p))
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " +
|
||||||
|
Demangle(typeid(*p).name()));
|
||||||
if(!IsRegistered(Demangle(typeid(*p).name())))
|
if(!IsRegistered(Demangle(typeid(*p).name())))
|
||||||
throw std::runtime_error(std::string("Archive error: Polymorphic type ")
|
throw Exception(std::string("Archive error: Polymorphic type ")
|
||||||
+ Demangle(typeid(*p).name())
|
+ Demangle(typeid(*p).name())
|
||||||
+ " not registered for archive");
|
+ " not registered for archive");
|
||||||
reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p));
|
reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p));
|
||||||
|
if(reg_ptr != static_cast<void*>(p))
|
||||||
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto pos = ptr2nr.find(reg_ptr);
|
auto pos = ptr2nr.find(reg_ptr);
|
||||||
// if the pointer is not found in the map create a new entry
|
// if the pointer is not found in the map create a new entry
|
||||||
if (pos == ptr2nr.end())
|
if (pos == ptr2nr.end())
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Didn't find pointer, create new registry entry at " +
|
||||||
|
std::to_string(ptr_count));
|
||||||
ptr2nr[reg_ptr] = ptr_count++;
|
ptr2nr[reg_ptr] = ptr_count++;
|
||||||
if(typeid(*p) == typeid(T))
|
if(typeid(*p) == typeid(T))
|
||||||
if (std::is_constructible<T>::value)
|
if (std::is_constructible<T>::value)
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Store standard class pointer (no virt. inh,...)");
|
||||||
return (*this) << -1 & (*p);
|
return (*this) << -1 & (*p);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw std::runtime_error(std::string("Archive error: Class ") +
|
throw Exception(std::string("Archive error: Class ") +
|
||||||
Demangle(typeid(*p).name()) + " does not provide a default constructor!");
|
Demangle(typeid(*p).name()) + " does not provide a default constructor!");
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// if a pointer to a base class is archived, the class hierarchy must be registered
|
// if a pointer to a base class is archived, the class hierarchy must be registered
|
||||||
@ -392,9 +463,10 @@ namespace ngcore
|
|||||||
// implement a void DoArchive(Archive&) member function
|
// implement a void DoArchive(Archive&) member function
|
||||||
// To recreate the object we need to store the true type of it
|
// To recreate the object we need to store the true type of it
|
||||||
if(!IsRegistered(Demangle(typeid(*p).name())))
|
if(!IsRegistered(Demangle(typeid(*p).name())))
|
||||||
throw std::runtime_error(std::string("Archive error: Polymorphic type ")
|
throw Exception(std::string("Archive error: Polymorphic type ")
|
||||||
+ Demangle(typeid(*p).name())
|
+ Demangle(typeid(*p).name())
|
||||||
+ " not registered for archive");
|
+ " not registered for archive");
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer");
|
||||||
return (*this) << -3 << Demangle(typeid(*p).name()) & (*p);
|
return (*this) << -3 << Demangle(typeid(*p).name()) & (*p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,27 +474,39 @@ namespace ngcore
|
|||||||
{
|
{
|
||||||
(*this) & pos->second;
|
(*this) & pos->second;
|
||||||
bool downcasted = !(reg_ptr == static_cast<void*>(p) );
|
bool downcasted = !(reg_ptr == static_cast<void*>(p) );
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Store a the existing position in registry at " +
|
||||||
|
std::to_string(pos->second));
|
||||||
|
NETGEN_DEBUG_LOG(logger, std::string("Pointer ") + (downcasted ? "needs " : "doesn't need ") +
|
||||||
|
"downcasting");
|
||||||
// store if the class has been downcasted and the name
|
// store if the class has been downcasted and the name
|
||||||
(*this) << downcasted << Demangle(typeid(*p).name());
|
(*this) << downcasted << Demangle(typeid(*p).name());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Reading pointer of type " + Demangle(typeid(T).name()));
|
||||||
int nr;
|
int nr;
|
||||||
(*this) & nr;
|
(*this) & nr;
|
||||||
if (nr == -2) // restore a nullptr
|
if (nr == -2) // restore a nullptr
|
||||||
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Loading a nullptr");
|
||||||
p = nullptr;
|
p = nullptr;
|
||||||
|
}
|
||||||
else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...)
|
else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...)
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Load a new pointer to a simple class");
|
||||||
p = detail::constructIfPossible<T>();
|
p = detail::constructIfPossible<T>();
|
||||||
nr2ptr.push_back(p);
|
nr2ptr.push_back(p);
|
||||||
(*this) & *p;
|
(*this) & *p;
|
||||||
}
|
}
|
||||||
else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,...
|
else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,...
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Load a new pointer to a potentially more complicated class "
|
||||||
|
"(allows for multiple/virtual inheritance,...)");
|
||||||
// As stated above, we want this special behaviour only for our classes that implement DoArchive
|
// As stated above, we want this special behaviour only for our classes that implement DoArchive
|
||||||
std::string name;
|
std::string name;
|
||||||
(*this) & name;
|
(*this) & name;
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Name = " + name);
|
||||||
auto info = GetArchiveRegister(name);
|
auto info = GetArchiveRegister(name);
|
||||||
// the creator creates a new object of type name, and returns a void* pointing
|
// the creator creates a new object of type name, and returns a void* pointing
|
||||||
// to T (which may have an offset)
|
// to T (which may have an offset)
|
||||||
@ -434,9 +518,13 @@ namespace ngcore
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
NETGEN_DEBUG_LOG(logger, "Restoring pointer to already existing object at registry position " +
|
||||||
|
std::to_string(nr));
|
||||||
bool downcasted;
|
bool downcasted;
|
||||||
std::string name;
|
std::string name;
|
||||||
(*this) & downcasted & name;
|
(*this) & downcasted & name;
|
||||||
|
NETGEN_DEBUG_LOG(logger, std::string(downcasted ? "Downcasted" : "Not downcasted") +
|
||||||
|
" object of type " + name);
|
||||||
if(downcasted)
|
if(downcasted)
|
||||||
{
|
{
|
||||||
// if the class has been downcasted we can assume it is in the register
|
// if the class has been downcasted we can assume it is in the register
|
||||||
@ -491,11 +579,11 @@ namespace ngcore
|
|||||||
{
|
{
|
||||||
static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/)
|
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!");
|
throw Exception("Upcast not successful, some classes are not registered properly for archiving!");
|
||||||
}
|
}
|
||||||
static void* tryDowncast (const std::type_info& /*unused*/, void* /*unused*/)
|
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!");
|
throw Exception("Downcast not successful, some classes are not registered properly for archiving!");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -507,7 +595,7 @@ namespace ngcore
|
|||||||
try
|
try
|
||||||
{ return GetArchiveRegister(Demangle(typeid(B1).name())).
|
{ return GetArchiveRegister(Demangle(typeid(B1).name())).
|
||||||
upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); }
|
upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); }
|
||||||
catch(std::exception&)
|
catch(const Exception&)
|
||||||
{ return Caster<T, Brest...>::tryUpcast(ti, p); }
|
{ return Caster<T, Brest...>::tryUpcast(ti, p); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,7 +608,7 @@ namespace ngcore
|
|||||||
return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())).
|
return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())).
|
||||||
downcaster(ti, p)));
|
downcaster(ti, p)));
|
||||||
}
|
}
|
||||||
catch(std::exception&)
|
catch(const Exception&)
|
||||||
{
|
{
|
||||||
return Caster<T, Brest...>::tryDowncast(ti, p);
|
return Caster<T, Brest...>::tryDowncast(ti, p);
|
||||||
}
|
}
|
||||||
@ -536,7 +624,7 @@ namespace ngcore
|
|||||||
{
|
{
|
||||||
static_assert(detail::all_of_tmpl<std::is_base_of<Bases,T>::value...>,
|
static_assert(detail::all_of_tmpl<std::is_base_of<Bases,T>::value...>,
|
||||||
"Variadic template arguments must be base classes of T");
|
"Variadic template arguments must be base classes of T");
|
||||||
detail::ClassArchiveInfo info;
|
detail::ClassArchiveInfo info {};
|
||||||
info.creator = [this,&info](const std::type_info& ti) -> void*
|
info.creator = [this,&info](const std::type_info& ti) -> void*
|
||||||
{ return typeid(T) == ti ? detail::constructIfPossible<T>()
|
{ return typeid(T) == ti ? detail::constructIfPossible<T>()
|
||||||
: Archive::Caster<T, Bases...>::tryUpcast(ti, detail::constructIfPossible<T>()); };
|
: Archive::Caster<T, Bases...>::tryUpcast(ti, detail::constructIfPossible<T>()); };
|
||||||
@ -805,7 +893,7 @@ namespace ngcore
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef NG_PYTHON
|
#ifdef NETGEN_PYTHON
|
||||||
|
|
||||||
template<typename ARCHIVE>
|
template<typename ARCHIVE>
|
||||||
class PyArchive : public ARCHIVE
|
class PyArchive : public ARCHIVE
|
||||||
@ -813,7 +901,11 @@ namespace ngcore
|
|||||||
private:
|
private:
|
||||||
pybind11::list lst;
|
pybind11::list lst;
|
||||||
size_t index = 0;
|
size_t index = 0;
|
||||||
|
protected:
|
||||||
using ARCHIVE::stream;
|
using ARCHIVE::stream;
|
||||||
|
using ARCHIVE::version_map;
|
||||||
|
using ARCHIVE::logger;
|
||||||
|
using ARCHIVE::GetLibraryVersions;
|
||||||
public:
|
public:
|
||||||
PyArchive(const pybind11::object& alst = pybind11::none()) :
|
PyArchive(const pybind11::object& alst = pybind11::none()) :
|
||||||
ARCHIVE(std::make_shared<std::stringstream>()),
|
ARCHIVE(std::make_shared<std::stringstream>()),
|
||||||
@ -821,8 +913,13 @@ namespace ngcore
|
|||||||
{
|
{
|
||||||
ARCHIVE::shallow_to_python = true;
|
ARCHIVE::shallow_to_python = true;
|
||||||
if(Input())
|
if(Input())
|
||||||
stream = std::make_shared<std::stringstream>
|
{
|
||||||
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-1]));
|
stream = std::make_shared<std::stringstream>
|
||||||
|
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-1]));
|
||||||
|
*this & version_map;
|
||||||
|
stream = std::make_shared<std::stringstream>
|
||||||
|
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-2]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
using ARCHIVE::Output;
|
using ARCHIVE::Output;
|
||||||
@ -831,39 +928,46 @@ namespace ngcore
|
|||||||
using ARCHIVE::operator&;
|
using ARCHIVE::operator&;
|
||||||
using ARCHIVE::operator<<;
|
using ARCHIVE::operator<<;
|
||||||
using ARCHIVE::GetVersion;
|
using ARCHIVE::GetVersion;
|
||||||
void ShallowOutPython(pybind11::object val) override { lst.append(val); }
|
void ShallowOutPython(const pybind11::object& val) override { lst.append(val); }
|
||||||
pybind11::object ShallowInPython() override { return lst[index++]; }
|
pybind11::object ShallowInPython() override { return lst[index++]; }
|
||||||
|
|
||||||
pybind11::list WriteOut()
|
pybind11::list WriteOut()
|
||||||
{
|
{
|
||||||
FlushBuffer();
|
FlushBuffer();
|
||||||
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
||||||
|
stream = std::make_shared<std::stringstream>();
|
||||||
|
*this & GetLibraryVersions();
|
||||||
|
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
||||||
return lst;
|
return lst;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T, typename T_ARCHIVE_OUT=BinaryOutArchive, typename T_ARCHIVE_IN=BinaryInArchive>
|
template<typename T, typename T_ARCHIVE_OUT=BinaryOutArchive, typename T_ARCHIVE_IN=BinaryInArchive>
|
||||||
auto NGSPickle(bool printoutput=false)
|
auto NGSPickle()
|
||||||
{
|
{
|
||||||
return pybind11::pickle([printoutput](T* self)
|
return pybind11::pickle([](T* self)
|
||||||
{
|
{
|
||||||
PyArchive<T_ARCHIVE_OUT> ar;
|
PyArchive<T_ARCHIVE_OUT> ar;
|
||||||
ar & self;
|
ar & self;
|
||||||
auto output = pybind11::make_tuple(ar.WriteOut());
|
auto output = pybind11::make_tuple(ar.WriteOut());
|
||||||
if(printoutput)
|
NETGEN_DEBUG_LOG(GetLogger("Archive"), "pickling output for object of type " +
|
||||||
pybind11::print("pickle output of", Demangle(typeid(T).name()),"=", output);
|
Demangle(typeid(T).name()) + " = " +
|
||||||
|
std::string(pybind11::str(output)));
|
||||||
return output;
|
return output;
|
||||||
},
|
},
|
||||||
[](pybind11::tuple state)
|
[](pybind11::tuple state)
|
||||||
{
|
{
|
||||||
T* val = nullptr;
|
T* val = nullptr;
|
||||||
|
NETGEN_DEBUG_LOG(GetLogger("Archive"), "State for unpickling of object of type " +
|
||||||
|
Demangle(typeid(T).name()) + " = " +
|
||||||
|
std::string(pybind11::str(state[0])));
|
||||||
PyArchive<T_ARCHIVE_IN> ar(state[0]);
|
PyArchive<T_ARCHIVE_IN> ar(state[0]);
|
||||||
ar & val;
|
ar & val;
|
||||||
return val;
|
return val;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // NG_PYTHON
|
#endif // NETGEN_PYTHON
|
||||||
} // namespace ngcore
|
} // namespace ngcore
|
||||||
|
|
||||||
#endif // NETGEN_CORE_ARCHIVE_HPP
|
#endif // NETGEN_CORE_ARCHIVE_HPP
|
||||||
|
90
libsrc/core/exception.hpp
Normal file
90
libsrc/core/exception.hpp
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
#ifndef NETGEN_CORE_EXCEPTION_HPP
|
||||||
|
#define NETGEN_CORE_EXCEPTION_HPP
|
||||||
|
|
||||||
|
#include <sstream> // for stringstream
|
||||||
|
#include <stdexcept> // for exception
|
||||||
|
#include <string> // for string
|
||||||
|
|
||||||
|
#include "ngcore_api.hpp" // for NGCORE_API
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
// Exception for code that shouldn't be executed
|
||||||
|
class NGCORE_API UnreachableCodeException : public std::exception
|
||||||
|
{
|
||||||
|
const char* what() const noexcept override
|
||||||
|
{
|
||||||
|
return "Shouldn't get here, something went wrong!";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Default exception class
|
||||||
|
class NGCORE_API Exception : public std::exception
|
||||||
|
{
|
||||||
|
/// a verbal description of the exception
|
||||||
|
std::string m_what;
|
||||||
|
public:
|
||||||
|
Exception() = default;
|
||||||
|
Exception(const Exception&) = default;
|
||||||
|
Exception(Exception&&) = default;
|
||||||
|
Exception(const std::string& s) : m_what(s) {}
|
||||||
|
Exception(const char* s) : m_what(s) {}
|
||||||
|
~Exception() override = default;
|
||||||
|
|
||||||
|
Exception& operator =(const Exception&) = default;
|
||||||
|
Exception& operator =(Exception&&) noexcept = default;
|
||||||
|
|
||||||
|
/// append string to description
|
||||||
|
Exception & Append (const std::string & s) { m_what += s; return *this; }
|
||||||
|
/// append string to description
|
||||||
|
Exception & Append (const char * s) { m_what += s; return *this; }
|
||||||
|
|
||||||
|
/// verbal description of exception
|
||||||
|
const std::string & What() const { return m_what; }
|
||||||
|
|
||||||
|
/// implement virtual function of std::exception
|
||||||
|
const char* what() const noexcept override { return m_what.c_str(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
// Out of Range exception
|
||||||
|
class NGCORE_API RangeException : public Exception
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// where it occurs, index, minimal and maximal indices
|
||||||
|
RangeException (const std::string & where,
|
||||||
|
int ind, int imin, int imax) : Exception("")
|
||||||
|
{
|
||||||
|
std::stringstream str;
|
||||||
|
str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n";
|
||||||
|
Append (str.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
RangeException(const std::string& where, const T& value)
|
||||||
|
{
|
||||||
|
std::stringstream str;
|
||||||
|
str << where << " called with wrong value " << value << "\n";
|
||||||
|
Append(str.str());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Exception used if no simd implementation is available to fall back to standard evaluation
|
||||||
|
class NGCORE_API ExceptionNOSIMD : public Exception
|
||||||
|
{ public: using Exception::Exception; };
|
||||||
|
} // namespace ngcore
|
||||||
|
|
||||||
|
#define NETGEN_CORE_NGEXEPTION_STR_HELPER(x) #x
|
||||||
|
#define NETGEN_CORE_NGEXEPTION_STR(x) NETGEN_CORE_NGEXEPTION_STR_HELPER(x)
|
||||||
|
|
||||||
|
// Convenience macro to append file name and line of exception origin to the string
|
||||||
|
#define NG_EXCEPTION(s) ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t"+std::string(s))
|
||||||
|
|
||||||
|
#ifdef NETGEN_ENABLE_CHECK_RANGE
|
||||||
|
#define NETGEN_CHECK_RANGE(value, min, max) \
|
||||||
|
{ if ((value)<(min) || (value)>=(max)) \
|
||||||
|
throw ngcore::RangeException(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", (value), (min), (max)); }
|
||||||
|
#else // NETGEN_ENABLE_CHECK_RANGE
|
||||||
|
#define NETGEN_CHECK_RANGE(value, min, max)
|
||||||
|
#endif // NETGEN_ENABLE_CHECK_RANGE
|
||||||
|
|
||||||
|
#endif // NETGEN_CORE_EXCEPTION_HPP
|
109
libsrc/core/logging.cpp
Normal file
109
libsrc/core/logging.cpp
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
|
||||||
|
#include "logging.hpp"
|
||||||
|
|
||||||
|
#ifdef NETGEN_USE_SPDLOG
|
||||||
|
|
||||||
|
#include <spdlog/sinks/ansicolor_sink.h>
|
||||||
|
#include <spdlog/sinks/basic_file_sink.h>
|
||||||
|
|
||||||
|
#endif // NETGEN_USE_SPDLOG
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
#ifdef NETGEN_USE_SPDLOG
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
std::vector<std::shared_ptr<spdlog::sinks::sink>>& GetDefaultSinks()
|
||||||
|
{
|
||||||
|
static std::vector<std::shared_ptr<spdlog::sinks::sink>> sinks =
|
||||||
|
{ std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>() };
|
||||||
|
return sinks;
|
||||||
|
}
|
||||||
|
std::shared_ptr<spdlog::logger> CreateDefaultLogger(const std::string& name)
|
||||||
|
{
|
||||||
|
auto& default_sinks = GetDefaultSinks();
|
||||||
|
auto logger = std::make_shared<spdlog::logger>(name, default_sinks.begin(), default_sinks.end());
|
||||||
|
spdlog::details::registry::instance().register_and_init(logger);
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
std::shared_ptr<spdlog::logger> GetLogger(const std::string& name)
|
||||||
|
{
|
||||||
|
auto logger = spdlog::get(name);
|
||||||
|
if(!logger)
|
||||||
|
logger = detail::CreateDefaultLogger(name);
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name)
|
||||||
|
{
|
||||||
|
if(!name.empty())
|
||||||
|
spdlog::get(name)->set_level(level);
|
||||||
|
else
|
||||||
|
spdlog::set_level(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger)
|
||||||
|
{
|
||||||
|
auto sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename);
|
||||||
|
sink->set_level(level);
|
||||||
|
if(!logger.empty())
|
||||||
|
GetLogger(logger)->sinks().push_back(sink);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
detail::GetDefaultSinks().push_back(sink);
|
||||||
|
spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger)
|
||||||
|
{
|
||||||
|
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
|
||||||
|
sink->set_level(level);
|
||||||
|
if(!logger.empty())
|
||||||
|
GetLogger(logger)->sinks().push_back(sink);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
detail::GetDefaultSinks().push_back(sink);
|
||||||
|
spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearLoggingSinks(const std::string& logger)
|
||||||
|
{
|
||||||
|
if(!logger.empty())
|
||||||
|
GetLogger(logger)->sinks().clear();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
detail::GetDefaultSinks().clear();
|
||||||
|
spdlog::details::registry::instance().apply_all([](auto logger) { logger->sinks().clear(); });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger)
|
||||||
|
{
|
||||||
|
if(!logger.empty())
|
||||||
|
GetLogger(logger)->flush_on(level);
|
||||||
|
else
|
||||||
|
spdlog::flush_on(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // NETGEN_USE_SPDLOG
|
||||||
|
|
||||||
|
// Dummy functions if no spdlog is available
|
||||||
|
|
||||||
|
std::shared_ptr<spdlog::logger> GetLogger(const std::string& /*unused*/)
|
||||||
|
{
|
||||||
|
return std::make_shared<spdlog::logger>();
|
||||||
|
}
|
||||||
|
void SetLoggingLevel(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {}
|
||||||
|
void AddFileSink(const std::string& /*unused*/, spdlog::level::level_enum /*unused*/,
|
||||||
|
const std::string& /*unused*/)
|
||||||
|
{}
|
||||||
|
void AddConsoleSink(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {}
|
||||||
|
void ClearLoggingSinks(const std::string& /*unused*/) {}
|
||||||
|
void FlushOnLoggingLevel(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {}
|
||||||
|
|
||||||
|
#endif // NETGEN_USE_SPDLOG
|
||||||
|
} //namespace ngcore
|
108
libsrc/core/logging.hpp
Normal file
108
libsrc/core/logging.hpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#ifndef NETGEN_CORE_LOGGING_HPP
|
||||||
|
#define NETGEN_CORE_LOGGING_HPP
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "ngcore_api.hpp"
|
||||||
|
|
||||||
|
#ifdef NETGEN_USE_SPDLOG
|
||||||
|
|
||||||
|
#ifdef NETGEN_LOG_DEBUG
|
||||||
|
#define SPDLOG_DEBUG_ON
|
||||||
|
#endif // NETGEN_LOG_DEBUG
|
||||||
|
|
||||||
|
#include <spdlog/logger.h>
|
||||||
|
#include <spdlog/sinks/sink.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
|
||||||
|
#define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__)
|
||||||
|
|
||||||
|
#else // NETGEN_USE_SPDLOG
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace spdlog
|
||||||
|
{
|
||||||
|
// Dummys if Netgen is compiled with USE_SPDLOG=OFF.
|
||||||
|
namespace level
|
||||||
|
{
|
||||||
|
enum level_enum
|
||||||
|
{
|
||||||
|
trace = 0,
|
||||||
|
debug = 1,
|
||||||
|
info = 2,
|
||||||
|
warn = 3,
|
||||||
|
err = 4,
|
||||||
|
critical = 5,
|
||||||
|
off = 6
|
||||||
|
};
|
||||||
|
} // namespace level
|
||||||
|
|
||||||
|
class logger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void log_helper() {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void log_helper( T t) { std::clog << t; }
|
||||||
|
|
||||||
|
template<typename T, typename ... Args>
|
||||||
|
void log_helper( T t, Args ... args)
|
||||||
|
{
|
||||||
|
std::clog << t;
|
||||||
|
log_helper(args...);
|
||||||
|
std::clog << ", ";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ... Args>
|
||||||
|
void log( level::level_enum level, const char* fmt, Args ... args)
|
||||||
|
{
|
||||||
|
std::clog << level << ": " << fmt << "\t Arguments: ";
|
||||||
|
log_helper(args...);
|
||||||
|
std::clog << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ... Args>
|
||||||
|
void trace( const char* fmt, Args ... args) { log(level::level_enum::trace, fmt, args...); }
|
||||||
|
template<typename ... Args>
|
||||||
|
void debug( const char* fmt, Args ... args) { log(level::level_enum::debug, fmt, args...); }
|
||||||
|
template<typename ... Args>
|
||||||
|
void info( const char* fmt, Args ... args) { log(level::level_enum::info, fmt, args...); }
|
||||||
|
template<typename ... Args>
|
||||||
|
void warn( const char* fmt, Args ... args) { log(level::level_enum::warn, fmt, args...); }
|
||||||
|
template<typename ... Args>
|
||||||
|
void error( const char* fmt, Args ... args) { log(level::level_enum::err, fmt, args...); }
|
||||||
|
template<typename ... Args>
|
||||||
|
void critical( const char* fmt, Args ... args) { log(level::level_enum::critical, fmt, args...); }
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace sinks
|
||||||
|
{
|
||||||
|
class sink {};
|
||||||
|
} // namespace sinks
|
||||||
|
|
||||||
|
} //namespace spdlog
|
||||||
|
|
||||||
|
#define NETGEN_DEBUG_LOG(logger, ...)
|
||||||
|
|
||||||
|
#endif // NETGEN_USE_SPDLOG
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
std::vector<std::shared_ptr<spdlog::sinks::sink>>& GetDefaultSinks();
|
||||||
|
inline std::shared_ptr<spdlog::logger> CreateDefaultLogger(const std::string& name);
|
||||||
|
} //namespace detail
|
||||||
|
|
||||||
|
NGCORE_API std::shared_ptr<spdlog::logger> GetLogger(const std::string& name);
|
||||||
|
NGCORE_API void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name);
|
||||||
|
NGCORE_API void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger);
|
||||||
|
NGCORE_API void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger);
|
||||||
|
NGCORE_API void ClearLoggingSinks(const std::string& logger);
|
||||||
|
NGCORE_API void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger);
|
||||||
|
} // namespace ngcore
|
||||||
|
|
||||||
|
#endif // NETGEN_CORE_LOGGING_HPP
|
@ -2,6 +2,10 @@
|
|||||||
#define NETGEN_CORE_NGCORE_HPP
|
#define NETGEN_CORE_NGCORE_HPP
|
||||||
|
|
||||||
#include "archive.hpp"
|
#include "archive.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
#include "logging.hpp"
|
||||||
|
#include "profiler.hpp"
|
||||||
|
#include "symboltable.hpp"
|
||||||
#include "version.hpp"
|
#include "version.hpp"
|
||||||
|
|
||||||
#endif // NETGEN_CORE_NGCORE_HPP
|
#endif // NETGEN_CORE_NGCORE_HPP
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#define NGCORE_API_EXPORT __declspec(dllexport)
|
#define NGCORE_API_EXPORT __declspec(dllexport)
|
||||||
#define NGCORE_API_IMPORT __declspec(dllimport)
|
#define NGCORE_API_IMPORT __declspec(dllimport)
|
||||||
#else
|
#else
|
||||||
#define NGCORE_API_EXPORT
|
#define NGCORE_API_EXPORT __attribute__((visibility("default")))
|
||||||
#define NGCORE_API_IMPORT
|
#define NGCORE_API_IMPORT __attribute__((visibility("default")))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef NGCORE_EXPORTS
|
#ifdef NGCORE_EXPORTS
|
||||||
@ -15,15 +15,23 @@
|
|||||||
#define NGCORE_API NGCORE_API_IMPORT
|
#define NGCORE_API NGCORE_API_IMPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace ngcore
|
#ifdef __INTEL_COMPILER
|
||||||
{
|
#ifdef WIN32
|
||||||
#if defined(__GNUC__)
|
#define NETGEN_INLINE __forceinline inline
|
||||||
inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); }
|
#define NETGEN_LAMBDA_INLINE
|
||||||
inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); }
|
#else
|
||||||
|
#define NETGEN_INLINE __forceinline inline
|
||||||
|
#define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__))
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
inline bool likely (bool x) { return x; }
|
#ifdef __GNUC__
|
||||||
inline bool unlikely (bool x) { return x; }
|
#define NETGEN_INLINE __attribute__ ((__always_inline__)) inline
|
||||||
|
#define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__))
|
||||||
|
#define NETGEN_VLA
|
||||||
|
#else
|
||||||
|
#define NETGEN_INLINE inline
|
||||||
|
#define NETGEN_LAMBDA_INLINE
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
} // namespace ngcore
|
|
||||||
|
|
||||||
#endif // NETGEN_CORE_NGCORE_API_HPP
|
#endif // NETGEN_CORE_NGCORE_API_HPP
|
||||||
|
668
libsrc/core/paje_trace.cpp
Normal file
668
libsrc/core/paje_trace.cpp
Normal file
@ -0,0 +1,668 @@
|
|||||||
|
#include <algorithm>
|
||||||
|
#include <atomic>
|
||||||
|
#include <iostream>
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#include "archive.hpp" // for Demangle
|
||||||
|
#include "paje_trace.hpp"
|
||||||
|
#include "profiler.hpp"
|
||||||
|
|
||||||
|
static constexpr int MAX_TRACE_LINE_SIZE = 50;
|
||||||
|
extern const char *header;
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
// Produce no traces by default
|
||||||
|
size_t PajeTrace::max_tracefile_size = 11110000;
|
||||||
|
|
||||||
|
// If true, produce variable counting active threads
|
||||||
|
// increases trace by a factor of two
|
||||||
|
bool PajeTrace::trace_thread_counter = true;
|
||||||
|
bool PajeTrace::trace_threads = true;
|
||||||
|
|
||||||
|
PajeTrace :: PajeTrace(int anthreads, std::string aname)
|
||||||
|
{
|
||||||
|
start_time = GetTimeCounter();
|
||||||
|
|
||||||
|
nthreads = anthreads;
|
||||||
|
tracefile_name = std::move(aname);
|
||||||
|
|
||||||
|
int bytes_per_event=33;
|
||||||
|
max_num_events_per_thread = std::min( static_cast<size_t>(std::numeric_limits<int>::max()), max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7);
|
||||||
|
if(max_num_events_per_thread>0)
|
||||||
|
{
|
||||||
|
logger->info( "Tracefile size = {}MB", max_tracefile_size/1024/1024);
|
||||||
|
logger->info( "Tracing {} events per thread", max_num_events_per_thread , " events per thread");
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.resize(nthreads);
|
||||||
|
int reserve_size = std::min(1000000U, max_num_events_per_thread);
|
||||||
|
for(auto & t : tasks)
|
||||||
|
t.reserve(reserve_size);
|
||||||
|
|
||||||
|
links.resize(nthreads);
|
||||||
|
for(auto & l : links)
|
||||||
|
l.reserve(reserve_size);
|
||||||
|
|
||||||
|
jobs.reserve(reserve_size);
|
||||||
|
timer_events.reserve(reserve_size);
|
||||||
|
|
||||||
|
tracing_enabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PajeTrace :: ~PajeTrace()
|
||||||
|
{
|
||||||
|
if(!tracefile_name.empty())
|
||||||
|
Write(tracefile_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PajeTrace::StopTracing()
|
||||||
|
{
|
||||||
|
if(tracing_enabled && max_num_events_per_thread>0)
|
||||||
|
{
|
||||||
|
logger->warn("Maximum number of traces reached, tracing is stopped now.");
|
||||||
|
}
|
||||||
|
tracing_enabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
class PajeFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void Hue2RGB ( double x, double &r, double &g, double &b )
|
||||||
|
{
|
||||||
|
double d = 1.0/6.0;
|
||||||
|
if(x<d)
|
||||||
|
r=1, g=6*x,b=0;
|
||||||
|
else if (x<2*d)
|
||||||
|
r=1.0-6*(x-d),g=1,b=0;
|
||||||
|
else if (x<3*d)
|
||||||
|
r=0, g=1,b=6*(x-2*d);
|
||||||
|
else if (x<4*d)
|
||||||
|
r=0, g=1-6*(x-3*d),b=1;
|
||||||
|
else if (x<5*d)
|
||||||
|
r=6*(x-4*d), g=0,b=1;
|
||||||
|
else
|
||||||
|
r=1, g=0,b=1-5*(x-d);
|
||||||
|
};
|
||||||
|
|
||||||
|
int alias_counter;
|
||||||
|
|
||||||
|
FILE * ctrace_stream;
|
||||||
|
TTimePoint start_time;
|
||||||
|
std::shared_ptr<spdlog::logger> logger = GetLogger("PajeTrace");
|
||||||
|
|
||||||
|
|
||||||
|
double ConvertTime(TTimePoint t) {
|
||||||
|
// return time in milliseconds as double
|
||||||
|
// return std::chrono::duration<double>(t-start_time).count()*1000.0;
|
||||||
|
// return std::chrono::duration<double>(t-start_time).count() / 2.7e3;
|
||||||
|
return (t-start_time) / 2.7e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum PType
|
||||||
|
{
|
||||||
|
SET_VARIABLE=1,
|
||||||
|
ADD_VARIABLE,
|
||||||
|
SUB_VARIABLE,
|
||||||
|
PUSH_STATE,
|
||||||
|
POP_STATE,
|
||||||
|
START_LINK,
|
||||||
|
STOP_LINK
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PajeEvent
|
||||||
|
{
|
||||||
|
PajeEvent( int aevent_type, double atime, int atype, int acontainer, double avar_value )
|
||||||
|
: time(atime), var_value(avar_value), event_type(aevent_type), type(atype), container(acontainer)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue = 0, int aid = 0, bool avalue_is_alias = true )
|
||||||
|
: time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), id(aid), value_is_alias(avalue_is_alias)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue, int astart_container, int akey )
|
||||||
|
: time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), start_container(astart_container), id(akey)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
double time;
|
||||||
|
double var_value = 0.0;
|
||||||
|
int event_type;
|
||||||
|
int type;
|
||||||
|
int container;
|
||||||
|
int value = 0;
|
||||||
|
int start_container = 0;
|
||||||
|
int id = 0;
|
||||||
|
bool value_is_alias = true;
|
||||||
|
|
||||||
|
bool operator < (const PajeEvent & other) const {
|
||||||
|
// Same start and stop times can occur for very small tasks -> take "starting" events first (eg. PajePushState before PajePopState)
|
||||||
|
if(time == other.time)
|
||||||
|
return event_type < other.event_type;
|
||||||
|
return (time < other.time);
|
||||||
|
}
|
||||||
|
|
||||||
|
int write(FILE *stream)
|
||||||
|
{
|
||||||
|
const int &key = id;
|
||||||
|
const int &end_container = start_container;
|
||||||
|
switch(event_type)
|
||||||
|
{
|
||||||
|
case PajeSetVariable:
|
||||||
|
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); // NOLINT
|
||||||
|
case PajeAddVariable:
|
||||||
|
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); // NOLINT
|
||||||
|
case PajeSubVariable:
|
||||||
|
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSubVariable, time, type, container, var_value ); // NOLINT
|
||||||
|
case PajePushState:
|
||||||
|
if(value_is_alias)
|
||||||
|
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT
|
||||||
|
else
|
||||||
|
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT
|
||||||
|
case PajePopState:
|
||||||
|
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); // NOLINT
|
||||||
|
case PajeStartLink:
|
||||||
|
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeStartLink, time, type, container, value, start_container, key ); // NOLINT
|
||||||
|
case PajeEndLink:
|
||||||
|
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeEndLink, time, type, container, value, end_container, key ); // NOLINT
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<PajeEvent> events;
|
||||||
|
|
||||||
|
public:
|
||||||
|
PajeFile() = delete;
|
||||||
|
PajeFile(const PajeFile &) = delete;
|
||||||
|
PajeFile(PajeFile &&) = delete;
|
||||||
|
void operator=(const PajeFile &) = delete;
|
||||||
|
void operator=(PajeFile &&) = delete;
|
||||||
|
|
||||||
|
PajeFile( const std::string & filename, TTimePoint astart_time )
|
||||||
|
{
|
||||||
|
start_time = astart_time;
|
||||||
|
ctrace_stream = fopen (filename.c_str(),"w"); // NOLINT
|
||||||
|
fprintf(ctrace_stream, "%s", header ); // NOLINT
|
||||||
|
alias_counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
~PajeFile()
|
||||||
|
{
|
||||||
|
fclose (ctrace_stream); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
int DefineContainerType ( int parent_type, const std::string & name )
|
||||||
|
{
|
||||||
|
int alias = ++alias_counter;
|
||||||
|
if(parent_type!=0)
|
||||||
|
fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT
|
||||||
|
else
|
||||||
|
fprintf( ctrace_stream, "%d\ta%d\t%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); // NOLINT
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DefineVariableType ( int container_type, const std::string & name )
|
||||||
|
{
|
||||||
|
int alias = ++alias_counter;
|
||||||
|
fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"1.0 1.0 1.0\"\n", PajeDefineVariableType, alias, container_type, name.c_str() ); // NOLINT
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DefineStateType ( int type, const std::string & name )
|
||||||
|
{
|
||||||
|
int alias = ++alias_counter;
|
||||||
|
fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineStateType, alias, type, name.c_str() ); // NOLINT
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
// int DefineEventType ()
|
||||||
|
// {
|
||||||
|
// Write("event not implemented");
|
||||||
|
// }
|
||||||
|
|
||||||
|
int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, const std::string & name)
|
||||||
|
{
|
||||||
|
int alias = ++alias_counter;
|
||||||
|
fprintf( ctrace_stream, "%d\ta%d\ta%d\ta%d\ta%d\t\"%s\"\n", PajeDefineLinkType, alias, parent_container_type, start_container_type, stop_container_type, name.c_str() ); // NOLINT
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
int DefineEntityValue (int type, const std::string & name, double hue = -1)
|
||||||
|
{
|
||||||
|
if(hue==-1)
|
||||||
|
{
|
||||||
|
std::hash<std::string> shash;
|
||||||
|
size_t h = shash(name);
|
||||||
|
h ^= h>>32U;
|
||||||
|
h = static_cast<uint32_t>(h);
|
||||||
|
hue = h*1.0/std::numeric_limits<uint32_t>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
int alias = ++alias_counter;
|
||||||
|
double r,g,b;
|
||||||
|
Hue2RGB( hue, r, g, b );
|
||||||
|
fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\t\"%.15g %.15g %.15g\"\n", PajeDefineEntityValue, alias, type, name.c_str(), r,g,b ); // NOLINT
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
|
||||||
|
int CreateContainer ( int type, int parent, const std::string & name )
|
||||||
|
{
|
||||||
|
int alias = ++alias_counter;
|
||||||
|
if(parent!=0)
|
||||||
|
fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\ta%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT
|
||||||
|
else
|
||||||
|
fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\t%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); // NOLINT
|
||||||
|
return alias;
|
||||||
|
}
|
||||||
|
void DestroyContainer ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void SetVariable (TTimePoint time, int type, int container, double value )
|
||||||
|
{
|
||||||
|
events.emplace_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddVariable (TTimePoint time, int type, int container, double value )
|
||||||
|
{
|
||||||
|
events.emplace_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SubVariable (TTimePoint time, int type, int container, double value )
|
||||||
|
{
|
||||||
|
events.emplace_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetState ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void PushState ( TTimePoint time, int type, int container, int value, int id = 0, bool value_is_alias = true )
|
||||||
|
{
|
||||||
|
events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id, value_is_alias) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void PopState ( TTimePoint time, int type, int container )
|
||||||
|
{
|
||||||
|
events.emplace_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResetState ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void StartLink ( TTimePoint time, int type, int container, int value, int start_container, int key )
|
||||||
|
{
|
||||||
|
events.emplace_back( PajeEvent( PajeStartLink, ConvertTime(time), type, container, value, start_container, key ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void EndLink ( TTimePoint time, int type, int container, int value, int end_container, int key )
|
||||||
|
{
|
||||||
|
events.emplace_back( PajeEvent( PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void NewEvent ()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void WriteEvents()
|
||||||
|
{
|
||||||
|
logger->info("Sorting traces...");
|
||||||
|
std::sort (events.begin(), events.end());
|
||||||
|
|
||||||
|
logger->info("Writing traces... ");
|
||||||
|
for (auto & event : events)
|
||||||
|
{
|
||||||
|
event.write( ctrace_stream );
|
||||||
|
// fprintf( ctrace_stream, "%s", buf ); // NOLINT
|
||||||
|
}
|
||||||
|
logger->info("Done");
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PajeDefineContainerType = 0,
|
||||||
|
PajeDefineVariableType = 1,
|
||||||
|
PajeDefineStateType = 2,
|
||||||
|
PajeDefineEventType = 3,
|
||||||
|
PajeDefineLinkType = 4,
|
||||||
|
PajeDefineEntityValue = 5,
|
||||||
|
PajeCreateContainer = 6,
|
||||||
|
PajeDestroyContainer = 7,
|
||||||
|
PajeSetVariable = 8,
|
||||||
|
PajeAddVariable = 9,
|
||||||
|
PajeSubVariable = 10,
|
||||||
|
PajeSetState = 11,
|
||||||
|
PajePushState = 12,
|
||||||
|
PajePopState = 13,
|
||||||
|
PajeResetState = 14,
|
||||||
|
PajeStartLink = 15,
|
||||||
|
PajeEndLink = 16,
|
||||||
|
PajeNewEvent = 17
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
NGCORE_API PajeTrace *trace;
|
||||||
|
|
||||||
|
void PajeTrace::Write( const std::string & filename )
|
||||||
|
{
|
||||||
|
int n_events = jobs.size() + timer_events.size();
|
||||||
|
for(auto & vtasks : tasks)
|
||||||
|
n_events += vtasks.size();
|
||||||
|
|
||||||
|
logger->info("{} events traced", n_events);
|
||||||
|
|
||||||
|
if(n_events==0)
|
||||||
|
{
|
||||||
|
logger->info("No data traced, skip writing trace file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!tracing_enabled)
|
||||||
|
{
|
||||||
|
logger->warn("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
PajeFile paje(filename, start_time);
|
||||||
|
|
||||||
|
const int container_type_task_manager = paje.DefineContainerType( 0, "Task Manager" );
|
||||||
|
const int container_type_node = paje.DefineContainerType( container_type_task_manager, "Node");
|
||||||
|
const int container_type_thread = paje.DefineContainerType( container_type_task_manager, "Thread");
|
||||||
|
const int container_type_timer = container_type_thread; //paje.DefineContainerType( container_type_task_manager, "Timers");
|
||||||
|
const int container_type_jobs = paje.DefineContainerType( container_type_task_manager, "Jobs");
|
||||||
|
|
||||||
|
const int state_type_job = paje.DefineStateType( container_type_jobs, "Job" );
|
||||||
|
const int state_type_task = paje.DefineStateType( container_type_thread, "Task" );
|
||||||
|
const int state_type_timer = paje.DefineStateType( container_type_timer, "Timer state" );
|
||||||
|
|
||||||
|
const int variable_type_active_threads = paje.DefineVariableType( container_type_jobs, "Active threads" );
|
||||||
|
|
||||||
|
const int container_task_manager = paje.CreateContainer( container_type_task_manager, 0, "The task manager" );
|
||||||
|
const int container_jobs = paje.CreateContainer( container_type_jobs, container_task_manager, "Jobs" );
|
||||||
|
paje.SetVariable( start_time, variable_type_active_threads, container_jobs, 0.0 );
|
||||||
|
|
||||||
|
const int num_nodes = 1; //task_manager ? task_manager->GetNumNodes() : 1;
|
||||||
|
|
||||||
|
std::vector<int> container_nodes;
|
||||||
|
container_nodes.reserve(num_nodes);
|
||||||
|
for(int i=0; i<num_nodes; i++)
|
||||||
|
container_nodes.emplace_back( paje.CreateContainer( container_type_node, container_task_manager, "Node " + ToString(i)) );
|
||||||
|
|
||||||
|
std::vector <int> thread_aliases;
|
||||||
|
thread_aliases.reserve(nthreads);
|
||||||
|
if(trace_threads)
|
||||||
|
for (int i=0; i<nthreads; i++)
|
||||||
|
{
|
||||||
|
auto name = "Timer level " + ToString(i);
|
||||||
|
thread_aliases.emplace_back( paje.CreateContainer( container_type_thread, container_nodes[i*num_nodes/nthreads], name ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<const std::type_info *, int> job_map;
|
||||||
|
std::map<const std::type_info *, int> job_task_map;
|
||||||
|
|
||||||
|
for(Job & j : jobs)
|
||||||
|
if(job_map.find(j.type) == job_map.end())
|
||||||
|
{
|
||||||
|
std::string name = Demangle(j.type->name());
|
||||||
|
job_map[j.type] = paje.DefineEntityValue( state_type_job, name, -1 );
|
||||||
|
job_task_map[j.type] = paje.DefineEntityValue( state_type_task, name, -1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Job & j : jobs)
|
||||||
|
{
|
||||||
|
paje.PushState( j.start_time, state_type_job, container_jobs, job_map[j.type] );
|
||||||
|
paje.PopState( j.stop_time, state_type_job, container_jobs );
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<int> timer_ids;
|
||||||
|
std::map<int,int> timer_aliases;
|
||||||
|
|
||||||
|
for(auto & event : timer_events)
|
||||||
|
timer_ids.insert(event.timer_id);
|
||||||
|
|
||||||
|
|
||||||
|
for(auto & vtasks : tasks)
|
||||||
|
for (Task & t : vtasks)
|
||||||
|
if(t.id_type==Task::ID_TIMER)
|
||||||
|
timer_ids.insert(t.id);
|
||||||
|
|
||||||
|
for(auto id : timer_ids)
|
||||||
|
timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id), -1 );
|
||||||
|
|
||||||
|
int timerdepth = 0;
|
||||||
|
int maxdepth = 0;
|
||||||
|
for(auto & event : timer_events)
|
||||||
|
{
|
||||||
|
if(event.is_start)
|
||||||
|
{
|
||||||
|
timerdepth++;
|
||||||
|
maxdepth = timerdepth>maxdepth ? timerdepth : maxdepth;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
timerdepth--;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int> timer_container_aliases;
|
||||||
|
timer_container_aliases.resize(maxdepth);
|
||||||
|
for(int i=0; i<maxdepth; i++)
|
||||||
|
{
|
||||||
|
auto name = "Timer level " + ToString(i);
|
||||||
|
timer_container_aliases[i] = paje.CreateContainer( container_type_timer, container_task_manager, name );
|
||||||
|
}
|
||||||
|
|
||||||
|
timerdepth = 0;
|
||||||
|
for(auto & event : timer_events)
|
||||||
|
{
|
||||||
|
if(event.is_start)
|
||||||
|
paje.PushState( event.time, state_type_timer, timer_container_aliases[timerdepth++], timer_aliases[event.timer_id] );
|
||||||
|
else
|
||||||
|
paje.PopState( event.time, state_type_timer, timer_container_aliases[--timerdepth] );
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto & vtasks : tasks)
|
||||||
|
{
|
||||||
|
for (Task & t : vtasks) {
|
||||||
|
int value_id = t.id;
|
||||||
|
|
||||||
|
switch(t.id_type)
|
||||||
|
{
|
||||||
|
case Task::ID_JOB:
|
||||||
|
value_id = job_task_map[jobs[t.id-1].type];
|
||||||
|
if(trace_thread_counter)
|
||||||
|
{
|
||||||
|
paje.AddVariable( t.start_time, variable_type_active_threads, container_jobs, 1.0 );
|
||||||
|
paje.SubVariable( t.stop_time, variable_type_active_threads, container_jobs, 1.0 );
|
||||||
|
}
|
||||||
|
if(trace_threads)
|
||||||
|
{
|
||||||
|
paje.PushState( t.start_time, state_type_task, thread_aliases[t.thread_id], value_id, t.additional_value, true );
|
||||||
|
paje.PopState( t.stop_time, state_type_task, thread_aliases[t.thread_id] );
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Task::ID_TIMER:
|
||||||
|
value_id = timer_aliases[t.id];
|
||||||
|
paje.PushState( t.start_time, state_type_timer, thread_aliases[t.thread_id], value_id, t.additional_value, true );
|
||||||
|
paje.PopState( t.stop_time, state_type_timer, thread_aliases[t.thread_id] );
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
paje.PushState( t.start_time, state_type_task, thread_aliases[t.thread_id], value_id, t.additional_value, false );
|
||||||
|
paje.PopState( t.stop_time, state_type_task, thread_aliases[t.thread_id] );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Merge link event
|
||||||
|
int nlinks = 0;
|
||||||
|
for( auto & l : links)
|
||||||
|
nlinks += l.size();
|
||||||
|
|
||||||
|
std::vector<ThreadLink> links_merged;
|
||||||
|
links_merged.reserve(nlinks);
|
||||||
|
std::vector<unsigned int> pos(nthreads);
|
||||||
|
|
||||||
|
int nlinks_merged = 0;
|
||||||
|
while(nlinks_merged < nlinks)
|
||||||
|
{
|
||||||
|
int minpos = -1;
|
||||||
|
TTimePoint mintime = -1;
|
||||||
|
for (int t = 0; t<nthreads; t++)
|
||||||
|
{
|
||||||
|
if(pos[t] < links[t].size() && (minpos==-1 || links[t][pos[t]].time < mintime))
|
||||||
|
{
|
||||||
|
minpos = t;
|
||||||
|
mintime = links[t][pos[t]].time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
links_merged.push_back( links[minpos][pos[minpos]] );
|
||||||
|
pos[minpos]++;
|
||||||
|
nlinks_merged++;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<ThreadLink> started_links;
|
||||||
|
|
||||||
|
int link_type = paje.DefineLinkType(container_type_node, container_type_thread, container_type_thread, "links");
|
||||||
|
|
||||||
|
// match links
|
||||||
|
for ( auto & l : links_merged )
|
||||||
|
{
|
||||||
|
if(l.is_start)
|
||||||
|
{
|
||||||
|
started_links.push_back(l);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int i = 0;
|
||||||
|
while(i<started_links.size())
|
||||||
|
{
|
||||||
|
while(i<started_links.size() && started_links[i].key == l.key)
|
||||||
|
{
|
||||||
|
ThreadLink & sl = started_links[i];
|
||||||
|
// Avoid links on same thread
|
||||||
|
if(sl.thread_id != l.thread_id)
|
||||||
|
{
|
||||||
|
paje.StartLink( sl.time, link_type, container_nodes[sl.thread_id*num_nodes/nthreads], l.key, thread_aliases[sl.thread_id], l.key);
|
||||||
|
paje.EndLink( l.time, link_type, container_nodes[l.thread_id*num_nodes/nthreads], l.key, thread_aliases[l.thread_id], l.key);
|
||||||
|
}
|
||||||
|
started_links.erase(started_links.begin()+i);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
paje.WriteEvents();
|
||||||
|
}
|
||||||
|
} // namespace ngcore
|
||||||
|
|
||||||
|
const char *header =
|
||||||
|
"%EventDef PajeDefineContainerType 0 \n"
|
||||||
|
"% Alias string \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Name string \n"
|
||||||
|
"%EndEventDef \n"
|
||||||
|
"%EventDef PajeDefineVariableType 1 \n"
|
||||||
|
"% Alias string \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Name string \n"
|
||||||
|
"% Color color \n"
|
||||||
|
"%EndEventDef \n"
|
||||||
|
"%EventDef PajeDefineStateType 2 \n"
|
||||||
|
"% Alias string \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Name string \n"
|
||||||
|
"%EndEventDef \n"
|
||||||
|
"%EventDef PajeDefineEventType 3 \n"
|
||||||
|
"% Alias string \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Name string \n"
|
||||||
|
"% Color color \n"
|
||||||
|
"%EndEventDef \n"
|
||||||
|
"%EventDef PajeDefineLinkType 4 \n"
|
||||||
|
"% Alias string \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% StartContainerType string \n"
|
||||||
|
"% EndContainerType string \n"
|
||||||
|
"% Name string \n"
|
||||||
|
"%EndEventDef \n"
|
||||||
|
"%EventDef PajeDefineEntityValue 5 \n"
|
||||||
|
"% Alias string \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Name string \n"
|
||||||
|
"% Color color \n"
|
||||||
|
"%EndEventDef \n"
|
||||||
|
"%EventDef PajeCreateContainer 6 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Alias string \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Name string \n"
|
||||||
|
"%EndEventDef \n"
|
||||||
|
"%EventDef PajeDestroyContainer 7 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Name string \n"
|
||||||
|
"%EndEventDef \n"
|
||||||
|
"%EventDef PajeSetVariable 8 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Value double \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajeAddVariable 9 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Value double \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajeSubVariable 10 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Value double \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajeSetState 11 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Value string \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajePushState 12 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Value string \n"
|
||||||
|
"% Id string \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajePopState 13 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajeResetState 14 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajeStartLink 15 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Value string \n"
|
||||||
|
"% StartContainer string \n"
|
||||||
|
"% Key string \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajeEndLink 16 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Value string \n"
|
||||||
|
"% EndContainer string \n"
|
||||||
|
"% Key string \n"
|
||||||
|
"%EndEventDef\n"
|
||||||
|
"%EventDef PajeNewEvent 17 \n"
|
||||||
|
"% Time date \n"
|
||||||
|
"% Type string \n"
|
||||||
|
"% Container string \n"
|
||||||
|
"% Value string \n"
|
||||||
|
"%EndEventDef\n";
|
190
libsrc/core/paje_trace.hpp
Normal file
190
libsrc/core/paje_trace.hpp
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
#ifndef NETGEN_CORE_PAJE_TRACE_HPP
|
||||||
|
#define NETGEN_CORE_PAJE_TRACE_HPP
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "logging.hpp" // for logger
|
||||||
|
#include "ngcore_api.hpp" // for NGCORE_API
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
|
||||||
|
extern NGCORE_API class PajeTrace *trace;
|
||||||
|
class PajeTrace
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using TClock = std::chrono::system_clock;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<spdlog::logger> logger = GetLogger("PajeTrace");
|
||||||
|
private:
|
||||||
|
NGCORE_API static size_t max_tracefile_size;
|
||||||
|
NGCORE_API static bool trace_thread_counter;
|
||||||
|
NGCORE_API static bool trace_threads;
|
||||||
|
|
||||||
|
bool tracing_enabled;
|
||||||
|
TTimePoint start_time;
|
||||||
|
int nthreads;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Approximate number of events to trace. Tracing will
|
||||||
|
// be stopped if any thread reaches this number of events
|
||||||
|
unsigned int max_num_events_per_thread;
|
||||||
|
|
||||||
|
static void SetTraceThreads( bool atrace_threads )
|
||||||
|
{
|
||||||
|
trace_threads = atrace_threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetTraceThreadCounter( bool trace_threads )
|
||||||
|
{
|
||||||
|
trace_thread_counter = trace_threads;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void SetMaxTracefileSize( size_t max_size )
|
||||||
|
{
|
||||||
|
max_tracefile_size = max_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tracefile_name;
|
||||||
|
|
||||||
|
struct Job
|
||||||
|
{
|
||||||
|
int job_id;
|
||||||
|
const std::type_info *type;
|
||||||
|
TTimePoint start_time;
|
||||||
|
TTimePoint stop_time;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Task
|
||||||
|
{
|
||||||
|
int thread_id;
|
||||||
|
|
||||||
|
int id;
|
||||||
|
int id_type;
|
||||||
|
|
||||||
|
int additional_value;
|
||||||
|
|
||||||
|
TTimePoint start_time;
|
||||||
|
TTimePoint stop_time;
|
||||||
|
|
||||||
|
static constexpr int ID_NONE = -1;
|
||||||
|
static constexpr int ID_JOB = 1;
|
||||||
|
static constexpr int ID_TIMER = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimerEvent
|
||||||
|
{
|
||||||
|
int timer_id;
|
||||||
|
TTimePoint time;
|
||||||
|
bool is_start;
|
||||||
|
int thread_id;
|
||||||
|
|
||||||
|
bool operator < (const TimerEvent & other) const { return time < other.time; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ThreadLink
|
||||||
|
{
|
||||||
|
int thread_id;
|
||||||
|
int key;
|
||||||
|
TTimePoint time;
|
||||||
|
bool is_start;
|
||||||
|
bool operator < (const ThreadLink & other) const { return time < other.time; }
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::vector<Task> > tasks;
|
||||||
|
std::vector<Job> jobs;
|
||||||
|
std::vector<TimerEvent> timer_events;
|
||||||
|
std::vector<std::vector<ThreadLink> > links;
|
||||||
|
|
||||||
|
public:
|
||||||
|
NGCORE_API void StopTracing();
|
||||||
|
|
||||||
|
PajeTrace() = delete;
|
||||||
|
PajeTrace(const PajeTrace &) = delete;
|
||||||
|
PajeTrace(PajeTrace &&) = delete;
|
||||||
|
NGCORE_API PajeTrace(int anthreads, std::string aname = "");
|
||||||
|
NGCORE_API ~PajeTrace();
|
||||||
|
|
||||||
|
void operator=(const PajeTrace &) = delete;
|
||||||
|
void operator=(PajeTrace &&) = delete;
|
||||||
|
|
||||||
|
void StartTimer(int timer_id)
|
||||||
|
{
|
||||||
|
if(!tracing_enabled) return;
|
||||||
|
if(unlikely(timer_events.size() == max_num_events_per_thread))
|
||||||
|
StopTracing();
|
||||||
|
timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), true});
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopTimer(int timer_id)
|
||||||
|
{
|
||||||
|
if(!tracing_enabled) return;
|
||||||
|
if(unlikely(timer_events.size() == max_num_events_per_thread))
|
||||||
|
StopTracing();
|
||||||
|
timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), false});
|
||||||
|
}
|
||||||
|
|
||||||
|
NETGEN_INLINE int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1)
|
||||||
|
{
|
||||||
|
if(!tracing_enabled) return -1;
|
||||||
|
if(!trace_threads && !trace_thread_counter) return -1;
|
||||||
|
if(unlikely(tasks[thread_id].size() == max_num_events_per_thread))
|
||||||
|
StopTracing();
|
||||||
|
int task_num = tasks[thread_id].size();
|
||||||
|
tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter()} );
|
||||||
|
return task_num;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopTask(int thread_id, int task_num)
|
||||||
|
{
|
||||||
|
if(!trace_threads && !trace_thread_counter) return;
|
||||||
|
if(task_num>=0)
|
||||||
|
tasks[thread_id][task_num].stop_time = GetTimeCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetTask(int thread_id, int task_num, int additional_value) {
|
||||||
|
if(!trace_threads && !trace_thread_counter) return;
|
||||||
|
if(task_num>=0)
|
||||||
|
tasks[thread_id][task_num].additional_value = additional_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartJob(int job_id, const std::type_info & type)
|
||||||
|
{
|
||||||
|
if(!tracing_enabled) return;
|
||||||
|
if(jobs.size() == max_num_events_per_thread)
|
||||||
|
StopTracing();
|
||||||
|
jobs.push_back( Job{job_id, &type, GetTimeCounter()} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopJob()
|
||||||
|
{
|
||||||
|
if(tracing_enabled)
|
||||||
|
jobs.back().stop_time = GetTimeCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartLink(int thread_id, int key)
|
||||||
|
{
|
||||||
|
if(!tracing_enabled) return;
|
||||||
|
if(links[thread_id].size() == max_num_events_per_thread)
|
||||||
|
StopTracing();
|
||||||
|
links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), true} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void StopLink(int thread_id, int key)
|
||||||
|
{
|
||||||
|
if(!tracing_enabled) return;
|
||||||
|
if(links[thread_id].size() == max_num_events_per_thread)
|
||||||
|
StopTracing();
|
||||||
|
links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write( const std::string & filename );
|
||||||
|
|
||||||
|
};
|
||||||
|
} // namespace ngcore
|
||||||
|
|
||||||
|
#endif // NETGEN_CORE_PAJE_TRACE_HPP
|
117
libsrc/core/profiler.cpp
Normal file
117
libsrc/core/profiler.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
#include "profiler.hpp"
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
std::vector<NgProfiler::TimerVal> NgProfiler::timers(NgProfiler::SIZE); // NOLINT
|
||||||
|
|
||||||
|
std::string NgProfiler::filename;
|
||||||
|
|
||||||
|
size_t NgProfiler::dummy_thread_times[NgProfiler::SIZE];
|
||||||
|
size_t * NgProfiler::thread_times = NgProfiler::dummy_thread_times; // NOLINT
|
||||||
|
size_t NgProfiler::dummy_thread_flops[NgProfiler::SIZE];
|
||||||
|
size_t * NgProfiler::thread_flops = NgProfiler::dummy_thread_flops; // NOLINT
|
||||||
|
|
||||||
|
std::shared_ptr<spdlog::logger> NgProfiler::logger = GetLogger("Profiler"); // NOLINT
|
||||||
|
|
||||||
|
NgProfiler :: NgProfiler()
|
||||||
|
{
|
||||||
|
for (auto & t : timers)
|
||||||
|
{
|
||||||
|
t.tottime = 0.0;
|
||||||
|
t.usedcounter = 0;
|
||||||
|
t.flops = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NgProfiler :: ~NgProfiler()
|
||||||
|
{
|
||||||
|
if (filename.length())
|
||||||
|
{
|
||||||
|
logger->debug( "write profile to file {}", filename );
|
||||||
|
FILE *prof = fopen(filename.c_str(),"w"); // NOLINT
|
||||||
|
Print (prof);
|
||||||
|
fclose(prof); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getenv ("NGPROFILE"))
|
||||||
|
{
|
||||||
|
std::string filename = "netgen.prof";
|
||||||
|
#ifdef PARALLEL
|
||||||
|
filename += "."+ToString(id);
|
||||||
|
#endif
|
||||||
|
if (id == 0) logger->info( "write profile to file {}", filename );
|
||||||
|
FILE *prof = fopen(filename.c_str(),"w"); // NOLINT
|
||||||
|
Print (prof);
|
||||||
|
fclose(prof); // NOLINT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void NgProfiler :: Print (FILE * prof)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
for (auto & t : timers)
|
||||||
|
{
|
||||||
|
if (t.count != 0 || t.usedcounter != 0)
|
||||||
|
{
|
||||||
|
fprintf(prof,"job %3i calls %8li, time %6.4f sec",i,t.count,t.tottime); // NOLINT
|
||||||
|
if(t.flops != 0.0)
|
||||||
|
fprintf(prof,", MFlops = %6.2f",t.flops / (t.tottime) * 1e-6); // NOLINT
|
||||||
|
if(t.loads != 0.0)
|
||||||
|
fprintf(prof,", MLoads = %6.2f",t.loads / (t.tottime) * 1e-6); // NOLINT
|
||||||
|
if(t.stores != 0.0)
|
||||||
|
fprintf(prof,", MStores = %6.2f",t.stores / (t.tottime) * 1e-6); // NOLINT
|
||||||
|
if(t.usedcounter)
|
||||||
|
fprintf(prof," %s",t.name.c_str()); // NOLINT
|
||||||
|
fprintf(prof,"\n"); // NOLINT
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int NgProfiler :: CreateTimer (const std::string & name)
|
||||||
|
{
|
||||||
|
static std::mutex createtimer_mutex;
|
||||||
|
int nr = -1;
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(createtimer_mutex);
|
||||||
|
for (int i = SIZE-1; i > 0; i--)
|
||||||
|
{
|
||||||
|
auto & t = timers[i];
|
||||||
|
if (!t.usedcounter)
|
||||||
|
{
|
||||||
|
t.usedcounter = 1;
|
||||||
|
t.name = name;
|
||||||
|
nr = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (nr > -1) return nr;
|
||||||
|
static bool first_overflow = true;
|
||||||
|
if (first_overflow)
|
||||||
|
{
|
||||||
|
first_overflow = false;
|
||||||
|
NgProfiler::logger->warn("no more timer available, reusing last one");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NgProfiler :: Reset ()
|
||||||
|
{
|
||||||
|
for(auto & t : timers)
|
||||||
|
{
|
||||||
|
t.tottime = 0.0;
|
||||||
|
t.count = 0;
|
||||||
|
t.flops = 0.0;
|
||||||
|
t.loads = 0;
|
||||||
|
t.stores = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NgProfiler prof; // NOLINT
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ngcore
|
304
libsrc/core/profiler.hpp
Normal file
304
libsrc/core/profiler.hpp
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
#ifndef NETGEN_CORE_PROFILER_HPP
|
||||||
|
#define NETGEN_CORE_PROFILER_HPP
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "logging.hpp"
|
||||||
|
#include "paje_trace.hpp"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
class NgProfiler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/// maximal number of timers
|
||||||
|
enum { SIZE = 8*1024 };
|
||||||
|
|
||||||
|
struct TimerVal
|
||||||
|
{
|
||||||
|
TimerVal() = default;
|
||||||
|
|
||||||
|
double tottime = 0.0;
|
||||||
|
double starttime = 0.0;
|
||||||
|
double flops = 0.0;
|
||||||
|
double loads = 0.0;
|
||||||
|
double stores = 0.0;
|
||||||
|
long count = 0;
|
||||||
|
std::string name = "";
|
||||||
|
int usedcounter = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
NGCORE_API static std::vector<TimerVal> timers;
|
||||||
|
|
||||||
|
NGCORE_API static TTimePoint * thread_times;
|
||||||
|
NGCORE_API static TTimePoint * thread_flops;
|
||||||
|
NGCORE_API static std::shared_ptr<spdlog::logger> logger;
|
||||||
|
NGCORE_API static size_t dummy_thread_times[NgProfiler::SIZE];
|
||||||
|
NGCORE_API static size_t dummy_thread_flops[NgProfiler::SIZE];
|
||||||
|
private:
|
||||||
|
|
||||||
|
NGCORE_API static std::string filename;
|
||||||
|
public:
|
||||||
|
NgProfiler();
|
||||||
|
~NgProfiler();
|
||||||
|
|
||||||
|
NgProfiler(const NgProfiler &) = delete;
|
||||||
|
NgProfiler(NgProfiler &&) = delete;
|
||||||
|
void operator=(const NgProfiler &) = delete;
|
||||||
|
void operator=(NgProfiler &&) = delete;
|
||||||
|
|
||||||
|
static void SetFileName (const std::string & afilename) { filename = afilename; }
|
||||||
|
|
||||||
|
/// create new timer, use integer index
|
||||||
|
NGCORE_API static int CreateTimer (const std::string & name);
|
||||||
|
|
||||||
|
NGCORE_API static void Reset ();
|
||||||
|
|
||||||
|
|
||||||
|
/// start timer of index nr
|
||||||
|
static void StartTimer (int nr)
|
||||||
|
{
|
||||||
|
timers[nr].starttime = WallTime(); timers[nr].count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// stop timer of index nr
|
||||||
|
static void StopTimer (int nr)
|
||||||
|
{
|
||||||
|
timers[nr].tottime += WallTime()-timers[nr].starttime;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void StartThreadTimer (size_t nr, size_t tid)
|
||||||
|
{
|
||||||
|
thread_times[tid*SIZE+nr] -= GetTimeCounter(); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
static void StopThreadTimer (size_t nr, size_t tid)
|
||||||
|
{
|
||||||
|
thread_times[tid*SIZE+nr] += GetTimeCounter(); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
static void AddThreadFlops (size_t nr, size_t tid, size_t flops)
|
||||||
|
{
|
||||||
|
thread_flops[tid*SIZE+nr] += flops; // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
/// if you know number of flops, provide them to obtain the MFlop - rate
|
||||||
|
static void AddFlops (int nr, double aflops) { timers[nr].flops += aflops; }
|
||||||
|
static void AddLoads (int nr, double aloads) { timers[nr].loads += aloads; }
|
||||||
|
static void AddStores (int nr, double astores) { timers[nr].stores += astores; }
|
||||||
|
|
||||||
|
static int GetNr (const std::string & name)
|
||||||
|
{
|
||||||
|
for (int i = SIZE-1; i >= 0; i--)
|
||||||
|
if (timers[i].name == name)
|
||||||
|
return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double GetTime (int nr)
|
||||||
|
{
|
||||||
|
return timers[nr].tottime;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double GetTime (const std::string & name)
|
||||||
|
{
|
||||||
|
for (int i = SIZE-1; i >= 0; i--)
|
||||||
|
if (timers[i].name == name)
|
||||||
|
return GetTime (i);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long int GetCounts (int nr)
|
||||||
|
{
|
||||||
|
return timers[nr].count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static double GetFlops (int nr)
|
||||||
|
{
|
||||||
|
return timers[nr].flops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// change name
|
||||||
|
static void SetName (int nr, const std::string & name) { timers[nr].name = name; }
|
||||||
|
static std::string GetName (int nr) { return timers[nr].name; }
|
||||||
|
/// print profile
|
||||||
|
NGCORE_API static void Print (FILE * prof);
|
||||||
|
|
||||||
|
class RegionTimer
|
||||||
|
{
|
||||||
|
int nr;
|
||||||
|
public:
|
||||||
|
/// start timer
|
||||||
|
RegionTimer (int anr) : nr(anr) { NgProfiler::StartTimer(nr); }
|
||||||
|
/// stop timer
|
||||||
|
~RegionTimer () { NgProfiler::StopTimer(nr); }
|
||||||
|
|
||||||
|
RegionTimer() = delete;
|
||||||
|
RegionTimer(const RegionTimer &) = delete;
|
||||||
|
RegionTimer(RegionTimer &&) = delete;
|
||||||
|
void operator=(const RegionTimer &) = delete;
|
||||||
|
void operator=(RegionTimer &&) = delete;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class NGCORE_API Timer
|
||||||
|
{
|
||||||
|
int timernr;
|
||||||
|
int priority;
|
||||||
|
public:
|
||||||
|
Timer (const std::string & name, int apriority = 1)
|
||||||
|
: priority(apriority)
|
||||||
|
{
|
||||||
|
timernr = NgProfiler::CreateTimer (name);
|
||||||
|
}
|
||||||
|
void SetName (const std::string & name)
|
||||||
|
{
|
||||||
|
NgProfiler::SetName (timernr, name);
|
||||||
|
}
|
||||||
|
void Start ()
|
||||||
|
{
|
||||||
|
if (priority <= 2)
|
||||||
|
NgProfiler::StartTimer (timernr);
|
||||||
|
if (priority <= 1)
|
||||||
|
if(trace) trace->StartTimer(timernr);
|
||||||
|
}
|
||||||
|
void Stop ()
|
||||||
|
{
|
||||||
|
if (priority <= 2)
|
||||||
|
NgProfiler::StopTimer (timernr);
|
||||||
|
if (priority <= 1)
|
||||||
|
if(trace) trace->StopTimer(timernr);
|
||||||
|
}
|
||||||
|
void AddFlops (double aflops)
|
||||||
|
{
|
||||||
|
if (priority <= 2)
|
||||||
|
NgProfiler::AddFlops (timernr, aflops);
|
||||||
|
}
|
||||||
|
|
||||||
|
double GetTime () { return NgProfiler::GetTime(timernr); }
|
||||||
|
long int GetCounts () { return NgProfiler::GetCounts(timernr); }
|
||||||
|
double GetMFlops ()
|
||||||
|
{ return NgProfiler::GetFlops(timernr)
|
||||||
|
/ NgProfiler::GetTime(timernr) * 1e-6; }
|
||||||
|
operator int () { return timernr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Timer object.
|
||||||
|
Start / stop timer at constructor / destructor.
|
||||||
|
*/
|
||||||
|
class RegionTimer
|
||||||
|
{
|
||||||
|
Timer & timer;
|
||||||
|
public:
|
||||||
|
/// start timer
|
||||||
|
RegionTimer (Timer & atimer) : timer(atimer) { timer.Start(); }
|
||||||
|
/// stop timer
|
||||||
|
~RegionTimer () { timer.Stop(); }
|
||||||
|
|
||||||
|
RegionTimer() = delete;
|
||||||
|
RegionTimer(const RegionTimer &) = delete;
|
||||||
|
RegionTimer(RegionTimer &&) = delete;
|
||||||
|
void operator=(const RegionTimer &) = delete;
|
||||||
|
void operator=(RegionTimer &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ThreadRegionTimer
|
||||||
|
{
|
||||||
|
size_t nr;
|
||||||
|
size_t tid;
|
||||||
|
public:
|
||||||
|
/// start timer
|
||||||
|
ThreadRegionTimer (size_t _nr, size_t _tid) : nr(_nr), tid(_tid)
|
||||||
|
{ NgProfiler::StartThreadTimer(nr, tid); }
|
||||||
|
/// stop timer
|
||||||
|
~ThreadRegionTimer ()
|
||||||
|
{ NgProfiler::StopThreadTimer(nr, tid); }
|
||||||
|
|
||||||
|
ThreadRegionTimer() = delete;
|
||||||
|
ThreadRegionTimer(ThreadRegionTimer &&) = delete;
|
||||||
|
ThreadRegionTimer(const ThreadRegionTimer &) = delete;
|
||||||
|
void operator=(const ThreadRegionTimer &) = delete;
|
||||||
|
void operator=(ThreadRegionTimer &&) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
class RegionTracer
|
||||||
|
{
|
||||||
|
int nr;
|
||||||
|
int thread_id;
|
||||||
|
public:
|
||||||
|
static constexpr int ID_JOB = PajeTrace::Task::ID_JOB;
|
||||||
|
static constexpr int ID_NONE = PajeTrace::Task::ID_NONE;
|
||||||
|
static constexpr int ID_TIMER = PajeTrace::Task::ID_TIMER;
|
||||||
|
|
||||||
|
RegionTracer() = delete;
|
||||||
|
RegionTracer(RegionTracer &&) = delete;
|
||||||
|
RegionTracer(const RegionTracer &) = delete;
|
||||||
|
void operator=(const RegionTracer &) = delete;
|
||||||
|
void operator=(RegionTracer &&) = delete;
|
||||||
|
|
||||||
|
/// start trace
|
||||||
|
RegionTracer (int athread_id, int region_id, int id_type = ID_NONE, int additional_value = -1 )
|
||||||
|
: thread_id(athread_id)
|
||||||
|
{
|
||||||
|
if (trace)
|
||||||
|
nr = trace->StartTask (athread_id, region_id, id_type, additional_value);
|
||||||
|
}
|
||||||
|
/// start trace with timer
|
||||||
|
RegionTracer (int athread_id, Timer & timer, int additional_value = -1 )
|
||||||
|
: thread_id(athread_id)
|
||||||
|
{
|
||||||
|
if (trace)
|
||||||
|
nr = trace->StartTask (athread_id, static_cast<int>(timer), ID_TIMER, additional_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// set user defined value
|
||||||
|
void SetValue( int additional_value )
|
||||||
|
{
|
||||||
|
if (trace)
|
||||||
|
trace->SetTask( thread_id, nr, additional_value );
|
||||||
|
}
|
||||||
|
|
||||||
|
/// stop trace
|
||||||
|
~RegionTracer ()
|
||||||
|
{
|
||||||
|
if (trace)
|
||||||
|
trace->StopTask (thread_id, nr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Helper function for timings
|
||||||
|
// Run f() at least min_iterations times until max_time seconds elapsed
|
||||||
|
// returns minimum runtime for a call of f()
|
||||||
|
template<typename TFunc>
|
||||||
|
double RunTiming( TFunc f, double max_time = 0.5, int min_iterations = 10 )
|
||||||
|
{
|
||||||
|
// Make sure the whole test run does not exceed maxtime
|
||||||
|
double tend = WallTime()+max_time;
|
||||||
|
|
||||||
|
// warmup
|
||||||
|
f();
|
||||||
|
|
||||||
|
double tres = std::numeric_limits<double>::max();
|
||||||
|
int iteration = 0;
|
||||||
|
while(WallTime()<tend || iteration++ < min_iterations)
|
||||||
|
{
|
||||||
|
double t = -WallTime();
|
||||||
|
f();
|
||||||
|
t += WallTime();
|
||||||
|
tres = std::min(tres, t);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tres;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ngcore
|
||||||
|
|
||||||
|
|
||||||
|
#endif // NETGEN_CORE_PROFILER_HPP
|
30
libsrc/core/python_ngcore.cpp
Normal file
30
libsrc/core/python_ngcore.cpp
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
|
||||||
|
#include <pybind11/pybind11.h>
|
||||||
|
|
||||||
|
#include "logging.hpp"
|
||||||
|
|
||||||
|
namespace py = pybind11;
|
||||||
|
using namespace ngcore;
|
||||||
|
|
||||||
|
PYBIND11_MODULE(pyngcore, m) // NOLINT
|
||||||
|
{
|
||||||
|
py::enum_<spdlog::level::level_enum>(m, "LOG_LEVEL", "Logging level")
|
||||||
|
.value("Trace", spdlog::level::trace)
|
||||||
|
.value("Debug", spdlog::level::debug)
|
||||||
|
.value("Info", spdlog::level::info)
|
||||||
|
.value("Warn", spdlog::level::warn)
|
||||||
|
.value("Error", spdlog::level::err)
|
||||||
|
.value("Critical", spdlog::level::critical)
|
||||||
|
.value("Off", spdlog::level::off);
|
||||||
|
|
||||||
|
m.def("SetLoggingLevel", &SetLoggingLevel, py::arg("level"), py::arg("logger")="",
|
||||||
|
"Set logging level, if name is given only to the specific logger, else set the global logging level");
|
||||||
|
m.def("AddFileSink", &AddFileSink, py::arg("filename"), py::arg("level"), py::arg("logger")="",
|
||||||
|
"Add File sink, either only to logger specified or globally to all loggers");
|
||||||
|
m.def("AddConsoleSink", &AddConsoleSink, py::arg("level"), py::arg("logger")="",
|
||||||
|
"Add console output for specific logger or all if none given");
|
||||||
|
m.def("ClearLoggingSinks", &ClearLoggingSinks, py::arg("logger")="",
|
||||||
|
"Clear sinks of specific logger, or all if none given");
|
||||||
|
m.def("FlushOnLoggingLevel", &FlushOnLoggingLevel, py::arg("level"), py::arg("logger")="",
|
||||||
|
"Flush every message with level at least `level` for specific logger or all loggers if none given.");
|
||||||
|
}
|
144
libsrc/core/symboltable.hpp
Normal file
144
libsrc/core/symboltable.hpp
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
#ifndef NETGEN_CORE_SYMBOLTABLE_HPP
|
||||||
|
#define NETGEN_CORE_SYMBOLTABLE_HPP
|
||||||
|
|
||||||
|
#include <ostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "archive.hpp"
|
||||||
|
#include "exception.hpp"
|
||||||
|
#include "ngcore_api.hpp"
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
A symbol table.
|
||||||
|
|
||||||
|
The symboltable provides a mapping from string identifiers
|
||||||
|
to the generic type T. The strings are copied.
|
||||||
|
Complexity by name access is linear, by index is constant.
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
class SymbolTable
|
||||||
|
{
|
||||||
|
std::vector<std::string> names;
|
||||||
|
std::vector<T> data;
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using reference = typename std::vector<T>::reference;
|
||||||
|
using const_reference = typename std::vector<T>::const_reference;
|
||||||
|
|
||||||
|
/// Creates a symboltable
|
||||||
|
SymbolTable () = default;
|
||||||
|
SymbolTable (const SymbolTable<T> &) = default;
|
||||||
|
SymbolTable (SymbolTable<T> &&) noexcept = default;
|
||||||
|
|
||||||
|
~SymbolTable() = default;
|
||||||
|
|
||||||
|
SymbolTable& operator=(const SymbolTable<T>&) = default;
|
||||||
|
SymbolTable& operator=(SymbolTable<T>&&) = default;
|
||||||
|
|
||||||
|
template<typename T2=T>
|
||||||
|
auto DoArchive(Archive& ar) -> typename std::enable_if<is_archivable<T2>, void>::type
|
||||||
|
{
|
||||||
|
ar & names & data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// INDEX of symbol name, throws exception if unused
|
||||||
|
size_t Index (const std::string & name) const
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < names.size(); i++)
|
||||||
|
if (names[i] == name) return i;
|
||||||
|
throw RangeException("SymbolTable", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Index of symbol name, returns -1 if unused
|
||||||
|
int CheckIndex (const std::string & name) const
|
||||||
|
{
|
||||||
|
for (int i = 0; i < names.size(); i++)
|
||||||
|
if (names[i] == name) return i;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// number of identifiers
|
||||||
|
size_t Size() const
|
||||||
|
{
|
||||||
|
return data.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns reference to element. exception for unused identifier
|
||||||
|
reference operator[] (const std::string & name)
|
||||||
|
{
|
||||||
|
return data[Index (name)];
|
||||||
|
}
|
||||||
|
|
||||||
|
const_reference operator[] (const std::string & name) const
|
||||||
|
{
|
||||||
|
return data[Index (name)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns reference to i-th element, range check only in debug build
|
||||||
|
reference operator[] (size_t i)
|
||||||
|
{
|
||||||
|
NETGEN_CHECK_RANGE(i, 0, data.size());
|
||||||
|
return data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns const reference to i-th element, range check only in debug build
|
||||||
|
const_reference operator[] (size_t i) const
|
||||||
|
{
|
||||||
|
NETGEN_CHECK_RANGE(i, 0, data.size());
|
||||||
|
return data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns name of i-th element, range check only in debug build
|
||||||
|
const std::string & GetName (size_t i) const
|
||||||
|
{
|
||||||
|
NETGEN_CHECK_RANGE(i, 0, names.size());
|
||||||
|
return names[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Associates el to the string name, overrides if name is used
|
||||||
|
void Set (const std::string & name, const T & el)
|
||||||
|
{
|
||||||
|
int i = CheckIndex (name);
|
||||||
|
if (i >= 0)
|
||||||
|
data[i] = el;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.push_back(el);
|
||||||
|
names.push_back(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Used (const std::string & name) const
|
||||||
|
{
|
||||||
|
return CheckIndex(name) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes symboltable
|
||||||
|
inline void DeleteAll ()
|
||||||
|
{
|
||||||
|
names.clear();
|
||||||
|
data.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adds all elements from other symboltable
|
||||||
|
SymbolTable<T>& Update(const SymbolTable<T>& tbl2)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < tbl2.Size(); i++)
|
||||||
|
Set (tbl2.GetName(i), tbl2[i]);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::ostream & operator<< (std::ostream & ost, const SymbolTable<T> & st)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < st.Size(); i++)
|
||||||
|
ost << st.GetName(i) << " : " << st[i] << std::endl;
|
||||||
|
return ost;
|
||||||
|
}
|
||||||
|
} // namespace ngcore
|
||||||
|
|
||||||
|
#endif // NETGEN_CORE_SYMBOLTABLE_HPP
|
42
libsrc/core/utils.cpp
Normal file
42
libsrc/core/utils.cpp
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
#include "utils.hpp"
|
||||||
|
#include "logging.hpp"
|
||||||
|
|
||||||
|
#ifndef WIN32
|
||||||
|
#include <cxxabi.h>
|
||||||
|
#endif
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
// parallel netgen
|
||||||
|
int id = 0, ntasks = 1;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
// windows does demangling in typeid(T).name()
|
||||||
|
NGCORE_API std::string Demangle(const char* typeinfo) { return typeinfo; }
|
||||||
|
#else
|
||||||
|
NGCORE_API std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo,
|
||||||
|
nullptr,
|
||||||
|
nullptr,
|
||||||
|
&status); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
double ticks_per_second = [] () noexcept
|
||||||
|
{
|
||||||
|
auto tick_start = GetTimeCounter();
|
||||||
|
double tstart = WallTime();
|
||||||
|
double tend = WallTime()+0.001;
|
||||||
|
|
||||||
|
// wait for 1ms and compare wall time with time counter
|
||||||
|
while(WallTime()<tend);
|
||||||
|
|
||||||
|
auto tick_end = GetTimeCounter();
|
||||||
|
tend = WallTime();
|
||||||
|
|
||||||
|
return (tick_end-tick_start)/(tend-tstart);
|
||||||
|
}();
|
||||||
|
|
||||||
|
const std::chrono::time_point<TClock> wall_time_start = TClock::now();
|
||||||
|
|
||||||
|
} // namespace ngcore
|
||||||
|
|
62
libsrc/core/utils.hpp
Normal file
62
libsrc/core/utils.hpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#ifndef NETGEN_CORE_UTILS_HPP
|
||||||
|
#define NETGEN_CORE_UTILS_HPP
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <intrin.h> // for __rdtsc() CPU time step counter
|
||||||
|
#else
|
||||||
|
#include <x86intrin.h> // for __rdtsc() CPU time step counter
|
||||||
|
#endif // WIN32
|
||||||
|
|
||||||
|
#include "ngcore_api.hpp" // for NGCORE_API
|
||||||
|
|
||||||
|
namespace ngcore
|
||||||
|
{
|
||||||
|
// MPI rank, nranks TODO: Rename
|
||||||
|
extern NGCORE_API int id, ntasks;
|
||||||
|
|
||||||
|
NGCORE_API std::string Demangle(const char* typeinfo);
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); }
|
||||||
|
inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); }
|
||||||
|
#else
|
||||||
|
inline bool likely (bool x) { return x; }
|
||||||
|
inline bool unlikely (bool x) { return x; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
using TClock = std::chrono::system_clock;
|
||||||
|
extern NGCORE_API const std::chrono::time_point<TClock> wall_time_start;
|
||||||
|
|
||||||
|
// Time in seconds since program start
|
||||||
|
inline double WallTime () noexcept
|
||||||
|
{
|
||||||
|
std::chrono::time_point<TClock> now = TClock::now();
|
||||||
|
std::chrono::duration<double> elapsed_seconds = now-wall_time_start;
|
||||||
|
return elapsed_seconds.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
// High precision clock counter register
|
||||||
|
using TTimePoint = size_t;
|
||||||
|
extern NGCORE_API double ticks_per_second;
|
||||||
|
|
||||||
|
inline TTimePoint GetTimeCounter() noexcept
|
||||||
|
{
|
||||||
|
return TTimePoint(__rdtsc());
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
inline std::string ToString (const T& t)
|
||||||
|
{
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << t;
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace ngcore
|
||||||
|
|
||||||
|
#endif // NETGEN_CORE_UTILS_HPP
|
@ -12,11 +12,11 @@ if(APPLE)
|
|||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_link_libraries(csg mesh ${PYTHON_LIBRARIES})
|
target_link_libraries(csg PUBLIC mesh ${PYTHON_LIBRARIES})
|
||||||
target_link_libraries(csg ${PYTHON_LIBRARIES})
|
|
||||||
install( TARGETS csg ${NG_INSTALL_DIR})
|
install( TARGETS csg ${NG_INSTALL_DIR})
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
target_link_libraries(csg PUBLIC ngcore)
|
||||||
|
|
||||||
if(USE_GUI)
|
if(USE_GUI)
|
||||||
add_library(csgvis ${NG_LIB_TYPE} vscsg.cpp )
|
add_library(csgvis ${NG_LIB_TYPE} vscsg.cpp )
|
||||||
|
@ -562,7 +562,7 @@ namespace netgen
|
|||||||
const Surface * CSGeometry :: GetSurface (const char * name) const
|
const Surface * CSGeometry :: GetSurface (const char * name) const
|
||||||
{
|
{
|
||||||
if (surfaces.Used(name))
|
if (surfaces.Used(name))
|
||||||
return surfaces.Get(name);
|
return surfaces[name];
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -585,7 +585,7 @@ namespace netgen
|
|||||||
Solid * oldsol = NULL;
|
Solid * oldsol = NULL;
|
||||||
|
|
||||||
if (solids.Used (name))
|
if (solids.Used (name))
|
||||||
oldsol = solids.Get(name);
|
oldsol = solids[name];
|
||||||
|
|
||||||
solids.Set (name, sol);
|
solids.Set (name, sol);
|
||||||
sol->SetName (name);
|
sol->SetName (name);
|
||||||
@ -605,7 +605,7 @@ namespace netgen
|
|||||||
const Solid * CSGeometry :: GetSolid (const char * name) const
|
const Solid * CSGeometry :: GetSolid (const char * name) const
|
||||||
{
|
{
|
||||||
if (solids.Used(name))
|
if (solids.Used(name))
|
||||||
return solids.Get(name);
|
return solids[name];
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -616,8 +616,8 @@ namespace netgen
|
|||||||
|
|
||||||
const Solid * CSGeometry :: GetSolid (const string & name) const
|
const Solid * CSGeometry :: GetSolid (const string & name) const
|
||||||
{
|
{
|
||||||
if (solids.Used(name.c_str()))
|
if (solids.Used(name))
|
||||||
return solids.Get(name.c_str());
|
return solids[name];
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -637,15 +637,15 @@ namespace netgen
|
|||||||
|
|
||||||
const SplineGeometry<2> * CSGeometry :: GetSplineCurve2d (const string & name) const
|
const SplineGeometry<2> * CSGeometry :: GetSplineCurve2d (const string & name) const
|
||||||
{
|
{
|
||||||
if (splinecurves2d.Used(name.c_str()))
|
if (splinecurves2d.Used(name))
|
||||||
return splinecurves2d.Get(name.c_str());
|
return splinecurves2d[name];
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
const SplineGeometry<3> * CSGeometry :: GetSplineCurve3d (const string & name) const
|
const SplineGeometry<3> * CSGeometry :: GetSplineCurve3d (const string & name) const
|
||||||
{
|
{
|
||||||
if (splinecurves3d.Used(name.c_str()))
|
if (splinecurves3d.Used(name))
|
||||||
return splinecurves3d.Get(name.c_str());
|
return splinecurves3d[name];
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -721,7 +721,7 @@ namespace netgen
|
|||||||
|
|
||||||
void CSGeometry :: SetFlags (const char * solidname, const Flags & flags)
|
void CSGeometry :: SetFlags (const char * solidname, const Flags & flags)
|
||||||
{
|
{
|
||||||
Solid * solid = solids.Elem(solidname);
|
Solid * solid = solids[solidname];
|
||||||
Array<int> surfind;
|
Array<int> surfind;
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
@ -102,7 +102,7 @@ namespace netgen
|
|||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/// all surfaces
|
/// all surfaces
|
||||||
SYMBOLTABLE<Surface*> surfaces;
|
SymbolTable<Surface*> surfaces;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// primitive of surface
|
/// primitive of surface
|
||||||
@ -112,12 +112,12 @@ namespace netgen
|
|||||||
Array<Surface*> delete_them;
|
Array<Surface*> delete_them;
|
||||||
|
|
||||||
/// all named solids
|
/// all named solids
|
||||||
SYMBOLTABLE<Solid*> solids;
|
SymbolTable<Solid*> solids;
|
||||||
|
|
||||||
/// all 2d splinecurves
|
/// all 2d splinecurves
|
||||||
SYMBOLTABLE< SplineGeometry<2>* > splinecurves2d;
|
SymbolTable< SplineGeometry<2>* > splinecurves2d;
|
||||||
/// all 3d splinecurves
|
/// all 3d splinecurves
|
||||||
SYMBOLTABLE< SplineGeometry<3>* > splinecurves3d;
|
SymbolTable< SplineGeometry<3>* > splinecurves3d;
|
||||||
|
|
||||||
/// all top level objects: solids and surfaces
|
/// all top level objects: solids and surfaces
|
||||||
Array<TopLevelObject*> toplevelobjects;
|
Array<TopLevelObject*> toplevelobjects;
|
||||||
@ -203,7 +203,7 @@ namespace netgen
|
|||||||
const Solid * GetSolid (const string & name) const;
|
const Solid * GetSolid (const string & name) const;
|
||||||
int GetNSolids () const { return solids.Size(); }
|
int GetNSolids () const { return solids.Size(); }
|
||||||
const Solid * GetSolid (int i) const { return solids[i]; }
|
const Solid * GetSolid (int i) const { return solids[i]; }
|
||||||
const SYMBOLTABLE<Solid*> & GetSolids () const { return solids; }
|
const SymbolTable<Solid*> & GetSolids () const { return solids; }
|
||||||
|
|
||||||
|
|
||||||
void SetSplineCurve (const char * name, SplineGeometry<2> * spl);
|
void SetSplineCurve (const char * name, SplineGeometry<2> * spl);
|
||||||
|
@ -419,9 +419,9 @@ namespace netgen
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
static Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE<Solid*> & solids);
|
static Solid * CreateSolidExpr (istream & ist, const SymbolTable<Solid*> & solids);
|
||||||
static Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE<Solid*> & solids);
|
static Solid * CreateSolidTerm (istream & ist, const SymbolTable<Solid*> & solids);
|
||||||
static Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE<Solid*> & solids);
|
static Solid * CreateSolidPrim (istream & ist, const SymbolTable<Solid*> & solids);
|
||||||
|
|
||||||
static void ReadString (istream & ist, char * str)
|
static void ReadString (istream & ist, char * str)
|
||||||
{
|
{
|
||||||
@ -461,7 +461,7 @@ namespace netgen
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE<Solid*> & solids)
|
Solid * CreateSolidExpr (istream & ist, const SymbolTable<Solid*> & solids)
|
||||||
{
|
{
|
||||||
// cout << "create expr" << endl;
|
// cout << "create expr" << endl;
|
||||||
|
|
||||||
@ -484,7 +484,7 @@ namespace netgen
|
|||||||
return s1;
|
return s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE<Solid*> & solids)
|
Solid * CreateSolidTerm (istream & ist, const SymbolTable<Solid*> & solids)
|
||||||
{
|
{
|
||||||
// cout << "create term" << endl;
|
// cout << "create term" << endl;
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ namespace netgen
|
|||||||
return s1;
|
return s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE<Solid*> & solids)
|
Solid * CreateSolidPrim (istream & ist, const SymbolTable<Solid*> & solids)
|
||||||
{
|
{
|
||||||
Solid * s1;
|
Solid * s1;
|
||||||
char ch;
|
char ch;
|
||||||
@ -533,7 +533,7 @@ namespace netgen
|
|||||||
}
|
}
|
||||||
|
|
||||||
(*testout) << "get terminal " << str << endl;
|
(*testout) << "get terminal " << str << endl;
|
||||||
s1 = solids.Get(str);
|
s1 = solids[str];
|
||||||
if (s1)
|
if (s1)
|
||||||
{
|
{
|
||||||
// cout << "primitive: " << str << endl;
|
// cout << "primitive: " << str << endl;
|
||||||
@ -545,7 +545,7 @@ namespace netgen
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Solid * Solid :: CreateSolid (istream & ist, const SYMBOLTABLE<Solid*> & solids)
|
Solid * Solid :: CreateSolid (istream & ist, const SymbolTable<Solid*> & solids)
|
||||||
{
|
{
|
||||||
Solid * nsol = CreateSolidExpr (ist, solids);
|
Solid * nsol = CreateSolidExpr (ist, solids);
|
||||||
nsol = new Solid (ROOT, nsol);
|
nsol = new Solid (ROOT, nsol);
|
||||||
|
@ -158,7 +158,7 @@ namespace netgen
|
|||||||
{ return maxh; }
|
{ return maxh; }
|
||||||
|
|
||||||
void GetSolidData (ostream & ost, int first = 1) const;
|
void GetSolidData (ostream & ost, int first = 1) const;
|
||||||
static Solid * CreateSolid (istream & ist, const SYMBOLTABLE<Solid*> & solids);
|
static Solid * CreateSolid (istream & ist, const SymbolTable<Solid*> & solids);
|
||||||
|
|
||||||
|
|
||||||
static BlockAllocator ball;
|
static BlockAllocator ball;
|
||||||
|
@ -1,21 +1,19 @@
|
|||||||
add_definitions(-DNGINTERFACE_EXPORTS)
|
add_definitions(-DNGINTERFACE_EXPORTS)
|
||||||
add_library(gen OBJECT
|
add_library(gen INTERFACE)
|
||||||
array.cpp bitarray.cpp dynamicmem.cpp flags.cpp
|
set(sdir ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
hashtabl.cpp mystring.cpp ngexception.cpp optmem.cpp parthreads.cpp
|
target_sources(gen INTERFACE
|
||||||
profiler.cpp seti.cpp sort.cpp spbita2d.cpp symbolta.cpp table.cpp
|
${sdir}/array.cpp ${sdir}/bitarray.cpp ${sdir}/dynamicmem.cpp ${sdir}/flags.cpp
|
||||||
mpi_interface.cpp gzstream.cpp
|
${sdir}/hashtabl.cpp ${sdir}/mystring.cpp ${sdir}/optmem.cpp ${sdir}/parthreads.cpp
|
||||||
|
${sdir}/seti.cpp ${sdir}/sort.cpp ${sdir}/spbita2d.cpp ${sdir}/table.cpp
|
||||||
|
${sdir}/mpi_interface.cpp ${sdir}/gzstream.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON )
|
|
||||||
|
|
||||||
install( FILES ngexception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel )
|
|
||||||
|
|
||||||
install(FILES
|
install(FILES
|
||||||
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
|
dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp
|
||||||
ngsimd.hpp mystring.hpp netgenout.hpp ngexception.hpp ngpython.hpp
|
ngsimd.hpp mystring.hpp netgenout.hpp ngpython.hpp
|
||||||
optmem.hpp parthreads.hpp profiler.hpp seti.hpp sort.hpp
|
optmem.hpp parthreads.hpp seti.hpp sort.hpp
|
||||||
spbita2d.hpp stack.hpp symbolta.hpp table.hpp template.hpp
|
spbita2d.hpp stack.hpp table.hpp template.hpp
|
||||||
gzstream.h
|
gzstream.h
|
||||||
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel
|
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel
|
||||||
)
|
)
|
||||||
|
@ -83,7 +83,7 @@ namespace netgen
|
|||||||
Flags :: GetStringFlag (const char * name, const char * def) const
|
Flags :: GetStringFlag (const char * name, const char * def) const
|
||||||
{
|
{
|
||||||
if (strflags.Used (name))
|
if (strflags.Used (name))
|
||||||
return strflags.Get(name);
|
return strflags[name];
|
||||||
else
|
else
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
@ -91,7 +91,7 @@ namespace netgen
|
|||||||
double Flags :: GetNumFlag (const char * name, double def) const
|
double Flags :: GetNumFlag (const char * name, double def) const
|
||||||
{
|
{
|
||||||
if (numflags.Used (name))
|
if (numflags.Used (name))
|
||||||
return numflags.Get(name);
|
return numflags[name];
|
||||||
else
|
else
|
||||||
return def;
|
return def;
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ namespace netgen
|
|||||||
const double * Flags :: GetNumFlagPtr (const char * name) const
|
const double * Flags :: GetNumFlagPtr (const char * name) const
|
||||||
{
|
{
|
||||||
if (numflags.Used (name))
|
if (numflags.Used (name))
|
||||||
return & ((SYMBOLTABLE<double>&)numflags).Elem(name);
|
return & ((SymbolTable<double>&)numflags)[name];
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -107,7 +107,7 @@ namespace netgen
|
|||||||
double * Flags :: GetNumFlagPtr (const char * name)
|
double * Flags :: GetNumFlagPtr (const char * name)
|
||||||
{
|
{
|
||||||
if (numflags.Used (name))
|
if (numflags.Used (name))
|
||||||
return & ((SYMBOLTABLE<double>&)numflags).Elem(name);
|
return & ((SymbolTable<double>&)numflags)[name];
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -122,7 +122,7 @@ namespace netgen
|
|||||||
Flags :: GetStringListFlag (const char * name) const
|
Flags :: GetStringListFlag (const char * name) const
|
||||||
{
|
{
|
||||||
if (strlistflags.Used (name))
|
if (strlistflags.Used (name))
|
||||||
return *strlistflags.Get(name);
|
return *strlistflags[name];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static Array<char*> dummy_array(0);
|
static Array<char*> dummy_array(0);
|
||||||
@ -134,7 +134,7 @@ namespace netgen
|
|||||||
Flags ::GetNumListFlag (const char * name) const
|
Flags ::GetNumListFlag (const char * name) const
|
||||||
{
|
{
|
||||||
if (numlistflags.Used (name))
|
if (numlistflags.Used (name))
|
||||||
return *numlistflags.Get(name);
|
return *numlistflags[name];
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
static Array<double> dummy_array(0);
|
static Array<double> dummy_array(0);
|
||||||
@ -170,9 +170,9 @@ namespace netgen
|
|||||||
ofstream outfile (filename);
|
ofstream outfile (filename);
|
||||||
|
|
||||||
for (i = 1; i <= strflags.Size(); i++)
|
for (i = 1; i <= strflags.Size(); i++)
|
||||||
outfile << strflags.GetName(i) << " = " << strflags.Get(i) << endl;
|
outfile << strflags.GetName(i) << " = " << strflags[i] << endl;
|
||||||
for (i = 1; i <= numflags.Size(); i++)
|
for (i = 1; i <= numflags.Size(); i++)
|
||||||
outfile << numflags.GetName(i) << " = " << numflags.Get(i) << endl;
|
outfile << numflags.GetName(i) << " = " << numflags[i] << endl;
|
||||||
for (i = 1; i <= defflags.Size(); i++)
|
for (i = 1; i <= defflags.Size(); i++)
|
||||||
outfile << defflags.GetName(i) << endl;
|
outfile << defflags.GetName(i) << endl;
|
||||||
}
|
}
|
||||||
@ -184,9 +184,9 @@ namespace netgen
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 1; i <= strflags.Size(); i++)
|
for (i = 1; i <= strflags.Size(); i++)
|
||||||
ost << strflags.GetName(i) << " = " << strflags.Get(i) << endl;
|
ost << strflags.GetName(i) << " = " << strflags[i] << endl;
|
||||||
for (i = 1; i <= numflags.Size(); i++)
|
for (i = 1; i <= numflags.Size(); i++)
|
||||||
ost << numflags.GetName(i) << " = " << numflags.Get(i) << endl;
|
ost << numflags.GetName(i) << " = " << numflags[i] << endl;
|
||||||
for (i = 1; i <= defflags.Size(); i++)
|
for (i = 1; i <= defflags.Size(); i++)
|
||||||
ost << defflags.GetName(i) << endl;
|
ost << defflags.GetName(i) << endl;
|
||||||
}
|
}
|
||||||
|
@ -19,15 +19,15 @@ namespace netgen
|
|||||||
class Flags
|
class Flags
|
||||||
{
|
{
|
||||||
///
|
///
|
||||||
SYMBOLTABLE<char *> strflags;
|
SymbolTable<char *> strflags;
|
||||||
///
|
///
|
||||||
SYMBOLTABLE<double> numflags;
|
SymbolTable<double> numflags;
|
||||||
///
|
///
|
||||||
SYMBOLTABLE<int> defflags;
|
SymbolTable<int> defflags;
|
||||||
///
|
///
|
||||||
SYMBOLTABLE<Array<char*>*> strlistflags;
|
SymbolTable<Array<char*>*> strlistflags;
|
||||||
///
|
///
|
||||||
SYMBOLTABLE<Array<double>*> numlistflags;
|
SymbolTable<Array<double>*> numlistflags;
|
||||||
public:
|
public:
|
||||||
///
|
///
|
||||||
DLL_HEADER Flags ();
|
DLL_HEADER Flags ();
|
||||||
|
@ -14,9 +14,8 @@
|
|||||||
|
|
||||||
namespace netgen
|
namespace netgen
|
||||||
{
|
{
|
||||||
|
using ngcore::id;
|
||||||
extern DLL_HEADER int id, ntasks;
|
using ngcore::ntasks;
|
||||||
|
|
||||||
|
|
||||||
#ifdef PARALLEL
|
#ifdef PARALLEL
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
namespace netgen
|
namespace netgen
|
||||||
{
|
{
|
||||||
using namespace ngcore;
|
using namespace ngcore;
|
||||||
|
using NgException = Exception;
|
||||||
}
|
}
|
||||||
#include "ngexception.hpp"
|
|
||||||
#include "parthreads.hpp"
|
#include "parthreads.hpp"
|
||||||
// #include "moveablemem.hpp"
|
// #include "moveablemem.hpp"
|
||||||
#include "dynamicmem.hpp"
|
#include "dynamicmem.hpp"
|
||||||
@ -33,7 +33,6 @@ namespace netgen
|
|||||||
#include "hashtabl.hpp"
|
#include "hashtabl.hpp"
|
||||||
|
|
||||||
|
|
||||||
#include "symbolta.hpp"
|
|
||||||
#include "bitarray.hpp"
|
#include "bitarray.hpp"
|
||||||
#include "flags.hpp"
|
#include "flags.hpp"
|
||||||
#include "spbita2d.hpp"
|
#include "spbita2d.hpp"
|
||||||
@ -44,7 +43,6 @@ namespace netgen
|
|||||||
#include "sort.hpp"
|
#include "sort.hpp"
|
||||||
#include "stack.hpp"
|
#include "stack.hpp"
|
||||||
#include "mystring.hpp"
|
#include "mystring.hpp"
|
||||||
#include "profiler.hpp"
|
|
||||||
|
|
||||||
#include "mpi_interface.hpp"
|
#include "mpi_interface.hpp"
|
||||||
#include "netgenout.hpp"
|
#include "netgenout.hpp"
|
||||||
|
@ -4,14 +4,11 @@
|
|||||||
// #include <ostream>
|
// #include <ostream>
|
||||||
// #include <mystdlib.h>
|
// #include <mystdlib.h>
|
||||||
// #include <meshing.hpp>
|
// #include <meshing.hpp>
|
||||||
|
#include "mpi_interface.hpp"
|
||||||
|
|
||||||
namespace netgen
|
namespace netgen
|
||||||
{
|
{
|
||||||
|
|
||||||
#ifdef PARALLEL
|
|
||||||
extern int id;
|
|
||||||
extern int ntasks;
|
|
||||||
#endif
|
|
||||||
DLL_HEADER extern int printmessage_importance;
|
DLL_HEADER extern int printmessage_importance;
|
||||||
DLL_HEADER extern int printdots;
|
DLL_HEADER extern int printdots;
|
||||||
|
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
/**************************************************************************/
|
|
||||||
/* File: ngexception.cpp */
|
|
||||||
/* Author: Joachim Schoeberl */
|
|
||||||
/* Date: 16. Jan. 02 */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
#include <myadt.hpp>
|
|
||||||
|
|
||||||
namespace netgen
|
|
||||||
{
|
|
||||||
//using namespace netgen;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NgException :: NgException (const string & s)
|
|
||||||
: m_what(s)
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
NgException :: ~NgException ()
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// append string to description
|
|
||||||
void NgException :: Append (const string & s)
|
|
||||||
{
|
|
||||||
m_what += s;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
#ifndef FILE_NGEXCEPTION
|
|
||||||
#define FILE_NGEXCEPTION
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/* File: ngexception.hpp */
|
|
||||||
/* Author: Joachim Schoeberl */
|
|
||||||
/* Date: 16. Jan. 2002 */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
namespace netgen
|
|
||||||
{
|
|
||||||
|
|
||||||
/// Base class for all ng exceptions
|
|
||||||
class NgException : public std::exception
|
|
||||||
{
|
|
||||||
/// verbal description of exception
|
|
||||||
string m_what;
|
|
||||||
public:
|
|
||||||
///
|
|
||||||
DLL_HEADER NgException (const string & s);
|
|
||||||
///
|
|
||||||
DLL_HEADER virtual ~NgException ();
|
|
||||||
|
|
||||||
/// append string to description
|
|
||||||
DLL_HEADER void Append (const string & s);
|
|
||||||
// void Append (const char * s);
|
|
||||||
|
|
||||||
/// verbal description of exception
|
|
||||||
const string & What() const { return m_what; }
|
|
||||||
virtual const char* what() const noexcept override { return m_what.c_str(); }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -66,16 +66,7 @@ namespace netgen
|
|||||||
return static_cast<typename function_traits<Function>::pointer>(lambda);
|
return static_cast<typename function_traits<Function>::pointer>(lambda);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace netgen
|
||||||
template <class T>
|
|
||||||
inline std::string ToString (const T& t)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << t;
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1,131 +0,0 @@
|
|||||||
/**************************************************************************/
|
|
||||||
/* File: profiler.cpp */
|
|
||||||
/* Author: Joachim Schoeberl */
|
|
||||||
/* Date: 19. Apr. 2002 */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
#include <myadt.hpp>
|
|
||||||
|
|
||||||
namespace netgen
|
|
||||||
{
|
|
||||||
//using namespace netgen;
|
|
||||||
|
|
||||||
long int NgProfiler::tottimes[SIZE];
|
|
||||||
long int NgProfiler::starttimes[SIZE];
|
|
||||||
long int NgProfiler::counts[SIZE];
|
|
||||||
string NgProfiler::names[SIZE];
|
|
||||||
int NgProfiler::usedcounter[SIZE];
|
|
||||||
|
|
||||||
|
|
||||||
NgProfiler :: NgProfiler()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < SIZE; i++)
|
|
||||||
{
|
|
||||||
tottimes[i] = 0;
|
|
||||||
usedcounter[i] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
total_timer = CreateTimer ("total CPU time");
|
|
||||||
StartTimer (total_timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
NgProfiler :: ~NgProfiler()
|
|
||||||
{
|
|
||||||
#ifndef PARALLEL
|
|
||||||
StopTimer (total_timer);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//ofstream prof;
|
|
||||||
//prof.open("ng.prof");
|
|
||||||
|
|
||||||
// ofstream-constructor may be called after STL-stuff is destructed,
|
|
||||||
// which leads to an "order of destruction"-problem,
|
|
||||||
// thus we use the C-variant:
|
|
||||||
|
|
||||||
if (getenv ("NGPROFILE"))
|
|
||||||
{
|
|
||||||
char filename[100];
|
|
||||||
#ifdef PARALLEL
|
|
||||||
sprintf (filename, "netgen.prof.%d", id);
|
|
||||||
#else
|
|
||||||
sprintf (filename, "netgen.prof");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (id == 0) printf ("write profile to file netgen.prof\n");
|
|
||||||
FILE *prof = fopen(filename,"w");
|
|
||||||
Print (prof);
|
|
||||||
fclose(prof);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// void NgProfiler :: Print (ostream & prof)
|
|
||||||
// {
|
|
||||||
// for (int i = 0; i < SIZE; i++)
|
|
||||||
// if (counts[i] != 0 || usedcounter[i] != 0)
|
|
||||||
// {
|
|
||||||
// prof.setf (ios::fixed, ios::floatfield);
|
|
||||||
// prof.setf (ios::showpoint);
|
|
||||||
|
|
||||||
// prof // << "job " << setw(3) << i
|
|
||||||
// << "calls " << setw(8) << counts[i]
|
|
||||||
// << ", time " << setprecision(2) << setw(6) << double(tottimes[i]) / CLOCKS_PER_SEC << " sec";
|
|
||||||
|
|
||||||
// if (usedcounter[i])
|
|
||||||
// prof << " " << names[i];
|
|
||||||
// else
|
|
||||||
// prof << " " << i;
|
|
||||||
|
|
||||||
// prof << endl;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
void NgProfiler :: Print (FILE * prof)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < SIZE; i++)
|
|
||||||
if (counts[i] != 0 || usedcounter[i] != 0)
|
|
||||||
{
|
|
||||||
//fprintf(prof,"job %3i calls %8i, time %6.2f sec",i,counts[i],double(tottimes[i]) / CLOCKS_PER_SEC);
|
|
||||||
#ifndef USE_TSC
|
|
||||||
fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / CLOCKS_PER_SEC);
|
|
||||||
#else
|
|
||||||
fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / 2.7e9);
|
|
||||||
#endif
|
|
||||||
if(usedcounter[i])
|
|
||||||
fprintf(prof," %s",names[i].c_str());
|
|
||||||
else
|
|
||||||
fprintf(prof," %i",i);
|
|
||||||
fprintf(prof,"\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int NgProfiler :: CreateTimer (const string & name)
|
|
||||||
{
|
|
||||||
for (int i = SIZE-1; i > 0; i--)
|
|
||||||
if(names[i] == name)
|
|
||||||
return i;
|
|
||||||
|
|
||||||
for (int i = SIZE-1; i > 0; i--)
|
|
||||||
if (!usedcounter[i])
|
|
||||||
{
|
|
||||||
usedcounter[i] = 1;
|
|
||||||
names[i] = name;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void NgProfiler :: ClearTimers ()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < SIZE; i++)
|
|
||||||
{
|
|
||||||
tottimes[i] = 0;
|
|
||||||
counts[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NgProfiler prof;
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
#ifndef FILE_NG_PROFILER
|
|
||||||
#define FILE_NG_PROFILER
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/* File: profiler.hpp */
|
|
||||||
/* Author: Joachim Schoeberl */
|
|
||||||
/* Date: 5. Jan. 2005 */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef VTRACE
|
|
||||||
#include "vt_user.h"
|
|
||||||
#else
|
|
||||||
#define VT_USER_START(n)
|
|
||||||
#define VT_USER_END(n)
|
|
||||||
#define VT_TRACER(n)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
// #define USE_TSC
|
|
||||||
#ifdef USE_TSC
|
|
||||||
#include <x86intrin.h> // for __rdtsc() CPU time step counter
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace netgen
|
|
||||||
{
|
|
||||||
|
|
||||||
class NgProfiler
|
|
||||||
{
|
|
||||||
enum { SIZE = 1000 };
|
|
||||||
|
|
||||||
static long int tottimes[SIZE];
|
|
||||||
static long int starttimes[SIZE];
|
|
||||||
static long int counts[SIZE];
|
|
||||||
static string names[SIZE];
|
|
||||||
static int usedcounter[SIZE];
|
|
||||||
|
|
||||||
int total_timer;
|
|
||||||
public:
|
|
||||||
NgProfiler();
|
|
||||||
~NgProfiler();
|
|
||||||
static int CreateTimer (const string & name);
|
|
||||||
#ifndef USE_TSC
|
|
||||||
static void StartTimer (int nr)
|
|
||||||
{
|
|
||||||
starttimes[nr] = clock(); counts[nr]++;
|
|
||||||
// VT_USER_START (const_cast<char*> (names[nr].c_str()));
|
|
||||||
VT_USER_START ( (char * const) (names[nr].c_str()));
|
|
||||||
}
|
|
||||||
static void StopTimer (int nr)
|
|
||||||
{
|
|
||||||
tottimes[nr] += clock()-starttimes[nr];
|
|
||||||
VT_USER_END (const_cast<char*> (names[nr].c_str()));
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static void StartTimer (int nr)
|
|
||||||
{
|
|
||||||
starttimes[nr] = __rdtsc(); counts[nr]++;
|
|
||||||
// VT_USER_START (const_cast<char*> (names[nr].c_str()));
|
|
||||||
// VT_USER_START ( (char * const) (names[nr].c_str()));
|
|
||||||
}
|
|
||||||
static void StopTimer (int nr)
|
|
||||||
{
|
|
||||||
tottimes[nr] += __rdtsc()-starttimes[nr];
|
|
||||||
VT_USER_END (const_cast<char*> (names[nr].c_str()));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
//static void Print (ostream & ost);
|
|
||||||
static void Print (FILE * prof);
|
|
||||||
|
|
||||||
static void ClearTimers ();
|
|
||||||
|
|
||||||
class RegionTimer
|
|
||||||
{
|
|
||||||
int nr;
|
|
||||||
public:
|
|
||||||
RegionTimer (int anr) : nr(anr)
|
|
||||||
{ StartTimer (nr); }
|
|
||||||
~RegionTimer () { StopTimer (nr); }
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,52 +0,0 @@
|
|||||||
/**************************************************************************/
|
|
||||||
/* File: symbolta.cc */
|
|
||||||
/* Author: Joachim Schoeberl */
|
|
||||||
/* Date: 01. Jun. 95 */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
/*
|
|
||||||
Abstract data type Symbol Table
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <mystdlib.h>
|
|
||||||
#include <myadt.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef FILE_SYMBOLTABLECC
|
|
||||||
#define FILE_SYMBOLTABLECC
|
|
||||||
// necessary for SGI ????
|
|
||||||
|
|
||||||
|
|
||||||
namespace netgen
|
|
||||||
{
|
|
||||||
//using namespace netgen;
|
|
||||||
|
|
||||||
BASE_SYMBOLTABLE :: BASE_SYMBOLTABLE ()
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
BASE_SYMBOLTABLE :: ~BASE_SYMBOLTABLE()
|
|
||||||
{
|
|
||||||
DelNames();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void BASE_SYMBOLTABLE :: DelNames()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < names.Size(); i++)
|
|
||||||
delete [] names[i];
|
|
||||||
names.SetSize (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int BASE_SYMBOLTABLE :: Index (const char * name) const
|
|
||||||
{
|
|
||||||
if (!name) return 0;
|
|
||||||
for (int i = 0; i < names.Size(); i++)
|
|
||||||
if (strcmp (names[i], name) == 0) return i+1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,163 +0,0 @@
|
|||||||
#ifndef FILE_SYMBOLTA
|
|
||||||
#define FILE_SYMBOLTA
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/* File: symbolta.hh */
|
|
||||||
/* Author: Joachim Schoeberl */
|
|
||||||
/* Date: 01. Jun. 95 */
|
|
||||||
/**************************************************************************/
|
|
||||||
|
|
||||||
namespace netgen
|
|
||||||
{
|
|
||||||
|
|
||||||
/**
|
|
||||||
Base class for the generic SYMBOLTABLE.
|
|
||||||
An array of identifiers is maintained.
|
|
||||||
*/
|
|
||||||
class DLL_HEADER BASE_SYMBOLTABLE
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
/// identifiers
|
|
||||||
Array <char*> names;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Constructor
|
|
||||||
BASE_SYMBOLTABLE ();
|
|
||||||
///
|
|
||||||
~BASE_SYMBOLTABLE ();
|
|
||||||
///
|
|
||||||
void DelNames ();
|
|
||||||
/// Index of symbol name, returns 0 if not used.
|
|
||||||
int Index (const char * name) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Abstract data type Symbol Table.
|
|
||||||
|
|
||||||
To a string an value of the generic type T is associated.
|
|
||||||
The string is not copied into the symbol table class!
|
|
||||||
*/
|
|
||||||
template <class T>
|
|
||||||
class SYMBOLTABLE : public BASE_SYMBOLTABLE
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
/// Associated data
|
|
||||||
Array <T> data;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Creates a symboltable
|
|
||||||
inline SYMBOLTABLE ();
|
|
||||||
/// Returns size of symboltable
|
|
||||||
inline INDEX Size() const;
|
|
||||||
/// Returns reference to element, error if not used
|
|
||||||
inline T & Elem (const char * name);
|
|
||||||
/// Returns reference to i-th element
|
|
||||||
inline T & Elem (int i)
|
|
||||||
{ return data.Elem(i); }
|
|
||||||
/// Returns element, error if not used
|
|
||||||
inline const T & Get (const char * name) const;
|
|
||||||
/// Returns i-th element
|
|
||||||
inline const T & Get (int i) const;
|
|
||||||
/// Returns name of i-th element
|
|
||||||
inline const char* GetName (int i) const;
|
|
||||||
/// Associates el to the string name, overrides if name is used
|
|
||||||
inline void Set (const char * name, const T & el);
|
|
||||||
/// Checks whether name is used
|
|
||||||
inline bool Used (const char * name) const;
|
|
||||||
/// Deletes symboltable
|
|
||||||
inline void DeleteAll ();
|
|
||||||
|
|
||||||
void DoArchive(Archive& archive) { archive & names & data;}
|
|
||||||
|
|
||||||
inline T & operator[] (int i)
|
|
||||||
{ return data[i]; }
|
|
||||||
inline const T & operator[] (int i) const
|
|
||||||
{ return data[i]; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
/// Prevents from copying symboltable by pointer assignment
|
|
||||||
SYMBOLTABLE<T> & operator= (SYMBOLTABLE<T> &);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline SYMBOLTABLE<T> :: SYMBOLTABLE ()
|
|
||||||
{
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline INDEX SYMBOLTABLE<T> :: Size() const
|
|
||||||
{
|
|
||||||
return data.Size();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline T & SYMBOLTABLE<T> :: Elem (const char * name)
|
|
||||||
{
|
|
||||||
int i = Index (name);
|
|
||||||
if (i)
|
|
||||||
return data.Elem (i);
|
|
||||||
else
|
|
||||||
return data.Elem(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline const T & SYMBOLTABLE<T> :: Get (const char * name) const
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
i = Index (name);
|
|
||||||
if (i)
|
|
||||||
return data.Get(i);
|
|
||||||
else
|
|
||||||
return data.Get(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline const T & SYMBOLTABLE<T> :: Get (int i) const
|
|
||||||
{
|
|
||||||
return data.Get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline const char* SYMBOLTABLE<T> :: GetName (int i) const
|
|
||||||
{
|
|
||||||
return names.Get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void SYMBOLTABLE<T> :: Set (const char * name, const T & el)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
i = Index (name);
|
|
||||||
if (i)
|
|
||||||
data.Set(i, el);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
data.Append (el);
|
|
||||||
char * hname = new char [strlen (name) + 1];
|
|
||||||
strcpy (hname, name);
|
|
||||||
names.Append (hname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline bool SYMBOLTABLE<T> :: Used (const char * name) const
|
|
||||||
{
|
|
||||||
return (Index(name)) ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class T>
|
|
||||||
inline void SYMBOLTABLE<T> :: DeleteAll ()
|
|
||||||
{
|
|
||||||
DelNames();
|
|
||||||
data.DeleteAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
@ -9,6 +9,8 @@ if(NOT WIN32)
|
|||||||
install( TARGETS geom2d ${NG_INSTALL_DIR})
|
install( TARGETS geom2d ${NG_INSTALL_DIR})
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
target_link_libraries(geom2d ngcore)
|
||||||
|
|
||||||
if(USE_GUI)
|
if(USE_GUI)
|
||||||
add_library(geom2dvis ${NG_LIB_TYPE} vsgeom2d.cpp)
|
add_library(geom2dvis ${NG_LIB_TYPE} vsgeom2d.cpp)
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
add_definitions(-DNGINTERFACE_EXPORTS)
|
add_definitions(-DNGINTERFACE_EXPORTS)
|
||||||
add_library(gprim OBJECT
|
add_library(gprim INTERFACE)
|
||||||
adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp
|
set(sdir ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp
|
target_sources(gprim INTERFACE
|
||||||
|
${sdir}/adtree.cpp ${sdir}/geom2d.cpp ${sdir}/geom3d.cpp ${sdir}/geomfuncs.cpp
|
||||||
|
${sdir}/geomtest3d.cpp ${sdir}/transform3d.cpp ${sdir}/spline.cpp ${sdir}/splinegeometry.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set_target_properties( gprim PROPERTIES POSITION_INDEPENDENT_CODE ON )
|
|
||||||
|
|
||||||
install(FILES
|
install(FILES
|
||||||
adtree.hpp geom2d.hpp geom3d.hpp geomfuncs.hpp geomobjects2.hpp
|
adtree.hpp geom2d.hpp geom3d.hpp geomfuncs.hpp geomobjects2.hpp
|
||||||
geomobjects.hpp geomops2.hpp geomops.hpp geomtest3d.hpp gprim.hpp
|
geomobjects.hpp geomops2.hpp geomops.hpp geomtest3d.hpp gprim.hpp
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
add_library( la OBJECT
|
add_library( la INTERFACE )
|
||||||
densemat.cpp polynomial.cpp bfgs.cpp linopt.cpp linsearch.cpp
|
set(sdir ${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
)
|
target_sources( la INTERFACE
|
||||||
|
${sdir}/densemat.cpp ${sdir}/polynomial.cpp ${sdir}/bfgs.cpp ${sdir}/linopt.cpp ${sdir}/linsearch.cpp
|
||||||
set_target_properties(la PROPERTIES POSITION_INDEPENDENT_CODE ON )
|
)
|
||||||
|
|
||||||
install(FILES
|
install(FILES
|
||||||
densemat.hpp linalg.hpp opti.hpp
|
densemat.hpp linalg.hpp opti.hpp
|
||||||
|
@ -1,12 +1,4 @@
|
|||||||
add_definitions(-DNGINTERFACE_EXPORTS)
|
add_definitions(-DNGINTERFACE_EXPORTS)
|
||||||
if(NOT WIN32)
|
|
||||||
set(mesh_object_libs
|
|
||||||
$<TARGET_OBJECTS:la>
|
|
||||||
$<TARGET_OBJECTS:gprim>
|
|
||||||
$<TARGET_OBJECTS:gen>
|
|
||||||
)
|
|
||||||
endif(NOT WIN32)
|
|
||||||
|
|
||||||
add_library(mesh ${NG_LIB_TYPE}
|
add_library(mesh ${NG_LIB_TYPE}
|
||||||
adfront2.cpp adfront3.cpp bisect.cpp boundarylayer.cpp
|
adfront2.cpp adfront3.cpp bisect.cpp boundarylayer.cpp
|
||||||
clusters.cpp curvedelems.cpp delaunay.cpp delaunay2d.cpp
|
clusters.cpp curvedelems.cpp delaunay.cpp delaunay2d.cpp
|
||||||
@ -29,8 +21,10 @@ if(APPLE)
|
|||||||
set_target_properties( mesh PROPERTIES SUFFIX ".so")
|
set_target_properties( mesh PROPERTIES SUFFIX ".so")
|
||||||
endif(APPLE)
|
endif(APPLE)
|
||||||
|
|
||||||
|
target_link_libraries( mesh PUBLIC ngcore PRIVATE gprim la gen )
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_link_libraries( mesh ngcore ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY})
|
target_link_libraries( mesh PUBLIC ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY})
|
||||||
install( TARGETS mesh ${NG_INSTALL_DIR})
|
install( TARGETS mesh ${NG_INSTALL_DIR})
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
@ -50,10 +50,6 @@ namespace netgen
|
|||||||
|
|
||||||
string ngdir = ".";
|
string ngdir = ".";
|
||||||
|
|
||||||
// parallel netgen
|
|
||||||
int id = 0, ntasks = 1;
|
|
||||||
|
|
||||||
|
|
||||||
void Ng_PrintDest(const char * s)
|
void Ng_PrintDest(const char * s)
|
||||||
{
|
{
|
||||||
if (id == 0)
|
if (id == 0)
|
||||||
|
@ -6016,7 +6016,7 @@ namespace netgen
|
|||||||
void Mesh :: SetUserData(const char * id, Array<int> & data)
|
void Mesh :: SetUserData(const char * id, Array<int> & data)
|
||||||
{
|
{
|
||||||
if(userdata_int.Used(id))
|
if(userdata_int.Used(id))
|
||||||
delete userdata_int.Get(id);
|
delete userdata_int[id];
|
||||||
|
|
||||||
Array<int> * newdata = new Array<int>(data);
|
Array<int> * newdata = new Array<int>(data);
|
||||||
|
|
||||||
@ -6026,10 +6026,10 @@ namespace netgen
|
|||||||
{
|
{
|
||||||
if(userdata_int.Used(id))
|
if(userdata_int.Used(id))
|
||||||
{
|
{
|
||||||
if(data.Size() < (*userdata_int.Get(id)).Size()+shift)
|
if(data.Size() < (*userdata_int[id]).Size()+shift)
|
||||||
data.SetSize((*userdata_int.Get(id)).Size()+shift);
|
data.SetSize((*userdata_int[id]).Size()+shift);
|
||||||
for(int i=0; i<(*userdata_int.Get(id)).Size(); i++)
|
for(int i=0; i<(*userdata_int[id]).Size(); i++)
|
||||||
data[i+shift] = (*userdata_int.Get(id))[i];
|
data[i+shift] = (*userdata_int[id])[i];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -6041,7 +6041,7 @@ namespace netgen
|
|||||||
void Mesh :: SetUserData(const char * id, Array<double> & data)
|
void Mesh :: SetUserData(const char * id, Array<double> & data)
|
||||||
{
|
{
|
||||||
if(userdata_double.Used(id))
|
if(userdata_double.Used(id))
|
||||||
delete userdata_double.Get(id);
|
delete userdata_double[id];
|
||||||
|
|
||||||
Array<double> * newdata = new Array<double>(data);
|
Array<double> * newdata = new Array<double>(data);
|
||||||
|
|
||||||
@ -6051,10 +6051,10 @@ namespace netgen
|
|||||||
{
|
{
|
||||||
if(userdata_double.Used(id))
|
if(userdata_double.Used(id))
|
||||||
{
|
{
|
||||||
if(data.Size() < (*userdata_double.Get(id)).Size()+shift)
|
if(data.Size() < (*userdata_double[id]).Size()+shift)
|
||||||
data.SetSize((*userdata_double.Get(id)).Size()+shift);
|
data.SetSize((*userdata_double[id]).Size()+shift);
|
||||||
for(int i=0; i<(*userdata_double.Get(id)).Size(); i++)
|
for(int i=0; i<(*userdata_double[id]).Size(); i++)
|
||||||
data[i+shift] = (*userdata_double.Get(id))[i];
|
data[i+shift] = (*userdata_double[id])[i];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -132,8 +132,8 @@ namespace netgen
|
|||||||
/// mesh access semaphors.
|
/// mesh access semaphors.
|
||||||
NgMutex majormutex;
|
NgMutex majormutex;
|
||||||
|
|
||||||
SYMBOLTABLE< Array<int>* > userdata_int;
|
SymbolTable< Array<int>* > userdata_int;
|
||||||
SYMBOLTABLE< Array<double>* > userdata_double;
|
SymbolTable< Array<double>* > userdata_double;
|
||||||
|
|
||||||
|
|
||||||
mutable Array< Point3d > pointcurves;
|
mutable Array< Point3d > pointcurves;
|
||||||
|
@ -506,7 +506,6 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
|
|||||||
)
|
)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.def("__str__", &ToString<Mesh>)
|
|
||||||
.def_property_readonly("_timestamp", &Mesh::GetTimeStamp)
|
.def_property_readonly("_timestamp", &Mesh::GetTimeStamp)
|
||||||
.def("Load", FunctionPointer
|
.def("Load", FunctionPointer
|
||||||
([](Mesh & self, const string & filename)
|
([](Mesh & self, const string & filename)
|
||||||
|
@ -8,11 +8,13 @@ if(USE_GUI)
|
|||||||
add_library(occvis ${NG_LIB_TYPE} vsocc.cpp)
|
add_library(occvis ${NG_LIB_TYPE} vsocc.cpp)
|
||||||
endif(USE_GUI)
|
endif(USE_GUI)
|
||||||
|
|
||||||
|
target_link_libraries(occ PUBLIC ngcore)
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_link_libraries( occ ${OCC_LIBRARIES} ${PYTHON_LIBRARIES})
|
target_link_libraries( occ PUBLIC ${OCC_LIBRARIES} ${PYTHON_LIBRARIES})
|
||||||
install( TARGETS occ ${NG_INSTALL_DIR})
|
install( TARGETS occ ${NG_INSTALL_DIR})
|
||||||
if (USE_GUI)
|
if (USE_GUI)
|
||||||
target_link_libraries( occvis occ )
|
target_link_libraries( occvis PUBLIC occ )
|
||||||
install( TARGETS occvis ${NG_INSTALL_DIR})
|
install( TARGETS occvis ${NG_INSTALL_DIR})
|
||||||
endif(USE_GUI)
|
endif(USE_GUI)
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
@ -4,11 +4,13 @@ add_library(stl ${NG_LIB_TYPE}
|
|||||||
)
|
)
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_link_libraries( stl mesh ${PYTHON_LIBRARIES})
|
target_link_libraries( stl mesh ${PYTHON_LIBRARIES})
|
||||||
target_link_libraries( stl ${PYTHON_LIBRARIES})
|
|
||||||
install( TARGETS stl ${NG_INSTALL_DIR})
|
install( TARGETS stl ${NG_INSTALL_DIR})
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
target_link_libraries( stl ngcore )
|
||||||
|
|
||||||
|
|
||||||
if(USE_GUI)
|
if(USE_GUI)
|
||||||
add_library(stlvis ${NG_LIB_TYPE}
|
add_library(stlvis ${NG_LIB_TYPE}
|
||||||
vsstl.cpp
|
vsstl.cpp
|
||||||
|
@ -598,7 +598,6 @@ void STLSurfaceMeshing1 (STLGeometry & geom,
|
|||||||
|
|
||||||
for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++)
|
for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++)
|
||||||
{
|
{
|
||||||
if (fnr == 100) NgProfiler::ClearTimers();
|
|
||||||
if (!opensegsperface[fnr]) continue;
|
if (!opensegsperface[fnr]) continue;
|
||||||
if (multithread.terminate) return;
|
if (multithread.terminate) return;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ endif(USE_GUI)
|
|||||||
add_library(visual ${NG_LIB_TYPE} ${LIB_VISUAL_SOURCES})
|
add_library(visual ${NG_LIB_TYPE} ${LIB_VISUAL_SOURCES})
|
||||||
|
|
||||||
if(NOT WIN32)
|
if(NOT WIN32)
|
||||||
target_link_libraries( visual ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} )
|
target_link_libraries( visual ngcore ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} )
|
||||||
install( TARGETS visual ${NG_INSTALL_DIR})
|
install( TARGETS visual ${NG_INSTALL_DIR})
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
@ -1840,9 +1840,9 @@ namespace netgen
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
SYMBOLTABLE<VisualScene*> & GetVisualizationScenes ()
|
SymbolTable<VisualScene*> & GetVisualizationScenes ()
|
||||||
{
|
{
|
||||||
static SYMBOLTABLE<VisualScene*> vss;
|
static SymbolTable<VisualScene*> vss;
|
||||||
return vss;
|
return vss;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1860,7 +1860,7 @@ namespace netgen
|
|||||||
vs = &vscross;
|
vs = &vscross;
|
||||||
if (GetVisualizationScenes().Used(vismode))
|
if (GetVisualizationScenes().Used(vismode))
|
||||||
{
|
{
|
||||||
vs = GetVisualizationScenes().Get(vismode);
|
vs = GetVisualizationScenes()[vismode];
|
||||||
}
|
}
|
||||||
else if (vismode)
|
else if (vismode)
|
||||||
{
|
{
|
||||||
|
@ -8,9 +8,6 @@ if(WIN32)
|
|||||||
$<TARGET_OBJECTS:geom2d>
|
$<TARGET_OBJECTS:geom2d>
|
||||||
$<TARGET_OBJECTS:csg>
|
$<TARGET_OBJECTS:csg>
|
||||||
$<TARGET_OBJECTS:stl>
|
$<TARGET_OBJECTS:stl>
|
||||||
$<TARGET_OBJECTS:gen>
|
|
||||||
$<TARGET_OBJECTS:la>
|
|
||||||
$<TARGET_OBJECTS:gprim>
|
|
||||||
|
|
||||||
$<TARGET_OBJECTS:visual>
|
$<TARGET_OBJECTS:visual>
|
||||||
$<TARGET_OBJECTS:occ>
|
$<TARGET_OBJECTS:occ>
|
||||||
@ -32,6 +29,7 @@ if(NOT WIN32)
|
|||||||
endif(USE_GUI)
|
endif(USE_GUI)
|
||||||
endif(NOT WIN32)
|
endif(NOT WIN32)
|
||||||
|
|
||||||
|
# target_link_libraries(nglib PRIVATE gen la gprim PUBLIC ngcore)
|
||||||
target_link_libraries(nglib PUBLIC ngcore)
|
target_link_libraries(nglib PUBLIC ngcore)
|
||||||
|
|
||||||
target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} )
|
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} )
|
||||||
|
8
tests/build_nospdlog.sh
Normal file
8
tests/build_nospdlog.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
cd
|
||||||
|
mkdir -p build/netgen
|
||||||
|
cd build/netgen
|
||||||
|
cmake ../../src/netgen -DUSE_CCACHE=ON -DUSE_SPDLOG=OFF -DCMAKE_CXX_COMPILER=clang++ \
|
||||||
|
-DCMAKE_C_COMPILER=clang
|
||||||
|
make -j12
|
||||||
|
make install
|
||||||
|
|
@ -3,8 +3,7 @@ if(ENABLE_UNIT_TESTS)
|
|||||||
add_custom_target(unit_tests)
|
add_custom_target(unit_tests)
|
||||||
|
|
||||||
# Build catch_main test object
|
# Build catch_main test object
|
||||||
message("netgen include dir = ${NETGEN_INCLUDE_DIR_ABSOLUTE} --------------------------------------")
|
include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include ${SPDLOG_INCLUDE_DIR})
|
||||||
include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include})
|
|
||||||
add_library(catch_main STATIC main.cpp)
|
add_library(catch_main STATIC main.cpp)
|
||||||
set_target_properties(catch_main PROPERTIES CXX_STANDARD 17)
|
set_target_properties(catch_main PROPERTIES CXX_STANDARD 17)
|
||||||
add_dependencies(unit_tests catch_main)
|
add_dependencies(unit_tests catch_main)
|
||||||
@ -15,23 +14,19 @@ add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_
|
|||||||
|
|
||||||
macro(add_unit_test name sources)
|
macro(add_unit_test name sources)
|
||||||
add_executable(test_${name} ${sources} )
|
add_executable(test_${name} ${sources} )
|
||||||
if (WIN32)
|
target_link_libraries(test_${name} ngcore catch_main)
|
||||||
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_dependencies(unit_tests test_${name})
|
||||||
add_test(NAME unit_${name} COMMAND test_${name})
|
add_test(NAME unit_${name} COMMAND test_${name})
|
||||||
set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built)
|
set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built)
|
||||||
|
|
||||||
|
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
||||||
|
set_target_properties(test_${name} PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}")
|
||||||
|
endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
add_unit_test(archive archive.cpp)
|
add_unit_test(archive archive.cpp)
|
||||||
|
add_unit_test(symboltable symboltable.cpp)
|
||||||
add_unit_test(version version.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)
|
endif(ENABLE_UNIT_TESTS)
|
||||||
|
64
tests/catch/symboltable.cpp
Normal file
64
tests/catch/symboltable.cpp
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
|
||||||
|
#include "catch.hpp"
|
||||||
|
#include <../core/ngcore.hpp>
|
||||||
|
using namespace ngcore;
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
TEST_CASE("Symboltable")
|
||||||
|
{
|
||||||
|
SymbolTable<int> table;
|
||||||
|
CHECK_THROWS_AS(table["test"], RangeException);
|
||||||
|
table.Set("first", 1);
|
||||||
|
CHECK(table["first"] == 1);
|
||||||
|
table["first"] = 2;
|
||||||
|
CHECK(table["first"] == 2);
|
||||||
|
auto index = table.Index("first");
|
||||||
|
CHECK(index == 0);
|
||||||
|
CHECK(table[index] == 2);
|
||||||
|
table[index] = 3;
|
||||||
|
CHECK(table["first"] == 3);
|
||||||
|
#ifndef NDEBUG
|
||||||
|
int a;
|
||||||
|
CHECK_THROWS_AS(a = table[5], RangeException);
|
||||||
|
CHECK_THROWS_AS(table.GetName(5), RangeException);
|
||||||
|
#endif
|
||||||
|
CHECK(table.Used("first"));
|
||||||
|
CHECK(!table.Used("second"));
|
||||||
|
SymbolTable<int> another;
|
||||||
|
another.Set("first", 1);
|
||||||
|
another.Set("second", 2);
|
||||||
|
table.Update(another);
|
||||||
|
CHECK(table["first"] == 1);
|
||||||
|
CHECK(table["second"] == 2);
|
||||||
|
std::stringstream s;
|
||||||
|
s << table;
|
||||||
|
CHECK(s.str() == "first : 1\nsecond : 2\n");
|
||||||
|
auto ss = std::make_shared<std::stringstream>();
|
||||||
|
BinaryOutArchive ao(ss);
|
||||||
|
ao & table;
|
||||||
|
ao.FlushBuffer();
|
||||||
|
BinaryInArchive ai(ss);
|
||||||
|
SymbolTable<int> read;
|
||||||
|
ai & read;
|
||||||
|
for(size_t i = 0; i<table.Size(); i++)
|
||||||
|
{
|
||||||
|
CHECK(read[i] == table[i]);
|
||||||
|
CHECK(read.GetName(i) == table.GetName(i));
|
||||||
|
}
|
||||||
|
table.DeleteAll();
|
||||||
|
CHECK(table.Size() == 0);
|
||||||
|
// SymbolTable<bool> is special because of vector<bool> is special...
|
||||||
|
SymbolTable<bool> btable;
|
||||||
|
btable.Set("true", true);
|
||||||
|
btable.Set("false", false);
|
||||||
|
CHECK(btable[0]);
|
||||||
|
CHECK(!btable[1]);
|
||||||
|
CHECK(btable["true"]);
|
||||||
|
CHECK(!btable["false"]);
|
||||||
|
ao & btable;
|
||||||
|
ao.FlushBuffer();
|
||||||
|
SymbolTable<bool> bread;
|
||||||
|
ai & bread;
|
||||||
|
CHECK(bread["true"]);
|
||||||
|
CHECK(!bread["false"]);
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user