From 2a39b426aa0d0a0df8578fbe145ae0e47b1ffa63 Mon Sep 17 00:00:00 2001 From: Michael Date: Mon, 5 Nov 2018 10:45:33 +0100 Subject: [PATCH 01/98] add get refinement level function for hp refinement. Works for point singularities --- libsrc/include/nginterface_v2.hpp | 2 + libsrc/interface/nginterface_v2.cpp | 20 +++++++++ libsrc/meshing/hprefinement.cpp | 69 ++++++++++++----------------- 3 files changed, 51 insertions(+), 40 deletions(-) diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 580a340a..61714700 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -296,6 +296,8 @@ namespace netgen void (*taskmanager)(function) = &DummyTaskManager2, void (*tracer)(string, bool) = &DummyTracer2); + int GetElementLevel (int ei) const; + void GetParentNodes (int ni, int * parents) const; int GetParentElement (int ei) const; int GetParentSElement (int ei) const; diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index 5e2bbd34..f2b5032b 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -675,6 +675,26 @@ namespace netgen } + int Ngx_Mesh :: GetElementLevel (int ei) const + { + ei++; + + if (mesh->hpelements) + { + int hpelnr = -1; + if (mesh->GetDimension() == 2) + hpelnr = mesh->SurfaceElement(ei).hp_elnr; + else + hpelnr = mesh->VolumeElement(ei).hp_elnr; + + return (*mesh->hpelements)[hpelnr].levelx; + } + //else + // throw NgException("Ngx_Mesh::GetElementLevel only for HPRefinement implemented!"); + + return -1; + } + int Ngx_Mesh :: GetParentElement (int ei) const { ei++; diff --git a/libsrc/meshing/hprefinement.cpp b/libsrc/meshing/hprefinement.cpp index a26945e6..0216a711 100644 --- a/libsrc/meshing/hprefinement.cpp +++ b/libsrc/meshing/hprefinement.cpp @@ -22,8 +22,9 @@ namespace netgen { pnums[i] = -1; param[i][0] = param[i][1] = param[i][2] = 0; - domin=-1; domout=-1; // he: } + domin=-1; domout=-1; // he: + levelx = 0; levely = 0; levelz = 0; } HPRefElement :: HPRefElement () @@ -31,46 +32,40 @@ namespace netgen Reset(); } - HPRefElement :: HPRefElement(Element & el) + HPRefElement :: HPRefElement(Element & el) : + np(el.GetNV()), index(el.GetIndex()), levelx(0), levely(0), levelz(0), type(HP_NONE), domin(-1), domout(-1) //domin,out for segements { //Reset(); - np = el.GetNV(); for (int i=0; igeom) { @@ -823,21 +800,33 @@ namespace netgen *testout << endl; */ + bool last = false; while (hprs->neweltypes[j]) { + if (!hprs->neweltypes[j+1] || !hprs->neweltypes[j+2]) + last = true; + HPRef_Struct * hprsnew = Get_HPRef_Struct (hprs->neweltypes[j]); HPRefElement newel(el); newel.type = hprs->neweltypes[j]; - // newel.index = elements[i].index; // newel.coarse_elnr = elements[i].coarse_elnr; newel.levelx = newel.levely = newel.levelz = newlevel; + switch(hprsnew->geom) { case HP_SEGM: newel.np=2; break; - case HP_QUAD: newel.np=4; break; - case HP_TRIG: newel.np=3; break; + case HP_QUAD: + newel.np=4; + if (last) + newlevel--; + break; + case HP_TRIG: + newel.np=3; + if (last) + newlevel--; + break; case HP_HEX: newel.np=8; break; case HP_PRISM: newel.np=6; break; case HP_TET: newel.np=4; break; @@ -868,7 +857,7 @@ namespace netgen if (j == 0) elements[i] = newel; // overwrite old element - else + else elements.Append (newel); j++; } @@ -1337,7 +1326,7 @@ namespace netgen Array & hpelements = *mesh.hpelements; InitHPElements(mesh,hpelements); - + Array nplevel; nplevel.Append (mesh.GetNP()); From 355eed48183dd6aa1bef561df124ac241d9c16a0 Mon Sep 17 00:00:00 2001 From: Michael Neunteufel Date: Thu, 6 Dec 2018 11:23:20 +0100 Subject: [PATCH 02/98] hp level (should) work now for all singularities in 2D. Maybe also 3D? --- libsrc/meshing/hprefinement.cpp | 37 +++++++++++++++------------------ 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/libsrc/meshing/hprefinement.cpp b/libsrc/meshing/hprefinement.cpp index 0216a711..d2752ba8 100644 --- a/libsrc/meshing/hprefinement.cpp +++ b/libsrc/meshing/hprefinement.cpp @@ -684,7 +684,7 @@ namespace netgen { HPRefElement el = elements[i]; HPRef_Struct * hprs = Get_HPRef_Struct (el.type); - int newlevel = el.levelx + 1; + int newlevel = el.levelx; int oldnp = 0; switch (hprs->geom) { @@ -800,36 +800,33 @@ namespace netgen *testout << endl; */ - bool last = false; while (hprs->neweltypes[j]) { - if (!hprs->neweltypes[j+1] || !hprs->neweltypes[j+2]) - last = true; - HPRef_Struct * hprsnew = Get_HPRef_Struct (hprs->neweltypes[j]); HPRefElement newel(el); newel.type = hprs->neweltypes[j]; // newel.index = elements[i].index; // newel.coarse_elnr = elements[i].coarse_elnr; - newel.levelx = newel.levely = newel.levelz = newlevel; + if (newel.type == HP_SEGM || + newel.type == HP_TRIG || + newel.type == HP_QUAD || + newel.type == HP_TET || + newel.type == HP_PRISM || + newel.type == HP_HEX || + newel.type == HP_PYRAMID) + newel.levelx = newel.levely = newel.levelz = newlevel; + else + newel.levelx = newel.levely = newel.levelz = newlevel+1; switch(hprsnew->geom) { - case HP_SEGM: newel.np=2; break; - case HP_QUAD: - newel.np=4; - if (last) - newlevel--; - break; - case HP_TRIG: - newel.np=3; - if (last) - newlevel--; - break; - case HP_HEX: newel.np=8; break; - case HP_PRISM: newel.np=6; break; - case HP_TET: newel.np=4; break; + case HP_SEGM: newel.np=2; break; + case HP_QUAD: newel.np=4; break; + case HP_TRIG: newel.np=3; break; + case HP_HEX: newel.np=8; break; + case HP_PRISM: newel.np=6; break; + case HP_TET: newel.np=4; break; case HP_PYRAMID: newel.np=5; break; default: throw NgException (string("hprefinement.cpp: illegal type")); From d17e6c42bcc00af152942e238186b11d62719326 Mon Sep 17 00:00:00 2001 From: Michael Neunteufel Date: Thu, 6 Dec 2018 12:49:38 +0100 Subject: [PATCH 03/98] anisotrop level possible --- libsrc/include/nginterface_v2.hpp | 2 +- libsrc/interface/nginterface_v2.cpp | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 61714700..5a9627a5 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -296,7 +296,7 @@ namespace netgen void (*taskmanager)(function) = &DummyTaskManager2, void (*tracer)(string, bool) = &DummyTracer2); - int GetElementLevel (int ei) const; + int GetHPElementLevel (int ei, int dir) const; void GetParentNodes (int ni, int * parents) const; int GetParentElement (int ei) const; diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index f2b5032b..97414a6f 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -675,9 +675,10 @@ namespace netgen } - int Ngx_Mesh :: GetElementLevel (int ei) const + int Ngx_Mesh :: GetHPElementLevel (int ei, int dir) const { ei++; + int level = -1; if (mesh->hpelements) { @@ -687,12 +688,22 @@ namespace netgen else hpelnr = mesh->VolumeElement(ei).hp_elnr; - return (*mesh->hpelements)[hpelnr].levelx; + if (hpelnr < 0) + throw NgException("Ngx_Mesh::GetHPElementLevel: Wrong hp-element number!"); + + if (dir == 1) + level = (*mesh->hpelements)[hpelnr].levelx; + else if (dir == 2) + level = (*mesh->hpelements)[hpelnr].levely; + else if (dir == 3) + level = (*mesh->hpelements)[hpelnr].levelz; + else + throw NgException("Ngx_Mesh::GetHPElementLevel: dir has to be 1, 2 or 3!"); } //else - // throw NgException("Ngx_Mesh::GetElementLevel only for HPRefinement implemented!"); + // throw NgException("Ngx_Mesh::GetHPElementLevel only for HPRefinement implemented!"); - return -1; + return level; } int Ngx_Mesh :: GetParentElement (int ei) const From 8665dea15e91030780f57d29b906594f335fa1e9 Mon Sep 17 00:00:00 2001 From: Michael Neunteufel Date: Fri, 7 Dec 2018 13:47:35 +0100 Subject: [PATCH 04/98] Added material name for 0D elements --- libsrc/include/nginterface_v2_impl.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libsrc/include/nginterface_v2_impl.hpp b/libsrc/include/nginterface_v2_impl.hpp index aa538761..dec640b6 100644 --- a/libsrc/include/nginterface_v2_impl.hpp +++ b/libsrc/include/nginterface_v2_impl.hpp @@ -63,6 +63,13 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (size_t nr) const ret.facets.num = 1; ret.facets.base = 1; ret.facets.ptr = (int*)&el.pnum; + + if (mesh->GetDimension() == 1) + ret.mat = mesh->GetBCNamePtr(el.index-1); + else if (mesh->GetDimension() == 2) + ret.mat = mesh->GetCD2NamePtr(el.index-1); + else + ret.mat = mesh->GetCD3NamePtr(el.index-1); return ret; } From fd3474f5cb5632f219e4f70b79792c9a804ec19e Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 28 Dec 2018 13:43:15 +0100 Subject: [PATCH 05/98] logging in ngcore --- .gitlab-ci.yml | 7 ++ CMakeLists.txt | 8 ++ cmake/SuperBuild.cmake | 2 + cmake/external_projects/spdlog.cmake | 18 ++++ libsrc/core/CMakeLists.txt | 31 +++++- libsrc/core/archive.hpp | 140 +++++++++++++++++++++------ libsrc/core/logging.cpp | 109 +++++++++++++++++++++ libsrc/core/logging.hpp | 87 +++++++++++++++++ libsrc/core/ngcore.hpp | 1 + libsrc/core/ngcore_api.hpp | 4 +- libsrc/core/python_ngcore.cpp | 30 ++++++ libsrc/general/CMakeLists.txt | 4 + libsrc/gprim/CMakeLists.txt | 3 + libsrc/linalg/CMakeLists.txt | 4 + libsrc/meshing/python_mesh.cpp | 1 - libsrc/occ/CMakeLists.txt | 2 +- libsrc/stlgeom/CMakeLists.txt | 3 +- libsrc/visualization/CMakeLists.txt | 2 +- tests/build_nospdlog.sh | 8 ++ tests/catch/CMakeLists.txt | 9 +- 20 files changed, 428 insertions(+), 45 deletions(-) create mode 100644 cmake/external_projects/spdlog.cmake create mode 100644 libsrc/core/logging.cpp create mode 100644 libsrc/core/logging.hpp create mode 100644 libsrc/core/python_ngcore.cpp create mode 100644 tests/build_nospdlog.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 86105bfb..d493bdab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -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 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: stage: cleanup tags: diff --git a/CMakeLists.txt b/CMakeLists.txt index 14931c4d..5d2e6a9f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,6 +19,8 @@ option( USE_CCACHE "use ccache") option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON) option( ENABLE_UNIT_TESTS "Enable Catch unit tests") option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF) +option( USE_SPDLOG "Enable spd log logging" ON) +option( DEBUG_LOG "Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON" OFF) option( USE_SUPERBUILD "use ccache" ON) @@ -258,6 +260,7 @@ endif (USE_GUI) ####################################################################### if (USE_PYTHON) + add_subdirectory(external_dependencies/pybind11) add_definitions(-DNG_PYTHON) find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h HINTS ${PYTHON_INCLUDE_DIR}) if( PYBIND_INCLUDE_DIR ) @@ -350,6 +353,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) find_program( CLANG_TIDY_EXE diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 36ea3fcb..6e7fabd7 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -142,6 +142,8 @@ set_vars( NETGEN_CMAKE_ARGS CMAKE_INSTALL_PREFIX ENABLE_UNIT_TESTS ENABLE_CPP_CORE_GUIDELINES_CHECK + USE_SPDLOG + DEBUG_LOG ) # propagate all variables set on the command line using cmake -DFOO=BAR diff --git a/cmake/external_projects/spdlog.cmake b/cmake/external_projects/spdlog.cmake new file mode 100644 index 00000000..d932ebef --- /dev/null +++ b/cmake/external_projects/spdlog.cmake @@ -0,0 +1,18 @@ +include(ExternalProject) +find_program(GIT_EXECUTABLE git) + +ExternalProject_Add( + project_spdlog + PREFIX ${CMAKE_BINARY_DIR}/spdlog + GIT_REPOSITORY https://github.com/gabime/spdlog.git + GIT_TAG v1.2.1 + TIMEOUT 01 + UPDATE_COMMAND "" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + +ExternalProject_Get_Property(project_spdlog source_dir) +set(SPDLOG_INCLUDE_DIR ${source_dir}/include) diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 92f2e8b7..16cec927 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,16 +1,41 @@ -add_library(ngcore SHARED archive.cpp) -target_compile_definitions(ngcore PRIVATE -DNGCORE_EXPORTS) +add_library(ngcore SHARED archive.cpp logging.cpp) + +target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) +if(NOT WIN32) + target_compile_options(ngcore PRIVATE -fvisibility=hidden) +endif(NOT WIN32) + +if(USE_SPDLOG) + include_directories(${SPDLOG_INCLUDE_DIR}) + install(DIRECTORY ${SPDLOG_INCLUDE_DIR} + DESTINATION ${NG_INSTALL_DIR_INCLUDE} + ) + add_dependencies(ngcore project_spdlog) + target_compile_definitions(ngcore PUBLIC NETGEN_USE_SPDLOG) + if(DEBUG_LOG) + target_compile_definitions(ngcore PUBLIC NETGEN_LOG_DEBUG) + endif(DEBUG_LOG) +endif(USE_SPDLOG) install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) if(USE_PYTHON) + target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON) target_include_directories(ngcore PUBLIC ${PYTHON_INCLUDE_DIRS}) 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 DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) set_target_properties(ngcore PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) + +if(USE_PYTHON) + pybind11_add_module(pyngcore SHARED python_ngcore.cpp) + target_link_libraries(pyngcore PUBLIC ngcore) + set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}") + install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen) +endif(USE_PYTHON) + diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index fd2ee275..aa6537d2 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -3,24 +3,25 @@ #include // for complex #include // for size_t, strlen -#include // for operator<<, ifstream, ofstream, basic... +#include // for ifstream, ofstream #include // for function -#include // for map, _Rb_tree_iterator -#include // for __shared_ptr_access, __shared_ptr_acc... +#include // for map +#include // for shared_ptr #include // for runtime_error -#include // for string, operator+ +#include // for string #include // for declval, enable_if, false_type, is_co... #include // for type_info #include // for move, swap, pair #include // for vector +#include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API, unlikely #include "type_traits.hpp" // for all_of_tmpl #include "version.hpp" // for VersionInfo -#ifdef NG_PYTHON +#ifdef NETGEN_PYTHON #include -#endif // NG_PYTHON +#endif // NETGEN_PYTHON namespace ngcore { @@ -104,20 +105,28 @@ namespace ngcore std::vector nr2ptr; protected: bool shallow_to_python = false; + // version map is only used in InArchives + std::map version_map; + std::shared_ptr logger; public: Archive() = delete; Archive(const Archive&) = delete; Archive(Archive&&) = delete; - Archive (bool ais_output) : - is_output(ais_output), shared_ptr_count(0), ptr_count(0) { ; } + Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), + ptr_count(0), logger(GetLogger("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 Archive& Shallow(T& val) { static_assert(detail::is_any_pointer, "ShallowArchive must be given pointer type!"); -#ifdef NG_PYTHON +#ifdef NETGEN_PYTHON if(shallow_to_python) { if(is_output) @@ -126,17 +135,17 @@ namespace ngcore val = pybind11::cast(ShallowInPython()); } else -#endif // NG_PYTHON +#endif // NETGEN_PYTHON *this & val; return *this; } -#ifdef NG_PYTHON - virtual void ShallowOutPython(pybind11::object /*unused*/) // NOLINT (copy by val is ok for this virt func) +#ifdef NETGEN_PYTHON + virtual void ShallowOutPython(const pybind11::object& /*unused*/) { throw std::runtime_error("Should not get in ShallowToPython base class implementation!"); } virtual pybind11::object ShallowInPython() { throw std::runtime_error("Should not get in ShallowFromPython base class implementation!"); } -#endif // NG_PYTHON +#endif // NETGEN_PYTHON Archive& operator=(const Archive&) = delete; Archive& operator=(Archive&&) = delete; @@ -261,28 +270,39 @@ namespace ngcore { if(Output()) { + NETGEN_DEBUG_LOG(logger, "Store shared ptr of type " + Demangle(typeid(T).name())); // save -2 for nullptr if(!ptr) - return (*this) << -2; + { + NETGEN_DEBUG_LOG(logger, "Storing nullptr"); + return (*this) << -2; + } void* reg_ptr = ptr.get(); bool neededDowncast = false; // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { + NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " + + Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*ptr).name()) + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information - if(reg_ptr != static_cast(ptr.get()) ) + if(reg_ptr != static_cast(ptr.get())) + { + NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer"); neededDowncast = true; + } } auto pos = shared_ptr2nr.find(reg_ptr); // if not found store -1 and the pointer if(pos == shared_ptr2nr.end()) { + 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(); (*this) << -1; (*this) & neededDowncast & p; @@ -293,23 +313,27 @@ namespace ngcore return *this; } // 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; if(neededDowncast) (*this) << Demangle(typeid(*ptr).name()); } else // Input { + NETGEN_DEBUG_LOG(logger, "Reading shared_ptr of type " + Demangle(typeid(T).name())); int nr; (*this) & nr; // -2 restores a nullptr if(nr == -2) { + NETGEN_DEBUG_LOG(logger, "Reading a nullptr"); ptr = nullptr; return *this; } // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it if (nr == -1) { + NETGEN_DEBUG_LOG(logger, "Createing new shared_ptr"); T* p = nullptr; bool neededDowncast; (*this) & neededDowncast & p; @@ -317,6 +341,7 @@ namespace ngcore // if we did downcast we need to store a shared_ptr to the true object if(neededDowncast) { + NETGEN_DEBUG_LOG(logger, "Shared pointer needed downcasting"); std::string name; (*this) & name; auto info = GetArchiveRegister(name); @@ -327,15 +352,20 @@ namespace ngcore ptr.get()))); } else - nr2shared_ptr.push_back(ptr); + { + NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need downcasting"); + nr2shared_ptr.push_back(ptr); + } } else { + NETGEN_DEBUG_LOG(logger, "Reading already existing pointer at entry " + std::to_string(nr)); auto other = nr2shared_ptr[nr]; bool neededDowncast; (*this) & 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 // wouldn't have worked else) std::string name; @@ -348,7 +378,10 @@ namespace ngcore other.get()))); } else - ptr = std::static_pointer_cast(other); + { + NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need pointer casts"); + ptr = std::static_pointer_cast(other); + } } } return *this; @@ -360,26 +393,39 @@ namespace ngcore { if (Output()) { + NETGEN_DEBUG_LOG(logger, "Store pointer of type " + Demangle(typeid(T).name())); // if the pointer is null store -2 if (!p) - return (*this) << -2; + { + NETGEN_DEBUG_LOG(logger, "Storing nullptr"); + return (*this) << -2; + } auto reg_ptr = static_cast(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()))) throw std::runtime_error(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); + if(reg_ptr != static_cast(p)) + { + NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer"); + } } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry if (pos == ptr2nr.end()) { + NETGEN_DEBUG_LOG(logger, "Didn't find pointer, create new registry entry at " + + std::to_string(ptr_count)); ptr2nr[reg_ptr] = ptr_count++; if(typeid(*p) == typeid(T)) if (std::is_constructible::value) { + NETGEN_DEBUG_LOG(logger, "Store standard class pointer (no virt. inh,...)"); return (*this) << -1 & (*p); } else @@ -395,6 +441,7 @@ namespace ngcore throw std::runtime_error(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) + " not registered for archive"); + NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer"); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } } @@ -402,27 +449,39 @@ namespace ngcore { (*this) & pos->second; bool downcasted = !(reg_ptr == static_cast(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 (*this) << downcasted << Demangle(typeid(*p).name()); } } else { + NETGEN_DEBUG_LOG(logger, "Reading pointer of type " + Demangle(typeid(T).name())); int nr; (*this) & nr; if (nr == -2) // restore a nullptr + { + NETGEN_DEBUG_LOG(logger, "Loading a nullptr"); p = nullptr; + } 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(); nr2ptr.push_back(p); (*this) & *p; } 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 std::string name; (*this) & name; + NETGEN_DEBUG_LOG(logger, "Name = " + name); auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) @@ -434,9 +493,13 @@ namespace ngcore } else { + NETGEN_DEBUG_LOG(logger, "Restoring pointer to already existing object at registry position " + + std::to_string(nr)); bool downcasted; std::string name; (*this) & downcasted & name; + NETGEN_DEBUG_LOG(logger, std::string(downcasted ? "Downcasted" : "Not downcasted") + + " object of type " + name); if(downcasted) { // if the class has been downcasted we can assume it is in the register @@ -536,7 +599,7 @@ namespace ngcore { static_assert(detail::all_of_tmpl::value...>, "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* { return typeid(T) == ti ? detail::constructIfPossible() : Archive::Caster::tryUpcast(ti, detail::constructIfPossible()); }; @@ -643,6 +706,9 @@ namespace ngcore BinaryInArchive (const std::string& filename) : BinaryInArchive(std::make_shared(filename)) { ; } + const VersionInfo& GetVersion(const std::string& library) override + { return version_map[library]; } + using Archive::operator&; Archive & operator & (double & d) override { Read(d); return *this; } @@ -758,6 +824,9 @@ namespace ngcore TextInArchive (const std::string& filename) : TextInArchive(std::make_shared(filename)) {} + const VersionInfo& GetVersion(const std::string& library) override + { return version_map[library]; } + using Archive::operator&; Archive & operator & (double & d) override { *stream >> d; return *this; } @@ -805,7 +874,7 @@ namespace ngcore } }; -#ifdef NG_PYTHON +#ifdef NETGEN_PYTHON template class PyArchive : public ARCHIVE @@ -813,7 +882,11 @@ namespace ngcore private: pybind11::list lst; size_t index = 0; + protected: using ARCHIVE::stream; + using ARCHIVE::version_map; + using ARCHIVE::logger; + using ARCHIVE::GetLibraryVersions; public: PyArchive(const pybind11::object& alst = pybind11::none()) : ARCHIVE(std::make_shared()), @@ -821,8 +894,13 @@ namespace ngcore { ARCHIVE::shallow_to_python = true; if(Input()) - stream = std::make_shared - (pybind11::cast(lst[pybind11::len(lst)-1])); + { + stream = std::make_shared + (pybind11::cast(lst[pybind11::len(lst)-1])); + *this & version_map; + stream = std::make_shared + (pybind11::cast(lst[pybind11::len(lst)-2])); + } } using ARCHIVE::Output; @@ -831,39 +909,45 @@ namespace ngcore using ARCHIVE::operator&; using ARCHIVE::operator<<; 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::list WriteOut() { FlushBuffer(); lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); + stream = std::make_shared(); + *this & GetLibraryVersions(); return lst; } }; template - auto NGSPickle(bool printoutput=false) + auto NGSPickle() { - return pybind11::pickle([printoutput](T* self) + return pybind11::pickle([](T* self) { PyArchive ar; ar & self; auto output = pybind11::make_tuple(ar.WriteOut()); - if(printoutput) - pybind11::print("pickle output of", Demangle(typeid(T).name()),"=", output); + NETGEN_DEBUG_LOG(GetLogger("Archive"), "pickling output for object of type " + + Demangle(typeid(T).name()) + " = " + + std::string(pybind11::str(output))); return output; }, [](pybind11::tuple state) { 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 ar(state[0]); ar & val; return val; }); } -#endif // NG_PYTHON +#endif // NETGEN_PYTHON } // namespace ngcore #endif // NETGEN_CORE_ARCHIVE_HPP diff --git a/libsrc/core/logging.cpp b/libsrc/core/logging.cpp new file mode 100644 index 00000000..467255cd --- /dev/null +++ b/libsrc/core/logging.cpp @@ -0,0 +1,109 @@ + +#include "logging.hpp" + +#ifdef NETGEN_USE_SPDLOG + +#include +#include + +#endif // NETGEN_USE_SPDLOG + +namespace ngcore +{ +#ifdef NETGEN_USE_SPDLOG + namespace detail + { + std::vector>& GetDefaultSinks() + { + static std::vector> sinks = + { std::make_shared() }; + return sinks; + } + std::shared_ptr CreateDefaultLogger(const std::string& name) + { + auto& default_sinks = GetDefaultSinks(); + auto logger = std::make_shared(name, default_sinks.begin(), default_sinks.end()); + spdlog::details::registry::instance().register_and_init(logger); + return logger; + } + } // namespace detail + + std::shared_ptr GetLogger(const std::string& name) + { + auto logger = spdlog::get(name); + if(!logger) + logger = detail::CreateDefaultLogger(name); + return logger; + } + + void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name) + { + if(!name.empty()) + spdlog::get(name)->set_level(level); + else + spdlog::set_level(level); + } + + void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger) + { + auto sink = std::make_shared(filename); + sink->set_level(level); + if(!logger.empty()) + GetLogger(logger)->sinks().push_back(sink); + else + { + detail::GetDefaultSinks().push_back(sink); + spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); }); + } + } + + void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger) + { + auto sink = std::make_shared(); + sink->set_level(level); + if(!logger.empty()) + GetLogger(logger)->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 GetLogger(const std::string& /*unused*/) + { + return std::make_shared(); + } + 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 diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp new file mode 100644 index 00000000..8952a5f6 --- /dev/null +++ b/libsrc/core/logging.hpp @@ -0,0 +1,87 @@ +#ifndef NETGEN_CORE_LOGGING_HPP +#define NETGEN_CORE_LOGGING_HPP + +#include +#include +#include + +#include "ngcore_api.hpp" + +#ifdef NETGEN_USE_SPDLOG + +#ifdef NETGEN_LOG_DEBUG +#define SPDLOG_DEBUG_ON +#endif // NETGEN_LOG_DEBUG + +#include +#include +#include + +#define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__) + +#else // NETGEN_USE_SPDLOG + +#include + +namespace spdlog +{ + // Dummys if Netgen is compiled with USE_SPDLOG=OFF. + class logger + { + public: + template + void trace(const T& /*unused*/) {} + template + void debug(const T& /*unused*/) {} + template + void info(const T& text) { std::cout << text << std::endl; } + template + void warn(const T& text) { std::cout << text << std::endl; } + template + void error(const T& text) { std::cout << text << std::endl; } + template + void critical(const T& text) { std::cout << text << std::endl; } + }; + + namespace level + { + enum level_enum + { + trace = 0, + debug = 1, + info = 2, + warn = 3, + err = 4, + critical = 5, + off = 6 + }; + } // namespace level + + namespace sinks + { + class sink {}; + } // namespace sinks + +} //namespace spdlog + +#define NETGEN_DEBUG_LOG(logger, ...) + +#endif // NETGEN_USE_SPDLOG + +namespace ngcore +{ + namespace detail + { + std::vector>& GetDefaultSinks(); + inline std::shared_ptr CreateDefaultLogger(const std::string& name); + } //namespace detail + + NGCORE_API std::shared_ptr 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 diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 1c8fa591..ea7f8eab 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -2,6 +2,7 @@ #define NETGEN_CORE_NGCORE_HPP #include "archive.hpp" +#include "logging.hpp" #include "version.hpp" #endif // NETGEN_CORE_NGCORE_HPP diff --git a/libsrc/core/ngcore_api.hpp b/libsrc/core/ngcore_api.hpp index c08d0ac9..5c65cf3a 100644 --- a/libsrc/core/ngcore_api.hpp +++ b/libsrc/core/ngcore_api.hpp @@ -5,8 +5,8 @@ #define NGCORE_API_EXPORT __declspec(dllexport) #define NGCORE_API_IMPORT __declspec(dllimport) #else - #define NGCORE_API_EXPORT - #define NGCORE_API_IMPORT + #define NGCORE_API_EXPORT __attribute__((visibility("default"))) + #define NGCORE_API_IMPORT __attribute__((visibility("default"))) #endif #ifdef NGCORE_EXPORTS diff --git a/libsrc/core/python_ngcore.cpp b/libsrc/core/python_ngcore.cpp new file mode 100644 index 00000000..b7624e43 --- /dev/null +++ b/libsrc/core/python_ngcore.cpp @@ -0,0 +1,30 @@ + +#include + +#include "logging.hpp" + +namespace py = pybind11; +using namespace ngcore; + +PYBIND11_MODULE(pyngcore, m) // NOLINT +{ + py::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."); +} diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index 00c59ea2..39b63d4c 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -6,6 +6,10 @@ add_library(gen OBJECT mpi_interface.cpp gzstream.cpp ) +if(NOT WIN32) + target_link_libraries(gen ngcore) +endif(NOT WIN32) + set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) install( FILES ngexception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel ) diff --git a/libsrc/gprim/CMakeLists.txt b/libsrc/gprim/CMakeLists.txt index 3957476a..ac4b8f11 100644 --- a/libsrc/gprim/CMakeLists.txt +++ b/libsrc/gprim/CMakeLists.txt @@ -3,6 +3,9 @@ add_library(gprim OBJECT adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp ) +if(NOT WIN32) + target_link_libraries(gprim ngcore) +endif(NOT WIN32) set_target_properties( gprim PROPERTIES POSITION_INDEPENDENT_CODE ON ) diff --git a/libsrc/linalg/CMakeLists.txt b/libsrc/linalg/CMakeLists.txt index a5a5a4f2..9f35d751 100644 --- a/libsrc/linalg/CMakeLists.txt +++ b/libsrc/linalg/CMakeLists.txt @@ -4,6 +4,10 @@ add_library( la OBJECT set_target_properties(la PROPERTIES POSITION_INDEPENDENT_CODE ON ) +if(NOT WIN32) + target_link_libraries(la ngcore) +endif(NOT WIN32) + install(FILES densemat.hpp linalg.hpp opti.hpp polynomial.hpp vector.hpp diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 6360174a..d349dfcf 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -506,7 +506,6 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) ) */ - .def("__str__", &ToString) .def_property_readonly("_timestamp", &Mesh::GetTimeStamp) .def("Load", FunctionPointer ([](Mesh & self, const string & filename) diff --git a/libsrc/occ/CMakeLists.txt b/libsrc/occ/CMakeLists.txt index 831a3875..a244e85b 100644 --- a/libsrc/occ/CMakeLists.txt +++ b/libsrc/occ/CMakeLists.txt @@ -9,7 +9,7 @@ if(USE_GUI) endif(USE_GUI) if(NOT WIN32) - target_link_libraries( occ ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) + target_link_libraries( occ ngcore ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) install( TARGETS occ ${NG_INSTALL_DIR}) if (USE_GUI) target_link_libraries( occvis occ ) diff --git a/libsrc/stlgeom/CMakeLists.txt b/libsrc/stlgeom/CMakeLists.txt index 3620c496..7b87a649 100644 --- a/libsrc/stlgeom/CMakeLists.txt +++ b/libsrc/stlgeom/CMakeLists.txt @@ -4,8 +4,7 @@ add_library(stl ${NG_LIB_TYPE} ) if(NOT WIN32) - target_link_libraries( stl mesh ${PYTHON_LIBRARIES}) - target_link_libraries( stl ${PYTHON_LIBRARIES}) + target_link_libraries( stl ngcore mesh ${PYTHON_LIBRARIES}) install( TARGETS stl ${NG_INSTALL_DIR}) endif(NOT WIN32) diff --git a/libsrc/visualization/CMakeLists.txt b/libsrc/visualization/CMakeLists.txt index 8f803d92..f1c82976 100644 --- a/libsrc/visualization/CMakeLists.txt +++ b/libsrc/visualization/CMakeLists.txt @@ -10,7 +10,7 @@ endif(USE_GUI) add_library(visual ${NG_LIB_TYPE} ${LIB_VISUAL_SOURCES}) 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}) endif(NOT WIN32) diff --git a/tests/build_nospdlog.sh b/tests/build_nospdlog.sh new file mode 100644 index 00000000..2fedbef2 --- /dev/null +++ b/tests/build_nospdlog.sh @@ -0,0 +1,8 @@ +cd +mkdir -p build/netgen +cd build/netgen +cmake ../../src/netgen -DUSE_CCACHE=ON -DUSE_SPDLOG=OFF -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=clang +make -j12 +make install + diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt index fc0ebe41..58386884 100644 --- a/tests/catch/CMakeLists.txt +++ b/tests/catch/CMakeLists.txt @@ -3,8 +3,7 @@ if(ENABLE_UNIT_TESTS) add_custom_target(unit_tests) # Build catch_main test object -message("netgen include dir = ${NETGEN_INCLUDE_DIR_ABSOLUTE} --------------------------------------") -include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include}) +include_directories(${CATCH_INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/../../libsrc/include ${SPDLOG_INCLUDE_DIR}) add_library(catch_main STATIC main.cpp) set_target_properties(catch_main PROPERTIES CXX_STANDARD 17) add_dependencies(unit_tests catch_main) @@ -15,11 +14,7 @@ add_test(NAME unit_tests_built COMMAND ${CMAKE_COMMAND} --build . --target unit_ macro(add_unit_test name sources) add_executable(test_${name} ${sources} ) - if (WIN32) - target_link_libraries(test_${name} ngcore catch_main) - else(WIN32) - target_link_libraries(test_${name} ngcore catch_main) - endif(WIN32) + target_link_libraries(test_${name} ngcore catch_main) add_dependencies(unit_tests test_${name}) add_test(NAME unit_${name} COMMAND test_${name}) From 8e53eb46bb945fe46a060cdc7c23a2729c0b387d Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 28 Dec 2018 15:52:51 +0100 Subject: [PATCH 06/98] fix archive version for pickling --- libsrc/core/archive.hpp | 29 +++++++++++------------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index aa6537d2..05766a14 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -97,23 +97,21 @@ namespace ngcore { const bool is_output; // 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 - std::map shared_ptr2nr, ptr2nr; + std::map shared_ptr2nr{}, ptr2nr{}; // vectors for storing the unarchived (shared) pointers - std::vector> nr2shared_ptr; - std::vector nr2ptr; + std::vector> nr2shared_ptr{}; + std::vector nr2ptr{}; protected: bool shallow_to_python = false; - // version map is only used in InArchives - std::map version_map; - std::shared_ptr logger; + std::map version_map = GetLibraryVersions(); + std::shared_ptr logger = GetLogger("Archive"); public: Archive() = delete; Archive(const Archive&) = delete; Archive(Archive&&) = delete; - Archive (bool ais_output) : is_output(ais_output), shared_ptr_count(0), - ptr_count(0), logger(GetLogger("Archive")) { ; } + Archive (bool ais_output) : is_output(ais_output) { ; } virtual ~Archive() { ; } @@ -152,8 +150,8 @@ namespace ngcore bool Output () const { return is_output; } bool Input () const { return !is_output; } - virtual const VersionInfo& GetVersion(const std::string& library) - { return GetLibraryVersions()[library]; } + const VersionInfo& GetVersion(const std::string& library) + { return version_map[library]; } // Pure virtual functions that have to be implemented by In-/OutArchive virtual Archive & operator & (double & d) = 0; @@ -166,7 +164,7 @@ namespace ngcore virtual Archive & operator & (std::string & str) = 0; virtual Archive & operator & (char *& str) = 0; - virtual Archive & operator & (VersionInfo & version) + Archive & operator & (VersionInfo & version) { if(Output()) (*this) << version.to_string(); @@ -706,9 +704,6 @@ namespace ngcore BinaryInArchive (const std::string& filename) : BinaryInArchive(std::make_shared(filename)) { ; } - const VersionInfo& GetVersion(const std::string& library) override - { return version_map[library]; } - using Archive::operator&; Archive & operator & (double & d) override { Read(d); return *this; } @@ -824,9 +819,6 @@ namespace ngcore TextInArchive (const std::string& filename) : TextInArchive(std::make_shared(filename)) {} - const VersionInfo& GetVersion(const std::string& library) override - { return version_map[library]; } - using Archive::operator&; Archive & operator & (double & d) override { *stream >> d; return *this; } @@ -918,6 +910,7 @@ namespace ngcore lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); stream = std::make_shared(); *this & GetLibraryVersions(); + lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); return lst; } }; From c000160f9227aa75186d83c8d94a6b7b39e9508e Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 28 Dec 2018 15:54:04 +0100 Subject: [PATCH 07/98] exceptions in ngcore --- libsrc/core/.clang-tidy | 2 +- libsrc/core/CMakeLists.txt | 1 + libsrc/core/archive.hpp | 38 ++++++++++----------- libsrc/core/exception.hpp | 68 ++++++++++++++++++++++++++++++++++++++ libsrc/core/ngcore.hpp | 1 + 5 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 libsrc/core/exception.hpp diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 290188fb..806e0616 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard' +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: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 16cec927..8f6cb5ad 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -26,6 +26,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp + exception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 05766a14..30c1023c 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -7,13 +7,13 @@ #include // for function #include // for map #include // for shared_ptr -#include // for runtime_error #include // for string #include // for declval, enable_if, false_type, is_co... #include // for type_info #include // for move, swap, pair #include // for vector +#include "exception.hpp" // for UnreachableCodeException, Exception #include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API, unlikely #include "type_traits.hpp" // for all_of_tmpl @@ -37,7 +37,7 @@ namespace ngcore // create new pointer of type T if it is default constructible, else throw template T* constructIfPossible_impl(Rest... /*unused*/) - { throw std::runtime_error(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } + { throw Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); } template::value>::type> T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT @@ -140,9 +140,9 @@ namespace ngcore #ifdef NETGEN_PYTHON 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() - { throw std::runtime_error("Should not get in ShallowFromPython base class implementation!"); } + { throw UnreachableCodeException{}; } #endif // NETGEN_PYTHON Archive& operator=(const Archive&) = delete; @@ -284,9 +284,9 @@ namespace ngcore NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " + Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*ptr).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*ptr).name()) + + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get()); // if there was a true downcast we have to store more information if(reg_ptr != static_cast(ptr.get())) @@ -404,9 +404,9 @@ namespace ngcore NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " + Demangle(typeid(*p).name())); if(!IsRegistered(Demangle(typeid(*p).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*p).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); if(reg_ptr != static_cast(p)) { @@ -427,8 +427,8 @@ namespace ngcore return (*this) << -1 & (*p); } else - throw std::runtime_error(std::string("Archive error: Class ") + - Demangle(typeid(*p).name()) + " does not provide a default constructor!"); + throw Exception(std::string("Archive error: Class ") + + Demangle(typeid(*p).name()) + " does not provide a default constructor!"); else { // if a pointer to a base class is archived, the class hierarchy must be registered @@ -436,9 +436,9 @@ namespace ngcore // implement a void DoArchive(Archive&) member function // To recreate the object we need to store the true type of it if(!IsRegistered(Demangle(typeid(*p).name()))) - throw std::runtime_error(std::string("Archive error: Polymorphic type ") - + Demangle(typeid(*p).name()) - + " not registered for archive"); + throw Exception(std::string("Archive error: Polymorphic type ") + + Demangle(typeid(*p).name()) + + " not registered for archive"); NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer"); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } @@ -552,11 +552,11 @@ namespace ngcore { 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*/) { - 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!"); } }; @@ -568,7 +568,7 @@ namespace ngcore try { return GetArchiveRegister(Demangle(typeid(B1).name())). upcaster(ti, static_cast(dynamic_cast(p))); } - catch(std::exception&) + catch(const Exception&) { return Caster::tryUpcast(ti, p); } } @@ -581,7 +581,7 @@ namespace ngcore return dynamic_cast(static_cast(GetArchiveRegister(Demangle(typeid(B1).name())). downcaster(ti, p))); } - catch(std::exception&) + catch(const Exception&) { return Caster::tryDowncast(ti, p); } diff --git a/libsrc/core/exception.hpp b/libsrc/core/exception.hpp new file mode 100644 index 00000000..248a180f --- /dev/null +++ b/libsrc/core/exception.hpp @@ -0,0 +1,68 @@ +#ifndef NETGEN_CORE_EXCEPTION_HPP +#define NETGEN_CORE_EXCEPTION_HPP + +#include // for stringstream +#include // for exception +#include // for string + +#include "ngcore_api.hpp" // for NGCORE_API + +namespace ngcore +{ + // Exception for code that shouldn't be executed + class NGCORE_API UnreachableCodeException : public std::exception + { + const char* what() const noexcept override + { + return "Shouldn't get here, something went wrong!"; + } + }; + + // Default exception class + class NGCORE_API Exception : public std::exception + { + /// a verbal description of the exception + std::string m_what; + public: + Exception() = default; + Exception(const Exception&) = default; + Exception(Exception&&) = default; + Exception(const std::string& s) : m_what(s) {} + Exception(const char* s) : m_what(s) {} + ~Exception() override = default; + + Exception& operator =(const Exception&) = default; + Exception& operator =(Exception&&) noexcept = default; + + /// append string to description + Exception & Append (const std::string & s) { m_what += s; return *this; } + /// append string to description + Exception & Append (const char * s) { m_what += s; return *this; } + + /// verbal description of exception + const std::string & What() const { return m_what; } + + /// implement virtual function of std::exception + const char* what() const noexcept override { return m_what.c_str(); } + }; + + // Out of Range exception + class NGCORE_API RangeException : public Exception + { + public: + /// where it occurs, index, minimal and maximal indices + RangeException (const std::string & where, + int ind, int imin, int imax) : Exception("") + { + std::stringstream str; + str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n"; + Append (str.str()); + } + }; + + // 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 + +#endif // NETGEN_CORE_EXCEPTION_HPP diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index ea7f8eab..b345a114 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -2,6 +2,7 @@ #define NETGEN_CORE_NGCORE_HPP #include "archive.hpp" +#include "exception.hpp" #include "logging.hpp" #include "version.hpp" From 5602322e9449e3f03f0f907e3da72a2cbee9a92c Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 2 Jan 2019 16:30:55 +0100 Subject: [PATCH 08/98] add RangeException, NETGEN_CHECK_RANGE macro --- CMakeLists.txt | 1 + cmake/SuperBuild.cmake | 1 + libsrc/core/CMakeLists.txt | 8 +++++++- libsrc/core/exception.hpp | 24 +++++++++++++++++++++++- 4 files changed, 32 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d2e6a9f..29a73670 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -21,6 +21,7 @@ option( ENABLE_UNIT_TESTS "Enable Catch unit tests") option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF) option( USE_SPDLOG "Enable spd log logging" ON) 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) diff --git a/cmake/SuperBuild.cmake b/cmake/SuperBuild.cmake index 6e7fabd7..646de088 100644 --- a/cmake/SuperBuild.cmake +++ b/cmake/SuperBuild.cmake @@ -144,6 +144,7 @@ set_vars( NETGEN_CMAKE_ARGS ENABLE_CPP_CORE_GUIDELINES_CHECK USE_SPDLOG DEBUG_LOG + CHECK_RANGE ) # propagate all variables set on the command line using cmake -DFOO=BAR diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 8f6cb5ad..805808d5 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,11 +1,17 @@ -add_library(ngcore SHARED archive.cpp logging.cpp) +add_library(ngcore SHARED archive.cpp logging.cpp flags.cpp) target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) if(NOT WIN32) target_compile_options(ngcore PRIVATE -fvisibility=hidden) endif(NOT WIN32) +target_compile_definitions(ngcore PUBLIC $<$:NETGEN_ENABLE_CHECK_RANGE>) + +if(CHECK_RANGE) + target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE) +endif(CHECK_RANGE) + if(USE_SPDLOG) include_directories(${SPDLOG_INCLUDE_DIR}) install(DIRECTORY ${SPDLOG_INCLUDE_DIR} diff --git a/libsrc/core/exception.hpp b/libsrc/core/exception.hpp index 248a180f..35359e65 100644 --- a/libsrc/core/exception.hpp +++ b/libsrc/core/exception.hpp @@ -51,13 +51,21 @@ namespace ngcore { public: /// where it occurs, index, minimal and maximal indices - RangeException (const std::string & where, + RangeException (const std::string & where, int ind, int imin, int imax) : Exception("") { std::stringstream str; str << where << ": index " << ind << " out of range [" << imin << "," << imax << "]\n"; Append (str.str()); } + + template + RangeException(const std::string& where, const T& value) + { + std::stringstream str; + str << where << " called with wrong value " << value << "\n"; + Append(str.str()); + } }; // Exception used if no simd implementation is available to fall back to standard evaluation @@ -65,4 +73,18 @@ namespace ngcore { 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 From a4f4b6c1be95ea11d580098b0f447fc0b9976785 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 2 Jan 2019 16:32:09 +0100 Subject: [PATCH 09/98] fix cmake file for ngcore --- libsrc/core/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 805808d5..01479a61 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(ngcore SHARED archive.cpp logging.cpp flags.cpp) +add_library(ngcore SHARED archive.cpp logging.cpp) target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) if(NOT WIN32) From f88cc77cfea66f651475f795993566c73c3210cf Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 2 Jan 2019 18:21:52 +0100 Subject: [PATCH 10/98] move SymbolTable to ngcore --- libsrc/core/CMakeLists.txt | 2 +- libsrc/core/archive.hpp | 28 ++++++ libsrc/core/ngcore.hpp | 1 + libsrc/core/symboltable.hpp | 144 ++++++++++++++++++++++++++++++ libsrc/csg/csgeom.cpp | 20 ++--- libsrc/csg/csgeom.hpp | 10 +-- libsrc/csg/solid.cpp | 16 ++-- libsrc/csg/solid.hpp | 2 +- libsrc/general/CMakeLists.txt | 4 +- libsrc/general/flags.cpp | 20 ++--- libsrc/general/flags.hpp | 10 +-- libsrc/general/myadt.hpp | 1 - libsrc/general/symbolta.cpp | 52 ----------- libsrc/general/symbolta.hpp | 163 ---------------------------------- libsrc/meshing/meshclass.cpp | 20 ++--- libsrc/meshing/meshclass.hpp | 4 +- ng/ngpkg.cpp | 6 +- tests/catch/CMakeLists.txt | 10 +-- tests/catch/symboltable.cpp | 64 +++++++++++++ 19 files changed, 299 insertions(+), 278 deletions(-) create mode 100644 libsrc/core/symboltable.hpp delete mode 100644 libsrc/general/symbolta.cpp delete mode 100644 libsrc/general/symbolta.hpp create mode 100644 tests/catch/symboltable.cpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 01479a61..b75e7582 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -32,7 +32,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp - exception.hpp + exception.hpp symboltable.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 30c1023c..11d4ae71 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -205,6 +205,34 @@ namespace ngcore Do(&v[0], size); return (*this); } + + // vector has special implementation (like a bitarray) therefore + // it needs a special overload (this could probably be more efficient, but we + // don't use it that often anyway) + template<> + Archive& operator& (std::vector& v) + { + size_t size; + if(Output()) + size = v.size(); + (*this) & size; + if(Input()) + { + v.resize(size); + bool b; + for(size_t i=0; i Archive& operator& (std::map& map) { diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index b345a114..153a0e6c 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -4,6 +4,7 @@ #include "archive.hpp" #include "exception.hpp" #include "logging.hpp" +#include "symboltable.hpp" #include "version.hpp" #endif // NETGEN_CORE_NGCORE_HPP diff --git a/libsrc/core/symboltable.hpp b/libsrc/core/symboltable.hpp new file mode 100644 index 00000000..53c07dd4 --- /dev/null +++ b/libsrc/core/symboltable.hpp @@ -0,0 +1,144 @@ +#ifndef NETGEN_CORE_SYMBOLTABLE_HPP +#define NETGEN_CORE_SYMBOLTABLE_HPP + +#include +#include +#include + +#include "archive.hpp" +#include "exception.hpp" +#include "ngcore_api.hpp" + +namespace ngcore +{ + /** + A symbol table. + + The symboltable provides a mapping from string identifiers + to the generic type T. The strings are copied. + Complexity by name access is linear, by index is constant. + */ + template + class NGCORE_API SymbolTable + { + std::vector names; + std::vector data; + public: + using value_type = T; + using reference = typename std::vector::reference; + using const_reference = typename std::vector::const_reference; + + /// Creates a symboltable + SymbolTable () = default; + SymbolTable (const SymbolTable &) = default; + SymbolTable (SymbolTable &&) noexcept = default; + + ~SymbolTable() = default; + + SymbolTable& operator=(const SymbolTable&) = default; + SymbolTable& operator=(SymbolTable&&) = default; + + template + auto DoArchive(Archive& ar) -> typename std::enable_if, void>::type + { + ar & names & data; + } + + /// INDEX of symbol name, throws exception if unused + NGCORE_API 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 + NGCORE_API int CheckIndex (const std::string & name) const + { + for (int i = 0; i < names.size(); i++) + if (names[i] == name) return i; + return -1; + } + + /// number of identifiers + size_t Size() const + { + return data.size(); + } + + /// Returns reference to element. exception for unused identifier + reference operator[] (const std::string & name) + { + return data[Index (name)]; + } + + const_reference operator[] (const std::string & name) const + { + return data[Index (name)]; + } + + /// Returns reference to i-th element, range check only in debug build + reference operator[] (size_t i) + { + NETGEN_CHECK_RANGE(i, 0, data.size()); + return data[i]; + } + + /// Returns const reference to i-th element, range check only in debug build + const_reference operator[] (size_t i) const + { + NETGEN_CHECK_RANGE(i, 0, data.size()); + return data[i]; + } + + /// Returns name of i-th element, range check only in debug build + const std::string & GetName (size_t i) const + { + NETGEN_CHECK_RANGE(i, 0, names.size()); + return names[i]; + } + + /// Associates el to the string name, overrides if name is used + void Set (const std::string & name, const T & el) + { + int i = CheckIndex (name); + if (i >= 0) + data[i] = el; + else + { + data.push_back(el); + names.push_back(name); + } + } + + bool Used (const std::string & name) const + { + return CheckIndex(name) >= 0; + } + + /// Deletes symboltable + inline void DeleteAll () + { + names.clear(); + data.clear(); + } + + // Adds all elements from other symboltable + SymbolTable& Update(const SymbolTable& tbl2) + { + for (size_t i = 0; i < tbl2.Size(); i++) + Set (tbl2.GetName(i), tbl2[i]); + return *this; + } + }; + + template + std::ostream & operator<< (std::ostream & ost, const SymbolTable & st) + { + for (int i = 0; i < st.Size(); i++) + ost << st.GetName(i) << " : " << st[i] << std::endl; + return ost; + } +} // namespace ngcore + +#endif // NETGEN_CORE_SYMBOLTABLE_HPP diff --git a/libsrc/csg/csgeom.cpp b/libsrc/csg/csgeom.cpp index 87cae1b4..4aebe271 100644 --- a/libsrc/csg/csgeom.cpp +++ b/libsrc/csg/csgeom.cpp @@ -562,7 +562,7 @@ namespace netgen const Surface * CSGeometry :: GetSurface (const char * name) const { if (surfaces.Used(name)) - return surfaces.Get(name); + return surfaces[name]; else return NULL; } @@ -585,7 +585,7 @@ namespace netgen Solid * oldsol = NULL; if (solids.Used (name)) - oldsol = solids.Get(name); + oldsol = solids[name]; solids.Set (name, sol); sol->SetName (name); @@ -605,7 +605,7 @@ namespace netgen const Solid * CSGeometry :: GetSolid (const char * name) const { if (solids.Used(name)) - return solids.Get(name); + return solids[name]; else return NULL; } @@ -616,8 +616,8 @@ namespace netgen const Solid * CSGeometry :: GetSolid (const string & name) const { - if (solids.Used(name.c_str())) - return solids.Get(name.c_str()); + if (solids.Used(name)) + return solids[name]; else return NULL; } @@ -637,15 +637,15 @@ namespace netgen const SplineGeometry<2> * CSGeometry :: GetSplineCurve2d (const string & name) const { - if (splinecurves2d.Used(name.c_str())) - return splinecurves2d.Get(name.c_str()); + if (splinecurves2d.Used(name)) + return splinecurves2d[name]; else return NULL; } const SplineGeometry<3> * CSGeometry :: GetSplineCurve3d (const string & name) const { - if (splinecurves3d.Used(name.c_str())) - return splinecurves3d.Get(name.c_str()); + if (splinecurves3d.Used(name)) + return splinecurves3d[name]; else return NULL; } @@ -721,7 +721,7 @@ namespace netgen void CSGeometry :: SetFlags (const char * solidname, const Flags & flags) { - Solid * solid = solids.Elem(solidname); + Solid * solid = solids[solidname]; Array surfind; int i; diff --git a/libsrc/csg/csgeom.hpp b/libsrc/csg/csgeom.hpp index f82407b4..40d90d51 100644 --- a/libsrc/csg/csgeom.hpp +++ b/libsrc/csg/csgeom.hpp @@ -102,7 +102,7 @@ namespace netgen { private: /// all surfaces - SYMBOLTABLE surfaces; + SymbolTable surfaces; public: /// primitive of surface @@ -112,12 +112,12 @@ namespace netgen Array delete_them; /// all named solids - SYMBOLTABLE solids; + SymbolTable solids; /// all 2d splinecurves - SYMBOLTABLE< SplineGeometry<2>* > splinecurves2d; + SymbolTable< SplineGeometry<2>* > splinecurves2d; /// all 3d splinecurves - SYMBOLTABLE< SplineGeometry<3>* > splinecurves3d; + SymbolTable< SplineGeometry<3>* > splinecurves3d; /// all top level objects: solids and surfaces Array toplevelobjects; @@ -203,7 +203,7 @@ namespace netgen const Solid * GetSolid (const string & name) const; int GetNSolids () const { return solids.Size(); } const Solid * GetSolid (int i) const { return solids[i]; } - const SYMBOLTABLE & GetSolids () const { return solids; } + const SymbolTable & GetSolids () const { return solids; } void SetSplineCurve (const char * name, SplineGeometry<2> * spl); diff --git a/libsrc/csg/solid.cpp b/libsrc/csg/solid.cpp index a7e5fff5..c61f4e39 100644 --- a/libsrc/csg/solid.cpp +++ b/libsrc/csg/solid.cpp @@ -419,9 +419,9 @@ namespace netgen - static Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE & solids); - static Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE & solids); - static Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE & solids); + static Solid * CreateSolidExpr (istream & ist, const SymbolTable & solids); + static Solid * CreateSolidTerm (istream & ist, const SymbolTable & solids); + static Solid * CreateSolidPrim (istream & ist, const SymbolTable & solids); static void ReadString (istream & ist, char * str) { @@ -461,7 +461,7 @@ namespace netgen } - Solid * CreateSolidExpr (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidExpr (istream & ist, const SymbolTable & solids) { // cout << "create expr" << endl; @@ -484,7 +484,7 @@ namespace netgen return s1; } - Solid * CreateSolidTerm (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidTerm (istream & ist, const SymbolTable & solids) { // cout << "create term" << endl; @@ -508,7 +508,7 @@ namespace netgen return s1; } - Solid * CreateSolidPrim (istream & ist, const SYMBOLTABLE & solids) + Solid * CreateSolidPrim (istream & ist, const SymbolTable & solids) { Solid * s1; char ch; @@ -533,7 +533,7 @@ namespace netgen } (*testout) << "get terminal " << str << endl; - s1 = solids.Get(str); + s1 = solids[str]; if (s1) { // cout << "primitive: " << str << endl; @@ -545,7 +545,7 @@ namespace netgen } - Solid * Solid :: CreateSolid (istream & ist, const SYMBOLTABLE & solids) + Solid * Solid :: CreateSolid (istream & ist, const SymbolTable & solids) { Solid * nsol = CreateSolidExpr (ist, solids); nsol = new Solid (ROOT, nsol); diff --git a/libsrc/csg/solid.hpp b/libsrc/csg/solid.hpp index 4d620c04..193cb363 100644 --- a/libsrc/csg/solid.hpp +++ b/libsrc/csg/solid.hpp @@ -158,7 +158,7 @@ namespace netgen { return maxh; } void GetSolidData (ostream & ost, int first = 1) const; - static Solid * CreateSolid (istream & ist, const SYMBOLTABLE & solids); + static Solid * CreateSolid (istream & ist, const SymbolTable & solids); static BlockAllocator ball; diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index 39b63d4c..b65fee96 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -2,7 +2,7 @@ add_definitions(-DNGINTERFACE_EXPORTS) add_library(gen OBJECT array.cpp bitarray.cpp dynamicmem.cpp flags.cpp hashtabl.cpp mystring.cpp ngexception.cpp optmem.cpp parthreads.cpp - profiler.cpp seti.cpp sort.cpp spbita2d.cpp symbolta.cpp table.cpp + profiler.cpp seti.cpp sort.cpp spbita2d.cpp table.cpp mpi_interface.cpp gzstream.cpp ) @@ -19,7 +19,7 @@ install(FILES dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp ngsimd.hpp mystring.hpp netgenout.hpp ngexception.hpp ngpython.hpp optmem.hpp parthreads.hpp profiler.hpp seti.hpp sort.hpp - spbita2d.hpp stack.hpp symbolta.hpp table.hpp template.hpp + spbita2d.hpp stack.hpp table.hpp template.hpp gzstream.h DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel ) diff --git a/libsrc/general/flags.cpp b/libsrc/general/flags.cpp index e5916f87..993413ed 100644 --- a/libsrc/general/flags.cpp +++ b/libsrc/general/flags.cpp @@ -83,7 +83,7 @@ namespace netgen Flags :: GetStringFlag (const char * name, const char * def) const { if (strflags.Used (name)) - return strflags.Get(name); + return strflags[name]; else return def; } @@ -91,7 +91,7 @@ namespace netgen double Flags :: GetNumFlag (const char * name, double def) const { if (numflags.Used (name)) - return numflags.Get(name); + return numflags[name]; else return def; } @@ -99,7 +99,7 @@ namespace netgen const double * Flags :: GetNumFlagPtr (const char * name) const { if (numflags.Used (name)) - return & ((SYMBOLTABLE&)numflags).Elem(name); + return & ((SymbolTable&)numflags)[name]; else return NULL; } @@ -107,7 +107,7 @@ namespace netgen double * Flags :: GetNumFlagPtr (const char * name) { if (numflags.Used (name)) - return & ((SYMBOLTABLE&)numflags).Elem(name); + return & ((SymbolTable&)numflags)[name]; else return NULL; } @@ -122,7 +122,7 @@ namespace netgen Flags :: GetStringListFlag (const char * name) const { if (strlistflags.Used (name)) - return *strlistflags.Get(name); + return *strlistflags[name]; else { static Array dummy_array(0); @@ -134,7 +134,7 @@ namespace netgen Flags ::GetNumListFlag (const char * name) const { if (numlistflags.Used (name)) - return *numlistflags.Get(name); + return *numlistflags[name]; else { static Array dummy_array(0); @@ -170,9 +170,9 @@ namespace netgen ofstream outfile (filename); for (i = 1; i <= strflags.Size(); i++) - outfile << strflags.GetName(i) << " = " << strflags.Get(i) << endl; + outfile << strflags.GetName(i) << " = " << strflags[i] << endl; for (i = 1; i <= numflags.Size(); i++) - outfile << numflags.GetName(i) << " = " << numflags.Get(i) << endl; + outfile << numflags.GetName(i) << " = " << numflags[i] << endl; for (i = 1; i <= defflags.Size(); i++) outfile << defflags.GetName(i) << endl; } @@ -184,9 +184,9 @@ namespace netgen int i; for (i = 1; i <= strflags.Size(); i++) - ost << strflags.GetName(i) << " = " << strflags.Get(i) << endl; + ost << strflags.GetName(i) << " = " << strflags[i] << endl; for (i = 1; i <= numflags.Size(); i++) - ost << numflags.GetName(i) << " = " << numflags.Get(i) << endl; + ost << numflags.GetName(i) << " = " << numflags[i] << endl; for (i = 1; i <= defflags.Size(); i++) ost << defflags.GetName(i) << endl; } diff --git a/libsrc/general/flags.hpp b/libsrc/general/flags.hpp index e156d328..e7ba0382 100644 --- a/libsrc/general/flags.hpp +++ b/libsrc/general/flags.hpp @@ -19,15 +19,15 @@ namespace netgen class Flags { /// - SYMBOLTABLE strflags; + SymbolTable strflags; /// - SYMBOLTABLE numflags; + SymbolTable numflags; /// - SYMBOLTABLE defflags; + SymbolTable defflags; /// - SYMBOLTABLE*> strlistflags; + SymbolTable*> strlistflags; /// - SYMBOLTABLE*> numlistflags; + SymbolTable*> numlistflags; public: /// DLL_HEADER Flags (); diff --git a/libsrc/general/myadt.hpp b/libsrc/general/myadt.hpp index 601a3da0..7263d088 100644 --- a/libsrc/general/myadt.hpp +++ b/libsrc/general/myadt.hpp @@ -33,7 +33,6 @@ namespace netgen #include "hashtabl.hpp" -#include "symbolta.hpp" #include "bitarray.hpp" #include "flags.hpp" #include "spbita2d.hpp" diff --git a/libsrc/general/symbolta.cpp b/libsrc/general/symbolta.cpp deleted file mode 100644 index bd35ac7c..00000000 --- a/libsrc/general/symbolta.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/**************************************************************************/ -/* File: symbolta.cc */ -/* Author: Joachim Schoeberl */ -/* Date: 01. Jun. 95 */ -/**************************************************************************/ - -/* - Abstract data type Symbol Table -*/ - -#include -#include - - -#ifndef FILE_SYMBOLTABLECC -#define FILE_SYMBOLTABLECC -// necessary for SGI ???? - - -namespace netgen -{ - //using namespace netgen; - - BASE_SYMBOLTABLE :: BASE_SYMBOLTABLE () - { - ; - } - - - BASE_SYMBOLTABLE :: ~BASE_SYMBOLTABLE() - { - DelNames(); - } - - - void BASE_SYMBOLTABLE :: DelNames() - { - for (int i = 0; i < names.Size(); i++) - delete [] names[i]; - names.SetSize (0); - } - - int BASE_SYMBOLTABLE :: Index (const char * name) const - { - if (!name) return 0; - for (int i = 0; i < names.Size(); i++) - if (strcmp (names[i], name) == 0) return i+1; - return 0; - } -} - -#endif diff --git a/libsrc/general/symbolta.hpp b/libsrc/general/symbolta.hpp deleted file mode 100644 index b599ea42..00000000 --- a/libsrc/general/symbolta.hpp +++ /dev/null @@ -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 names; - -public: - /// Constructor - BASE_SYMBOLTABLE (); - /// - ~BASE_SYMBOLTABLE (); - /// - void DelNames (); - /// Index of symbol name, returns 0 if not used. - int Index (const char * name) const; -}; - - -/** - Abstract data type Symbol Table. - - To a string an value of the generic type T is associated. - The string is not copied into the symbol table class! -*/ -template -class SYMBOLTABLE : public BASE_SYMBOLTABLE -{ -private: - /// Associated data - Array data; - -public: - /// Creates a symboltable - inline SYMBOLTABLE (); - /// Returns size of symboltable - inline INDEX Size() const; - /// Returns reference to element, error if not used - inline T & Elem (const char * name); - /// Returns reference to i-th element - inline T & Elem (int i) - { return data.Elem(i); } - /// Returns element, error if not used - inline const T & Get (const char * name) const; - /// Returns i-th element - inline const T & Get (int i) const; - /// Returns name of i-th element - inline const char* GetName (int i) const; - /// Associates el to the string name, overrides if name is used - inline void Set (const char * name, const T & el); - /// Checks whether name is used - inline bool Used (const char * name) const; - /// Deletes symboltable - inline void DeleteAll (); - - 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 & operator= (SYMBOLTABLE &); -}; - - - - -template -inline SYMBOLTABLE :: SYMBOLTABLE () -{ - ; -} - - -template -inline INDEX SYMBOLTABLE :: Size() const -{ - return data.Size(); -} - -template -inline T & SYMBOLTABLE :: Elem (const char * name) -{ - int i = Index (name); - if (i) - return data.Elem (i); - else - return data.Elem(1); -} - -template -inline const T & SYMBOLTABLE :: Get (const char * name) const -{ - int i; - i = Index (name); - if (i) - return data.Get(i); - else - return data.Get(1); -} - -template -inline const T & SYMBOLTABLE :: Get (int i) const -{ - return data.Get(i); -} - -template -inline const char* SYMBOLTABLE :: GetName (int i) const -{ - return names.Get(i); -} - -template -inline void SYMBOLTABLE :: Set (const char * name, const T & el) -{ - int i; - i = Index (name); - if (i) - data.Set(i, el); - else - { - data.Append (el); - char * hname = new char [strlen (name) + 1]; - strcpy (hname, name); - names.Append (hname); - } -} - -template -inline bool SYMBOLTABLE :: Used (const char * name) const -{ - return (Index(name)) ? true : false; -} - -template -inline void SYMBOLTABLE :: DeleteAll () -{ - DelNames(); - data.DeleteAll(); -} - -} -#endif diff --git a/libsrc/meshing/meshclass.cpp b/libsrc/meshing/meshclass.cpp index ebf75ff4..9e96a055 100644 --- a/libsrc/meshing/meshclass.cpp +++ b/libsrc/meshing/meshclass.cpp @@ -6016,7 +6016,7 @@ namespace netgen void Mesh :: SetUserData(const char * id, Array & data) { if(userdata_int.Used(id)) - delete userdata_int.Get(id); + delete userdata_int[id]; Array * newdata = new Array(data); @@ -6026,10 +6026,10 @@ namespace netgen { if(userdata_int.Used(id)) { - if(data.Size() < (*userdata_int.Get(id)).Size()+shift) - data.SetSize((*userdata_int.Get(id)).Size()+shift); - for(int i=0; i<(*userdata_int.Get(id)).Size(); i++) - data[i+shift] = (*userdata_int.Get(id))[i]; + if(data.Size() < (*userdata_int[id]).Size()+shift) + data.SetSize((*userdata_int[id]).Size()+shift); + for(int i=0; i<(*userdata_int[id]).Size(); i++) + data[i+shift] = (*userdata_int[id])[i]; return true; } else @@ -6041,7 +6041,7 @@ namespace netgen void Mesh :: SetUserData(const char * id, Array & data) { if(userdata_double.Used(id)) - delete userdata_double.Get(id); + delete userdata_double[id]; Array * newdata = new Array(data); @@ -6051,10 +6051,10 @@ namespace netgen { if(userdata_double.Used(id)) { - if(data.Size() < (*userdata_double.Get(id)).Size()+shift) - data.SetSize((*userdata_double.Get(id)).Size()+shift); - for(int i=0; i<(*userdata_double.Get(id)).Size(); i++) - data[i+shift] = (*userdata_double.Get(id))[i]; + if(data.Size() < (*userdata_double[id]).Size()+shift) + data.SetSize((*userdata_double[id]).Size()+shift); + for(int i=0; i<(*userdata_double[id]).Size(); i++) + data[i+shift] = (*userdata_double[id])[i]; return true; } else diff --git a/libsrc/meshing/meshclass.hpp b/libsrc/meshing/meshclass.hpp index fe72de2a..956946ce 100644 --- a/libsrc/meshing/meshclass.hpp +++ b/libsrc/meshing/meshclass.hpp @@ -132,8 +132,8 @@ namespace netgen /// mesh access semaphors. NgMutex majormutex; - SYMBOLTABLE< Array* > userdata_int; - SYMBOLTABLE< Array* > userdata_double; + SymbolTable< Array* > userdata_int; + SymbolTable< Array* > userdata_double; mutable Array< Point3d > pointcurves; diff --git a/ng/ngpkg.cpp b/ng/ngpkg.cpp index a80b0ea6..5b67637a 100644 --- a/ng/ngpkg.cpp +++ b/ng/ngpkg.cpp @@ -1840,9 +1840,9 @@ namespace netgen - SYMBOLTABLE & GetVisualizationScenes () + SymbolTable & GetVisualizationScenes () { - static SYMBOLTABLE vss; + static SymbolTable vss; return vss; } @@ -1860,7 +1860,7 @@ namespace netgen vs = &vscross; if (GetVisualizationScenes().Used(vismode)) { - vs = GetVisualizationScenes().Get(vismode); + vs = GetVisualizationScenes()[vismode]; } else if (vismode) { diff --git a/tests/catch/CMakeLists.txt b/tests/catch/CMakeLists.txt index 58386884..f0a25744 100644 --- a/tests/catch/CMakeLists.txt +++ b/tests/catch/CMakeLists.txt @@ -19,14 +19,14 @@ macro(add_unit_test name sources) add_dependencies(unit_tests test_${name}) add_test(NAME unit_${name} COMMAND test_${name}) set_tests_properties(unit_${name} PROPERTIES DEPENDS unit_tests_built) + + if(ENABLE_CPP_CORE_GUIDELINES_CHECK) + set_target_properties(test_${name} PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") + endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) endmacro() add_unit_test(archive archive.cpp) +add_unit_test(symboltable symboltable.cpp) add_unit_test(version version.cpp) -if(ENABLE_CPP_CORE_GUIDELINES_CHECK) - set_target_properties(test_archive PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") - set_target_properties(test_version PROPERTIES CXX_CLANG_TIDY "${DO_CLANG_TIDY}") -endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) - endif(ENABLE_UNIT_TESTS) diff --git a/tests/catch/symboltable.cpp b/tests/catch/symboltable.cpp new file mode 100644 index 00000000..5e6ecd2c --- /dev/null +++ b/tests/catch/symboltable.cpp @@ -0,0 +1,64 @@ + +#include "catch.hpp" +#include <../core/ngcore.hpp> +using namespace ngcore; +using namespace std; + +TEST_CASE("Symboltable") +{ + SymbolTable table; + CHECK_THROWS_AS(table["test"], RangeException); + table.Set("first", 1); + CHECK(table["first"] == 1); + table["first"] = 2; + CHECK(table["first"] == 2); + auto index = table.Index("first"); + CHECK(index == 0); + CHECK(table[index] == 2); + table[index] = 3; + CHECK(table["first"] == 3); +#ifndef NDEBUG + int a; + CHECK_THROWS_AS(a = table[5], RangeException); + CHECK_THROWS_AS(table.GetName(5), RangeException); +#endif + CHECK(table.Used("first")); + CHECK(!table.Used("second")); + SymbolTable another; + another.Set("first", 1); + another.Set("second", 2); + table.Update(another); + CHECK(table["first"] == 1); + CHECK(table["second"] == 2); + std::stringstream s; + s << table; + CHECK(s.str() == "first : 1\nsecond : 2\n"); + auto ss = std::make_shared(); + BinaryOutArchive ao(ss); + ao & table; + ao.FlushBuffer(); + BinaryInArchive ai(ss); + SymbolTable read; + ai & read; + for(size_t i = 0; i is special because of vector is special... + SymbolTable btable; + btable.Set("true", true); + btable.Set("false", false); + CHECK(btable[0]); + CHECK(!btable[1]); + CHECK(btable["true"]); + CHECK(!btable["false"]); + ao & btable; + ao.FlushBuffer(); + SymbolTable bread; + ai & bread; + CHECK(bread["true"]); + CHECK(!bread["false"]); +} From 678b4497c2bc230de4e00e43e89fc6d2b0055c53 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 2 Jan 2019 18:38:03 +0100 Subject: [PATCH 11/98] Paje tracing --- libsrc/core/CMakeLists.txt | 4 +- libsrc/core/archive.cpp | 10 - libsrc/core/archive.hpp | 4 +- libsrc/core/logging.hpp | 53 ++- libsrc/core/ngcore_api.hpp | 24 +- libsrc/core/paje_trace.cpp | 659 +++++++++++++++++++++++++++++++++++++ libsrc/core/paje_trace.hpp | 215 ++++++++++++ libsrc/core/utils.cpp | 20 ++ libsrc/core/utils.hpp | 23 ++ 9 files changed, 973 insertions(+), 39 deletions(-) create mode 100644 libsrc/core/paje_trace.cpp create mode 100644 libsrc/core/paje_trace.hpp create mode 100644 libsrc/core/utils.cpp create mode 100644 libsrc/core/utils.hpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index b75e7582..3e10f58d 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(ngcore SHARED archive.cpp logging.cpp) +add_library(ngcore SHARED archive.cpp logging.cpp paje_trace.cpp utils.cpp) target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS) if(NOT WIN32) @@ -32,7 +32,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp - exception.hpp symboltable.hpp + exception.hpp symboltable.hpp paje_trace.hpp utils.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/archive.cpp b/libsrc/core/archive.cpp index 64789904..9d7f2cd5 100644 --- a/libsrc/core/archive.cpp +++ b/libsrc/core/archive.cpp @@ -19,16 +19,6 @@ namespace ngcore void SetLibraryVersion(const std::string& library, const VersionInfo& version) { library_versions[library] = version; } -#ifdef WIN32 - // windows does demangling in typeid(T).name() - std::string Demangle(const char* typeinfo) { return typeinfo; } -#else - std::string Demangle(const char* typeinfo) { int status; return abi::__cxa_demangle(typeinfo, - nullptr, - nullptr, - &status); } -#endif - // clang-tidy should ignore this static object static std::unique_ptr> type_register; // NOLINT const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 11d4ae71..04915cbc 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -15,8 +15,9 @@ #include "exception.hpp" // for UnreachableCodeException, Exception #include "logging.hpp" // for logger -#include "ngcore_api.hpp" // for NGCORE_API, unlikely +#include "ngcore_api.hpp" // for NGCORE_API #include "type_traits.hpp" // for all_of_tmpl +#include "utils.hpp" // for Demangle, unlikely #include "version.hpp" // for VersionInfo #ifdef NETGEN_PYTHON @@ -28,7 +29,6 @@ namespace ngcore // Libraries using this archive can store their version here to implement backwards compatibility NGCORE_API const VersionInfo& GetLibraryVersion(const std::string& library); NGCORE_API void SetLibraryVersion(const std::string& library, const VersionInfo& version); - NGCORE_API std::string Demangle(const char* typeinfo); class NGCORE_API Archive; diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index 8952a5f6..e0e3efd6 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -26,23 +26,6 @@ namespace spdlog { // Dummys if Netgen is compiled with USE_SPDLOG=OFF. - class logger - { - public: - template - void trace(const T& /*unused*/) {} - template - void debug(const T& /*unused*/) {} - template - void info(const T& text) { std::cout << text << std::endl; } - template - void warn(const T& text) { std::cout << text << std::endl; } - template - void error(const T& text) { std::cout << text << std::endl; } - template - void critical(const T& text) { std::cout << text << std::endl; } - }; - namespace level { enum level_enum @@ -57,6 +40,42 @@ namespace spdlog }; } // namespace level + class logger + { + public: + template + void log_helper( T t) { std::clog << t; } + + template + void log_helper( T t, Args ... args) + { + std::clog << t; + log_helper(args...); + std::clog << ", "; + } + + template + void log( level::level_enum level, const char* fmt, Args ... args) + { + std::clog << level << ": " << fmt << "\t Arguments: "; + log_helper(args...); + std::clog << "\n"; + } + + template + void trace( const char* fmt, Args ... args) { log(level::level_enum::trace, fmt, args...); } + template + void debug( const char* fmt, Args ... args) { log(level::level_enum::debug, fmt, args...); } + template + void info( const char* fmt, Args ... args) { log(level::level_enum::info, fmt, args...); } + template + void warn( const char* fmt, Args ... args) { log(level::level_enum::warn, fmt, args...); } + template + void error( const char* fmt, Args ... args) { log(level::level_enum::err, fmt, args...); } + template + void critical( const char* fmt, Args ... args) { log(level::level_enum::critical, fmt, args...); } + }; + namespace sinks { class sink {}; diff --git a/libsrc/core/ngcore_api.hpp b/libsrc/core/ngcore_api.hpp index 5c65cf3a..a84a1381 100644 --- a/libsrc/core/ngcore_api.hpp +++ b/libsrc/core/ngcore_api.hpp @@ -15,15 +15,23 @@ #define NGCORE_API NGCORE_API_IMPORT #endif -namespace ngcore -{ -#if defined(__GNUC__) - inline bool likely (bool x) { return bool(__builtin_expect(long(x), 1L)); } - inline bool unlikely (bool x) { return bool(__builtin_expect(long(x), 0L)); } +#ifdef __INTEL_COMPILER + #ifdef WIN32 + #define NETGEN_INLINE __forceinline inline + #define NETGEN_LAMBDA_INLINE + #else + #define NETGEN_INLINE __forceinline inline + #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) + #endif #else - inline bool likely (bool x) { return x; } - inline bool unlikely (bool x) { return x; } + #ifdef __GNUC__ + #define NETGEN_INLINE __attribute__ ((__always_inline__)) inline + #define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) + #define NETGEN_VLA + #else + #define NETGEN_INLINE inline + #define NETGEN_LAMBDA_INLINE + #endif #endif -} // namespace ngcore #endif // NETGEN_CORE_NGCORE_API_HPP diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp new file mode 100644 index 00000000..2742d25e --- /dev/null +++ b/libsrc/core/paje_trace.cpp @@ -0,0 +1,659 @@ +#include +#include +#include +#include +#include +#include + +#include "archive.hpp" // for Demangle +#include "paje_trace.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 = GetTime(); + + nthreads = anthreads; + tracefile_name = aname; + + int bytes_per_event=33; + max_num_events_per_thread = std::min( (size_t)std::numeric_limits::max, max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7); + if(max_num_events_per_thread>0) + { + logger->info( "Tracefile size = {}MB", max_tracefile_size/1024/1024); + logger->info( "Tracing {} events per thread", max_num_events_per_thread , " 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.size()>0) + 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; + } + + using std::string; + class PajeFile + { + public: + typedef PajeTrace::TTimePoint TTimePoint; + static void Hue2RGB ( double x, double &r, double &g, double &b ) + { + double d = 1.0/6.0; + if(x logger = GetLogger("PajeTrace"); + + + double ConvertTime(TTimePoint t) { + // return time in milliseconds as double + // return std::chrono::duration(t-start_time).count()*1000.0; + // return std::chrono::duration(t-start_time).count() / 2.7e3; + return (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 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; + else + return (time < other.time); + } + + int write(char *buf) + { + const int &key = id; + const int &end_container = start_container; + switch(event_type) + { + case PajeSetVariable: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); + case PajeAddVariable: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); + case PajeSubVariable: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSubVariable, time, type, container, var_value ); + case PajePushState: + if(value_is_alias) + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); + else + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); + case PajePopState: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); + case PajeStartLink: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeStartLink, time, type, container, value, start_container, key ); + case PajeEndLink: + return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeEndLink, time, type, container, value, end_container, key ); + } + return 0; + } + }; + + std::vector events; + + public: + PajeFile( string filename, TTimePoint astart_time ) + { + start_time = astart_time; + ctrace_stream = fopen (filename.c_str(),"w"); + fprintf(ctrace_stream, "%s", header ); + alias_counter = 0; + } + int DefineContainerType ( int parent_type, 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() ); + else + fprintf( ctrace_stream, "%d\ta%d\t%d\t\"%s\"\n", PajeDefineContainerType, alias, parent_type, name.c_str() ); + return alias; + } + + int DefineVariableType ( int container_type, 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() ); + return alias; + } + + int DefineStateType ( int type, string name ) + { + int alias = ++alias_counter; + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineStateType, alias, type, name.c_str() ); + return alias; + } + + // int DefineEventType () + // { + // Write("event not implemented"); + // } + + int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, 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() ); + return alias; + } + + int DefineEntityValue (int type, string name, double hue = -1) + { + if(hue==-1) + { + std::hash shash; + size_t h = shash(name); + h ^= h>>32; + h = (uint32_t)h; + hue = h*1.0/std::numeric_limits::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 ); + return alias; + } + + int CreateContainer ( int type, int parent, 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() ); + else + fprintf( ctrace_stream, "%d\t0\ta%d\ta%d\t%d\t\"%s\"\n", PajeCreateContainer, alias, type, parent, name.c_str() ); + return alias; + } + void DestroyContainer () + {} + + void SetVariable (TTimePoint time, int type, int container, double value ) + { + events.push_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) ); + } + + void AddVariable (TTimePoint time, int type, int container, double value ) + { + events.push_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) ); + } + + void SubVariable (TTimePoint time, int type, int container, double value ) + { + events.push_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.push_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id) ); + } + + void PopState ( TTimePoint time, int type, int container ) + { + events.push_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.push_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.push_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()); + + char buf[2*MAX_TRACE_LINE_SIZE]; + logger->info("Writing traces... "); + for (int i = 0; i < events.size(); i++) + { + events[i].write( buf ); + fprintf( ctrace_stream, "%s", buf ); + } + 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( 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->warning("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024); + } + + PajeFile paje(filename, start_time); + + const int container_type_task_manager = paje.DefineContainerType( 0, "Task Manager" ); + const int container_type_node = paje.DefineContainerType( container_type_task_manager, "Node"); + const int container_type_thread = paje.DefineContainerType( container_type_task_manager, "Thread"); + const int container_type_timer = container_type_thread; //paje.DefineContainerType( container_type_task_manager, "Timers"); + const int container_type_jobs = paje.DefineContainerType( container_type_task_manager, "Jobs"); + + const int state_type_job = paje.DefineStateType( container_type_jobs, "Job" ); + const int state_type_task = paje.DefineStateType( container_type_thread, "Task" ); + const int state_type_timer = paje.DefineStateType( container_type_timer, "Timer state" ); + + const int variable_type_active_threads = paje.DefineVariableType( container_type_jobs, "Active threads" ); + + const int container_task_manager = paje.CreateContainer( container_type_task_manager, 0, "The task manager" ); + const int container_jobs = paje.CreateContainer( container_type_jobs, container_task_manager, "Jobs" ); + paje.SetVariable( start_time, variable_type_active_threads, container_jobs, 0.0 ); + + const int num_nodes = 1; //task_manager ? task_manager->GetNumNodes() : 1; + std::vector container_nodes; + + for(int i=0; i thread_aliases; + if(trace_threads) + for (int i=0; i job_map; + std::map job_task_map; + + for(Job & j : jobs) + if(job_map.find(j.type) == job_map.end()) + { + string name = Demangle(j.type->name()); + job_map[j.type] = paje.DefineEntityValue( state_type_job, name, -1 ); + job_task_map[j.type] = paje.DefineEntityValue( state_type_task, name, -1 ); + } + + for(Job & j : jobs) + { + paje.PushState( j.start_time, state_type_job, container_jobs, job_map[j.type] ); + paje.PopState( j.stop_time, state_type_job, container_jobs ); + } + + std::set timer_ids; + std::map timer_aliases; + + for(auto & event : timer_events) + timer_ids.insert(event.timer_id); + + + for(auto & vtasks : tasks) + for (Task & t : vtasks) + if(t.id_type==Task::ID_TIMER) + timer_ids.insert(t.id); + + for(auto id : timer_ids) + timer_aliases[id] = paje.DefineEntityValue( state_type_timer, "a timer" /* TODO: NgProfiler::GetName(id).c_str()*/, -1 ); + + int timerdepth = 0; + int maxdepth = 0; + for(auto & event : timer_events) + { + if(event.is_start) + { + timerdepth++; + maxdepth = timerdepth>maxdepth ? timerdepth : maxdepth; + } + else + timerdepth--; + } + + std::vector timer_container_aliases; + timer_container_aliases.resize(maxdepth); + for(int i=0; i links_merged; + links_merged.reserve(nlinks); + std::vector pos(nthreads); + + int nlinks_merged = 0; + while(nlinks_merged < nlinks) + { + int minpos = -1; + TTimePoint mintime; + for (int t = 0; t started_links; + + int link_type = paje.DefineLinkType(container_type_node, container_type_thread, container_type_thread, "links"); + + // match links + for ( auto & l : links_merged ) + { + if(l.is_start) + { + started_links.push_back(l); + } + else + { + unsigned int i = 0; + while(i +#include +#include // for __rdtsc() CPU time step counter + +#include "ngcore_api.hpp" // for NGCORE_API +#include "logging.hpp" // for logger + +namespace ngcore +{ + + extern NGCORE_API class PajeTrace *trace; + class PajeTrace + { + public: + typedef std::chrono::system_clock TClock; + // typedef TClock::time_point TTimePoint; + typedef size_t TTimePoint; + + protected: + std::shared_ptr logger = GetLogger("PajeTrace"); + private: + friend class TraceDisabler; + + NGCORE_API static size_t max_tracefile_size; + static bool trace_thread_counter; + 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 > tasks; + std::vector jobs; + std::vector timer_events; + std::vector > links; + + TTimePoint GetTime() + { + // return TClock::now(); + return TTimePoint(__rdtsc()); + } + + public: + NGCORE_API void StopTracing(); + + PajeTrace(int anthreads, std::string aname = ""); + ~PajeTrace(); + + 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, GetTime(), 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, GetTime(), 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, GetTime()} ); + 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 = GetTime(); + } + + 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, GetTime()} ); + } + + void StopJob() + { + if(tracing_enabled) + jobs.back().stop_time = GetTime(); + } + + 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, GetTime(), 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, GetTime(), false} ); + } + + void Write( std::string filename ); + + }; + + class TraceDisabler + { + bool trace_thread_counter; + bool trace_threads; + + public: + TraceDisabler() + { + trace_thread_counter = PajeTrace::trace_thread_counter; + PajeTrace::trace_thread_counter = false; + trace_threads = PajeTrace::trace_threads; + PajeTrace::trace_threads = false; + } + + ~TraceDisabler() + { + PajeTrace::trace_thread_counter = trace_thread_counter; + PajeTrace::trace_threads = trace_threads; + } + }; +} + +#endif // NETGEN_CORE_PAJE_TRACE_HPP diff --git a/libsrc/core/utils.cpp b/libsrc/core/utils.cpp new file mode 100644 index 00000000..5fbb11a4 --- /dev/null +++ b/libsrc/core/utils.cpp @@ -0,0 +1,20 @@ +#include "utils.hpp" + +#ifndef WIN32 +#include +#endif + +namespace ngcore +{ +#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); } +} // namespace ngcore + +#endif + diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp new file mode 100644 index 00000000..f80d55d8 --- /dev/null +++ b/libsrc/core/utils.hpp @@ -0,0 +1,23 @@ +#ifndef NETGEN_CORE_UTILS_HPP +#define NETGEN_CORE_UTILS_HPP + +#include +#include + +#include "ngcore_api.hpp" // for NGCORE_API + +namespace ngcore +{ + 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 + +} // namespace ngcore + +#endif // NETGEN_CORE_UTILS_HPP From 3a1cea6cbfa2046f4fcbd9832070b01838139ff8 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:54:50 +0100 Subject: [PATCH 12/98] [ngcore] Profiler --- libsrc/core/CMakeLists.txt | 4 +- libsrc/core/paje_trace.cpp | 134 +++++++++-------- libsrc/core/paje_trace.hpp | 62 +++----- libsrc/core/profiler.cpp | 106 +++++++++++++ libsrc/core/profiler.hpp | 286 ++++++++++++++++++++++++++++++++++++ libsrc/core/utils.cpp | 20 +++ libsrc/core/utils.hpp | 33 ++++- libsrc/general/ngpython.hpp | 11 +- 8 files changed, 537 insertions(+), 119 deletions(-) create mode 100644 libsrc/core/profiler.cpp create mode 100644 libsrc/core/profiler.hpp diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index 3e10f58d..c43a79ab 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -1,5 +1,5 @@ -add_library(ngcore SHARED archive.cpp logging.cpp paje_trace.cpp utils.cpp) +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) @@ -32,7 +32,7 @@ if(USE_PYTHON) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp - exception.hpp symboltable.hpp paje_trace.hpp utils.hpp + exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel) if(ENABLE_CPP_CORE_GUIDELINES_CHECK) diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 2742d25e..873a93d7 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -1,9 +1,9 @@ #include #include +#include #include #include #include -#include #include "archive.hpp" // for Demangle #include "paje_trace.hpp" @@ -23,13 +23,13 @@ namespace ngcore PajeTrace :: PajeTrace(int anthreads, std::string aname) { - start_time = GetTime(); + start_time = GetTimeCounter(); nthreads = anthreads; - tracefile_name = aname; + tracefile_name = std::move(aname); int bytes_per_event=33; - max_num_events_per_thread = std::min( (size_t)std::numeric_limits::max, max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7); + max_num_events_per_thread = std::min( static_cast(std::numeric_limits::max()), max_tracefile_size/bytes_per_event/(2*nthreads+1)*10/7); if(max_num_events_per_thread>0) { logger->info( "Tracefile size = {}MB", max_tracefile_size/1024/1024); @@ -53,7 +53,7 @@ namespace ngcore PajeTrace :: ~PajeTrace() { - if(tracefile_name.size()>0) + if(!tracefile_name.empty()) Write(tracefile_name); } @@ -67,11 +67,9 @@ namespace ngcore tracing_enabled = false; } - using std::string; class PajeFile { public: - typedef PajeTrace::TTimePoint TTimePoint; static void Hue2RGB ( double x, double &r, double &g, double &b ) { double d = 1.0/6.0; @@ -139,36 +137,35 @@ namespace ngcore bool value_is_alias = true; bool operator < (const PajeEvent & other) const { - // Same times can occur for very small tasks -> take "starting" events first (eg. PajePushState before PajePopState) + // 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; - else - return (time < other.time); + return (time < other.time); } - int write(char *buf) + int write(FILE *stream) { const int &key = id; const int &end_container = start_container; switch(event_type) { case PajeSetVariable: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSetVariable, time, type, container, var_value ); // NOLINT case PajeAddVariable: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeAddVariable, time, type, container, var_value ); // NOLINT case PajeSubVariable: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%.15g\n", PajeSubVariable, time, type, container, var_value ); + 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 sprintf( buf, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT else - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); + 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 sprintf( buf, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); + return fprintf( stream, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); // NOLINT case PajeStartLink: - return sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeStartLink, time, type, container, value, start_container, key ); + 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 sprintf( buf, "%d\t%.15g\ta%d\ta%d\t%d\ta%d\t%d\n", PajeEndLink, time, type, container, value, end_container, key ); + 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; } @@ -177,34 +174,46 @@ namespace ngcore std::vector events; public: - PajeFile( string filename, TTimePoint astart_time ) + 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"); - fprintf(ctrace_stream, "%s", header ); + ctrace_stream = fopen (filename.c_str(),"w"); // NOLINT + fprintf(ctrace_stream, "%s", header ); // NOLINT alias_counter = 0; } - int DefineContainerType ( int parent_type, string name ) + + ~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() ); + 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() ); + 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, string name ) + 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() ); + 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, string name ) + 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() ); + fprintf( ctrace_stream, "%d\ta%d\ta%d\t\"%s\"\n", PajeDefineStateType, alias, type, name.c_str() ); // NOLINT return alias; } @@ -213,38 +222,38 @@ namespace ngcore // Write("event not implemented"); // } - int DefineLinkType (int parent_container_type, int start_container_type, int stop_container_type, string name) + 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() ); + 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, string name, double hue = -1) + int DefineEntityValue (int type, const std::string & name, double hue = -1) { if(hue==-1) { - std::hash shash; + std::hash shash; size_t h = shash(name); - h ^= h>>32; - h = (uint32_t)h; + h ^= h>>32U; + h = static_cast(h); hue = h*1.0/std::numeric_limits::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 ); + 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, string name ) + 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() ); + 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() ); + 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 () @@ -252,17 +261,17 @@ namespace ngcore void SetVariable (TTimePoint time, int type, int container, double value ) { - events.push_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) ); + events.emplace_back( PajeEvent( PajeSetVariable, ConvertTime(time), type, container, value ) ); } void AddVariable (TTimePoint time, int type, int container, double value ) { - events.push_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) ); + events.emplace_back( PajeEvent( PajeAddVariable, ConvertTime(time), type, container, value ) ); } void SubVariable (TTimePoint time, int type, int container, double value ) { - events.push_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) ); + events.emplace_back( PajeEvent( PajeSubVariable, ConvertTime(time), type, container, value ) ); } void SetState () @@ -270,12 +279,12 @@ namespace ngcore void PushState ( TTimePoint time, int type, int container, int value, int id = 0, bool value_is_alias = true ) { - events.push_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id) ); + events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id, value_is_alias) ); } void PopState ( TTimePoint time, int type, int container ) { - events.push_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) ); + events.emplace_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) ); } void ResetState () @@ -283,12 +292,12 @@ namespace ngcore void StartLink ( TTimePoint time, int type, int container, int value, int start_container, int key ) { - events.push_back( PajeEvent( PajeStartLink, ConvertTime(time), type, container, value, start_container, 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.push_back( PajeEvent( PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) ); + events.emplace_back( PajeEvent( PajeEndLink, ConvertTime(time), type, container, value, end_container, key ) ); } void NewEvent () @@ -299,12 +308,11 @@ namespace ngcore logger->info("Sorting traces..."); std::sort (events.begin(), events.end()); - char buf[2*MAX_TRACE_LINE_SIZE]; logger->info("Writing traces... "); - for (int i = 0; i < events.size(); i++) + for (auto & event : events) { - events[i].write( buf ); - fprintf( ctrace_stream, "%s", buf ); + event.write( ctrace_stream ); +// fprintf( ctrace_stream, "%s", buf ); // NOLINT } logger->info("Done"); } @@ -336,7 +344,7 @@ namespace ngcore NGCORE_API PajeTrace *trace; - void PajeTrace::Write( string filename ) + void PajeTrace::Write( const std::string & filename ) { int n_events = jobs.size() + timer_events.size(); for(auto & vtasks : tasks) @@ -352,7 +360,7 @@ namespace ngcore if(!tracing_enabled) { - logger->warning("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024); + logger->warn("Tracing stopped during computation due to tracefile size limit of {} megabytes.", max_tracefile_size/1024/1024); } PajeFile paje(filename, start_time); @@ -374,18 +382,19 @@ namespace ngcore paje.SetVariable( start_time, variable_type_active_threads, container_jobs, 0.0 ); const int num_nodes = 1; //task_manager ? task_manager->GetNumNodes() : 1; - std::vector container_nodes; + std::vector container_nodes; + container_nodes.reserve(num_nodes); for(int i=0; i thread_aliases; + thread_aliases.reserve(nthreads); if(trace_threads) for (int i=0; i job_map; @@ -394,7 +403,7 @@ namespace ngcore for(Job & j : jobs) if(job_map.find(j.type) == job_map.end()) { - string name = Demangle(j.type->name()); + 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 ); } @@ -437,8 +446,7 @@ namespace ngcore timer_container_aliases.resize(maxdepth); for(int i=0; i #include // for __rdtsc() CPU time step counter -#include "ngcore_api.hpp" // for NGCORE_API #include "logging.hpp" // for logger +#include "ngcore_api.hpp" // for NGCORE_API +#include "utils.hpp" namespace ngcore { @@ -15,15 +16,11 @@ namespace ngcore class PajeTrace { public: - typedef std::chrono::system_clock TClock; - // typedef TClock::time_point TTimePoint; - typedef size_t TTimePoint; + using TClock = std::chrono::system_clock; protected: std::shared_ptr logger = GetLogger("PajeTrace"); private: - friend class TraceDisabler; - NGCORE_API static size_t max_tracefile_size; static bool trace_thread_counter; static bool trace_threads; @@ -104,24 +101,24 @@ namespace ngcore std::vector timer_events; std::vector > links; - TTimePoint GetTime() - { - // return TClock::now(); - return TTimePoint(__rdtsc()); - } - public: NGCORE_API void StopTracing(); + PajeTrace() = delete; + PajeTrace(const PajeTrace &) = delete; + PajeTrace(PajeTrace &&) = delete; PajeTrace(int anthreads, std::string aname = ""); ~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, GetTime(), true}); + timer_events.push_back(TimerEvent{timer_id, GetTimeCounter(), true}); } void StopTimer(int timer_id) @@ -129,7 +126,7 @@ namespace ngcore if(!tracing_enabled) return; if(unlikely(timer_events.size() == max_num_events_per_thread)) StopTracing(); - timer_events.push_back(TimerEvent{timer_id, GetTime(), false}); + 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) @@ -139,7 +136,7 @@ namespace ngcore 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, GetTime()} ); + tasks[thread_id].push_back( Task{thread_id, id, id_type, additional_value, GetTimeCounter()} ); return task_num; } @@ -147,7 +144,7 @@ namespace ngcore { if(!trace_threads && !trace_thread_counter) return; if(task_num>=0) - tasks[thread_id][task_num].stop_time = GetTime(); + tasks[thread_id][task_num].stop_time = GetTimeCounter(); } void SetTask(int thread_id, int task_num, int additional_value) { @@ -161,13 +158,13 @@ namespace ngcore if(!tracing_enabled) return; if(jobs.size() == max_num_events_per_thread) StopTracing(); - jobs.push_back( Job{job_id, &type, GetTime()} ); + jobs.push_back( Job{job_id, &type, GetTimeCounter()} ); } void StopJob() { if(tracing_enabled) - jobs.back().stop_time = GetTime(); + jobs.back().stop_time = GetTimeCounter(); } void StartLink(int thread_id, int key) @@ -175,7 +172,7 @@ namespace ngcore if(!tracing_enabled) return; if(links[thread_id].size() == max_num_events_per_thread) StopTracing(); - links[thread_id].push_back( ThreadLink{thread_id, key, GetTime(), true} ); + links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), true} ); } void StopLink(int thread_id, int key) @@ -183,33 +180,12 @@ namespace ngcore if(!tracing_enabled) return; if(links[thread_id].size() == max_num_events_per_thread) StopTracing(); - links[thread_id].push_back( ThreadLink{thread_id, key, GetTime(), false} ); + links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} ); } - void Write( std::string filename ); + void Write( const std::string & filename ); }; - - class TraceDisabler - { - bool trace_thread_counter; - bool trace_threads; - - public: - TraceDisabler() - { - trace_thread_counter = PajeTrace::trace_thread_counter; - PajeTrace::trace_thread_counter = false; - trace_threads = PajeTrace::trace_threads; - PajeTrace::trace_threads = false; - } - - ~TraceDisabler() - { - PajeTrace::trace_thread_counter = trace_thread_counter; - PajeTrace::trace_threads = trace_threads; - } - }; -} +} // namespace ngcore #endif // NETGEN_CORE_PAJE_TRACE_HPP diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp new file mode 100644 index 00000000..e3350145 --- /dev/null +++ b/libsrc/core/profiler.cpp @@ -0,0 +1,106 @@ +#include + +#include "profiler.hpp" + +namespace ngcore +{ + std::array NgProfiler::timers; // NOLINT + + std::string NgProfiler::filename; + + size_t dummy_thread_times[NgProfiler::SIZE]; + size_t * NgProfiler::thread_times = dummy_thread_times; // NOLINT + size_t dummy_thread_flops[NgProfiler::SIZE]; + size_t * NgProfiler::thread_flops = dummy_thread_flops; // NOLINT + + std::shared_ptr 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 + } + + } + + void NgProfiler :: Print (FILE * prof) + { + int i = 0; + for (auto & t : timers) + { + if (t.count != 0 || t.usedcounter != 0) + { + fprintf(prof,"job %3i calls %8li, time %6.4f sec",i,t.count,t.tottime); // NOLINT + if(t.flops != 0.0) + fprintf(prof,", MFlops = %6.2f",t.flops / (t.tottime) * 1e-6); // NOLINT + if(t.loads != 0.0) + fprintf(prof,", MLoads = %6.2f",t.loads / (t.tottime) * 1e-6); // NOLINT + if(t.stores != 0.0) + fprintf(prof,", MStores = %6.2f",t.stores / (t.tottime) * 1e-6); // NOLINT + if(t.usedcounter) + fprintf(prof," %s",t.name.c_str()); // NOLINT + fprintf(prof,"\n"); // NOLINT + } + i++; + } + } + + + int NgProfiler :: CreateTimer (const std::string & name) + { + static std::mutex createtimer_mutex; + int nr = -1; + { + std::lock_guard guard(createtimer_mutex); + for (int i = SIZE-1; i > 0; i--) + { + auto & t = timers[i]; + if (!t.usedcounter) + { + t.usedcounter = 1; + t.name = name; + nr = i; + break; + } + } + } + if (nr > -1) return nr; + static bool first_overflow = true; + if (first_overflow) + { + first_overflow = false; + NgProfiler::logger->warn("no more timer available, reusing last one"); + } + return 0; + } + + void NgProfiler :: Reset () + { + for(auto & t : timers) + { + t.tottime = 0.0; + t.count = 0; + t.flops = 0.0; + t.loads = 0; + t.stores = 0; + } + } + + NgProfiler prof; // NOLINT + + +} // namespace ngcore diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp new file mode 100644 index 00000000..b1b75dd5 --- /dev/null +++ b/libsrc/core/profiler.hpp @@ -0,0 +1,286 @@ +#ifndef NETGEN_CORE_PROFILER_HPP +#define NETGEN_CORE_PROFILER_HPP + +#include +#include + +#include "logging.hpp" +#include "paje_trace.hpp" +#include "utils.hpp" + +namespace ngcore +{ + class NgProfiler + { + public: + /// maximal number of timers + enum { SIZE = 8*1024 }; + + struct TimerVal + { + TimerVal() = default; + + double tottime = 0.0; + double starttime = 0.0; + double flops = 0.0; + double loads = 0.0; + double stores = 0.0; + long count = 0; + std::string name = ""; + int usedcounter = 0; + }; + + NGCORE_API static std::array timers; + + NGCORE_API static TTimePoint * thread_times; + NGCORE_API static TTimePoint * thread_flops; + NGCORE_API static std::shared_ptr logger; + private: + + 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(); + } + + static void StopThreadTimer (size_t nr, size_t tid) + { + thread_times[tid*SIZE+nr] += GetTimeCounter(); + } + + static void AddThreadFlops (size_t nr, size_t tid, size_t flops) + { + thread_flops[tid*SIZE+nr] += flops; + } + + /// 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 * ost); + }; + + + + class 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(RegionTimer &&) = delete; + RegionTimer(const RegionTimer &) = delete; + void operator=(const RegionTimer &) = delete; + void operator=(RegionTimer &&) = delete; + }; + + class ThreadRegionTimer + { + size_t nr; + size_t tid; + public: + /// start timer + ThreadRegionTimer (size_t _nr, size_t _tid) : nr(_nr), tid(_tid) + { NgProfiler::StartThreadTimer(nr, tid); } + /// stop timer + ~ThreadRegionTimer () + { NgProfiler::StopThreadTimer(nr, tid); } + + ThreadRegionTimer() = delete; + ThreadRegionTimer(ThreadRegionTimer &&) = delete; + ThreadRegionTimer(const ThreadRegionTimer &) = delete; + void operator=(const ThreadRegionTimer &) = delete; + void operator=(ThreadRegionTimer &&) = delete; + }; + + class RegionTracer + { + int nr; + int thread_id; + public: + static constexpr int ID_JOB = PajeTrace::Task::ID_JOB; + static constexpr int ID_NONE = PajeTrace::Task::ID_NONE; + static constexpr int ID_TIMER = PajeTrace::Task::ID_TIMER; + + RegionTracer() = delete; + RegionTracer(RegionTracer &&) = delete; + RegionTracer(const RegionTracer &) = delete; + void operator=(const RegionTracer &) = delete; + void operator=(RegionTracer &&) = delete; + + /// start trace + RegionTracer (int athread_id, int region_id, int id_type = ID_NONE, int additional_value = -1 ) + : thread_id(athread_id) + { + if (trace) + nr = trace->StartTask (athread_id, region_id, id_type, additional_value); + } + /// start trace with timer + RegionTracer (int athread_id, Timer & timer, int additional_value = -1 ) + : thread_id(athread_id) + { + if (trace) + nr = trace->StartTask (athread_id, static_cast(timer), ID_TIMER, additional_value); + } + + /// set user defined value + void SetValue( int additional_value ) + { + if (trace) + trace->SetTask( thread_id, nr, additional_value ); + } + + /// stop trace + ~RegionTracer () + { + if (trace) + trace->StopTask (thread_id, nr); + } + }; + + + // Helper function for timings + // Run f() at least min_iterations times until max_time seconds elapsed + // returns minimum runtime for a call of f() + template + double RunTiming( TFunc f, double max_time = 0.5, int min_iterations = 10 ) + { + // Make sure the whole test run does not exceed maxtime + double tend = WallTime()+max_time; + + // warmup + f(); + + double tres = std::numeric_limits::max(); + int iteration = 0; + while(WallTime() #endif +#include namespace ngcore { @@ -14,6 +16,24 @@ namespace ngcore nullptr, nullptr, &status); } + + 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() wall_time_start = TClock::now(); + } // namespace ngcore #endif diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index f80d55d8..2c88629d 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -1,8 +1,10 @@ #ifndef NETGEN_CORE_UTILS_HPP #define NETGEN_CORE_UTILS_HPP -#include +#include #include +#include +#include // for __rdtsc() CPU time step counter #include "ngcore_api.hpp" // for NGCORE_API @@ -18,6 +20,35 @@ namespace ngcore inline bool unlikely (bool x) { return x; } #endif + using TClock = std::chrono::system_clock; + extern NGCORE_API const std::chrono::time_point wall_time_start; + + // Time in seconds since program start + inline double WallTime () noexcept + { + std::chrono::time_point now = TClock::now(); + std::chrono::duration elapsed_seconds = now-wall_time_start; + return elapsed_seconds.count(); + } + + // High precision clock counter register + using TTimePoint = size_t; + extern NGCORE_API double ticks_per_second; + + inline TTimePoint GetTimeCounter() noexcept + { + return TTimePoint(__rdtsc()); + } + + template + inline std::string ToString (const T& t) + { + std::stringstream ss; + ss << t; + return ss.str(); + } + + } // namespace ngcore #endif // NETGEN_CORE_UTILS_HPP diff --git a/libsrc/general/ngpython.hpp b/libsrc/general/ngpython.hpp index fa9862b1..0604cb00 100644 --- a/libsrc/general/ngpython.hpp +++ b/libsrc/general/ngpython.hpp @@ -66,16 +66,7 @@ namespace netgen return static_cast::pointer>(lambda); } - - template - inline std::string ToString (const T& t) - { - std::stringstream ss; - ss << t; - return ss.str(); - } - -} +} // namespace netgen #endif From 8c54fd70afddbcfa03f43636152a418b91493540 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:55:17 +0100 Subject: [PATCH 13/98] [gitlab-ci] Fix builds --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d493bdab..276a0ec8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,8 +14,8 @@ stages: - x64 before_script: - "echo off" - - 'call "%VS140COMNTOOLS%\..\..\VC\bin\amd64\vcvars64.bat"' - - set CMAKE_GENERATOR=Visual Studio 14 2015 Win64 + - 'call "%VS2017INSTALLDIR%\VC\Auxiliary\Build\vcvars64"' + - set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - set CI_DIR=C:\ci\%CI_PIPELINE_ID% - set NETGEN_BUILD_DIR=%CI_DIR%\build - set INSTALL_DIR=%CI_DIR%\install From 930d82ba38a508f444f8116fa1d4f0ad8abe8f1c Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:55:42 +0100 Subject: [PATCH 14/98] [lint] allow pointer arithmetic --- libsrc/core/.clang-tidy | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 806e0616..63d05e89 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -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,-modernize-pass-by-value' +Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic' CheckOptions: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 -WarningsAsErrors: '*' \ No newline at end of file +WarningsAsErrors: '*' From 8ab625c3fa9ba72506218954571c40d6ac94e38c Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:55:51 +0100 Subject: [PATCH 15/98] Fix build error --- libsrc/core/archive.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 04915cbc..6a4a0792 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -209,7 +209,6 @@ namespace ngcore // vector has special implementation (like a bitarray) therefore // it needs a special overload (this could probably be more efficient, but we // don't use it that often anyway) - template<> Archive& operator& (std::vector& v) { size_t size; From baca4a57a0d4744218c5f5ca20c7a4c5430f15c6 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:57:00 +0100 Subject: [PATCH 16/98] Fix link error --- libsrc/core/profiler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index e3350145..bb95a111 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -13,7 +13,7 @@ namespace ngcore size_t dummy_thread_flops[NgProfiler::SIZE]; size_t * NgProfiler::thread_flops = dummy_thread_flops; // NOLINT - std::shared_ptr logger = GetLogger("Profiler"); // NOLINT + std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT NgProfiler :: NgProfiler() { From c6a401e0663c121d3b2cc2eba0be43097834c964 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 11:26:46 +0100 Subject: [PATCH 17/98] Remove old profiler.hpp --- libsrc/core/.clang-tidy | 2 +- libsrc/core/ngcore.hpp | 1 + libsrc/core/profiler.cpp | 2 +- libsrc/core/profiler.hpp | 26 ++++-- libsrc/general/CMakeLists.txt | 10 +-- libsrc/general/myadt.hpp | 3 +- libsrc/general/ngexception.cpp | 33 -------- libsrc/general/ngexception.hpp | 34 -------- libsrc/general/profiler.cpp | 131 ------------------------------ libsrc/general/profiler.hpp | 88 -------------------- libsrc/stlgeom/meshstlsurface.cpp | 1 - 11 files changed, 29 insertions(+), 302 deletions(-) delete mode 100644 libsrc/general/ngexception.cpp delete mode 100644 libsrc/general/ngexception.hpp delete mode 100644 libsrc/general/profiler.cpp delete mode 100644 libsrc/general/profiler.hpp diff --git a/libsrc/core/.clang-tidy b/libsrc/core/.clang-tidy index 63d05e89..5742a3d8 100644 --- a/libsrc/core/.clang-tidy +++ b/libsrc/core/.clang-tidy @@ -1,4 +1,4 @@ -Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-pro-bounds-constant-array-index,-cppcoreguidelines-pro-bounds-pointer-arithmetic' +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: - key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor value: 1 diff --git a/libsrc/core/ngcore.hpp b/libsrc/core/ngcore.hpp index 153a0e6c..d73a3ed9 100644 --- a/libsrc/core/ngcore.hpp +++ b/libsrc/core/ngcore.hpp @@ -4,6 +4,7 @@ #include "archive.hpp" #include "exception.hpp" #include "logging.hpp" +#include "profiler.hpp" #include "symboltable.hpp" #include "version.hpp" diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index bb95a111..e24de4e3 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -4,7 +4,7 @@ namespace ngcore { - std::array NgProfiler::timers; // NOLINT + std::vector NgProfiler::timers(NgProfiler::SIZE); // NOLINT std::string NgProfiler::filename; diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index b1b75dd5..10a5cf0d 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -30,7 +30,7 @@ namespace ngcore int usedcounter = 0; }; - NGCORE_API static std::array timers; + NGCORE_API static std::vector timers; NGCORE_API static TTimePoint * thread_times; NGCORE_API static TTimePoint * thread_flops; @@ -69,17 +69,17 @@ namespace ngcore static void StartThreadTimer (size_t nr, size_t tid) { - thread_times[tid*SIZE+nr] -= GetTimeCounter(); + thread_times[tid*SIZE+nr] -= GetTimeCounter(); // NOLINT } static void StopThreadTimer (size_t nr, size_t tid) { - thread_times[tid*SIZE+nr] += GetTimeCounter(); + 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; + thread_flops[tid*SIZE+nr] += flops; // NOLINT } /// if you know number of flops, provide them to obtain the MFlop - rate @@ -123,6 +123,22 @@ namespace ngcore static std::string GetName (int nr) { return timers[nr].name; } /// print profile NGCORE_API static void Print (FILE * ost); + + 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; + }; }; @@ -184,8 +200,8 @@ namespace ngcore ~RegionTimer () { timer.Stop(); } RegionTimer() = delete; - RegionTimer(RegionTimer &&) = delete; RegionTimer(const RegionTimer &) = delete; + RegionTimer(RegionTimer &&) = delete; void operator=(const RegionTimer &) = delete; void operator=(RegionTimer &&) = delete; }; diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index b65fee96..f1c39183 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -1,8 +1,8 @@ add_definitions(-DNGINTERFACE_EXPORTS) add_library(gen OBJECT array.cpp bitarray.cpp dynamicmem.cpp flags.cpp - hashtabl.cpp mystring.cpp ngexception.cpp optmem.cpp parthreads.cpp - profiler.cpp seti.cpp sort.cpp spbita2d.cpp table.cpp + hashtabl.cpp mystring.cpp optmem.cpp parthreads.cpp + seti.cpp sort.cpp spbita2d.cpp table.cpp mpi_interface.cpp gzstream.cpp ) @@ -12,13 +12,11 @@ endif(NOT WIN32) set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) -install( FILES ngexception.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel ) - install(FILES array.hpp autodiff.hpp autoptr.hpp bitarray.hpp dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp - ngsimd.hpp mystring.hpp netgenout.hpp ngexception.hpp ngpython.hpp - optmem.hpp parthreads.hpp profiler.hpp seti.hpp sort.hpp + ngsimd.hpp mystring.hpp netgenout.hpp ngpython.hpp + optmem.hpp parthreads.hpp seti.hpp sort.hpp spbita2d.hpp stack.hpp table.hpp template.hpp gzstream.h DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel diff --git a/libsrc/general/myadt.hpp b/libsrc/general/myadt.hpp index 7263d088..4284a42f 100644 --- a/libsrc/general/myadt.hpp +++ b/libsrc/general/myadt.hpp @@ -21,8 +21,8 @@ namespace netgen { using namespace ngcore; + using NgException = Exception; } -#include "ngexception.hpp" #include "parthreads.hpp" // #include "moveablemem.hpp" #include "dynamicmem.hpp" @@ -43,7 +43,6 @@ namespace netgen #include "sort.hpp" #include "stack.hpp" #include "mystring.hpp" -#include "profiler.hpp" #include "mpi_interface.hpp" #include "netgenout.hpp" diff --git a/libsrc/general/ngexception.cpp b/libsrc/general/ngexception.cpp deleted file mode 100644 index 6bcd2cc9..00000000 --- a/libsrc/general/ngexception.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/**************************************************************************/ -/* File: ngexception.cpp */ -/* Author: Joachim Schoeberl */ -/* Date: 16. Jan. 02 */ -/**************************************************************************/ - -#include - -namespace netgen -{ - //using namespace netgen; - - - - NgException :: NgException (const string & s) - : m_what(s) - { - ; - } - - - NgException :: ~NgException () - { - ; - } - - /// append string to description - void NgException :: Append (const string & s) - { - m_what += s; - } - -} diff --git a/libsrc/general/ngexception.hpp b/libsrc/general/ngexception.hpp deleted file mode 100644 index 6e06498c..00000000 --- a/libsrc/general/ngexception.hpp +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef FILE_NGEXCEPTION -#define FILE_NGEXCEPTION - -/**************************************************************************/ -/* File: ngexception.hpp */ -/* Author: Joachim Schoeberl */ -/* Date: 16. Jan. 2002 */ -/**************************************************************************/ - -namespace netgen -{ - -/// Base class for all ng exceptions -class NgException : public std::exception -{ - /// verbal description of exception - string m_what; -public: - /// - DLL_HEADER NgException (const string & s); - /// - DLL_HEADER virtual ~NgException (); - - /// append string to description - DLL_HEADER void Append (const string & s); - // void Append (const char * s); - - /// verbal description of exception - const string & What() const { return m_what; } - virtual const char* what() const noexcept override { return m_what.c_str(); } -}; -} - -#endif diff --git a/libsrc/general/profiler.cpp b/libsrc/general/profiler.cpp deleted file mode 100644 index e6a9685b..00000000 --- a/libsrc/general/profiler.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************/ -/* File: profiler.cpp */ -/* Author: Joachim Schoeberl */ -/* Date: 19. Apr. 2002 */ -/**************************************************************************/ - - -#include - -namespace netgen -{ - //using namespace netgen; - - long int NgProfiler::tottimes[SIZE]; - long int NgProfiler::starttimes[SIZE]; - long int NgProfiler::counts[SIZE]; - string NgProfiler::names[SIZE]; - int NgProfiler::usedcounter[SIZE]; - - - NgProfiler :: NgProfiler() - { - for (int i = 0; i < SIZE; i++) - { - tottimes[i] = 0; - usedcounter[i] = 0; - } - - total_timer = CreateTimer ("total CPU time"); - StartTimer (total_timer); - } - - NgProfiler :: ~NgProfiler() - { -#ifndef PARALLEL - StopTimer (total_timer); -#endif - - //ofstream prof; - //prof.open("ng.prof"); - - // ofstream-constructor may be called after STL-stuff is destructed, - // which leads to an "order of destruction"-problem, - // thus we use the C-variant: - - if (getenv ("NGPROFILE")) - { - char filename[100]; -#ifdef PARALLEL - sprintf (filename, "netgen.prof.%d", id); -#else - sprintf (filename, "netgen.prof"); -#endif - - if (id == 0) printf ("write profile to file netgen.prof\n"); - FILE *prof = fopen(filename,"w"); - Print (prof); - fclose(prof); - } - } - - -// void NgProfiler :: Print (ostream & prof) -// { -// for (int i = 0; i < SIZE; i++) -// if (counts[i] != 0 || usedcounter[i] != 0) -// { -// prof.setf (ios::fixed, ios::floatfield); -// prof.setf (ios::showpoint); - -// prof // << "job " << setw(3) << i -// << "calls " << setw(8) << counts[i] -// << ", time " << setprecision(2) << setw(6) << double(tottimes[i]) / CLOCKS_PER_SEC << " sec"; - -// if (usedcounter[i]) -// prof << " " << names[i]; -// else -// prof << " " << i; - -// prof << endl; -// } -// } - - - void NgProfiler :: Print (FILE * prof) - { - for (int i = 0; i < SIZE; i++) - if (counts[i] != 0 || usedcounter[i] != 0) - { - //fprintf(prof,"job %3i calls %8i, time %6.2f sec",i,counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); -#ifndef USE_TSC - fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / CLOCKS_PER_SEC); -#else - fprintf(prof,"calls %8li, time %6.2f sec",counts[i],double(tottimes[i]) / 2.7e9); -#endif - if(usedcounter[i]) - fprintf(prof," %s",names[i].c_str()); - else - fprintf(prof," %i",i); - fprintf(prof,"\n"); - } - } - - int NgProfiler :: CreateTimer (const string & name) - { - for (int i = SIZE-1; i > 0; i--) - if(names[i] == name) - return i; - - for (int i = SIZE-1; i > 0; i--) - if (!usedcounter[i]) - { - usedcounter[i] = 1; - names[i] = name; - return i; - } - return -1; - } - - - void NgProfiler :: ClearTimers () - { - for (int i = 0; i < SIZE; i++) - { - tottimes[i] = 0; - counts[i] = 0; - } - } - - NgProfiler prof; -} diff --git a/libsrc/general/profiler.hpp b/libsrc/general/profiler.hpp deleted file mode 100644 index 98039114..00000000 --- a/libsrc/general/profiler.hpp +++ /dev/null @@ -1,88 +0,0 @@ -#ifndef FILE_NG_PROFILER -#define FILE_NG_PROFILER - -/**************************************************************************/ -/* File: profiler.hpp */ -/* Author: Joachim Schoeberl */ -/* Date: 5. Jan. 2005 */ -/**************************************************************************/ - - - -#ifdef VTRACE -#include "vt_user.h" -#else - #define VT_USER_START(n) - #define VT_USER_END(n) - #define VT_TRACER(n) -#endif - - -// #define USE_TSC -#ifdef USE_TSC -#include // for __rdtsc() CPU time step counter -#endif - -namespace netgen -{ - -class NgProfiler -{ - enum { SIZE = 1000 }; - - static long int tottimes[SIZE]; - static long int starttimes[SIZE]; - static long int counts[SIZE]; - static string names[SIZE]; - static int usedcounter[SIZE]; - - int total_timer; -public: - NgProfiler(); - ~NgProfiler(); - static int CreateTimer (const string & name); -#ifndef USE_TSC - static void StartTimer (int nr) - { - starttimes[nr] = clock(); counts[nr]++; - // VT_USER_START (const_cast (names[nr].c_str())); - VT_USER_START ( (char * const) (names[nr].c_str())); - } - static void StopTimer (int nr) - { - tottimes[nr] += clock()-starttimes[nr]; - VT_USER_END (const_cast (names[nr].c_str())); - } -#else - static void StartTimer (int nr) - { - starttimes[nr] = __rdtsc(); counts[nr]++; - // VT_USER_START (const_cast (names[nr].c_str())); - // VT_USER_START ( (char * const) (names[nr].c_str())); - } - static void StopTimer (int nr) - { - tottimes[nr] += __rdtsc()-starttimes[nr]; - VT_USER_END (const_cast (names[nr].c_str())); - } -#endif - - - //static void Print (ostream & ost); - static void Print (FILE * prof); - - static void ClearTimers (); - - class RegionTimer - { - int nr; - public: - RegionTimer (int anr) : nr(anr) - { StartTimer (nr); } - ~RegionTimer () { StopTimer (nr); } - }; -}; - -} - -#endif diff --git a/libsrc/stlgeom/meshstlsurface.cpp b/libsrc/stlgeom/meshstlsurface.cpp index 4e267193..02753fb8 100644 --- a/libsrc/stlgeom/meshstlsurface.cpp +++ b/libsrc/stlgeom/meshstlsurface.cpp @@ -598,7 +598,6 @@ void STLSurfaceMeshing1 (STLGeometry & geom, for (int fnr = 1; fnr <= mesh.GetNFD(); fnr++) { - if (fnr == 100) NgProfiler::ClearTimers(); if (!opensegsperface[fnr]) continue; if (multithread.terminate) return; From 5fa0cb850afef271b30a8c7963305ca70be4a5e7 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 11:54:28 +0100 Subject: [PATCH 18/98] Fix cmake error --- libsrc/general/CMakeLists.txt | 4 ---- 1 file changed, 4 deletions(-) diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index f1c39183..f5c16e82 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -6,10 +6,6 @@ add_library(gen OBJECT mpi_interface.cpp gzstream.cpp ) -if(NOT WIN32) - target_link_libraries(gen ngcore) -endif(NOT WIN32) - set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) install(FILES From 58007f1eaf5eb8409f7affc09bba8a8a79ba4705 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 11:54:28 +0100 Subject: [PATCH 19/98] Fix cmake error --- libsrc/general/CMakeLists.txt | 4 ---- libsrc/gprim/CMakeLists.txt | 3 --- libsrc/linalg/CMakeLists.txt | 4 ---- 3 files changed, 11 deletions(-) diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index f1c39183..f5c16e82 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -6,10 +6,6 @@ add_library(gen OBJECT mpi_interface.cpp gzstream.cpp ) -if(NOT WIN32) - target_link_libraries(gen ngcore) -endif(NOT WIN32) - set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) install(FILES diff --git a/libsrc/gprim/CMakeLists.txt b/libsrc/gprim/CMakeLists.txt index ac4b8f11..3957476a 100644 --- a/libsrc/gprim/CMakeLists.txt +++ b/libsrc/gprim/CMakeLists.txt @@ -3,9 +3,6 @@ add_library(gprim OBJECT adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp ) -if(NOT WIN32) - target_link_libraries(gprim ngcore) -endif(NOT WIN32) set_target_properties( gprim PROPERTIES POSITION_INDEPENDENT_CODE ON ) diff --git a/libsrc/linalg/CMakeLists.txt b/libsrc/linalg/CMakeLists.txt index 9f35d751..a5a5a4f2 100644 --- a/libsrc/linalg/CMakeLists.txt +++ b/libsrc/linalg/CMakeLists.txt @@ -4,10 +4,6 @@ add_library( la OBJECT set_target_properties(la PROPERTIES POSITION_INDEPENDENT_CODE ON ) -if(NOT WIN32) - target_link_libraries(la ngcore) -endif(NOT WIN32) - install(FILES densemat.hpp linalg.hpp opti.hpp polynomial.hpp vector.hpp From 90de81f96e6d0eaee601f8c4431434d0ee118ab6 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 13:18:27 +0100 Subject: [PATCH 20/98] Fix wrong header include on Windows --- libsrc/core/utils.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index 2c88629d..c8dc1e9e 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -4,7 +4,12 @@ #include #include #include + +#ifdef WIN32 +#include // for __rdtsc() CPU time step counter +#else #include // for __rdtsc() CPU time step counter +#endif // WIN32 #include "ngcore_api.hpp" // for NGCORE_API From 74a4cd7d93bd485d01fe4eb07ddd04b7237ff043 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 13:18:27 +0100 Subject: [PATCH 21/98] Fix wrong header include on Windows --- libsrc/core/paje_trace.hpp | 1 - libsrc/core/utils.hpp | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/libsrc/core/paje_trace.hpp b/libsrc/core/paje_trace.hpp index d2584487..2addc0e3 100644 --- a/libsrc/core/paje_trace.hpp +++ b/libsrc/core/paje_trace.hpp @@ -3,7 +3,6 @@ #include #include -#include // for __rdtsc() CPU time step counter #include "logging.hpp" // for logger #include "ngcore_api.hpp" // for NGCORE_API diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index 2c88629d..c8dc1e9e 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -4,7 +4,12 @@ #include #include #include + +#ifdef WIN32 +#include // for __rdtsc() CPU time step counter +#else #include // for __rdtsc() CPU time step counter +#endif // WIN32 #include "ngcore_api.hpp" // for NGCORE_API From 8659e4aa84c6db40a4278559e980de87598b10e9 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 7 Jan 2019 13:49:59 +0100 Subject: [PATCH 22/98] Remove double (class and method) NGCORE_API --- libsrc/core/symboltable.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/core/symboltable.hpp b/libsrc/core/symboltable.hpp index 53c07dd4..582a7a37 100644 --- a/libsrc/core/symboltable.hpp +++ b/libsrc/core/symboltable.hpp @@ -45,7 +45,7 @@ namespace ngcore } /// INDEX of symbol name, throws exception if unused - NGCORE_API size_t Index (const std::string & name) const + size_t Index (const std::string & name) const { for (size_t i = 0; i < names.size(); i++) if (names[i] == name) return i; @@ -53,7 +53,7 @@ namespace ngcore } /// Index of symbol name, returns -1 if unused - NGCORE_API int CheckIndex (const std::string & name) const + int CheckIndex (const std::string & name) const { for (int i = 0; i < names.size(); i++) if (names[i] == name) return i; From e46787dd5d8c04004d4322ae8b8286f42372dd52 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 7 Jan 2019 14:17:43 +0100 Subject: [PATCH 23/98] fixes for profiler to work with ngsolve --- libsrc/core/paje_trace.hpp | 8 ++++---- libsrc/core/profiler.cpp | 8 ++++---- libsrc/core/profiler.hpp | 6 ++++-- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/libsrc/core/paje_trace.hpp b/libsrc/core/paje_trace.hpp index d2584487..83c66bab 100644 --- a/libsrc/core/paje_trace.hpp +++ b/libsrc/core/paje_trace.hpp @@ -22,8 +22,8 @@ namespace ngcore std::shared_ptr logger = GetLogger("PajeTrace"); private: NGCORE_API static size_t max_tracefile_size; - static bool trace_thread_counter; - static bool trace_threads; + NGCORE_API static bool trace_thread_counter; + NGCORE_API static bool trace_threads; bool tracing_enabled; TTimePoint start_time; @@ -107,8 +107,8 @@ namespace ngcore PajeTrace() = delete; PajeTrace(const PajeTrace &) = delete; PajeTrace(PajeTrace &&) = delete; - PajeTrace(int anthreads, std::string aname = ""); - ~PajeTrace(); + NGCORE_API PajeTrace(int anthreads, std::string aname = ""); + NGCORE_API ~PajeTrace(); void operator=(const PajeTrace &) = delete; void operator=(PajeTrace &&) = delete; diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index e24de4e3..f738fd55 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -8,10 +8,10 @@ namespace ngcore std::string NgProfiler::filename; - size_t dummy_thread_times[NgProfiler::SIZE]; - size_t * NgProfiler::thread_times = dummy_thread_times; // NOLINT - size_t dummy_thread_flops[NgProfiler::SIZE]; - size_t * NgProfiler::thread_flops = dummy_thread_flops; // NOLINT + 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 NgProfiler::logger = GetLogger("Profiler"); // NOLINT diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index 10a5cf0d..f7415881 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -35,9 +35,11 @@ namespace ngcore NGCORE_API static TTimePoint * thread_times; NGCORE_API static TTimePoint * thread_flops; NGCORE_API static std::shared_ptr logger; + NGCORE_API static size_t dummy_thread_times[NgProfiler::SIZE]; + NGCORE_API static size_t dummy_thread_flops[NgProfiler::SIZE]; private: - static std::string filename; + NGCORE_API static std::string filename; public: NgProfiler(); ~NgProfiler(); @@ -143,7 +145,7 @@ namespace ngcore - class Timer + class NGCORE_API Timer { int timernr; int priority; From 99c95757a3860ddd3c74f8ac4bc279117d21873f Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 7 Jan 2019 15:17:56 +0100 Subject: [PATCH 24/98] [ngcore] ngspickle ngcore_api --- libsrc/core/archive.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 6a4a0792..2848b8f1 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -943,7 +943,7 @@ namespace ngcore }; template - auto NGSPickle() + NGCORE_API auto NGSPickle() { return pybind11::pickle([](T* self) { From 247b2a289287de67a9a113cba9107f512d48552a Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Tue, 8 Jan 2019 11:26:29 +0100 Subject: [PATCH 25/98] [cmake] Replace object libraries with interface libraries --- libsrc/general/CMakeLists.txt | 14 +++++++------- libsrc/gprim/CMakeLists.txt | 10 +++++----- libsrc/linalg/CMakeLists.txt | 10 +++++----- libsrc/meshing/CMakeLists.txt | 12 +++--------- nglib/CMakeLists.txt | 5 +---- 5 files changed, 21 insertions(+), 30 deletions(-) diff --git a/libsrc/general/CMakeLists.txt b/libsrc/general/CMakeLists.txt index f5c16e82..3f6c2aad 100644 --- a/libsrc/general/CMakeLists.txt +++ b/libsrc/general/CMakeLists.txt @@ -1,13 +1,13 @@ add_definitions(-DNGINTERFACE_EXPORTS) -add_library(gen OBJECT - array.cpp bitarray.cpp dynamicmem.cpp flags.cpp - hashtabl.cpp mystring.cpp optmem.cpp parthreads.cpp - seti.cpp sort.cpp spbita2d.cpp table.cpp - mpi_interface.cpp gzstream.cpp +add_library(gen INTERFACE) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources(gen INTERFACE + ${sdir}/array.cpp ${sdir}/bitarray.cpp ${sdir}/dynamicmem.cpp ${sdir}/flags.cpp + ${sdir}/hashtabl.cpp ${sdir}/mystring.cpp ${sdir}/optmem.cpp ${sdir}/parthreads.cpp + ${sdir}/seti.cpp ${sdir}/sort.cpp ${sdir}/spbita2d.cpp ${sdir}/table.cpp + ${sdir}/mpi_interface.cpp ${sdir}/gzstream.cpp ) -set_target_properties( gen PROPERTIES POSITION_INDEPENDENT_CODE ON ) - install(FILES array.hpp autodiff.hpp autoptr.hpp bitarray.hpp dynamicmem.hpp flags.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp diff --git a/libsrc/gprim/CMakeLists.txt b/libsrc/gprim/CMakeLists.txt index 3957476a..402973dc 100644 --- a/libsrc/gprim/CMakeLists.txt +++ b/libsrc/gprim/CMakeLists.txt @@ -1,11 +1,11 @@ add_definitions(-DNGINTERFACE_EXPORTS) -add_library(gprim OBJECT - adtree.cpp geom2d.cpp geom3d.cpp geomfuncs.cpp - geomtest3d.cpp transform3d.cpp spline.cpp splinegeometry.cpp +add_library(gprim INTERFACE) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources(gprim INTERFACE + ${sdir}/adtree.cpp ${sdir}/geom2d.cpp ${sdir}/geom3d.cpp ${sdir}/geomfuncs.cpp + ${sdir}/geomtest3d.cpp ${sdir}/transform3d.cpp ${sdir}/spline.cpp ${sdir}/splinegeometry.cpp ) -set_target_properties( gprim PROPERTIES POSITION_INDEPENDENT_CODE ON ) - install(FILES adtree.hpp geom2d.hpp geom3d.hpp geomfuncs.hpp geomobjects2.hpp geomobjects.hpp geomops2.hpp geomops.hpp geomtest3d.hpp gprim.hpp diff --git a/libsrc/linalg/CMakeLists.txt b/libsrc/linalg/CMakeLists.txt index a5a5a4f2..a8ab1b5a 100644 --- a/libsrc/linalg/CMakeLists.txt +++ b/libsrc/linalg/CMakeLists.txt @@ -1,8 +1,8 @@ -add_library( la OBJECT - densemat.cpp polynomial.cpp bfgs.cpp linopt.cpp linsearch.cpp - ) - -set_target_properties(la PROPERTIES POSITION_INDEPENDENT_CODE ON ) +add_library( la INTERFACE ) +set(sdir ${CMAKE_CURRENT_SOURCE_DIR}) +target_sources( la INTERFACE + ${sdir}/densemat.cpp ${sdir}/polynomial.cpp ${sdir}/bfgs.cpp ${sdir}/linopt.cpp ${sdir}/linsearch.cpp +) install(FILES densemat.hpp linalg.hpp opti.hpp diff --git a/libsrc/meshing/CMakeLists.txt b/libsrc/meshing/CMakeLists.txt index bc9f7f18..0c7433cc 100644 --- a/libsrc/meshing/CMakeLists.txt +++ b/libsrc/meshing/CMakeLists.txt @@ -1,12 +1,4 @@ add_definitions(-DNGINTERFACE_EXPORTS) -if(NOT WIN32) - set(mesh_object_libs - $ - $ - $ - ) -endif(NOT WIN32) - add_library(mesh ${NG_LIB_TYPE} adfront2.cpp adfront3.cpp bisect.cpp boundarylayer.cpp clusters.cpp curvedelems.cpp delaunay.cpp delaunay2d.cpp @@ -29,8 +21,10 @@ if(APPLE) set_target_properties( mesh PROPERTIES SUFFIX ".so") endif(APPLE) +target_link_libraries( mesh PUBLIC ngcore PRIVATE gprim la gen ) + 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}) endif(NOT WIN32) diff --git a/nglib/CMakeLists.txt b/nglib/CMakeLists.txt index ff8bd1d5..5f705c8c 100644 --- a/nglib/CMakeLists.txt +++ b/nglib/CMakeLists.txt @@ -8,9 +8,6 @@ if(WIN32) $ $ $ - $ - $ - $ $ $ @@ -32,7 +29,7 @@ if(NOT WIN32) endif(USE_GUI) endif(NOT WIN32) -target_link_libraries(nglib PUBLIC ngcore) +target_link_libraries(nglib PRIVATE gen la gprim 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} ) From 460ee696fdf82b1c94d0c0fc91b0f259efd5bfd9 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Tue, 8 Jan 2019 11:30:11 +0100 Subject: [PATCH 26/98] [cmake] Link ngcore to other libraries --- CMakeLists.txt | 8 +++++++- libsrc/csg/CMakeLists.txt | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 29a73670..cf153b4c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,13 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING INTERNAL) endif(NOT CMAKE_BUILD_TYPE) -cmake_minimum_required(VERSION 3.1.3) +if(WIN32) + # we are linking to object libraries on Windows + cmake_minimum_required(VERSION 3.12) +else(WIN32) + cmake_minimum_required(VERSION 3.1.3) +endif(WIN32) + if(NOT WIN32) option( USE_NATIVE_ARCH "build which -march=native" ON) endif(NOT WIN32) diff --git a/libsrc/csg/CMakeLists.txt b/libsrc/csg/CMakeLists.txt index 224a48e4..d05d62c1 100644 --- a/libsrc/csg/CMakeLists.txt +++ b/libsrc/csg/CMakeLists.txt @@ -12,11 +12,11 @@ if(APPLE) endif(APPLE) if(NOT WIN32) - target_link_libraries(csg mesh ${PYTHON_LIBRARIES}) - target_link_libraries(csg ${PYTHON_LIBRARIES}) + target_link_libraries(csg PUBLIC mesh ${PYTHON_LIBRARIES}) install( TARGETS csg ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries(csg PUBLIC ngcore) if(USE_GUI) add_library(csgvis ${NG_LIB_TYPE} vscsg.cpp ) From 4a563f09affee6050ea983e99e639990500d4bdf Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Tue, 8 Jan 2019 13:12:12 +0100 Subject: [PATCH 27/98] Fix build errors on Windows --- libsrc/core/CMakeLists.txt | 3 ++- libsrc/core/archive.hpp | 2 +- libsrc/core/symboltable.hpp | 2 +- libsrc/core/utils.cpp | 3 +-- libsrc/geom2d/CMakeLists.txt | 2 ++ libsrc/occ/CMakeLists.txt | 6 ++++-- libsrc/stlgeom/CMakeLists.txt | 5 ++++- nglib/CMakeLists.txt | 3 ++- 8 files changed, 17 insertions(+), 9 deletions(-) diff --git a/libsrc/core/CMakeLists.txt b/libsrc/core/CMakeLists.txt index c43a79ab..46a2230b 100644 --- a/libsrc/core/CMakeLists.txt +++ b/libsrc/core/CMakeLists.txt @@ -29,6 +29,7 @@ install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen) if(USE_PYTHON) target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON) target_include_directories(ngcore PUBLIC ${PYTHON_INCLUDE_DIRS}) + target_link_libraries(ngcore PUBLIC ${PYTHON_LIBRARIES}) endif(USE_PYTHON) install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp @@ -41,7 +42,7 @@ endif(ENABLE_CPP_CORE_GUIDELINES_CHECK) if(USE_PYTHON) pybind11_add_module(pyngcore SHARED python_ngcore.cpp) - target_link_libraries(pyngcore PUBLIC ngcore) + target_link_libraries(pyngcore PUBLIC ngcore ${PYTHON_LIBRARIES}) set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}") install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen) endif(USE_PYTHON) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 2848b8f1..6a4a0792 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -943,7 +943,7 @@ namespace ngcore }; template - NGCORE_API auto NGSPickle() + auto NGSPickle() { return pybind11::pickle([](T* self) { diff --git a/libsrc/core/symboltable.hpp b/libsrc/core/symboltable.hpp index 582a7a37..fdab713c 100644 --- a/libsrc/core/symboltable.hpp +++ b/libsrc/core/symboltable.hpp @@ -19,7 +19,7 @@ namespace ngcore Complexity by name access is linear, by index is constant. */ template - class NGCORE_API SymbolTable + class SymbolTable { std::vector names; std::vector data; diff --git a/libsrc/core/utils.cpp b/libsrc/core/utils.cpp index ae831447..82fcfb31 100644 --- a/libsrc/core/utils.cpp +++ b/libsrc/core/utils.cpp @@ -16,6 +16,7 @@ namespace ngcore nullptr, nullptr, &status); } +#endif double ticks_per_second = [] () noexcept { @@ -36,5 +37,3 @@ namespace ngcore } // namespace ngcore -#endif - diff --git a/libsrc/geom2d/CMakeLists.txt b/libsrc/geom2d/CMakeLists.txt index 754c79fb..26d0db92 100644 --- a/libsrc/geom2d/CMakeLists.txt +++ b/libsrc/geom2d/CMakeLists.txt @@ -9,6 +9,8 @@ if(NOT WIN32) install( TARGETS geom2d ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries(geom2d ngcore) + if(USE_GUI) add_library(geom2dvis ${NG_LIB_TYPE} vsgeom2d.cpp) if(NOT WIN32) diff --git a/libsrc/occ/CMakeLists.txt b/libsrc/occ/CMakeLists.txt index a244e85b..1f093ad8 100644 --- a/libsrc/occ/CMakeLists.txt +++ b/libsrc/occ/CMakeLists.txt @@ -8,11 +8,13 @@ if(USE_GUI) add_library(occvis ${NG_LIB_TYPE} vsocc.cpp) endif(USE_GUI) +target_link_libraries(occ PUBLIC ngcore) + if(NOT WIN32) - target_link_libraries( occ ngcore ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) + target_link_libraries( occ PUBLIC ${OCC_LIBRARIES} ${PYTHON_LIBRARIES}) install( TARGETS occ ${NG_INSTALL_DIR}) if (USE_GUI) - target_link_libraries( occvis occ ) + target_link_libraries( occvis PUBLIC occ ) install( TARGETS occvis ${NG_INSTALL_DIR}) endif(USE_GUI) endif(NOT WIN32) diff --git a/libsrc/stlgeom/CMakeLists.txt b/libsrc/stlgeom/CMakeLists.txt index 7b87a649..8925c828 100644 --- a/libsrc/stlgeom/CMakeLists.txt +++ b/libsrc/stlgeom/CMakeLists.txt @@ -4,10 +4,13 @@ add_library(stl ${NG_LIB_TYPE} ) if(NOT WIN32) - target_link_libraries( stl ngcore mesh ${PYTHON_LIBRARIES}) + target_link_libraries( stl mesh ${PYTHON_LIBRARIES}) install( TARGETS stl ${NG_INSTALL_DIR}) endif(NOT WIN32) +target_link_libraries( stl ngcore ) + + if(USE_GUI) add_library(stlvis ${NG_LIB_TYPE} vsstl.cpp diff --git a/nglib/CMakeLists.txt b/nglib/CMakeLists.txt index 5f705c8c..7253230a 100644 --- a/nglib/CMakeLists.txt +++ b/nglib/CMakeLists.txt @@ -29,7 +29,8 @@ if(NOT WIN32) endif(USE_GUI) endif(NOT WIN32) -target_link_libraries(nglib PRIVATE gen la gprim PUBLIC ngcore) +# target_link_libraries(nglib PRIVATE gen la gprim PUBLIC ngcore) +target_link_libraries(nglib PUBLIC ngcore) target_link_libraries( nglib PRIVATE ${OCC_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} ${X11_Xmu_LIB} ${JPEG_LIBRARIES} ${MKL_LIBRARIES} ${ZLIB_LIBRARIES} ${OCC_LIBRARIES} ) From ed4240b9c60bf295a1d6a4631ce99a6bb4094444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 10 Jan 2019 09:41:42 +0100 Subject: [PATCH 28/98] singular face --- libsrc/csg/python_csg.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libsrc/csg/python_csg.cpp b/libsrc/csg/python_csg.cpp index 0db96e6d..665a7392 100644 --- a/libsrc/csg/python_csg.cpp +++ b/libsrc/csg/python_csg.cpp @@ -469,6 +469,17 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails! self.AddSplineSurface(surf); }), py::arg("SplineSurface")) + .def("SingularFace", [] (CSGeometry & self, shared_ptr sol, shared_ptr surfaces, double factor) + { + int tlonum = -1; + for (int i = 0; i < self.GetNTopLevelObjects(); i++) + if (self.GetTopLevelObject(i)->GetSolid() == sol->GetSolid()) + tlonum = i; + if (tlonum == -1) throw NgException("not a top-level-object"); + if (!surfaces) surfaces = sol; + auto singface = new SingularFace(tlonum, surfaces->GetSolid(), factor); + self.singfaces.Append(singface); + }, py::arg("solid"), py::arg("surfaces")=nullptr, py::arg("factor")=0.25) .def("SingularEdge", [] (CSGeometry & self, shared_ptr s1,shared_ptr s2, double factor) { auto singedge = new SingularEdge(1, -1, self, s1->GetSolid(), s2->GetSolid(), factor); From bcb2935dbb703f6b3c3f974ca9473c8966362e7b Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 11 Jan 2019 10:34:07 +0100 Subject: [PATCH 29/98] Fix build errors --- libsrc/core/logging.hpp | 3 +++ libsrc/core/profiler.hpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index e0e3efd6..6d3a40c8 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -43,6 +43,9 @@ namespace spdlog class logger { public: + template + void log_helper() { std::clog << t; } + template void log_helper( T t) { std::clog << t; } diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index f7415881..96a3fc44 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -124,7 +124,7 @@ namespace ngcore 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 * ost); + NGCORE_API static void Print (FILE * prof); class RegionTimer { From 0b2011a4a60f240eeee08e48f9bbdf5ebb51058b Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 11 Jan 2019 13:12:45 +0100 Subject: [PATCH 30/98] Set timer names in paje trace --- libsrc/core/paje_trace.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 873a93d7..b3abf262 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -427,7 +427,7 @@ namespace ngcore timer_ids.insert(t.id); for(auto id : timer_ids) - timer_aliases[id] = paje.DefineEntityValue( state_type_timer, "a timer" /* TODO: NgProfiler::GetName(id).c_str()*/, -1 ); + timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id).c_str(), -1 ); int timerdepth = 0; int maxdepth = 0; From a40e70526ede50f04914c5c368a7b933e1a4918d Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 11 Jan 2019 13:25:43 +0100 Subject: [PATCH 31/98] Fix build errors --- libsrc/core/logging.hpp | 3 +-- libsrc/core/paje_trace.cpp | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index 6d3a40c8..d5fbf1ac 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -43,8 +43,7 @@ namespace spdlog class logger { public: - template - void log_helper() { std::clog << t; } + void log_helper() {} template void log_helper( T t) { std::clog << t; } diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index b3abf262..23d9e49e 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -7,6 +7,7 @@ #include "archive.hpp" // for Demangle #include "paje_trace.hpp" +#include "profiler.hpp" static constexpr int MAX_TRACE_LINE_SIZE = 50; extern const char *header; @@ -427,7 +428,7 @@ namespace ngcore timer_ids.insert(t.id); for(auto id : timer_ids) - timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id).c_str(), -1 ); + timer_aliases[id] = paje.DefineEntityValue( state_type_timer, NgProfiler::GetName(id), -1 ); int timerdepth = 0; int maxdepth = 0; From 96443e890b86a6e76daed48b228c84286dfbb456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Sat, 12 Jan 2019 08:19:57 +0100 Subject: [PATCH 32/98] timers --- libsrc/meshing/bisect.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsrc/meshing/bisect.cpp b/libsrc/meshing/bisect.cpp index 9edf90d2..d73718be 100644 --- a/libsrc/meshing/bisect.cpp +++ b/libsrc/meshing/bisect.cpp @@ -3398,6 +3398,7 @@ namespace netgen size_t nsel = mtris.Size(); NgProfiler::StartTimer (timer_bisecttrig); + (*opt.tracer)("Bisect trigs", false); for (size_t i = 0; i < nsel; i++) if (mtris[i].marked) { @@ -3440,7 +3441,7 @@ namespace netgen } NgProfiler::StopTimer (timer_bisecttrig); - + (*opt.tracer)("Bisect trigs", true); int nquad = mquads.Size(); for (int i = 1; i <= nquad; i++) From dbb798936365dbef0485f5f9c4bffe50ee3694ce Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 3 Jan 2019 15:55:17 +0100 Subject: [PATCH 33/98] [gitlab-ci] Fix builds --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 86105bfb..8c466bbe 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,8 +14,8 @@ stages: - x64 before_script: - "echo off" - - 'call "%VS140COMNTOOLS%\..\..\VC\bin\amd64\vcvars64.bat"' - - set CMAKE_GENERATOR=Visual Studio 14 2015 Win64 + - 'call "%VS2017INSTALLDIR%\VC\Auxiliary\Build\vcvars64"' + - set CMAKE_GENERATOR=Visual Studio 15 2017 Win64 - set CI_DIR=C:\ci\%CI_PIPELINE_ID% - set NETGEN_BUILD_DIR=%CI_DIR%\build - set INSTALL_DIR=%CI_DIR%\install From 523b8c086c17074b03cd3579b30bec5141d9b4dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Sat, 12 Jan 2019 14:18:56 +0100 Subject: [PATCH 34/98] GetFaceEdges in new mesh-interface (without global ptr) --- libsrc/include/nginterface_v2.hpp | 21 ++++++++++++++++++--- libsrc/interface/nginterface_v2.cpp | 10 ++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 33a596db..116219b4 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -44,6 +44,19 @@ namespace netgen size_t Size() const { return s; } T * Release() { T * hd = data; data = nullptr; return hd; } }; + + template + class Ng_BufferMS + { + size_t s; + T data[S]; + public: + Ng_BufferMS (size_t as) : s(as) { ; } + size_t Size() const { return s; } + T & operator[] (size_t i) { return data[i]; } + T operator[] (size_t i) const { return data[i]; } + }; + class Ng_Element { @@ -185,6 +198,7 @@ namespace netgen int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; } }; + /* class Ng_Edges { public: @@ -194,11 +208,11 @@ namespace netgen size_t Size() const { return ned; } int operator[] (size_t i) const { return ptr[i]-1; } }; - + */ public: Ng_Vertices vertices; - Ng_Edges edges; + // Ng_Edges edges; int surface_el; // -1 if face not on surface }; @@ -282,7 +296,8 @@ namespace netgen template const Ng_Node GetNode (int nr) const; - + + Ng_BufferMS GetFaceEdges (int fnr) const; template int GetNNodes (); diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index fee63976..cb7fd673 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -717,6 +717,16 @@ namespace netgen return mesh->GetIdentifications().GetType(idnr+1); } + Ng_BufferMS Ngx_Mesh::GetFaceEdges (int fnr) const + { + const MeshTopology & topology = mesh->GetTopology(); + ArrayMem ia; + topology.GetFaceEdges (fnr+1, ia); + Ng_BufferMS res(ia.Size()); + for (size_t i = 0; i < ia.Size(); i++) + res[i] = ia[i]-1; + return res; + } From 4aa7e76bd1e89c041e4109ac48e871fd7060f095 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 14 Jan 2019 13:04:27 +0100 Subject: [PATCH 35/98] MPI-Parallel output of profiler --- libsrc/core/profiler.cpp | 11 +++++++++++ libsrc/core/utils.cpp | 3 +++ libsrc/core/utils.hpp | 3 +++ libsrc/general/mpi_interface.hpp | 5 ++--- libsrc/general/netgenout.hpp | 5 +---- libsrc/meshing/global.cpp | 4 ---- 6 files changed, 20 insertions(+), 11 deletions(-) diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index f738fd55..29a69182 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -35,6 +35,17 @@ namespace ngcore 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) diff --git a/libsrc/core/utils.cpp b/libsrc/core/utils.cpp index 82fcfb31..0347d244 100644 --- a/libsrc/core/utils.cpp +++ b/libsrc/core/utils.cpp @@ -8,6 +8,9 @@ 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; } diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index c8dc1e9e..da90e1d3 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -15,6 +15,9 @@ namespace ngcore { + // MPI rank, nranks TODO: Rename + extern NGCORE_API int id, ntasks; + NGCORE_API std::string Demangle(const char* typeinfo); #if defined(__GNUC__) diff --git a/libsrc/general/mpi_interface.hpp b/libsrc/general/mpi_interface.hpp index c45494b6..91cb0af3 100644 --- a/libsrc/general/mpi_interface.hpp +++ b/libsrc/general/mpi_interface.hpp @@ -14,9 +14,8 @@ namespace netgen { - - extern DLL_HEADER int id, ntasks; - + using ngcore::id; + using ngcore::ntasks; #ifdef PARALLEL diff --git a/libsrc/general/netgenout.hpp b/libsrc/general/netgenout.hpp index fafe495e..076a6df1 100644 --- a/libsrc/general/netgenout.hpp +++ b/libsrc/general/netgenout.hpp @@ -4,14 +4,11 @@ // #include // #include // #include +#include "mpi_interface.hpp" namespace netgen { -#ifdef PARALLEL -extern int id; -extern int ntasks; -#endif DLL_HEADER extern int printmessage_importance; DLL_HEADER extern int printdots; diff --git a/libsrc/meshing/global.cpp b/libsrc/meshing/global.cpp index df6bcece..e5036cde 100644 --- a/libsrc/meshing/global.cpp +++ b/libsrc/meshing/global.cpp @@ -50,10 +50,6 @@ namespace netgen string ngdir = "."; - // parallel netgen - int id = 0, ntasks = 1; - - void Ng_PrintDest(const char * s) { if (id == 0) From 9a20974418cefda94ee6cfab00349d94799302ba Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 14 Jan 2019 13:07:10 +0100 Subject: [PATCH 36/98] Disable SPDLOG by default --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cf153b4c..bf7980e3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -25,7 +25,7 @@ option( USE_CCACHE "use ccache") option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON) option( ENABLE_UNIT_TESTS "Enable Catch unit tests") option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF) -option( USE_SPDLOG "Enable spd log logging" ON) +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) From 0a465694748f628c1bbc483025bbb8476a17954c Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 14 Jan 2019 13:41:38 +0100 Subject: [PATCH 37/98] logging in archive not compile time based --- libsrc/core/archive.hpp | 72 ++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 6a4a0792..b66c3187 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -211,6 +211,7 @@ namespace ngcore // don't use it that often anyway) Archive& operator& (std::vector& v) { + logger->debug("In special archive for std::vector"); size_t size; if(Output()) size = v.size(); @@ -295,11 +296,11 @@ namespace ngcore { if(Output()) { - NETGEN_DEBUG_LOG(logger, "Store shared ptr of type " + Demangle(typeid(T).name())); + logger->debug("Store shared ptr of type {}", Demangle(typeid(T).name())); // save -2 for nullptr if(!ptr) { - NETGEN_DEBUG_LOG(logger, "Storing nullptr"); + logger->debug("Storing nullptr"); return (*this) << -2; } @@ -308,7 +309,7 @@ namespace ngcore // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { - NETGEN_DEBUG_LOG(logger, "Typids are different: " + Demangle(typeid(T).name()) + " vs. " + + logger->debug("Typids are different: " + Demangle(typeid(T).name()) + " vs. " + Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) throw Exception(std::string("Archive error: Polymorphic type ") @@ -318,7 +319,7 @@ namespace ngcore // if there was a true downcast we have to store more information if(reg_ptr != static_cast(ptr.get())) { - NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer"); + logger->debug("Multiple/Virtual inheritance involved, need to cast pointer"); neededDowncast = true; } } @@ -326,8 +327,8 @@ namespace ngcore // if not found store -1 and the pointer 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)); + logger->debug("Didn't find the shared_ptr, create new registry entry at {}", + shared_ptr_count); auto p = ptr.get(); (*this) << -1; (*this) & neededDowncast & p; @@ -338,27 +339,27 @@ namespace ngcore return *this; } // 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)); + logger->debug("Found shared_ptr at position {}", pos->second); (*this) << pos->second << neededDowncast; if(neededDowncast) (*this) << Demangle(typeid(*ptr).name()); } else // Input { - NETGEN_DEBUG_LOG(logger, "Reading shared_ptr of type " + Demangle(typeid(T).name())); + logger->debug("Reading shared_ptr of type {}", Demangle(typeid(T).name())); int nr; (*this) & nr; // -2 restores a nullptr if(nr == -2) { - NETGEN_DEBUG_LOG(logger, "Reading a nullptr"); + logger->debug("Reading a nullptr"); ptr = nullptr; return *this; } // -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it if (nr == -1) { - NETGEN_DEBUG_LOG(logger, "Createing new shared_ptr"); + logger->debug("Createing new shared_ptr"); T* p = nullptr; bool neededDowncast; (*this) & neededDowncast & p; @@ -366,7 +367,7 @@ namespace ngcore // if we did downcast we need to store a shared_ptr to the true object if(neededDowncast) { - NETGEN_DEBUG_LOG(logger, "Shared pointer needed downcasting"); + logger->debug("Shared pointer needed downcasting"); std::string name; (*this) & name; auto info = GetArchiveRegister(name); @@ -378,19 +379,19 @@ namespace ngcore } else { - NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need downcasting"); + logger->debug("Shared pointer didn't need downcasting"); nr2shared_ptr.push_back(ptr); } } else { - NETGEN_DEBUG_LOG(logger, "Reading already existing pointer at entry " + std::to_string(nr)); + logger->debug("Reading already existing pointer at entry {}", nr); auto other = nr2shared_ptr[nr]; bool neededDowncast; (*this) & neededDowncast; if(neededDowncast) { - NETGEN_DEBUG_LOG(logger, "Shared pointer needed pointer downcast"); + logger->debug("Shared pointer needed pointer downcast"); // if there was a downcast we can expect the class to be registered (since archiving // wouldn't have worked else) std::string name; @@ -404,7 +405,7 @@ namespace ngcore } else { - NETGEN_DEBUG_LOG(logger, "Shared pointer didn't need pointer casts"); + logger->debug("Shared pointer didn't need pointer casts"); ptr = std::static_pointer_cast(other); } } @@ -418,18 +419,19 @@ namespace ngcore { if (Output()) { - NETGEN_DEBUG_LOG(logger, "Store pointer of type " + Demangle(typeid(T).name())); + logger->debug("Store pointer of type {}",Demangle(typeid(T).name())); // if the pointer is null store -2 if (!p) { - NETGEN_DEBUG_LOG(logger, "Storing nullptr"); + logger->debug("Storing nullptr"); return (*this) << -2; } auto reg_ptr = static_cast(p); if(typeid(T) != typeid(*p)) { - NETGEN_DEBUG_LOG(logger, "Typeids are different: " + Demangle(typeid(T).name()) + " vs. " + - Demangle(typeid(*p).name())); + logger->debug("Typeids are different: {} vs {}", + Demangle(typeid(T).name()), + Demangle(typeid(*p).name())); if(!IsRegistered(Demangle(typeid(*p).name()))) throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) @@ -437,20 +439,20 @@ namespace ngcore reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast(p)); if(reg_ptr != static_cast(p)) { - NETGEN_DEBUG_LOG(logger, "Multiple/Virtual inheritance involved, need to cast pointer"); + logger->debug("Multiple/Virtual inheritance involved, need to cast pointer"); } } auto pos = ptr2nr.find(reg_ptr); // if the pointer is not found in the map create a new entry if (pos == ptr2nr.end()) { - NETGEN_DEBUG_LOG(logger, "Didn't find pointer, create new registry entry at " + + logger->debug("Didn't find pointer, create new registry entry at " + std::to_string(ptr_count)); ptr2nr[reg_ptr] = ptr_count++; if(typeid(*p) == typeid(T)) if (std::is_constructible::value) { - NETGEN_DEBUG_LOG(logger, "Store standard class pointer (no virt. inh,...)"); + logger->debug("Store standard class pointer (no virt. inh,...)"); return (*this) << -1 & (*p); } else @@ -466,7 +468,7 @@ namespace ngcore throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*p).name()) + " not registered for archive"); - NETGEN_DEBUG_LOG(logger, "Store a possibly more complicated pointer"); + logger->debug("Store a possibly more complicated pointer"); return (*this) << -3 << Demangle(typeid(*p).name()) & (*p); } } @@ -474,39 +476,37 @@ namespace ngcore { (*this) & pos->second; bool downcasted = !(reg_ptr == static_cast(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"); + logger->debug("Store a the existing position in registry at {}", pos->second); + logger->debug("Pointer {} downcasting", downcasted ? "needs" : "doesn't need"); // store if the class has been downcasted and the name (*this) << downcasted << Demangle(typeid(*p).name()); } } else { - NETGEN_DEBUG_LOG(logger, "Reading pointer of type " + Demangle(typeid(T).name())); + logger->debug("Reading pointer of type {}", Demangle(typeid(T).name())); int nr; (*this) & nr; if (nr == -2) // restore a nullptr { - NETGEN_DEBUG_LOG(logger, "Loading a nullptr"); + logger->debug("Loading a nullptr"); p = nullptr; } else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...) { - NETGEN_DEBUG_LOG(logger, "Load a new pointer to a simple class"); + logger->debug("Load a new pointer to a simple class"); p = detail::constructIfPossible(); nr2ptr.push_back(p); (*this) & *p; } else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,... { - NETGEN_DEBUG_LOG(logger, "Load a new pointer to a potentially more complicated class " - "(allows for multiple/virtual inheritance,...)"); + logger->debug("Load a new pointer to a potentially more complicated class " + "(allows for multiple/virtual inheritance,...)"); // As stated above, we want this special behaviour only for our classes that implement DoArchive std::string name; (*this) & name; - NETGEN_DEBUG_LOG(logger, "Name = " + name); + logger->debug("Name = " + name); auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) @@ -518,13 +518,11 @@ namespace ngcore } else { - NETGEN_DEBUG_LOG(logger, "Restoring pointer to already existing object at registry position " + - std::to_string(nr)); + logger->debug("Restoring pointer to already existing object at registry position {}", nr); bool downcasted; std::string name; (*this) & downcasted & name; - NETGEN_DEBUG_LOG(logger, std::string(downcasted ? "Downcasted" : "Not downcasted") + - " object of type " + name); + logger->debug("{} object of type {}", downcasted ? "Downcasted" : "Not downcasted", name); if(downcasted) { // if the class has been downcasted we can assume it is in the register From 45f93138dd512cae7e9b879bd2e2fdc7b387e075 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 14 Jan 2019 14:00:52 +0100 Subject: [PATCH 38/98] fix wrong logger->debug call --- libsrc/core/archive.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index b66c3187..9b715ef2 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -506,7 +506,7 @@ namespace ngcore // As stated above, we want this special behaviour only for our classes that implement DoArchive std::string name; (*this) & name; - logger->debug("Name = " + name); + logger->debug("Name = {}", name); auto info = GetArchiveRegister(name); // the creator creates a new object of type name, and returns a void* pointing // to T (which may have an offset) From ab15ae12bc8779bfc39b72ea07a7982da18e9807 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Mon, 14 Jan 2019 14:47:26 +0100 Subject: [PATCH 39/98] [cmake] Export object libs on Windows --- libsrc/csg/CMakeLists.txt | 6 ++---- libsrc/geom2d/CMakeLists.txt | 6 ++---- libsrc/interface/CMakeLists.txt | 8 +++----- libsrc/meshing/CMakeLists.txt | 6 ++---- libsrc/visualization/CMakeLists.txt | 6 ++---- 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/libsrc/csg/CMakeLists.txt b/libsrc/csg/CMakeLists.txt index d05d62c1..eaf7dffc 100644 --- a/libsrc/csg/CMakeLists.txt +++ b/libsrc/csg/CMakeLists.txt @@ -11,10 +11,8 @@ if(APPLE) set_target_properties( csg PROPERTIES SUFFIX ".so") endif(APPLE) -if(NOT WIN32) - target_link_libraries(csg PUBLIC mesh ${PYTHON_LIBRARIES}) - install( TARGETS csg ${NG_INSTALL_DIR}) -endif(NOT WIN32) +target_link_libraries(csg PUBLIC mesh ${PYTHON_LIBRARIES}) +install( TARGETS csg ${NG_INSTALL_DIR}) target_link_libraries(csg PUBLIC ngcore) diff --git a/libsrc/geom2d/CMakeLists.txt b/libsrc/geom2d/CMakeLists.txt index 26d0db92..43c619a0 100644 --- a/libsrc/geom2d/CMakeLists.txt +++ b/libsrc/geom2d/CMakeLists.txt @@ -4,10 +4,8 @@ if(APPLE) set_target_properties( geom2d PROPERTIES SUFFIX ".so") endif(APPLE) -if(NOT WIN32) - target_link_libraries(geom2d mesh ${PYTHON_LIBRARIES}) - install( TARGETS geom2d ${NG_INSTALL_DIR}) -endif(NOT WIN32) +target_link_libraries(geom2d mesh ${PYTHON_LIBRARIES}) +install( TARGETS geom2d ${NG_INSTALL_DIR}) target_link_libraries(geom2d ngcore) diff --git a/libsrc/interface/CMakeLists.txt b/libsrc/interface/CMakeLists.txt index cb460fae..afd301d9 100644 --- a/libsrc/interface/CMakeLists.txt +++ b/libsrc/interface/CMakeLists.txt @@ -7,11 +7,9 @@ add_library(interface ${NG_LIB_TYPE} wuchemnitz.cpp writegmsh2.cpp writeOpenFOAM15x.cpp ) -if(NOT WIN32) - target_link_libraries(interface mesh csg geom2d) - target_link_libraries(interface visual) - install( TARGETS interface ${NG_INSTALL_DIR}) -endif(NOT WIN32) +target_link_libraries(interface mesh csg geom2d) +target_link_libraries(interface visual) +install( TARGETS interface ${NG_INSTALL_DIR}) install(FILES writeuser.hpp diff --git a/libsrc/meshing/CMakeLists.txt b/libsrc/meshing/CMakeLists.txt index 0c7433cc..12fe70ae 100644 --- a/libsrc/meshing/CMakeLists.txt +++ b/libsrc/meshing/CMakeLists.txt @@ -23,10 +23,8 @@ endif(APPLE) target_link_libraries( mesh PUBLIC ngcore PRIVATE gprim la gen ) -if(NOT WIN32) - target_link_libraries( mesh PUBLIC ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) - install( TARGETS mesh ${NG_INSTALL_DIR}) -endif(NOT WIN32) +target_link_libraries( mesh PUBLIC ${ZLIB_LIBRARIES} ${MPI_CXX_LIBRARIES} ${PYTHON_LIBRARIES} ${METIS_LIBRARY}) +install( TARGETS mesh ${NG_INSTALL_DIR}) install(FILES adfront2.hpp adfront3.hpp basegeom.hpp bcfunctions.hpp bisect.hpp diff --git a/libsrc/visualization/CMakeLists.txt b/libsrc/visualization/CMakeLists.txt index f1c82976..4288862c 100644 --- a/libsrc/visualization/CMakeLists.txt +++ b/libsrc/visualization/CMakeLists.txt @@ -9,10 +9,8 @@ endif(USE_GUI) add_library(visual ${NG_LIB_TYPE} ${LIB_VISUAL_SOURCES}) -if(NOT WIN32) - target_link_libraries( visual ngcore ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ) - install( TARGETS visual ${NG_INSTALL_DIR}) -endif(NOT WIN32) +target_link_libraries( visual ngcore ${PYTHON_LIBRARIES} ${MPI_CXX_LIBRARIES} ${OPENGL_LIBRARIES} ) +install( TARGETS visual ${NG_INSTALL_DIR}) install(FILES meshdoc.hpp mvdraw.hpp From 9f3e4aaa789314318c482928a3691e9117bbd5d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Mon, 14 Jan 2019 10:00:11 +0100 Subject: [PATCH 40/98] add more functions to interface V2 (no global pointer) --- libsrc/include/nginterface.h | 4 +- libsrc/include/nginterface_v2.hpp | 40 +++++++++ libsrc/interface/nginterface_v2.cpp | 127 ++++++++++++++++++++++++++++ 3 files changed, 169 insertions(+), 2 deletions(-) diff --git a/libsrc/include/nginterface.h b/libsrc/include/nginterface.h index 3ddf24b8..ed8e3cc1 100644 --- a/libsrc/include/nginterface.h +++ b/libsrc/include/nginterface.h @@ -312,7 +312,7 @@ extern "C" { struct Ng_SolutionData { - string name; // name of gridfunction + std::string name; // name of gridfunction double * data; // solution values int components; // relevant (double) components in solution vector int dist; // # doubles per entry alignment! @@ -333,7 +333,7 @@ extern "C" { // redraw DLL_HEADER void Ng_Redraw(bool blocking = false); /// - DLL_HEADER void Ng_TclCmd(string cmd); + DLL_HEADER void Ng_TclCmd(std::string cmd); /// DLL_HEADER void Ng_SetMouseEventHandler (netgen::MouseEventHandler * handler); /// diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 116219b4..28459370 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -12,6 +12,21 @@ C++ interface to Netgen */ +#ifndef NGINTERFACE + // implemented element types: +enum NG_ELEMENT_TYPE { + NG_PNT = 0, + NG_SEGM = 1, NG_SEGM3 = 2, + NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, + NG_TET = 20, NG_TET10 = 21, + NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, + NG_HEX = 25 +}; + +enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; +#endif + + namespace netgen { @@ -306,7 +321,11 @@ namespace netgen // 3D only // std::pair GetBoundaryNeighbouringDomains (int bnr); + template + void SetRefinementFlag (size_t elnr, bool flag); + void Curve (int order); + void Refine (NG_REFINEMENT_TYPE reftype, void (*taskmanager)(function) = &DummyTaskManager2, void (*tracer)(string, bool) = &DummyTracer2); @@ -334,6 +353,27 @@ namespace netgen shared_ptr GetMesh () const { return mesh; } shared_ptr SelectMesh () const; inline auto GetTimeStamp() const; + + + // also added from nginterface.h, still 1-based, need redesign + void HPRefinement (int levels, double parameter = 0.125, + bool setorders = true,bool ref_level = false); + size_t GetNP() const; + int GetSurfaceElementSurfaceNumber (size_t ei) const; + int GetSurfaceElementFDNumber (size_t ei) const; + + int GetElementOrder (int enr) const; + void GetElementOrders (int enr, int * ox, int * oy, int * oz) const; + void SetElementOrder (int enr, int order); + void SetElementOrders (int enr, int ox, int oy, int oz); + int GetSurfaceElementOrder (int enr) const; + void GetSurfaceElementOrders (int enr, int * ox, int * oy) const; + void SetSurfaceElementOrder (int enr, int order); + void SetSurfaceElementOrders (int enr, int ox, int oy); + int GetClusterRepVertex (int vi) const; + int GetClusterRepEdge (int edi) const; + int GetClusterRepFace (int fai) const; + int GetClusterRepElement (int eli) const; }; diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index cb7fd673..9f834b9c 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -1052,6 +1052,19 @@ namespace netgen NgLock meshlock (mesh->MajorMutex(), true); mesh->BuildCurvedElements(order); } + + + template <> + void Ngx_Mesh :: SetRefinementFlag<2> (size_t elnr, bool flag) + { + mesh->SurfaceElement(elnr+1).SetRefinementFlag(flag); + } + + template <> + void Ngx_Mesh :: SetRefinementFlag<3> (size_t elnr, bool flag) + { + mesh->VolumeElement(elnr+1).SetRefinementFlag(flag); + } void Ngx_Mesh :: Refine (NG_REFINEMENT_TYPE reftype, void (*task_manager)(function), @@ -1080,6 +1093,120 @@ namespace netgen } + + + + // just copied with redesign + + size_t Ngx_Mesh::GetNP() const + { + return mesh->GetNP(); + } + + + int Ngx_Mesh::GetSurfaceElementSurfaceNumber (size_t ei) const + { + if (mesh->GetDimension() == 3) + return mesh->GetFaceDescriptor(mesh->SurfaceElement(ei).GetIndex()).SurfNr(); + else + return mesh->LineSegment(ei).si; + } + int Ngx_Mesh::GetSurfaceElementFDNumber (size_t ei) const + { + if (mesh->GetDimension() == 3) + return mesh->SurfaceElement(ei).GetIndex(); + else + return -1; + } + + + void Ngx_Mesh::HPRefinement (int levels, double parameter, bool setorders, + bool ref_level) + { + NgLock meshlock (mesh->MajorMutex(), true); + Refinement & ref = const_cast (mesh->GetGeometry()->GetRefinement()); + ::netgen::HPRefinement (*mesh, &ref, levels, parameter, setorders, ref_level); + } + +int Ngx_Mesh::GetElementOrder (int enr) const +{ + if (mesh->GetDimension() == 3) + return mesh->VolumeElement(enr).GetOrder(); + else + return mesh->SurfaceElement(enr).GetOrder(); +} + +void Ngx_Mesh::GetElementOrders (int enr, int * ox, int * oy, int * oz) const +{ + if (mesh->GetDimension() == 3) + mesh->VolumeElement(enr).GetOrder(*ox, *oy, *oz); + else + mesh->SurfaceElement(enr).GetOrder(*ox, *oy, *oz); +} + +void Ngx_Mesh::SetElementOrder (int enr, int order) +{ + if (mesh->GetDimension() == 3) + return mesh->VolumeElement(enr).SetOrder(order); + else + return mesh->SurfaceElement(enr).SetOrder(order); +} + +void Ngx_Mesh::SetElementOrders (int enr, int ox, int oy, int oz) +{ + if (mesh->GetDimension() == 3) + mesh->VolumeElement(enr).SetOrder(ox, oy, oz); + else + mesh->SurfaceElement(enr).SetOrder(ox, oy); +} + + +int Ngx_Mesh::GetSurfaceElementOrder (int enr) const +{ + return mesh->SurfaceElement(enr).GetOrder(); +} + +int Ngx_Mesh::GetClusterRepVertex (int pi) const +{ + return mesh->GetClusters().GetVertexRepresentant(pi); +} + +int Ngx_Mesh::GetClusterRepEdge (int pi) const +{ + return mesh->GetClusters().GetEdgeRepresentant(pi); +} + +int Ngx_Mesh::GetClusterRepFace (int pi) const +{ + return mesh->GetClusters().GetFaceRepresentant(pi); +} + +int Ngx_Mesh::GetClusterRepElement (int pi) const +{ + return mesh->GetClusters().GetElementRepresentant(pi); +} + + + + +//HERBERT: falsche Anzahl von Argumenten +//void Ngx_Mesh::GetSurfaceElementOrders (int enr, int * ox, int * oy, int * oz) +void Ngx_Mesh::GetSurfaceElementOrders (int enr, int * ox, int * oy) const +{ + int d; + mesh->SurfaceElement(enr).GetOrder(*ox, *oy, d); +} + +void Ngx_Mesh::SetSurfaceElementOrder (int enr, int order) +{ + return mesh->SurfaceElement(enr).SetOrder(order); +} + +void Ngx_Mesh::SetSurfaceElementOrders (int enr, int ox, int oy) +{ + mesh->SurfaceElement(enr).SetOrder(ox, oy); +} + #ifdef PARALLEL From 1d37a82185c5bb026fe73011996b2fdf73cd3043 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Tue, 15 Jan 2019 09:49:19 +0100 Subject: [PATCH 41/98] fix another wrong logger call --- libsrc/core/archive.hpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 9b715ef2..120416b9 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -309,8 +309,9 @@ namespace ngcore // Downcasting is only possible for our registered classes if(typeid(T) != typeid(*ptr)) { - logger->debug("Typids are different: " + Demangle(typeid(T).name()) + " vs. " + - Demangle(typeid(*ptr).name())); + logger->debug("Typids are different: {} vs {}", + Demangle(typeid(T).name()), + Demangle(typeid(*ptr).name())); if(!IsRegistered(Demangle(typeid(*ptr).name()))) throw Exception(std::string("Archive error: Polymorphic type ") + Demangle(typeid(*ptr).name()) @@ -446,8 +447,8 @@ namespace ngcore // if the pointer is not found in the map create a new entry if (pos == ptr2nr.end()) { - logger->debug("Didn't find pointer, create new registry entry at " + - std::to_string(ptr_count)); + logger->debug("Didn't find pointer, create new registry entry at {}", + ptr_count); ptr2nr[reg_ptr] = ptr_count++; if(typeid(*p) == typeid(T)) if (std::is_constructible::value) From 7c6e2ae35e7f5bd69062743019d6dbc6d97415a6 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Tue, 15 Jan 2019 16:43:39 +0100 Subject: [PATCH 42/98] include spdlog/fmt/ostr.h to be able to parse things that implement operator << ostream --- libsrc/core/logging.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index d5fbf1ac..40445490 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -13,11 +13,12 @@ #define SPDLOG_DEBUG_ON #endif // NETGEN_LOG_DEBUG +#include // to be able to parse anything to logger that implements operator << ostream #include #include #include -#define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__) +#define NETGEN_DEBUG_LOG(...) SPDLOG_DEBUG(__VA_ARGS__) #else // NETGEN_USE_SPDLOG From b6a17ff5be062223238cf371055fd59f9f8c4a3d Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Tue, 15 Jan 2019 17:01:10 +0100 Subject: [PATCH 43/98] DLL_HEADER for SetRefinementFlag --- libsrc/interface/nginterface_v2.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index 9f834b9c..6ac24f40 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -1055,13 +1055,13 @@ namespace netgen template <> - void Ngx_Mesh :: SetRefinementFlag<2> (size_t elnr, bool flag) + DLL_HEADER void Ngx_Mesh :: SetRefinementFlag<2> (size_t elnr, bool flag) { mesh->SurfaceElement(elnr+1).SetRefinementFlag(flag); } template <> - void Ngx_Mesh :: SetRefinementFlag<3> (size_t elnr, bool flag) + DLL_HEADER void Ngx_Mesh :: SetRefinementFlag<3> (size_t elnr, bool flag) { mesh->VolumeElement(elnr+1).SetRefinementFlag(flag); } From 4ef76fa7108373d260b23b999c3c31836b5c25cf Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 16 Jan 2019 14:33:48 +0100 Subject: [PATCH 44/98] Include spdlog only in logger.cpp --- libsrc/core/archive.hpp | 2 +- libsrc/core/logging.cpp | 57 ++++++++--- libsrc/core/logging.hpp | 181 ++++++++++++++++++---------------- libsrc/core/paje_trace.cpp | 2 +- libsrc/core/paje_trace.hpp | 2 +- libsrc/core/profiler.cpp | 2 +- libsrc/core/profiler.hpp | 2 +- libsrc/core/python_ngcore.cpp | 16 +-- 8 files changed, 153 insertions(+), 111 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 120416b9..1fedde76 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -106,7 +106,7 @@ namespace ngcore protected: bool shallow_to_python = false; std::map version_map = GetLibraryVersions(); - std::shared_ptr logger = GetLogger("Archive"); + std::shared_ptr logger = GetLogger("Archive"); public: Archive() = delete; Archive(const Archive&) = delete; diff --git a/libsrc/core/logging.cpp b/libsrc/core/logging.cpp index 467255cd..e1bacf6f 100644 --- a/libsrc/core/logging.cpp +++ b/libsrc/core/logging.cpp @@ -1,15 +1,28 @@ - #include "logging.hpp" #ifdef NETGEN_USE_SPDLOG +#include #include #include +#else // NETGEN_USE_SPDLOG +#include #endif // NETGEN_USE_SPDLOG + namespace ngcore { + + void Logger::log(level::level_enum level, std::string && s) + { +#ifdef NETGEN_USE_SPDLOG + logger->log(spdlog::level::level_enum(level), s); +#else // NETGEN_USE_SPDLOG + std::clog << s << '\n'; +#endif // NETGEN_USE_SPDLOG + } + #ifdef NETGEN_USE_SPDLOG namespace detail { @@ -28,12 +41,12 @@ namespace ngcore } } // namespace detail - std::shared_ptr GetLogger(const std::string& name) + std::shared_ptr GetLogger(const std::string& name) { auto logger = spdlog::get(name); if(!logger) logger = detail::CreateDefaultLogger(name); - return logger; + return std::make_shared(logger); } void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name) @@ -49,7 +62,7 @@ namespace ngcore auto sink = std::make_shared(filename); sink->set_level(level); if(!logger.empty()) - GetLogger(logger)->sinks().push_back(sink); + GetLogger(logger)->logger->sinks().push_back(sink); else { detail::GetDefaultSinks().push_back(sink); @@ -62,7 +75,7 @@ namespace ngcore auto sink = std::make_shared(); sink->set_level(level); if(!logger.empty()) - GetLogger(logger)->sinks().push_back(sink); + GetLogger(logger)->logger->sinks().push_back(sink); else { detail::GetDefaultSinks().push_back(sink); @@ -73,7 +86,7 @@ namespace ngcore void ClearLoggingSinks(const std::string& logger) { if(!logger.empty()) - GetLogger(logger)->sinks().clear(); + GetLogger(logger)->logger->sinks().clear(); else { detail::GetDefaultSinks().clear(); @@ -84,26 +97,40 @@ namespace ngcore void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger) { if(!logger.empty()) - GetLogger(logger)->flush_on(level); + GetLogger(logger)->logger->flush_on(level); else spdlog::flush_on(level); } #else // NETGEN_USE_SPDLOG +} //namespace ngcore + +namespace spdlog +{ + class logger + { + public: + logger() = default; + }; +} // namespace spdlog + +namespace ngcore +{ // Dummy functions if no spdlog is available - std::shared_ptr GetLogger(const std::string& /*unused*/) + std::shared_ptr GetLogger(const std::string& /*unused*/) { - return std::make_shared(); + return std::make_shared(std::make_shared()); } - 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 SetLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {} + void AddFileSink(const std::string& /*unused*/, level::level_enum /*unused*/, + const std::string& /*unused*/) {} - void AddConsoleSink(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {} + void AddConsoleSink(level::level_enum /*unused*/, const std::string& /*unused*/) {} void ClearLoggingSinks(const std::string& /*unused*/) {} - void FlushOnLoggingLevel(spdlog::level::level_enum /*unused*/, const std::string& /*unused*/) {} + void FlushOnLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {} +} //namespace ngcore #endif // NETGEN_USE_SPDLOG -} //namespace ngcore diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index 40445490..91bae7a5 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -1,109 +1,124 @@ #ifndef NETGEN_CORE_LOGGING_HPP #define NETGEN_CORE_LOGGING_HPP +#undef NETGEN_USE_SPDLOG +#include #include #include #include +#include "exception.hpp" #include "ngcore_api.hpp" +#include "utils.hpp" #ifdef NETGEN_USE_SPDLOG - +#include +#include // to be able to parse anything to logger that implements operator << ostream #ifdef NETGEN_LOG_DEBUG #define SPDLOG_DEBUG_ON +#define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__) #endif // NETGEN_LOG_DEBUG +#endif // NETGEN_USE_SPDLOG -#include // to be able to parse anything to logger that implements operator << ostream -#include -#include -#include - -#define NETGEN_DEBUG_LOG(...) SPDLOG_DEBUG(__VA_ARGS__) - -#else // NETGEN_USE_SPDLOG - -#include +#ifndef NETGEN_DEBUG_LOG +#define NETGEN_DEBUG_LOG(logger, ...) +#endif // NETGEN_DEBUG_LOG 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 - void log_helper( T t) { std::clog << t; } - - template - void log_helper( T t, Args ... args) - { - std::clog << t; - log_helper(args...); - std::clog << ", "; - } - - template - void log( level::level_enum level, const char* fmt, Args ... args) - { - std::clog << level << ": " << fmt << "\t Arguments: "; - log_helper(args...); - std::clog << "\n"; - } - - template - void trace( const char* fmt, Args ... args) { log(level::level_enum::trace, fmt, args...); } - template - void debug( const char* fmt, Args ... args) { log(level::level_enum::debug, fmt, args...); } - template - void info( const char* fmt, Args ... args) { log(level::level_enum::info, fmt, args...); } - template - void warn( const char* fmt, Args ... args) { log(level::level_enum::warn, fmt, args...); } - template - void error( const char* fmt, Args ... args) { log(level::level_enum::err, fmt, args...); } - template - 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 + class logger; +} // namespace spdlog namespace ngcore { - namespace detail + namespace level { - std::vector>& GetDefaultSinks(); - inline std::shared_ptr CreateDefaultLogger(const std::string& name); - } //namespace detail + enum level_enum + { + trace = 0, + debug = 1, + info = 2, + warn = 3, + err = 4, + critical = 5, + off = 6 + }; + } - NGCORE_API std::shared_ptr 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); + class Logger + { + public: + std::shared_ptr logger; + + Logger(std::shared_ptr l) : logger(l) {} + + void NGCORE_API log( level::level_enum level, std::string && s); + +#ifdef NETGEN_USE_SPDLOG + template + void log( level::level_enum level, const char* str, Args ... args) + { + log(level, fmt::format(str, args...)); + } +#else // NETGEN_USE_SPDLOG + template + std::string replace(std::string s, const T & t) + { + auto p0 = s.find_first_of('{'); + auto p1 = s.find_first_of('}', p0); + if(p0==std::string::npos || p1==std::string::npos) + throw Exception("invalid format string"); + s.replace(p0, p1-p0+1, ToString(t)); + return s; + } + + std::string log_helper(std::string s) + { + return s; + } + + template + std::string log_helper(std::string s, const T &t) + { + return replace(s,t); + } + + template + std::string log_helper( std::string s, const T &t, Args ... args) + { + return log_helper(replace(s,t), args...); + } + + template + void log( level::level_enum level, const char* str, Args ... args) + { + log(level, log_helper(std::string(str), args...)); + } +#endif // NETGEN_USE_SPDLOG + + template + void trace( const char* str, Args ... args) { log(level::level_enum::trace, str, args...); } + template + void debug( const char* str, Args ... args) { log(level::level_enum::debug, str, args...); } + template + void info( const char* str, Args ... args) { log(level::level_enum::info, str, args...); } + template + void warn( const char* str, Args ... args) { log(level::level_enum::warn, str, args...); } + template + void error( const char* str, Args ... args) { log(level::level_enum::err, str, args...); } + template + void critical( const char* str, Args ... args) { log(level::level_enum::critical, str, args...); } + }; + + + + + NGCORE_API std::shared_ptr GetLogger(const std::string& name); + NGCORE_API void SetLoggingLevel(level::level_enum level, const std::string& name); + NGCORE_API void AddFileSink(const std::string& filename, level::level_enum level, const std::string& logger); + NGCORE_API void AddConsoleSink(level::level_enum level, const std::string& logger); NGCORE_API void ClearLoggingSinks(const std::string& logger); - NGCORE_API void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger); + NGCORE_API void FlushOnLoggingLevel(level::level_enum level, const std::string& logger); } // namespace ngcore #endif // NETGEN_CORE_LOGGING_HPP diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 23d9e49e..29a84d04 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -92,7 +92,7 @@ namespace ngcore FILE * ctrace_stream; TTimePoint start_time; - std::shared_ptr logger = GetLogger("PajeTrace"); + std::shared_ptr logger = GetLogger("PajeTrace"); double ConvertTime(TTimePoint t) { diff --git a/libsrc/core/paje_trace.hpp b/libsrc/core/paje_trace.hpp index c5169fdf..96684285 100644 --- a/libsrc/core/paje_trace.hpp +++ b/libsrc/core/paje_trace.hpp @@ -18,7 +18,7 @@ namespace ngcore using TClock = std::chrono::system_clock; protected: - std::shared_ptr logger = GetLogger("PajeTrace"); + std::shared_ptr logger = GetLogger("PajeTrace"); private: NGCORE_API static size_t max_tracefile_size; NGCORE_API static bool trace_thread_counter; diff --git a/libsrc/core/profiler.cpp b/libsrc/core/profiler.cpp index 29a69182..3302342d 100644 --- a/libsrc/core/profiler.cpp +++ b/libsrc/core/profiler.cpp @@ -13,7 +13,7 @@ namespace ngcore size_t NgProfiler::dummy_thread_flops[NgProfiler::SIZE]; size_t * NgProfiler::thread_flops = NgProfiler::dummy_thread_flops; // NOLINT - std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT + std::shared_ptr NgProfiler::logger = GetLogger("Profiler"); // NOLINT NgProfiler :: NgProfiler() { diff --git a/libsrc/core/profiler.hpp b/libsrc/core/profiler.hpp index 96a3fc44..5a9b16e1 100644 --- a/libsrc/core/profiler.hpp +++ b/libsrc/core/profiler.hpp @@ -34,7 +34,7 @@ namespace ngcore NGCORE_API static TTimePoint * thread_times; NGCORE_API static TTimePoint * thread_flops; - NGCORE_API static std::shared_ptr logger; + NGCORE_API static std::shared_ptr logger; NGCORE_API static size_t dummy_thread_times[NgProfiler::SIZE]; NGCORE_API static size_t dummy_thread_flops[NgProfiler::SIZE]; private: diff --git a/libsrc/core/python_ngcore.cpp b/libsrc/core/python_ngcore.cpp index b7624e43..47c16740 100644 --- a/libsrc/core/python_ngcore.cpp +++ b/libsrc/core/python_ngcore.cpp @@ -8,14 +8,14 @@ using namespace ngcore; PYBIND11_MODULE(pyngcore, m) // NOLINT { - py::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); + py::enum_(m, "LOG_LEVEL", "Logging level") + .value("Trace", level::trace) + .value("Debug", level::debug) + .value("Info", level::info) + .value("Warn", level::warn) + .value("Error", level::err) + .value("Critical", level::critical) + .value("Off", level::off); m.def("SetLoggingLevel", &SetLoggingLevel, py::arg("level"), py::arg("logger")="", "Set logging level, if name is given only to the specific logger, else set the global logging level"); From 5f9ec6cec691fbeed276708f736d048cc0762b20 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Wed, 16 Jan 2019 15:10:53 +0100 Subject: [PATCH 45/98] Fix core guidelines issues --- libsrc/core/logging.cpp | 3 ++- libsrc/core/logging.hpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libsrc/core/logging.cpp b/libsrc/core/logging.cpp index e1bacf6f..eaaedf02 100644 --- a/libsrc/core/logging.cpp +++ b/libsrc/core/logging.cpp @@ -19,7 +19,8 @@ namespace ngcore #ifdef NETGEN_USE_SPDLOG logger->log(spdlog::level::level_enum(level), s); #else // NETGEN_USE_SPDLOG - std::clog << s << '\n'; + if(level>level::debug) + std::clog << s << '\n'; #endif // NETGEN_USE_SPDLOG } diff --git a/libsrc/core/logging.hpp b/libsrc/core/logging.hpp index 91bae7a5..1553ad54 100644 --- a/libsrc/core/logging.hpp +++ b/libsrc/core/logging.hpp @@ -43,14 +43,14 @@ namespace ngcore critical = 5, off = 6 }; - } + } // namespace level class Logger { public: std::shared_ptr logger; - Logger(std::shared_ptr l) : logger(l) {} + Logger(std::shared_ptr l) : logger(std::move(l)) {} void NGCORE_API log( level::level_enum level, std::string && s); From 7b8c33ed4963967dfd2c936aa5dcd882484a7482 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Thu, 17 Jan 2019 03:20:18 +0100 Subject: [PATCH 46/98] Fix bug in pajetrace log, disable trace by default --- libsrc/core/paje_trace.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 29a84d04..508067fd 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -15,7 +15,7 @@ extern const char *header; namespace ngcore { // Produce no traces by default - size_t PajeTrace::max_tracefile_size = 11110000; + size_t PajeTrace::max_tracefile_size = 0; // If true, produce variable counting active threads // increases trace by a factor of two @@ -34,7 +34,7 @@ namespace ngcore 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"); + logger->info( "Tracing {} events per thread", max_num_events_per_thread); } tasks.resize(nthreads); From c0d0a3a1ab52c9549c9a0fe3970fe16fdd5b25e6 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Fri, 18 Jan 2019 12:32:10 +0100 Subject: [PATCH 47/98] [cmake] Fix Python version check --- cmake/external_projects/tcltk.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/external_projects/tcltk.cmake b/cmake/external_projects/tcltk.cmake index b7f0ba85..b071e495 100644 --- a/cmake/external_projects/tcltk.cmake +++ b/cmake/external_projects/tcltk.cmake @@ -1,6 +1,6 @@ if(APPLE) # use system tcl/tk - if(${PYTHON_VERSION_STRING} STREQUAL "3.7") + if((${PYTHON_VERSION_STRING} VERSION_EQUAL "3.7") OR (${PYTHON_VERSION_STRING} VERSION_GREATER "3.7")) # fetch tcl/tk sources to match the one used in Python 3.7 ExternalProject_Add(project_tcl URL "https://prdownloads.sourceforge.net/tcl/tcl8.6.8-src.tar.gz" From 66ac2f1a4f0bb87d261fdc6deb2d55835efac221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 17 Jan 2019 22:08:35 +0100 Subject: [PATCH 48/98] hex20 WIP --- libsrc/include/nginterface.h | 4 ++-- libsrc/include/nginterface_v2.hpp | 4 ++-- libsrc/meshing/meshtype.hpp | 4 ++-- libsrc/meshing/python_mesh.cpp | 14 ++++++++++++++ libsrc/meshing/topology.hpp | 15 +++++++++++++-- 5 files changed, 33 insertions(+), 8 deletions(-) diff --git a/libsrc/include/nginterface.h b/libsrc/include/nginterface.h index ed8e3cc1..9501bc29 100644 --- a/libsrc/include/nginterface.h +++ b/libsrc/include/nginterface.h @@ -43,10 +43,10 @@ enum NG_ELEMENT_TYPE { NG_PNT = 0, NG_SEGM = 1, NG_SEGM3 = 2, - NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, + NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14, NG_TET = 20, NG_TET10 = 21, NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, - NG_HEX = 25 + NG_HEX = 25, NG_HEX20 = 26 }; typedef double NG_POINT[3]; // coordinates diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 28459370..11276e0d 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -17,10 +17,10 @@ enum NG_ELEMENT_TYPE { NG_PNT = 0, NG_SEGM = 1, NG_SEGM3 = 2, - NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, + NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14, NG_TET = 20, NG_TET10 = 21, NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, - NG_HEX = 25 + NG_HEX = 25, NG_HEX20 = 26 }; enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; diff --git a/libsrc/meshing/meshtype.hpp b/libsrc/meshing/meshtype.hpp index 5ded7330..a894d090 100644 --- a/libsrc/meshing/meshtype.hpp +++ b/libsrc/meshing/meshtype.hpp @@ -22,7 +22,7 @@ namespace netgen TRIG = 10, QUAD=11, TRIG6 = 12, QUAD6 = 13, QUAD8 = 14, TET = 20, TET10 = 21, PYRAMID = 22, PRISM = 23, PRISM12 = 24, - HEX = 25 + HEX = 25, HEX20 = 26 }; /* @@ -45,7 +45,7 @@ namespace netgen }; -#define ELEMENT_MAXPOINTS 12 +#define ELEMENT_MAXPOINTS 20 #define ELEMENT2D_MAXPOINTS 8 diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index d349dfcf..b0c2a5c7 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -263,6 +263,13 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) (*newel)[i] = py::extract(vertices[i])(); newel->SetIndex(index); } + else if (py::len(vertices) == 20) + { + newel = new Element(HEX20); + for (int i = 0; i < 20; i++) + (*newel)[i] = py::extract(vertices[i])(); + newel->SetIndex(index); + } else throw NgException ("cannot create element"); return newel; @@ -316,6 +323,13 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) (*newel)[i] = py::extract(vertices[i])(); newel->SetIndex(index); } + else if (py::len(vertices) == 8) + { + newel = new Element2d(QUAD8); + for(int i = 0; i<8; i++) + (*newel)[i] = py::extract(vertices[i])(); + newel->SetIndex(index); + } else throw NgException("Inconsistent number of vertices in Element2D"); return newel; diff --git a/libsrc/meshing/topology.hpp b/libsrc/meshing/topology.hpp index 831a1ca5..625b15d7 100644 --- a/libsrc/meshing/topology.hpp +++ b/libsrc/meshing/topology.hpp @@ -219,6 +219,7 @@ inline short int MeshTopology :: GetNVertices (ELEMENT_TYPE et) return 6; case HEX: + case HEX20: return 8; // default: @@ -244,9 +245,11 @@ inline short int MeshTopology :: GetNPoints (ELEMENT_TYPE et) case QUAD: case QUAD6: - case QUAD8: return 4; + case QUAD8: + return 8; + case TET: return 4; case TET10: @@ -262,6 +265,8 @@ inline short int MeshTopology :: GetNPoints (ELEMENT_TYPE et) case HEX: return 8; + case HEX20: + return 20; // default: // cerr << "Ng_ME_GetNVertices, illegal element type " << et << endl; } @@ -300,6 +305,7 @@ inline short int MeshTopology :: GetNEdges (ELEMENT_TYPE et) return 9; case HEX: + case HEX20: return 12; default: return 0; @@ -340,6 +346,7 @@ inline short int MeshTopology :: GetNFaces (ELEMENT_TYPE et) return 5; case HEX: + case HEX20: return 6; default: @@ -443,6 +450,7 @@ const ELEMENT_EDGE * MeshTopology :: GetEdges1 (ELEMENT_TYPE et) return prism_edges; case HEX: + case HEX20: return hex_edges; // default: // cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; @@ -513,7 +521,7 @@ const ELEMENT_EDGE * MeshTopology :: GetEdges0 (ELEMENT_TYPE et) { 2, 6 }, { 3, 7 }, }; - + switch (et) { case SEGMENT: @@ -541,6 +549,7 @@ const ELEMENT_EDGE * MeshTopology :: GetEdges0 (ELEMENT_TYPE et) return prism_edges; case HEX: + case HEX20: return hex_edges; // default: // cerr << "Ng_ME_GetEdges, illegal element type " << et << endl; @@ -627,6 +636,7 @@ inline const ELEMENT_FACE * MeshTopology :: GetFaces1 (ELEMENT_TYPE et) case SEGMENT3: case HEX: + case HEX20: return hex_faces; // default: @@ -709,6 +719,7 @@ inline const ELEMENT_FACE * MeshTopology :: GetFaces0 (ELEMENT_TYPE et) case SEGMENT3: case HEX: + case HEX20: return hex_faces; // default: From ba1463511b75b519b4ab7b2ad1ef82708dfd4c48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 17 Jan 2019 23:32:57 +0100 Subject: [PATCH 49/98] more quad8 --- libsrc/meshing/curvedelems.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index 96a944fc..c4d0a73c 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -1888,6 +1888,7 @@ namespace netgen } case QUAD: + case QUAD8: { shapes(0) = (1-xi(0))*(1-xi(1)); shapes(1) = xi(0) *(1-xi(1)); @@ -2266,7 +2267,7 @@ namespace netgen } break; } - case QUAD: + case QUAD: case QUAD8: { if (info.order >= 2) return false; // not yet supported AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; @@ -3854,8 +3855,9 @@ namespace netgen case TRIG : info.nv = 3; break; case QUAD : info.nv = 4; break; case TRIG6: info.nv = 6; break; + case QUAD8 : info.nv = 8; break; default: - cerr << "undef element in CalcMultPointSurfaceTrao" << endl; + cerr << "undef element in CalcMultPointSurfaceTrafo" << endl; } info.ndof = info.nv; From 5776853952e265ae4689736c0b4f96d2df50e0e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 17 Jan 2019 23:35:23 +0100 Subject: [PATCH 50/98] more QUAD8 --- libsrc/meshing/curvedelems.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index c4d0a73c..df489349 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -1888,7 +1888,6 @@ namespace netgen } case QUAD: - case QUAD8: { shapes(0) = (1-xi(0))*(1-xi(1)); shapes(1) = xi(0) *(1-xi(1)); @@ -1928,6 +1927,19 @@ namespace netgen break; } + + case QUAD8: + { + shapes(0) = (1-xi(0))*(1-xi(1)); + shapes(1) = xi(0) *(1-xi(1)); + shapes(2) = xi(0) * xi(1) ; + shapes(3) = (1-xi(0))* xi(1) ; + shapes(4) = 0.0; + shapes(5) = 0.0; + shapes(6) = 0.0; + shapes(7) = 0.0; + break; + } default: throw NgException("CurvedElements::CalcShape 2d, element type not handled"); From 46f53b0d9e5dc92c2dc29ab34594de1bad48bb70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 17 Jan 2019 23:39:55 +0100 Subject: [PATCH 51/98] more QUAD8 --- libsrc/meshing/curvedelems.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index df489349..cd6e8d49 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -1708,6 +1708,7 @@ namespace netgen case TRIG : info.nv = 3; break; case QUAD : info.nv = 4; break; case TRIG6: info.nv = 6; break; + case QUAD8 : info.nv = 8; break; default: cerr << "undef element in CalcSurfaceTrafo" << endl; } From 70578f0d898d24599a1a66a0c10aee220516e30d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 17 Jan 2019 23:46:52 +0100 Subject: [PATCH 52/98] more QUAD8 --- libsrc/visualization/vssolution.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsrc/visualization/vssolution.cpp b/libsrc/visualization/vssolution.cpp index 2669c1c6..201f1fba 100644 --- a/libsrc/visualization/vssolution.cpp +++ b/libsrc/visualization/vssolution.cpp @@ -1373,7 +1373,7 @@ namespace netgen - if ( el.GetType() == QUAD || el.GetType() == QUAD6 ) + if ( el.GetType() == QUAD || el.GetType() == QUAD6 || el.GetType() == QUAD8 ) { bool curved = curv.IsSurfaceElementCurved (sei); @@ -3482,6 +3482,7 @@ namespace netgen case QUAD: case QUAD6: + case QUAD8: lami[0] = (1-lam1)*(1-lam2); lami[1] = lam1 * (1-lam2); lami[2] = lam1 * lam2; @@ -3723,6 +3724,7 @@ namespace netgen case QUAD: case QUAD6: + case QUAD8: lami[0] = (1-lam1)*(1-lam2); lami[1] = lam1 * (1-lam2); lami[2] = lam1 * lam2; From bd20d044b12794658713a6d04808b6832d84dc4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 18 Jan 2019 00:34:27 +0100 Subject: [PATCH 53/98] more QUAD8 --- libsrc/meshing/curvedelems.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index cd6e8d49..b3d26fd3 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -1931,14 +1931,19 @@ namespace netgen case QUAD8: { - shapes(0) = (1-xi(0))*(1-xi(1)); - shapes(1) = xi(0) *(1-xi(1)); - shapes(2) = xi(0) * xi(1) ; - shapes(3) = (1-xi(0))* xi(1) ; - shapes(4) = 0.0; - shapes(5) = 0.0; - shapes(6) = 0.0; - shapes(7) = 0.0; + auto x = xi(0), y = xi(1); + shapes(0) = (1-x)*(1-y); + shapes(1) = x*(1-y); + shapes(2) = x*y; + shapes(3) = (1-x)*y; + shapes(4) = 4*(1-x)*x*(1-y); + shapes(5) = 4*(1-x)*x*y; + shapes(6) = 4*(1-y)*y*(1-x); + shapes(7) = 4*(1-y)*y*x; + shapes(0) -= shapes(4) - shapes(6); + shapes(1) -= shapes(4) - shapes(7); + shapes(2) -= shapes(5) - shapes(7); + shapes(3) -= shapes(5) - shapes(6); break; } From 48186fc54d1276a013f100b9efe31c9ad0999cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 18 Jan 2019 00:35:25 +0100 Subject: [PATCH 54/98] more QUAD8 --- libsrc/meshing/curvedelems.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index b3d26fd3..0c4afb06 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -1940,10 +1940,10 @@ namespace netgen shapes(5) = 4*(1-x)*x*y; shapes(6) = 4*(1-y)*y*(1-x); shapes(7) = 4*(1-y)*y*x; - shapes(0) -= shapes(4) - shapes(6); - shapes(1) -= shapes(4) - shapes(7); - shapes(2) -= shapes(5) - shapes(7); - shapes(3) -= shapes(5) - shapes(6); + shapes(0) -= 0.5*(shapes(4)+shapes(6)); + shapes(1) -= 0.5*(shapes(4)+shapes(7)); + shapes(2) -= 0.5*(shapes(5)+shapes(7)); + shapes(3) -= 0.5*(shapes(5)-shapes(6)); break; } From b6e62f9ebc09eac8472c02ea8ee20b3d83076b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 18 Jan 2019 00:43:41 +0100 Subject: [PATCH 55/98] more QUAD8 --- libsrc/meshing/curvedelems.cpp | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index 0c4afb06..8d799628 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -1943,7 +1943,7 @@ namespace netgen shapes(0) -= 0.5*(shapes(4)+shapes(6)); shapes(1) -= 0.5*(shapes(4)+shapes(7)); shapes(2) -= 0.5*(shapes(5)+shapes(7)); - shapes(3) -= 0.5*(shapes(5)-shapes(6)); + shapes(3) -= 0.5*(shapes(5)+shapes(6)); break; } @@ -2285,7 +2285,7 @@ namespace netgen } break; } - case QUAD: case QUAD8: + case QUAD: { if (info.order >= 2) return false; // not yet supported AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; @@ -2297,6 +2297,35 @@ namespace netgen } break; } + case QUAD8: + { + AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; + + auto x = xi(0), y = xi(1); + AutoDiff<2,T> lami = + { (1-x)*(1-y), + x*(1-y), + x*y, + (1-x)*y, + 4*(1-x)*x*(1-y), + 4*(1-x)*x*y, + 4*(1-y)*y*(1-x), + 4*(1-y)*y*x }; + + lami[0] -= 0.5*(lami[4]+lami[6]); + lami[1] -= 0.5*(lami[4]+lami[7]); + lami[2] -= 0.5*(lami[5]+lami[7]); + lami[3] -= 0.5*(lami[5]+lami[6]); + + for (int j = 0; j < 8; j++) + { + Point<3> p = mesh[el[j]]; + for (int k = 0; k < DIM_SPACE; k++) + mapped_x[k] += p(k) * lami[j]; + } + break; + } + default: return false; } From b6c58a8d632a0f205f31e390052e81a3a52e3304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 18 Jan 2019 00:44:16 +0100 Subject: [PATCH 56/98] more QUAD8 --- libsrc/meshing/curvedelems.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index 8d799628..36c27170 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -2299,10 +2299,10 @@ namespace netgen } case QUAD8: { - AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; + // AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; auto x = xi(0), y = xi(1); - AutoDiff<2,T> lami = + AutoDiff<2,T> lami[8] = { (1-x)*(1-y), x*(1-y), x*y, From fcaabd38b7f3eb92619a8b97acfa95fe6be40d4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 18 Jan 2019 00:46:20 +0100 Subject: [PATCH 57/98] more QUAD8 --- libsrc/meshing/curvedelems.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index 36c27170..56c276d9 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -2300,8 +2300,6 @@ namespace netgen case QUAD8: { // AutoDiff<2,T> lami[4] = { (1-x)*(1-y), x*(1-y), x*y, (1-x)*y }; - - auto x = xi(0), y = xi(1); AutoDiff<2,T> lami[8] = { (1-x)*(1-y), x*(1-y), From ec0a2a5ae890cd990bfc99040108ecfe1cea672c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Sat, 19 Jan 2019 14:26:17 +0100 Subject: [PATCH 58/98] quad8 and hex20 geometric elements --- libsrc/meshing/curvedelems.cpp | 87 ++++++++++++++++++++++++++++++++-- libsrc/meshing/meshtype.cpp | 3 ++ libsrc/meshing/meshtype.hpp | 8 ++-- libsrc/meshing/secondorder.cpp | 24 ++++++++++ libsrc/meshing/topology.cpp | 13 ++--- 5 files changed, 121 insertions(+), 14 deletions(-) diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index 56c276d9..5e3fb052 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -2885,6 +2885,46 @@ namespace netgen break; + } + + case HEX20: + { + shapes = 0.0; + T x = xi(0); + T y = xi(1); + T z = xi(2); + + shapes[0] = (1-x)*(1-y)*(1-z); + shapes[1] = x *(1-y)*(1-z); + shapes[2] = x * y *(1-z); + shapes[3] = (1-x)* y *(1-z); + shapes[4] = (1-x)*(1-y)*(z); + shapes[5] = x *(1-y)*(z); + shapes[6] = x * y *(z); + shapes[7] = (1-x)* y *(z); + + T sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), + (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; + + static const int e[12][2] = + { + { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, + { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, + { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, + }; + + for (int i = 0; i < 12; i++) + { + T lame = shapes[e[i][0]]+shapes[e[i][1]]; + T xi = sigma[e[i][1]]-sigma[e[i][0]]; + shapes[8+i] = (1-xi*xi)*lame; + } + for (int i = 0; i < 12; i++) + { + shapes[e[i][0]] -= 0.5 * shapes[8+i]; + shapes[e[i][1]] -= 0.5 * shapes[8+i]; + } + break; } default: @@ -3489,12 +3529,49 @@ namespace netgen *testout << "quad, num dshape = " << endl << dshapes << endl; */ break; - - - - break; } - + case HEX20: + { + AutoDiff<3,T> x(xi(0), 0); + AutoDiff<3,T> y(xi(1), 1); + AutoDiff<3,T> z(xi(2), 2); + AutoDiff<3,T> ad[20]; + + ad[0] = (1-x)*(1-y)*(1-z); + ad[1] = x *(1-y)*(1-z); + ad[2] = x * y *(1-z); + ad[3] = (1-x)* y *(1-z); + ad[4] = (1-x)*(1-y)*(z); + ad[5] = x *(1-y)*(z); + ad[6] = x * y *(z); + ad[7] = (1-x)* y *(z); + + AutoDiff<3,T> sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), + (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; + + static const int e[12][2] = + { + { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, + { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, + { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, + }; + + for (int i = 0; i < 12; i++) + { + auto lame = ad[e[i][0]]+ad[e[i][1]]; + auto xi = sigma[e[i][1]]-sigma[e[i][0]]; + ad[8+i] = (1-xi*xi)*lame; + } + for (int i = 0; i < 12; i++) + { + ad[e[i][0]] -= 0.5 * ad[8+i]; + ad[e[i][1]] -= 0.5 * ad[8+i]; + } + for (int i = 0; i < 20; i++) + for (int j = 0; j < 3; j++) + dshapes(i,j) = ad[i].DValue(j); + break; + } default: throw NgException("CurvedElements::CalcDShape 3d, element type not handled"); } diff --git a/libsrc/meshing/meshtype.cpp b/libsrc/meshing/meshtype.cpp index baed182e..494a3879 100644 --- a/libsrc/meshing/meshtype.cpp +++ b/libsrc/meshing/meshtype.cpp @@ -1028,6 +1028,7 @@ namespace netgen case 6: typ = PRISM; break; case 8: typ = HEX; break; case 10: typ = TET10; break; + case 20: typ = HEX20; break; default: cerr << "Element::Element: unknown element with " << np << " points" << endl; } orderx = ordery = orderz = 1; @@ -1108,6 +1109,7 @@ namespace netgen case 6: typ = PRISM; break; case 8: typ = HEX; break; case 10: typ = TET10; break; + case 20: typ = HEX20; break; // default: break; cerr << "Element::SetNP unknown element with " << np << " points" << endl; @@ -1127,6 +1129,7 @@ namespace netgen case HEX: np = 8; break; case TET10: np = 10; break; case PRISM12: np = 12; break; + case HEX20: np = 20; break; default: break; cerr << "Element::SetType unknown type " << int(typ) << endl; diff --git a/libsrc/meshing/meshtype.hpp b/libsrc/meshing/meshtype.hpp index a894d090..1b31d597 100644 --- a/libsrc/meshing/meshtype.hpp +++ b/libsrc/meshing/meshtype.hpp @@ -647,7 +647,7 @@ namespace netgen /// ELEMENT_TYPE typ; /// number of points (4..tet, 5..pyramid, 6..prism, 8..hex, 10..quad tet, 12..quad prism) - int np:5; + int np:6; /// class flagstruct { public: @@ -708,7 +708,7 @@ namespace netgen /// uint8_t GetNV() const { - __assume(typ >= TET && typ <= HEX); + __assume(typ >= TET && typ <= HEX20); switch (typ) { case TET: @@ -720,6 +720,7 @@ namespace netgen case PYRAMID: return 5; case HEX: + case HEX20: return 8; default: // not a 3D element #ifdef DEBUG @@ -797,7 +798,8 @@ namespace netgen case PYRAMID: return 5; case PRISM: case PRISM12: return 5; - case HEX: return 6; + case HEX: case HEX20: + return 6; default: #ifdef DEBUG PrintSysError ("element3d::GetNFaces not implemented for typ", typ) diff --git a/libsrc/meshing/secondorder.cpp b/libsrc/meshing/secondorder.cpp index 861f99ed..6241fd4e 100644 --- a/libsrc/meshing/secondorder.cpp +++ b/libsrc/meshing/secondorder.cpp @@ -223,6 +223,22 @@ namespace netgen { 3, 4, 10 }, { 4, 5, 11 }, }; + static int betw_hex[12][3] = + { + { 0, 1, 8 }, + { 2, 3, 9 }, + { 3, 0, 10 }, + { 1, 2, 11 }, + { 4, 5, 12 }, + { 6, 7, 13 }, + { 7, 4, 14 }, + { 5, 6, 15 }, + { 0, 4, 16 }, + { 1, 5, 17 }, + { 2, 6, 18 }, + { 3, 7, 19 }, + }; + int (*betw)[3] = NULL; switch (el.GetType()) @@ -243,6 +259,14 @@ namespace netgen onp = 6; break; } + case HEX: + case HEX20: + { + betw = betw_hex; + newel.SetType (HEX20); + onp = 8; + break; + } default: PrintSysError ("MakeSecondOrder, illegal vol type ", int(el.GetType())); } diff --git a/libsrc/meshing/topology.cpp b/libsrc/meshing/topology.cpp index cddc731f..04962a57 100644 --- a/libsrc/meshing/topology.cpp +++ b/libsrc/meshing/topology.cpp @@ -543,7 +543,7 @@ namespace netgen cnt = 0; ParallelForRange - (tm, mesh->Points().Size(), + (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_CLOSED_HASHTABLE v2eht(2*max_edge_on_vertex+10); @@ -581,7 +581,7 @@ namespace netgen // accumulate number of edges int ned = edge2vert.Size(); - for (auto v : mesh->Points().Range()) + for (size_t v = 0; v < mesh->GetNV(); v++) { auto hv = cnt[v]; cnt[v] = ned; @@ -595,7 +595,7 @@ namespace netgen // for (PointIndex v = PointIndex::BASE; v < nv+PointIndex::BASE; v++) ParallelForRange - (tm, mesh->Points().Size(), + (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_CLOSED_HASHTABLE v2eht(2*max_edge_on_vertex+10); @@ -719,7 +719,7 @@ namespace netgen // for (auto v : mesh.Points().Range()) NgProfiler::StartTimer (timer2b1); ParallelForRange - (tm, mesh->Points().Size(), + (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); @@ -754,7 +754,8 @@ namespace netgen // accumulate number of faces int nfa = oldnfa; - for (auto v : mesh->Points().Range()) + // for (auto v : Range(mesh->GetNV())) // Points().Range()) + for (size_t v = 0; v < mesh->GetNV(); v++) { auto hv = cnt[v]; cnt[v] = nfa; @@ -765,7 +766,7 @@ namespace netgen // for (auto v : mesh.Points().Range()) ParallelForRange - (tm, mesh->Points().Size(), + (tm, mesh->GetNV(), // Points().Size(), [&] (size_t begin, size_t end) { INDEX_3_CLOSED_HASHTABLE vert2face(2*max_face_on_vertex+10); From 229d1da5ea4ebd657f8a17d5a8a43712f065bf11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Sat, 19 Jan 2019 18:06:40 +0100 Subject: [PATCH 59/98] use Range iterators --- libsrc/meshing/topology.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libsrc/meshing/topology.cpp b/libsrc/meshing/topology.cpp index 04962a57..dc57c347 100644 --- a/libsrc/meshing/topology.cpp +++ b/libsrc/meshing/topology.cpp @@ -581,7 +581,9 @@ namespace netgen // accumulate number of edges int ned = edge2vert.Size(); - for (size_t v = 0; v < mesh->GetNV(); v++) + + // for (size_t v = 0; v < mesh->GetNV(); v++) + for (size_t v : cnt.Range()) { auto hv = cnt[v]; cnt[v] = ned; @@ -755,7 +757,8 @@ namespace netgen // accumulate number of faces int nfa = oldnfa; // for (auto v : Range(mesh->GetNV())) // Points().Range()) - for (size_t v = 0; v < mesh->GetNV(); v++) + // for (size_t v = 0; v < mesh->GetNV(); v++) + for (auto v : cnt.Range()) { auto hv = cnt[v]; cnt[v] = nfa; From f10640428091ec475cc89796ecbd9063e0990db3 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 23 Jan 2019 10:19:43 +0100 Subject: [PATCH 60/98] implement "needs version" functionality for archiver --- libsrc/core/archive.hpp | 41 ++++++++++++++++++++++++++++++++++------- libsrc/core/utils.hpp | 10 +++++++++- libsrc/core/version.hpp | 6 ++++++ tests/catch/archive.cpp | 18 ++++++++++++++++-- 4 files changed, 65 insertions(+), 10 deletions(-) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 1fedde76..8c45baf2 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -153,6 +153,9 @@ namespace ngcore const VersionInfo& GetVersion(const std::string& library) { return version_map[library]; } + // only used for PyArchive + virtual void NeedsVersion(const std::string& library, const std::string& version) {} + // Pure virtual functions that have to be implemented by In-/OutArchive virtual Archive & operator & (double & d) = 0; virtual Archive & operator & (int & i) = 0; @@ -900,6 +903,7 @@ namespace ngcore private: pybind11::list lst; size_t index = 0; + std::map version_needed; protected: using ARCHIVE::stream; using ARCHIVE::version_map; @@ -915,9 +919,26 @@ namespace ngcore { stream = std::make_shared (pybind11::cast(lst[pybind11::len(lst)-1])); - *this & version_map; + *this & version_needed; + logger->debug("versions needed for unpickling = {}", version_needed); + for(auto& libversion : version_needed) + if(libversion.second > GetLibraryVersion(libversion.first)) + throw Exception("Error in unpickling data:\nLibrary " + libversion.first + + " must be at least " + libversion.second.to_string()); stream = std::make_shared (pybind11::cast(lst[pybind11::len(lst)-2])); + *this & version_map; + stream = std::make_shared + (pybind11::cast(lst[pybind11::len(lst)-3])); + } + } + + void NeedsVersion(const std::string& library, const std::string& version) override + { + if(Output()) + { + logger->debug("Need version {} of library {}.", version, library); + version_needed[library] = version_needed[library] > version ? version_needed[library] : version; } } @@ -936,6 +957,12 @@ namespace ngcore lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); stream = std::make_shared(); *this & GetLibraryVersions(); + FlushBuffer(); + lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); + stream = std::make_shared(); + logger->debug("Writeout version needed = {}", version_needed); + *this & version_needed; + FlushBuffer(); lst.append(pybind11::bytes(std::static_pointer_cast(stream)->str())); return lst; } @@ -949,17 +976,17 @@ namespace ngcore PyArchive ar; ar & self; auto output = pybind11::make_tuple(ar.WriteOut()); - NETGEN_DEBUG_LOG(GetLogger("Archive"), "pickling output for object of type " + - Demangle(typeid(T).name()) + " = " + - std::string(pybind11::str(output))); + GetLogger("Archive")->trace("Pickling output for object of type {} = {}", + Demangle(typeid(T).name()), + std::string(pybind11::str(output))); return output; }, [](pybind11::tuple state) { 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]))); + GetLogger("Archive")->trace("State for unpickling of object of type {} = {}", + Demangle(typeid(T).name()), + std::string(pybind11::str(state[0]))); PyArchive ar(state[0]); ar & val; return val; diff --git a/libsrc/core/utils.hpp b/libsrc/core/utils.hpp index da90e1d3..f2a73578 100644 --- a/libsrc/core/utils.hpp +++ b/libsrc/core/utils.hpp @@ -2,6 +2,8 @@ #define NETGEN_CORE_UTILS_HPP #include +#include +#include #include #include @@ -56,7 +58,13 @@ namespace ngcore return ss.str(); } - + template + std::ostream& operator << (std::ostream& ost, const std::map& map) + { + for(auto& val : map) + ost << "\n" << val.first << ": " << val.second; + return ost; + } } // namespace ngcore #endif // NETGEN_CORE_UTILS_HPP diff --git a/libsrc/core/version.hpp b/libsrc/core/version.hpp index 69598716..aea50bf6 100644 --- a/libsrc/core/version.hpp +++ b/libsrc/core/version.hpp @@ -1,6 +1,7 @@ #ifndef NETGEN_CORE_VERSION_HPP #define NETGEN_CORE_VERSION_HPP +#include #include #include @@ -83,6 +84,11 @@ namespace ngcore bool operator <=(const VersionInfo& other) const { return !((*this) > other); } bool operator >=(const VersionInfo& other) const { return !((*this) < other); } }; + + inline std::ostream& operator << (std::ostream& ost, const VersionInfo& version) + { + return ost << version.to_string(); + } } // namespace ngcore #endif // NETGEN_CORE_VERSION_HPP diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index b3f27d49..60cd33f0 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -236,6 +236,18 @@ void testMultipleInheritance(Archive& in, Archive& out) } } +void testMap(Archive& in, Archive& out) +{ + map map1; + map1["netgen"] = "v6.2.1901"; + out & map1; + out.FlushBuffer(); + map map2; + in & map2; + CHECK(map2.size() == 1); + CHECK(map2["netgen"] == "v6.2.1901"); +} + void testArchive(Archive& in, Archive& out) { SECTION("Empty String") @@ -285,11 +297,14 @@ void testArchive(Archive& in, Archive& out) { testNullPtr(in, out); } + SECTION("map") + { + testMap(in, out); + } } TEST_CASE("BinaryArchive") { - SetLibraryVersion("netgen","v6.2.1811"); auto stream = make_shared(); BinaryOutArchive out(stream); BinaryInArchive in(stream); @@ -298,7 +313,6 @@ TEST_CASE("BinaryArchive") TEST_CASE("TextArchive") { - SetLibraryVersion("netgen","v6.2.1811"); auto stream = make_shared(); TextOutArchive out(stream); TextInArchive in(stream); From 05f22e463dc2f8f80ffe3f47411cbb634063c14c Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 23 Jan 2019 10:35:20 +0100 Subject: [PATCH 61/98] add function to automatically create pml layer around convex 2d geometries --- libsrc/geom2d/geometry2d.hpp | 1 + libsrc/geom2d/python_geom2d.cpp | 49 ++++++++--------- libsrc/meshing/python_mesh.cpp | 2 + python/geom2d.py | 98 ++++++++++++++++++++++++++++++++- 4 files changed, 124 insertions(+), 26 deletions(-) diff --git a/libsrc/geom2d/geometry2d.hpp b/libsrc/geom2d/geometry2d.hpp index 52e7a20e..0d4bcb00 100644 --- a/libsrc/geom2d/geometry2d.hpp +++ b/libsrc/geom2d/geometry2d.hpp @@ -175,6 +175,7 @@ namespace netgen void CopyEdgeMesh (int from, int to, Mesh & mesh2d, Point3dTree & searchtree); + size_t GetNDomains() const { return materials.Size(); } void GetMaterial (int domnr, char* & material ); void SetMaterial (int domnr, const string & material); diff --git a/libsrc/geom2d/python_geom2d.cpp b/libsrc/geom2d/python_geom2d.cpp index a16c13f7..f2b20127 100644 --- a/libsrc/geom2d/python_geom2d.cpp +++ b/libsrc/geom2d/python_geom2d.cpp @@ -15,6 +15,22 @@ namespace netgen DLL_HEADER void ExportGeom2d(py::module &m) { + py::class_> + (m, "Spline", "Spline of a SplineGeometry object") + .def_property("leftdom", [] (SplineSegExt& self) { return self.leftdom; }, + [](SplineSegExt& self, int dom) { self.leftdom = dom; }) + .def_property("rightdom", [] (SplineSegExt& self) { return self.rightdom; }, + [](SplineSegExt& self, int dom) { self.rightdom = dom; }) + .def_property_readonly("bc", [] (SplineSegExt& self) { return self.bc; }) + .def("GetNormal", [](SplineSegExt& self, double t) + { + auto tang = self.GetTangent(t).Normalize(); + return Vec<2>(tang[1], -tang[0]); + }) + .def("StartPoint", [](SplineSegExt& self) { return Point<2>(self.StartPI()); }) + .def("EndPoint", [](SplineSegExt& self) { return Point<2>(self.EndPI()); }) + ; + py::class_> (m, "SplineGeometry", "a 2d boundary representation geometry model by lines and splines", @@ -121,38 +137,21 @@ DLL_HEADER void ExportGeom2d(py::module &m) seg->copyfrom = -1; self.AppendSegment(seg); }), py::arg("point_indices"), py::arg("leftdomain") = 1, py::arg("rightdomain") = py::int_(0)) - //.def("AppendSegment", FunctionPointer([](SplineGeometry2d &self, int point_index1, int point_index2)//, int leftdomain, int rightdomain) - // { - // LineSeg<2> * l = new LineSeg<2>(self.GetPoint(point_index1), self.GetPoint(point_index2)); - // SplineSegExt * seg = new SplineSegExt(*l); - // seg->leftdom = 1;// leftdomain; - // seg->rightdom = 0;// rightdomain; - // seg->hmax = 1e99; - // seg->reffak = 1; - // seg->copyfrom = -1; - - // self.AppendSegment(seg); - // }))//, (py::arg("self"), py::arg("point_index1"), py::arg("point_index2"), py::arg("leftdomain") = 1, py::arg("rightdomain") = 0) ) - //.def("AppendSegment", FunctionPointer([](SplineGeometry2d &self, int point_index1, int point_index2, int point_index3)//, int leftdomain, int rightdomain) - // { - // SplineSeg3<2> * seg3 = new SplineSeg3<2>(self.GetPoint(point_index1), self.GetPoint(point_index2), self.GetPoint(point_index3)); - // SplineSegExt * seg = new SplineSegExt(*seg3); - // seg->leftdom = 1;// leftdomain; - // seg->rightdom = 0;// rightdomain; - // seg->hmax = 1e99; - // seg->reffak = 1; - // seg->copyfrom = -1; - // self.AppendSegment(seg); - // }))//, (py::arg("self"), py::arg("point_index1"), py::arg("point_index2"), py::arg("point_index3"), py::arg("leftdomain") = 1, py::arg("rightdomain") = 0 ) ) - .def("SetMaterial", &SplineGeometry2d::SetMaterial) .def("SetDomainMaxH", &SplineGeometry2d::SetDomainMaxh) + .def("GetBCName", [](SplineGeometry2d& self, size_t index) { return self.GetBCName(index); }) + .def("GetNDomains", [](SplineGeometry2d& self) { return self.GetNDomains(); }) + .def("GetNSplines", [](SplineGeometry2d& self) { return self.splines.Size(); }) + .def("GetSpline", [](SplineGeometry2d& self, size_t index) + { return shared_ptr(&self.GetSpline(index), NOOP_Deleter); }, + py::return_value_policy::reference_internal) + .def("GetNPoints", [](SplineGeometry2d& self) { return self.GetNP(); }) + .def("GetPoint", [](SplineGeometry2d& self, size_t index) { return Point<2>(self.GetPoint(index)); }) - .def("PlotData", FunctionPointer([](SplineGeometry2d &self) { Box<2> box(self.GetBoundingBox()); diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index b0c2a5c7..436835ef 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -80,6 +80,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) .def(py::self-py::self) .def(py::self+Vec<2>()) .def(py::self-Vec<2>()) + .def("__getitem__", [](Point<2>& self, int index) { return self[index]; }) ; py::class_> (m, "Point3d") @@ -88,6 +89,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) .def(py::self-py::self) .def(py::self+Vec<3>()) .def(py::self-Vec<3>()) + .def("__getitem__", [](Point<2>& self, int index) { return self[index]; }) ; m.def ("Pnt", FunctionPointer diff --git a/python/geom2d.py b/python/geom2d.py index 88856964..34b37870 100644 --- a/python/geom2d.py +++ b/python/geom2d.py @@ -39,11 +39,107 @@ def MakeCircle (geo, c, r, **args): geo.Append( ["spline3", pts[p1], pts[p2], pts[p3]], **args) + +def CreatePML(geo, pml_size, tol=1e-12): + """Create a pml layer around the geometry. This function works only on convex geometries and +the highest existing domain number must be named by using the function geo.SetMaterial(domnr, name). +Points in the geometry are assumed to be the same if (pt1 - pt2).Norm() < tol. +Returned is a dict with information to create the pml layer: + normals: A dict from the names of the linear pml domains to the normal vectors pointing inside the pml.""" + + def Start(spline): + if spline.rightdom == 0: + return spline.StartPoint() + return spline.EndPoint() + def End(spline): + if spline.rightdom == 0: + return spline.EndPoint() + return spline.StartPoint() + + splines = [] + for i in range(geo.GetNSplines()): + splines.append(geo.GetSpline(i)) + border = [] + is_closed = False + current_endpoint = None + while not is_closed: + for spline in splines: + if spline.leftdom == 0 or spline.rightdom == 0: + if current_endpoint is not None: + if (Start(spline)-current_endpoint).Norm() < tol: + border.append(spline) + current_endpoint = End(spline) + if (current_endpoint - startpoint).Norm() < tol: + is_closed = True + break + else: + startpoint = Start(spline) + current_endpoint = End(spline) + border.append(spline) + break + else: + raise Exception("Couldn't find closed spline around domain") + endpointindex_map = [] + for spline in border: + pnt = End(spline) + for i in range(geo.GetNPoints()): + if (pnt - geo.GetPoint(i)).Norm() < tol: + endpointindex_map.append(i) + break + else: + raise Exception("Couldn't find endpoint of spline in geometry") + start_ndoms = ndoms = geo.GetNDomains() + 1 + new_spline_domains = [] + normals = {} + for i, spline in enumerate(border): + if i == 0: + global_start = Start(spline) + pml_size * spline.GetNormal(0) + global_start_pnt = current_start = geo.AppendPoint(global_start[0], global_start[1]) + next_spline = border[(i+1)%len(border)] + new_end = End(spline) + pml_size * spline.GetNormal(1) + spline_name = geo.GetBCName(spline.bc) + if (new_end - global_start).Norm() < tol: + new_spline_domains.append(ndoms) + geo.Append(["line", current_start, global_start_pnt], bc="outer_" + spline_name, leftdomain = ndoms) + geo.Append(["line", global_start_pnt, endpointindex_map[i]], leftdomain=ndoms, rightdomain=start_ndoms) + geo.SetMaterial(ndoms, "pml_" + spline_name) + normals["pml_" + spline_name] = spline.GetNormal(0) + ndoms += 1 + break + end = geo.AppendPoint(new_end[0], new_end[1]) + new_spline_domains.append(ndoms) + geo.Append(["line", current_start, end], bc="outer_" + spline_name, leftdomain = ndoms) + geo.Append(["line", end, endpointindex_map[i]], leftdomain=ndoms, rightdomain=ndoms+1) + geo.SetMaterial(ndoms, "pml_" + spline_name) + normals["pml_" + spline_name] = spline.GetNormal(0) + ndoms += 1 + new_start = Start(next_spline) + pml_size * next_spline.GetNormal(0) + if (new_start - global_start).Norm() < tol: + geo.Append(["line", end, global_start_pnt], bc="outer", leftdomain = ndoms) + geo.Append(["line", global_start_pnt, endpointindex_map[i]], leftdomain=ndoms, rightdomain=start_ndoms) + geo.SetMaterial(ndoms, "pml_corner") + ndoms += 1 + break + if (new_end - new_start).Norm() < tol: + current_start = end + else: + current_start = geo.AppendPoint(new_start[0], new_start[1]) + geo.Append(["line", end, current_start], bc="outer", leftdomain = ndoms) + geo.Append(["line", current_start, endpointindex_map[i]], leftdomain=ndoms, rightdomain=ndoms+1) + geo.SetMaterial(ndoms, "pml_corner") + ndoms += 1 + for spline, domnr in zip(border, new_spline_domains): + if spline.leftdom == 0: + spline.leftdom = domnr + else: + spline.rightdom = domnr + return {"normals" : normals} + SplineGeometry.AddCircle = lambda geo, c, r, **args : MakeCircle(geo, c, r, **args) SplineGeometry.AddRectangle = lambda geo, p1, p2, **args : MakeRectangle(geo, p1, p2, **args) SplineGeometry.AddSegment = lambda *args, **kwargs : SplineGeometry.Append(*args, **kwargs) SplineGeometry.AddPoint = lambda *args, **kwargs : SplineGeometry.AppendPoint(*args, **kwargs) - +SplineGeometry.CreatePML = CreatePML __all__ = ['SplineGeometry', 'unit_square'] From c062933c42ee943be644e68bb60fa7b59ae91efb Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 23 Jan 2019 16:00:57 +0100 Subject: [PATCH 62/98] fix secondorder mesh generation for closed occ edge --- libsrc/occ/occmeshsurf.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsrc/occ/occmeshsurf.cpp b/libsrc/occ/occmeshsurf.cpp index a1f60db6..13f034be 100644 --- a/libsrc/occ/occmeshsurf.cpp +++ b/libsrc/occ/occmeshsurf.cpp @@ -673,13 +673,13 @@ namespace netgen if (surfi > 0) { - double u = gi1.u+secpoint*(gi2.u-gi1.u); double v = gi1.v+secpoint*(gi2.v-gi1.v); - - if (!geometry.FastProject (surfi, hnewp, u, v)) + + if (!geometry.FastProject (surfi, hnewp, u, v) || Dist(hnewp, p1) > Dist(p1,p2)) { - // cout << "Fast projection to surface fails! Using OCC projection" << endl; + // cout << "Fast projection to surface fails! Using OCC projection" << endl; + hnewp = p1+secpoint*(p2-p1); geometry.Project (surfi, hnewp); } From fbd7d2340e861ee49e57469ca7a5ddc075f19dd6 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 23 Jan 2019 16:58:23 +0100 Subject: [PATCH 63/98] check dist to midpoint and save midpoint in PointBetween --- libsrc/occ/occmeshsurf.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsrc/occ/occmeshsurf.cpp b/libsrc/occ/occmeshsurf.cpp index 13f034be..56fbf07b 100644 --- a/libsrc/occ/occmeshsurf.cpp +++ b/libsrc/occ/occmeshsurf.cpp @@ -676,10 +676,11 @@ namespace netgen double u = gi1.u+secpoint*(gi2.u-gi1.u); double v = gi1.v+secpoint*(gi2.v-gi1.v); - if (!geometry.FastProject (surfi, hnewp, u, v) || Dist(hnewp, p1) > Dist(p1,p2)) + auto savept = hnewp; + if (!geometry.FastProject (surfi, hnewp, u, v) || Dist(hnewp, savept) > Dist(p1,p2)) { // cout << "Fast projection to surface fails! Using OCC projection" << endl; - hnewp = p1+secpoint*(p2-p1); + hnewp = savept; geometry.Project (surfi, hnewp); } From 21ba19bf10d3a8e6bc955bcc4038a40da85ce112 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Thu, 24 Jan 2019 16:13:22 +0100 Subject: [PATCH 64/98] export __getitem__ and __len__ for Vec --- libsrc/meshing/python_mesh.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 436835ef..6d7760a4 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -113,6 +113,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) .def(-py::self) .def(double()*py::self) .def("Norm", &Vec<2>::Length) + .def("__getitem__", [](Vec<2>& vec, int index) { return vec[index]; }) + .def("__len__", [](Vec<2>& /*unused*/) { return 2; }) ; py::class_> (m, "Vec3d") @@ -123,6 +125,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) .def(-py::self) .def(double()*py::self) .def("Norm", &Vec<3>::Length) + .def("__getitem__", [](Vec<3>& vec, int index) { return vec[index]; }) + .def("__len__", [](Vec<3>& /*unused*/) { return 3; }) ; m.def ("Vec", FunctionPointer From 476d43f9f77d236e77426de49e63294942790c83 Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Fri, 25 Jan 2019 08:26:18 +0100 Subject: [PATCH 65/98] guideline checks allowed to fail, fix guideline issue --- .gitlab-ci.yml | 1 + libsrc/core/archive.hpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 276a0ec8..c5ee2e8c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -100,6 +100,7 @@ test_guidelines: script: - docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_BUILD_REF_NAME}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh when: always + allow_failure: true # check if it compiles without spdlog test_noSpdlog: diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 8c45baf2..0ff17768 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -154,7 +154,7 @@ namespace ngcore { return version_map[library]; } // only used for PyArchive - virtual void NeedsVersion(const std::string& library, const std::string& version) {} + virtual void NeedsVersion(const std::string& /*unused*/, const std::string& /*unused*/) {} // Pure virtual functions that have to be implemented by In-/OutArchive virtual Archive & operator & (double & d) = 0; From 4f400878669d534f5612391b77ab91bc01325525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 25 Jan 2019 10:41:49 +0100 Subject: [PATCH 66/98] domain indices are 1-based --- libsrc/csg/python_csg.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/csg/python_csg.cpp b/libsrc/csg/python_csg.cpp index 665a7392..c82db668 100644 --- a/libsrc/csg/python_csg.cpp +++ b/libsrc/csg/python_csg.cpp @@ -477,7 +477,7 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails! tlonum = i; if (tlonum == -1) throw NgException("not a top-level-object"); if (!surfaces) surfaces = sol; - auto singface = new SingularFace(tlonum, surfaces->GetSolid(), factor); + auto singface = new SingularFace(tlonum+1, surfaces->GetSolid(), factor); self.singfaces.Append(singface); }, py::arg("solid"), py::arg("surfaces")=nullptr, py::arg("factor")=0.25) .def("SingularEdge", [] (CSGeometry & self, shared_ptr s1,shared_ptr s2, double factor) From f287df575b8af826c8794070879a5be72ee91f3d Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Mon, 28 Jan 2019 11:02:46 +0100 Subject: [PATCH 67/98] archive enums --- libsrc/core/archive.hpp | 13 +++++++++++++ tests/catch/archive.cpp | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/libsrc/core/archive.hpp b/libsrc/core/archive.hpp index 0ff17768..c1182b40 100644 --- a/libsrc/core/archive.hpp +++ b/libsrc/core/archive.hpp @@ -209,6 +209,19 @@ namespace ngcore return (*this); } + // archive implementation for enums + template + auto operator & (T& val) -> typename std::enable_if::value, Archive&>::type + { + int enumval; + if(Output()) + enumval = int(val); + *this & enumval; + if(Input()) + val = T(enumval); + return *this; + } + // vector has special implementation (like a bitarray) therefore // it needs a special overload (this could probably be more efficient, but we // don't use it that often anyway) diff --git a/tests/catch/archive.cpp b/tests/catch/archive.cpp index 60cd33f0..96c2087c 100644 --- a/tests/catch/archive.cpp +++ b/tests/catch/archive.cpp @@ -248,6 +248,22 @@ void testMap(Archive& in, Archive& out) CHECK(map2["netgen"] == "v6.2.1901"); } +enum MyEnum + { + CASE1, + CASE2 + }; + +void testEnum(Archive& in, Archive& out) + { + MyEnum en = CASE2; + out & en; + out.FlushBuffer(); + MyEnum enin; + in & enin; + CHECK(enin == CASE2); + } + void testArchive(Archive& in, Archive& out) { SECTION("Empty String") @@ -301,6 +317,10 @@ void testArchive(Archive& in, Archive& out) { testMap(in, out); } + SECTION("enum") + { + testEnum(in, out); + } } TEST_CASE("BinaryArchive") From c7fb6c7e4acdbac8b90a6a9413d3795f58338586 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 29 Jan 2019 16:10:02 +0100 Subject: [PATCH 68/98] Add a global communicator. The mesh now has a communicator. --- libsrc/general/mpi_interface.hpp | 89 +++++++++++++++++---------- libsrc/include/nginterface.h | 5 +- libsrc/include/nginterface_v2.hpp | 8 +++ libsrc/interface/nginterface.cpp | 23 +++---- libsrc/interface/nginterface_v2.cpp | 32 ++++++++-- libsrc/meshing/curvedelems.cpp | 8 ++- libsrc/meshing/global.cpp | 3 + libsrc/meshing/global.hpp | 4 ++ libsrc/meshing/meshclass.cpp | 17 +++++- libsrc/meshing/meshclass.hpp | 5 ++ libsrc/meshing/parallelmesh.cpp | 95 ++++++++++++++--------------- libsrc/meshing/paralleltop.cpp | 12 ++++ 12 files changed, 195 insertions(+), 106 deletions(-) diff --git a/libsrc/general/mpi_interface.hpp b/libsrc/general/mpi_interface.hpp index 91cb0af3..d293480f 100644 --- a/libsrc/general/mpi_interface.hpp +++ b/libsrc/general/mpi_interface.hpp @@ -17,14 +17,38 @@ namespace netgen using ngcore::id; using ngcore::ntasks; -#ifdef PARALLEL +#ifndef PARALLEL + typedef int MPI_Comm; + enum { MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 0}; + + inline int MyMPI_GetNTasks (MPI_Comm comm = ng_comm) { return 1; } + inline int MyMPI_GetId (MPI_Comm comm = ng_comm) { return 0; } + +#endif + + /** This is the "standard" communicator that will be used for netgen-objects. **/ + extern MPI_Comm ng_comm; +#ifdef PARALLEL + + inline int MyMPI_GetNTasks (MPI_Comm comm = ng_comm) + { + int ntasks; + MPI_Comm_size(comm, &ntasks); + return ntasks; + } + + inline int MyMPI_GetId (MPI_Comm comm = ng_comm) + { + int id; + MPI_Comm_rank(comm, &id); + return id; + } + enum { MPI_TAG_CMD = 110 }; enum { MPI_TAG_MESH = 210 }; enum { MPI_TAG_VIS = 310 }; - extern MPI_Comm mesh_comm; - template MPI_Datatype MyGetMPIType ( ) { cerr << "ERROR in GetMPIType() -- no type found" << endl;return 0; } @@ -38,76 +62,76 @@ namespace netgen { return MPI_DOUBLE; } - inline void MyMPI_Send (int i, int dest, int tag) + inline void MyMPI_Send (int i, int dest, int tag, MPI_Comm comm = ng_comm) { int hi = i; - MPI_Send( &hi, 1, MPI_INT, dest, tag, MPI_COMM_WORLD); + MPI_Send( &hi, 1, MPI_INT, dest, tag, comm); } - inline void MyMPI_Recv (int & i, int src, int tag) + inline void MyMPI_Recv (int & i, int src, int tag, MPI_Comm comm = ng_comm) { MPI_Status status; - MPI_Recv( &i, 1, MPI_INT, src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &i, 1, MPI_INT, src, tag, comm, &status); } - inline void MyMPI_Send (const string & s, int dest, int tag) + inline void MyMPI_Send (const string & s, int dest, int tag, MPI_Comm comm = ng_comm) { - MPI_Send( const_cast (s.c_str()), s.length(), MPI_CHAR, dest, tag, MPI_COMM_WORLD); + MPI_Send( const_cast (s.c_str()), s.length(), MPI_CHAR, dest, tag, comm); } - inline void MyMPI_Recv (string & s, int src, int tag) + inline void MyMPI_Recv (string & s, int src, int tag, MPI_Comm comm = ng_comm) { MPI_Status status; int len; MPI_Probe (src, tag, MPI_COMM_WORLD, &status); MPI_Get_count (&status, MPI_CHAR, &len); s.assign (len, ' '); - MPI_Recv( &s[0], len, MPI_CHAR, src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &s[0], len, MPI_CHAR, src, tag, comm, &status); } template - inline void MyMPI_Send (FlatArray s, int dest, int tag) + inline void MyMPI_Send (FlatArray s, int dest, int tag, MPI_Comm comm = ng_comm) { - MPI_Send( &s.First(), s.Size(), MyGetMPIType(), dest, tag, MPI_COMM_WORLD); + MPI_Send( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm); } template - inline void MyMPI_Recv ( FlatArray s, int src, int tag) + inline void MyMPI_Recv ( FlatArray s, int src, int tag, MPI_Comm comm = ng_comm) { MPI_Status status; - MPI_Recv( &s.First(), s.Size(), MyGetMPIType(), src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &s.First(), s.Size(), MyGetMPIType(), src, tag, comm, &status); } template - inline void MyMPI_Recv ( Array & s, int src, int tag) + inline void MyMPI_Recv ( Array & s, int src, int tag, MPI_Comm comm = ng_comm) { MPI_Status status; int len; - MPI_Probe (src, tag, MPI_COMM_WORLD, &status); + MPI_Probe (src, tag, comm, &status); MPI_Get_count (&status, MyGetMPIType(), &len); s.SetSize (len); - MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, comm, &status); } template - inline int MyMPI_Recv ( Array & s, int tag) + inline int MyMPI_Recv ( Array & s, int tag, MPI_Comm comm = ng_comm) { MPI_Status status; int len; - MPI_Probe (MPI_ANY_SOURCE, tag, MPI_COMM_WORLD, &status); + MPI_Probe (MPI_ANY_SOURCE, tag, comm, &status); int src = status.MPI_SOURCE; MPI_Get_count (&status, MyGetMPIType(), &len); s.SetSize (len); - MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, MPI_COMM_WORLD, &status); + MPI_Recv( &s.First(), len, MyGetMPIType(), src, tag, comm, &status); return src; } @@ -129,7 +153,7 @@ namespace netgen */ template - inline MPI_Request MyMPI_ISend (FlatArray s, int dest, int tag, MPI_Comm comm = MPI_COMM_WORLD) + inline MPI_Request MyMPI_ISend (FlatArray s, int dest, int tag, MPI_Comm comm = ng_comm) { MPI_Request request; MPI_Isend( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm, &request); @@ -138,7 +162,7 @@ namespace netgen template - inline MPI_Request MyMPI_IRecv (FlatArray s, int dest, int tag, MPI_Comm comm = MPI_COMM_WORLD) + inline MPI_Request MyMPI_IRecv (FlatArray s, int dest, int tag, MPI_Comm comm = ng_comm) { MPI_Request request; MPI_Irecv( &s.First(), s.Size(), MyGetMPIType(), dest, tag, comm, &request); @@ -203,11 +227,10 @@ namespace netgen template inline void MyMPI_ExchangeTable (TABLE & send_data, TABLE & recv_data, int tag, - MPI_Comm comm = MPI_COMM_WORLD) + MPI_Comm comm = ng_comm) { - int ntasks, rank; - MPI_Comm_size(comm, &ntasks); - MPI_Comm_rank(comm, &rank); + int rank = MyMPI_GetId(comm); + int ntasks = MyMPI_GetNTasks(comm); Array send_sizes(ntasks); Array recv_sizes(ntasks); @@ -251,13 +274,13 @@ namespace netgen template - inline void MyMPI_Bcast (T & s, MPI_Comm comm = MPI_COMM_WORLD) + inline void MyMPI_Bcast (T & s, MPI_Comm comm = ng_comm) { MPI_Bcast (&s, 1, MyGetMPIType(), 0, comm); } template - inline void MyMPI_Bcast (Array & s, MPI_Comm comm = MPI_COMM_WORLD) + inline void MyMPI_Bcast (Array & s, MPI_Comm comm = ng_comm) { int size = s.Size(); MyMPI_Bcast (size, comm); @@ -266,7 +289,7 @@ namespace netgen } template - inline void MyMPI_Bcast (Array & s, int root, MPI_Comm comm = MPI_COMM_WORLD) + inline void MyMPI_Bcast (Array & s, int root, MPI_Comm comm = ng_comm) { int id; MPI_Comm_rank(comm, &id); @@ -279,19 +302,19 @@ namespace netgen } template - inline void MyMPI_Allgather (const T & send, FlatArray recv, MPI_Comm comm) + inline void MyMPI_Allgather (const T & send, FlatArray recv, MPI_Comm comm = ng_comm) { MPI_Allgather( const_cast (&send), 1, MyGetMPIType(), &recv[0], 1, MyGetMPIType(), comm); } template - inline void MyMPI_Alltoall (FlatArray send, FlatArray recv, MPI_Comm comm) + inline void MyMPI_Alltoall (FlatArray send, FlatArray recv, MPI_Comm comm = ng_comm) { MPI_Alltoall( &send[0], 1, MyGetMPIType(), &recv[0], 1, MyGetMPIType(), comm); } // template -// inline void MyMPI_Alltoall_Block (FlatArray send, FlatArray recv, int blocklen, MPI_Comm comm) +// inline void MyMPI_Alltoall_Block (FlatArray send, FlatArray recv, int blocklen, MPI_Comm comm = ng_comm) // { // MPI_Alltoall( &send[0], blocklen, MyGetMPIType(), &recv[0], blocklen, MyGetMPIType(), comm); // } diff --git a/libsrc/include/nginterface.h b/libsrc/include/nginterface.h index 9501bc29..f299efe9 100644 --- a/libsrc/include/nginterface.h +++ b/libsrc/include/nginterface.h @@ -37,6 +37,7 @@ // max number of nodes per surface element #define NG_SURFACE_ELEMENT_MAXPOINTS 8 +namespace netgen { extern MPI_Comm ng_comm; } // implemented element types: @@ -60,9 +61,9 @@ extern "C" { // load geometry from file DLL_HEADER void Ng_LoadGeometry (const char * filename); - + // load netgen mesh - DLL_HEADER void Ng_LoadMesh (const char * filename); + DLL_HEADER void Ng_LoadMesh (const char * filename, MPI_Comm comm = netgen::ng_comm); // load netgen mesh DLL_HEADER void Ng_LoadMeshFromString (const char * mesh_as_string); diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 11276e0d..fdfaa22f 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -249,6 +249,9 @@ namespace netgen { private: shared_ptr mesh; +#ifdef PARALLEL + MPI_Comm comm; +#endif public: // Ngx_Mesh () { ; } @@ -261,6 +264,11 @@ namespace netgen void UpdateTopology (); void DoArchive (Archive & archive); +#ifdef PARALLEL + MPI_Comm GetCommunicator() const; + void SetCommunicator(MPI_Comm acomm); +#endif + virtual ~Ngx_Mesh(); bool Valid () { return mesh != NULL; } diff --git a/libsrc/interface/nginterface.cpp b/libsrc/interface/nginterface.cpp index ad0a72db..bd3bd712 100644 --- a/libsrc/interface/nginterface.cpp +++ b/libsrc/interface/nginterface.cpp @@ -117,14 +117,10 @@ void Ng_LoadMeshFromStream ( istream & input ) } - - -void Ng_LoadMesh (const char * filename) +void Ng_LoadMesh (const char * filename, MPI_Comm comm) { -#ifdef PARALLEL - MPI_Comm_size(MPI_COMM_WORLD, &ntasks); - MPI_Comm_rank(MPI_COMM_WORLD, &id); -#endif + int id = MyMPI_GetId(comm); + int ntasks = MyMPI_GetNTasks(comm); { ifstream infile(filename); @@ -134,11 +130,10 @@ void Ng_LoadMesh (const char * filename) if ( string(filename).find(".vol") == string::npos ) { -#ifdef PARALLEL if(ntasks>1) throw NgException("Not sure what to do with this?? Does this work with MPI??"); -#endif mesh.reset (new Mesh()); + mesh->SetCommunicator(comm); ReadFile(*mesh,filename); //mesh->SetGlobalH (mparam.maxh); //mesh->CalcLocalH(); @@ -149,9 +144,7 @@ void Ng_LoadMesh (const char * filename) char* buf; // for distributing geometry! int strs; - #ifdef PARALLEL if( id == 0) { - #endif string fn(filename); if (fn.substr (fn.length()-3, 3) == ".gz") @@ -159,6 +152,7 @@ void Ng_LoadMesh (const char * filename) else infile = new ifstream (filename); mesh.reset (new Mesh()); + mesh->SetCommunicator(comm); mesh -> Load(*infile); SetGlobalMesh (mesh); @@ -173,7 +167,6 @@ void Ng_LoadMesh (const char * filename) } delete infile; -#ifdef PARALLEL if (ntasks > 1) { @@ -239,17 +232,17 @@ void Ng_LoadMesh (const char * filename) } // id==0 end else { mesh.reset (new Mesh()); + mesh->SetCommunicator(comm); SetGlobalMesh (mesh); mesh->SendRecvMesh(); } if(!ng_geometry && ntasks>1) { /** Scatter the geometry-string **/ - MPI_Bcast(&strs, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&strs, 1, MPI_INT, 0, comm); if(id!=0) buf = new char[strs]; - MPI_Bcast(buf, strs, MPI_CHAR, 0, MPI_COMM_WORLD); + MPI_Bcast(buf, strs, MPI_CHAR, 0, comm); } -#endif if(!ng_geometry) { infile = new istringstream(string((const char*)buf, (size_t)strs)); diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index 6ac24f40..adeefe28 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -34,23 +34,40 @@ namespace netgen Ngx_Mesh :: Ngx_Mesh (shared_ptr amesh) { - if (amesh) + if (amesh) { mesh = amesh; - else + comm = amesh->GetCommunicator(); + } + else { mesh = netgen::mesh; + comm = netgen::ng_comm; + } } + +#ifdef PARALLEL + void Ngx_Mesh :: SetCommunicator (MPI_Comm acomm) + { + if (Valid() && acomm!=mesh->GetCommunicator()) + throw NgException("Redistribution of mesh not possible!"); + this->comm = acomm; + } + + + MPI_Comm Ngx_Mesh :: GetCommunicator() const + { return comm; } +#endif Ngx_Mesh * LoadMesh (const string & filename) { netgen::mesh.reset(); - Ng_LoadMesh (filename.c_str()); + Ng_LoadMesh (filename.c_str(), netgen::ng_comm); return new Ngx_Mesh (netgen::mesh); } void Ngx_Mesh :: LoadMesh (const string & filename) { netgen::mesh.reset(); - Ng_LoadMesh (filename.c_str()); + Ng_LoadMesh (filename.c_str(), this->comm); // mesh = move(netgen::mesh); mesh = netgen::mesh; } @@ -71,7 +88,12 @@ namespace netgen void Ngx_Mesh :: DoArchive (Archive & archive) { - if (archive.Input()) mesh = make_shared(); +#ifdef PARALLEL + if (archive.Input()) { + mesh = make_shared(); + mesh->SetCommunicator(GetCommunicator()); + } +#endif mesh->DoArchive(archive); if (archive.Input()) { diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index 5e3fb052..a3e7f209 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -553,14 +553,18 @@ namespace netgen order = 1; + MPI_Comm curve_comm; #ifdef PARALLEL enum { MPI_TAG_CURVE = MPI_TAG_MESH+20 }; const ParallelMeshTopology & partop = mesh.GetParallelTopology (); - MPI_Comm curve_comm; - MPI_Comm_dup (MPI_COMM_WORLD, &curve_comm); + MPI_Comm_dup (mesh.GetCommunicator(), &curve_comm); Array procs; +#else + curve_comm = ng_comm; // dummy! #endif + int rank = MyMPI_GetId(curve_comm); + int ntasks = MyMPI_GetNTasks(curve_comm); if (working) order = aorder; diff --git a/libsrc/meshing/global.cpp b/libsrc/meshing/global.cpp index e5036cde..988dc8e6 100644 --- a/libsrc/meshing/global.cpp +++ b/libsrc/meshing/global.cpp @@ -31,6 +31,9 @@ namespace netgen DLL_HEADER shared_ptr ng_geometry; // TraceGlobal glob2("global2"); + // global communicator for netgen + MPI_Comm ng_comm = MPI_COMM_WORLD; + weak_ptr global_mesh; void SetGlobalMesh (shared_ptr m) { diff --git a/libsrc/meshing/global.hpp b/libsrc/meshing/global.hpp index e6cb59de..9b1bbac7 100644 --- a/libsrc/meshing/global.hpp +++ b/libsrc/meshing/global.hpp @@ -59,6 +59,10 @@ namespace netgen DLL_HEADER extern weak_ptr global_mesh; DLL_HEADER void SetGlobalMesh (shared_ptr m); + + // global communicator for netgen (dummy if no MPI) + extern MPI_Comm ng_comm; + } #endif diff --git a/libsrc/meshing/meshclass.cpp b/libsrc/meshing/meshclass.cpp index 9e96a055..40c7c4e7 100644 --- a/libsrc/meshing/meshclass.cpp +++ b/libsrc/meshing/meshclass.cpp @@ -44,7 +44,7 @@ namespace netgen cd2names.SetSize(0); #ifdef PARALLEL - this->comm = MPI_COMM_WORLD; + this->comm = netgen :: ng_comm; paralleltop = new ParallelMeshTopology (*this); #endif } @@ -83,6 +83,12 @@ namespace netgen #endif } +#ifdef PARALLEL + void Mesh :: SetCommunicator(MPI_Comm acomm) + { + this->comm = acomm; + } +#endif Mesh & Mesh :: operator= (const Mesh & mesh2) { @@ -1321,6 +1327,15 @@ namespace netgen if (archive.Input()) { + int rank, ntasks; +#ifdef PARALLEL + MPI_Comm_size(this->comm, &ntasks); + MPI_Comm_rank(this->comm, &rank); +#else + rank = 0; + ntasks = 1; +#endif + RebuildSurfaceElementLists(); CalcSurfacesOfNode (); diff --git a/libsrc/meshing/meshclass.hpp b/libsrc/meshing/meshclass.hpp index 956946ce..e1659ca7 100644 --- a/libsrc/meshing/meshclass.hpp +++ b/libsrc/meshing/meshclass.hpp @@ -606,6 +606,11 @@ namespace netgen int AddEdgeDescriptor(const EdgeDescriptor & fd) { edgedecoding.Append(fd); return edgedecoding.Size() - 1; } +#ifdef PARALLEL + MPI_Comm GetCommunicator() const { return this->comm; } + void SetCommunicator(MPI_Comm acomm); +#endif + /// DLL_HEADER void SetMaterial (int domnr, const string & mat); /// diff --git a/libsrc/meshing/parallelmesh.cpp b/libsrc/meshing/parallelmesh.cpp index f574f1f6..e25bc8d8 100644 --- a/libsrc/meshing/parallelmesh.cpp +++ b/libsrc/meshing/parallelmesh.cpp @@ -35,9 +35,8 @@ namespace netgen void Mesh :: SendRecvMesh () { - int id, np; - MPI_Comm_rank(this->comm, &id); - MPI_Comm_size(this->comm, &np); + int id = MyMPI_GetId(GetCommunicator()); + int np = MyMPI_GetNTasks(GetCommunicator()); if (np == 1) { throw NgException("SendRecvMesh called, but only one rank in communicator!!"); @@ -72,17 +71,18 @@ namespace netgen void Mesh :: SendMesh () const { Array sendrequests; + + int id = MyMPI_GetId(GetCommunicator()); + int np = MyMPI_GetNTasks(GetCommunicator()); int dim = GetDimension(); - MyMPI_Bcast(dim); + MyMPI_Bcast(dim, comm); const_cast(GetTopology()).Update(); PrintMessage ( 3, "Sending nr of elements"); - MPI_Comm comm = this->comm; - Array num_els_on_proc(ntasks); num_els_on_proc = 0; for (ElementIndex ei = 0; ei < GetNE(); ei++) @@ -285,7 +285,7 @@ namespace netgen for (int dest = 1; dest < ntasks; dest++) { FlatArray verts = verts_of_proc[dest]; - sendrequests.Append (MyMPI_ISend (verts, dest, MPI_TAG_MESH+1)); + sendrequests.Append (MyMPI_ISend (verts, dest, MPI_TAG_MESH+1, comm)); MPI_Datatype mptype = MeshPoint::MyGetMPIType(); @@ -301,7 +301,7 @@ namespace netgen MPI_Type_commit (&newtype); MPI_Request request; - MPI_Isend( &points[0], 1, newtype, dest, MPI_TAG_MESH+1, MPI_COMM_WORLD, &request); + MPI_Isend( &points[0], 1, newtype, dest, MPI_TAG_MESH+1, comm, &request); sendrequests.Append (request); } @@ -367,7 +367,7 @@ namespace netgen } Array req_per; for(int dest = 1; dest < ntasks; dest++) - req_per.Append(MyMPI_ISend(pp_data[dest], dest, MPI_TAG_MESH+1)); + req_per.Append(MyMPI_ISend(pp_data[dest], dest, MPI_TAG_MESH+1, comm)); MPI_Waitall(req_per.Size(), &req_per[0], MPI_STATUS_IGNORE); PrintMessage ( 3, "Sending Vertices - distprocs"); @@ -395,7 +395,7 @@ namespace netgen } for ( int dest = 1; dest < ntasks; dest ++ ) - sendrequests.Append (MyMPI_ISend (distpnums[dest], dest, MPI_TAG_MESH+1)); + sendrequests.Append (MyMPI_ISend (distpnums[dest], dest, MPI_TAG_MESH+1, comm)); @@ -425,7 +425,7 @@ namespace netgen } for (int dest = 1; dest < ntasks; dest ++ ) - sendrequests.Append (MyMPI_ISend (elementarrays[dest], dest, MPI_TAG_MESH+2)); + sendrequests.Append (MyMPI_ISend (elementarrays[dest], dest, MPI_TAG_MESH+2, comm)); PrintMessage ( 3, "Sending Face Descriptors" ); @@ -442,7 +442,7 @@ namespace netgen } for (int dest = 1; dest < ntasks; dest++) - sendrequests.Append (MyMPI_ISend (fddata, dest, MPI_TAG_MESH+3)); + sendrequests.Append (MyMPI_ISend (fddata, dest, MPI_TAG_MESH+3, comm)); /** Surface Elements **/ @@ -526,7 +526,7 @@ namespace netgen }); // distribute sel data for (int dest = 1; dest < ntasks; dest++) - sendrequests.Append (MyMPI_ISend(selbuf[dest], dest, MPI_TAG_MESH+4)); + sendrequests.Append (MyMPI_ISend(selbuf[dest], dest, MPI_TAG_MESH+4, comm)); /** Segments **/ @@ -676,7 +676,7 @@ namespace netgen }); // distrubute segment data for (int dest = 1; dest < ntasks; dest++) - sendrequests.Append (MyMPI_ISend(segm_buf[dest], dest, MPI_TAG_MESH+5)); + sendrequests.Append (MyMPI_ISend(segm_buf[dest], dest, MPI_TAG_MESH+5, comm)); PrintMessage ( 3, "now wait ..."); @@ -700,9 +700,9 @@ namespace netgen compiled_bcnames[tot_bcsize++] = (*bcnames[k])[j]; for(int k=1;k(1, &nbcs), k, MPI_TAG_MESH+6); - sendrequests[6*(k-1)+1] = MyMPI_ISend(bcname_sizes, k, MPI_TAG_MESH+6); - (void) MPI_Isend(compiled_bcnames, tot_bcsize, MPI_CHAR, k, MPI_TAG_MESH+6, MPI_COMM_WORLD, &sendrequests[6*(k-1)+2]); + sendrequests[6*(k-1)] = MyMPI_ISend(FlatArray(1, &nbcs), k, MPI_TAG_MESH+6, comm); + sendrequests[6*(k-1)+1] = MyMPI_ISend(bcname_sizes, k, MPI_TAG_MESH+6, comm); + (void) MPI_Isend(compiled_bcnames, tot_bcsize, MPI_CHAR, k, MPI_TAG_MESH+6, comm, &sendrequests[6*(k-1)+2]); } /** Send mat-names **/ @@ -719,9 +719,9 @@ namespace netgen for(int j=0;j(1, &nmats), k, MPI_TAG_MESH+6); - sendrequests[6*(k-1)+4] = MyMPI_ISend(mat_sizes, k, MPI_TAG_MESH+6); - (void) MPI_Isend(compiled_mats, tot_matsize, MPI_CHAR, k, MPI_TAG_MESH+6, MPI_COMM_WORLD, &sendrequests[6*(k-1)+5]); + sendrequests[6*(k-1)+3] = MyMPI_ISend(FlatArray(1, &nmats), k, MPI_TAG_MESH+6, comm); + sendrequests[6*(k-1)+4] = MyMPI_ISend(mat_sizes, k, MPI_TAG_MESH+6, comm); + (void) MPI_Isend(compiled_mats, tot_matsize, MPI_CHAR, k, MPI_TAG_MESH+6, comm, &sendrequests[6*(k-1)+5]); } /* now wait ... **/ @@ -731,7 +731,7 @@ namespace netgen PrintMessage( 3, "send mesh complete"); - MPI_Barrier(MPI_COMM_WORLD); + MPI_Barrier(comm); } @@ -750,14 +750,17 @@ namespace netgen int timer_sels = NgProfiler::CreateTimer ("Receive surface elements"); NgProfiler::RegionTimer reg(timer); + int id = MyMPI_GetId(GetCommunicator()); + int np = MyMPI_GetNTasks(GetCommunicator()); + int dim; - MyMPI_Bcast(dim); + MyMPI_Bcast(dim, comm); SetDimension(dim); // Receive number of local elements int nelloc; MPI_Scatter (NULL, 0, MPI_INT, - &nelloc, 1, MPI_INT, 0, MPI_COMM_WORLD); + &nelloc, 1, MPI_INT, 0, comm); paralleltop -> SetNE (nelloc); // string st; @@ -766,8 +769,7 @@ namespace netgen NgProfiler::StartTimer (timer_pts); Array verts; - MyMPI_Recv (verts, 0, MPI_TAG_MESH+1); - + MyMPI_Recv (verts, 0, MPI_TAG_MESH+1, comm); int numvert = verts.Size(); paralleltop -> SetNV (numvert); @@ -787,11 +789,10 @@ namespace netgen MPI_Datatype mptype = MeshPoint::MyGetMPIType(); MPI_Status status; - MPI_Recv( &points[1], numvert, mptype, 0, MPI_TAG_MESH+1, MPI_COMM_WORLD, &status); + MPI_Recv( &points[1], numvert, mptype, 0, MPI_TAG_MESH+1, comm, &status); Array pp_data; - MyMPI_Recv(pp_data, 0, MPI_TAG_MESH+1); - + MyMPI_Recv(pp_data, 0, MPI_TAG_MESH+1, comm); int maxidentnr = pp_data[0]; auto & idents = GetIdentifications(); @@ -815,7 +816,7 @@ namespace netgen } Array dist_pnums; - MyMPI_Recv (dist_pnums, 0, MPI_TAG_MESH+1); + MyMPI_Recv (dist_pnums, 0, MPI_TAG_MESH+1, comm); for (int hi = 0; hi < dist_pnums.Size(); hi += 3) paralleltop -> @@ -828,7 +829,7 @@ namespace netgen Element el; Array elarray; - MyMPI_Recv (elarray, 0, MPI_TAG_MESH+2); + MyMPI_Recv (elarray, 0, MPI_TAG_MESH+2, comm); NgProfiler::RegionTimer reg(timer_els); @@ -848,7 +849,7 @@ namespace netgen { Array fddata; - MyMPI_Recv (fddata, 0, MPI_TAG_MESH+3); + MyMPI_Recv (fddata, 0, MPI_TAG_MESH+3, comm); for (int i = 0; i < fddata.Size(); i += 6) { int faceind = AddFaceDescriptor @@ -863,7 +864,7 @@ namespace netgen NgProfiler::RegionTimer reg(timer_sels); Array selbuf; - MyMPI_Recv ( selbuf, 0, MPI_TAG_MESH+4); + MyMPI_Recv ( selbuf, 0, MPI_TAG_MESH+4, comm); int ii = 0; int sel = 0; @@ -894,7 +895,7 @@ namespace netgen { Array segmbuf; - MyMPI_Recv ( segmbuf, 0, MPI_TAG_MESH+5); + MyMPI_Recv ( segmbuf, 0, MPI_TAG_MESH+5, comm); Segment seg; int globsegi; @@ -939,14 +940,14 @@ namespace netgen /** Recv bc-names **/ int nbcs; - MyMPI_Recv(nbcs, 0, MPI_TAG_MESH+6); + MyMPI_Recv(nbcs, 0, MPI_TAG_MESH+6, comm); Array bcs(nbcs); - MyMPI_Recv(bcs, 0, MPI_TAG_MESH+6); + MyMPI_Recv(bcs, 0, MPI_TAG_MESH+6, comm); int size_bc = 0; for(int k=0;k matsz(nmats); - MyMPI_Recv(matsz, 0, MPI_TAG_MESH+6); + MyMPI_Recv(matsz, 0, MPI_TAG_MESH+6, comm); int size_mats = 0; for(int k=0;kcomm; + MPI_Comm_size(comm, &ntasks); + MPI_Comm_rank(comm, &id); if (id != 0 || ntasks == 1 ) return; @@ -1120,12 +1122,9 @@ namespace netgen for (SurfaceElementIndex sei = 0; sei < GetNSE(); sei++) { const Element2d & el = (*this)[sei]; - cout << "surf-el " << sei << " verts: " << endl; for (int j = 0; j < el.GetNP(); j++) { - cout << el[j] << " "; f(el[j], sei); } - cout << endl; } }; auto loop_els_3d = [&](auto f) { @@ -1150,7 +1149,6 @@ namespace netgen if(boundarypoints[vertex]) cnt[vertex]++; }); - cout << "count: " << endl << cnt << endl; TABLE pnt2el(cnt); loop_els([&](auto vertex, int index) { @@ -1277,8 +1275,9 @@ namespace netgen // call it only for the master ! void Mesh :: Distribute (Array & volume_weights , Array & surface_weights, Array & segment_weights) { - MPI_Comm_size(MPI_COMM_WORLD, &ntasks); - MPI_Comm_rank(MPI_COMM_WORLD, &id); + MPI_Comm comm = this->comm; + MPI_Comm_size(comm, &ntasks); + MPI_Comm_rank(comm, &id); if (id != 0 || ntasks == 1 ) return; diff --git a/libsrc/meshing/paralleltop.cpp b/libsrc/meshing/paralleltop.cpp index 80c70121..0f67bddc 100644 --- a/libsrc/meshing/paralleltop.cpp +++ b/libsrc/meshing/paralleltop.cpp @@ -24,12 +24,19 @@ namespace netgen void ParallelMeshTopology :: Reset () { *testout << "ParallelMeshTopology::Reset" << endl; + + int id = MyMPI_GetId(mesh.GetCommunicator()); + int ntasks = MyMPI_GetNTasks(mesh.GetCommunicator()); if ( ntasks == 1 ) return; + cout << "Reset CG, this = " << this << " , mesh: " << &mesh << endl; + int ned = mesh.GetTopology().GetNEdges(); int nfa = mesh.GetTopology().GetNFaces(); + cout << "nnodes : " << mesh.GetNV() << " " << ned << " " << nfa << endl; + if (glob_edge.Size() != ned) { glob_edge.SetSize(ned); @@ -206,6 +213,11 @@ namespace netgen // cout << "UpdateCoarseGrid" << endl; // if (is_updated) return; + int id = MyMPI_GetId(mesh.GetCommunicator()); + int ntasks = MyMPI_GetNTasks(mesh.GetCommunicator()); + + cout << "Update CG, this = " << this << " , mesh: " << &mesh << endl; + Reset(); static int timer = NgProfiler::CreateTimer ("UpdateCoarseGrid"); NgProfiler::RegionTimer reg(timer); From 012d27d41e179dbf7d736d65e07b5fe2cf61b1d1 Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 29 Jan 2019 19:37:58 +0100 Subject: [PATCH 69/98] Fix paralleltop. Clean up mesh loading. --- libsrc/include/nginterface_v2.hpp | 19 ++++++------- libsrc/interface/nginterface_v2.cpp | 43 +++++++++-------------------- libsrc/meshing/paralleltop.cpp | 13 +++++---- 3 files changed, 29 insertions(+), 46 deletions(-) diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index fdfaa22f..184f3eb2 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -249,29 +249,28 @@ namespace netgen { private: shared_ptr mesh; -#ifdef PARALLEL - MPI_Comm comm; -#endif public: // Ngx_Mesh () { ; } // Ngx_Mesh(class Mesh * amesh) : mesh(amesh) { ; } - Ngx_Mesh(shared_ptr amesh = NULL); - void LoadMesh (const string & filename); - void LoadMesh (istream & str); + /** reuse a netgen-mesh **/ + Ngx_Mesh (shared_ptr amesh); + /** load a new mesh **/ + Ngx_Mesh (string filename, MPI_Comm acomm = netgen::ng_comm); + + void LoadMesh (const string & filename, MPI_Comm comm = netgen::ng_comm); + + void LoadMesh (istream & str, MPI_Comm comm = netgen::ng_comm); void SaveMesh (ostream & str) const; void UpdateTopology (); void DoArchive (Archive & archive); -#ifdef PARALLEL MPI_Comm GetCommunicator() const; - void SetCommunicator(MPI_Comm acomm); -#endif virtual ~Ngx_Mesh(); - bool Valid () { return mesh != NULL; } + bool Valid () const { return mesh != NULL; } int GetDimension() const; int GetNLevels() const; diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index adeefe28..80843705 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -31,56 +31,39 @@ namespace netgen return hmesh; } - - Ngx_Mesh :: Ngx_Mesh (shared_ptr amesh) - { - if (amesh) { - mesh = amesh; - comm = amesh->GetCommunicator(); - } - else { - mesh = netgen::mesh; - comm = netgen::ng_comm; - } - } - -#ifdef PARALLEL - void Ngx_Mesh :: SetCommunicator (MPI_Comm acomm) - { - if (Valid() && acomm!=mesh->GetCommunicator()) - throw NgException("Redistribution of mesh not possible!"); - this->comm = acomm; - } - - - MPI_Comm Ngx_Mesh :: GetCommunicator() const - { return comm; } -#endif + Ngx_Mesh :: Ngx_Mesh (shared_ptr amesh) + { mesh = amesh ? amesh : netgen::mesh; } + Ngx_Mesh :: Ngx_Mesh (string filename, MPI_Comm acomm) + { LoadMesh(filename, acomm); } - Ngx_Mesh * LoadMesh (const string & filename) + Ngx_Mesh * LoadMesh (const string & filename, MPI_Comm comm = netgen::ng_comm) { netgen::mesh.reset(); - Ng_LoadMesh (filename.c_str(), netgen::ng_comm); + Ng_LoadMesh (filename.c_str(), comm); return new Ngx_Mesh (netgen::mesh); } - void Ngx_Mesh :: LoadMesh (const string & filename) + void Ngx_Mesh :: LoadMesh (const string & filename, MPI_Comm comm) { netgen::mesh.reset(); - Ng_LoadMesh (filename.c_str(), this->comm); + Ng_LoadMesh (filename.c_str(), comm); // mesh = move(netgen::mesh); mesh = netgen::mesh; } - void Ngx_Mesh :: LoadMesh (istream & ist) + void Ngx_Mesh :: LoadMesh (istream & ist, MPI_Comm comm) { netgen::mesh = make_shared(); + netgen::mesh->SetCommunicator(comm); netgen::mesh -> Load (ist); // mesh = move(netgen::mesh); mesh = netgen::mesh; SetGlobalMesh (mesh); } + MPI_Comm Ngx_Mesh :: GetCommunicator() const + { return Valid() ? mesh->GetCommunicator() : MPI_COMM_NULL; } + void Ngx_Mesh :: SaveMesh (ostream & ost) const { mesh -> Save (ost); diff --git a/libsrc/meshing/paralleltop.cpp b/libsrc/meshing/paralleltop.cpp index 0f67bddc..34c51c69 100644 --- a/libsrc/meshing/paralleltop.cpp +++ b/libsrc/meshing/paralleltop.cpp @@ -213,8 +213,9 @@ namespace netgen // cout << "UpdateCoarseGrid" << endl; // if (is_updated) return; - int id = MyMPI_GetId(mesh.GetCommunicator()); - int ntasks = MyMPI_GetNTasks(mesh.GetCommunicator()); + MPI_Comm comm = mesh.GetCommunicator(); + int id = MyMPI_GetId(comm); + int ntasks = MyMPI_GetNTasks(comm); cout << "Update CG, this = " << this << " , mesh: " << &mesh << endl; @@ -234,14 +235,14 @@ namespace netgen // MPI_Barrier (MPI_COMM_WORLD); - MPI_Group MPI_GROUP_WORLD; + MPI_Group MPI_GROUP_comm; MPI_Group MPI_LocalGroup; MPI_Comm MPI_LocalComm; int process_ranks[] = { 0 }; - MPI_Comm_group (MPI_COMM_WORLD, &MPI_GROUP_WORLD); - MPI_Group_excl (MPI_GROUP_WORLD, 1, process_ranks, &MPI_LocalGroup); - MPI_Comm_create (MPI_COMM_WORLD, MPI_LocalGroup, &MPI_LocalComm); + MPI_Comm_group (comm, &MPI_GROUP_comm); + MPI_Group_excl (MPI_GROUP_comm, 1, process_ranks, &MPI_LocalGroup); + MPI_Comm_create (comm, MPI_LocalGroup, &MPI_LocalComm); if (id == 0) return; From ff847e6eff2b8d2bb90a16583f611c5bf1d19e59 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 30 Jan 2019 11:24:35 +0100 Subject: [PATCH 70/98] Without MPI, the mesh now has dummy-implementations for Distribute, SendRecvMesh, Get- and SetCommunicator. --- libsrc/meshing/meshclass.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libsrc/meshing/meshclass.hpp b/libsrc/meshing/meshclass.hpp index e1659ca7..e855c3f2 100644 --- a/libsrc/meshing/meshclass.hpp +++ b/libsrc/meshing/meshclass.hpp @@ -32,10 +32,8 @@ namespace netgen /// point coordinates T_POINTS points; -#ifdef PARALLEL - // The communicator for this mesh. (more or less dummy for now!) + // The communicator for this mesh. Just a dummy if compiled without MPI. MPI_Comm comm; -#endif /// line-segments at edges Array segments; @@ -606,10 +604,8 @@ namespace netgen int AddEdgeDescriptor(const EdgeDescriptor & fd) { edgedecoding.Append(fd); return edgedecoding.Size() - 1; } -#ifdef PARALLEL MPI_Comm GetCommunicator() const { return this->comm; } void SetCommunicator(MPI_Comm acomm); -#endif /// DLL_HEADER void SetMaterial (int domnr, const string & mat); @@ -863,7 +859,11 @@ namespace netgen void SendMesh ( ) const; // Mesh * mastermesh, Array & neloc) const; /// loads a mesh sent from master processor void ReceiveParallelMesh (); - +#else + void Distribute () {} + void SendRecvMesh () {} + void Distribute (Array & volume_weights, Array & surface_weights, + Array & segment_weights){ } #endif From 0f4ca1c7a7e6f5daf316b25a949fabcc517106cb Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 30 Jan 2019 11:27:21 +0100 Subject: [PATCH 71/98] Fewer ifdefs for MPI. More consistent use of mpi_interface instead of direct MPI calls. --- libsrc/general/mpi_interface.hpp | 18 ++++++++++++------ libsrc/include/nginterface.h | 3 +++ libsrc/interface/nginterface.cpp | 19 ++++++++++--------- libsrc/meshing/meshclass.cpp | 14 +++----------- libsrc/meshing/parallelmesh.cpp | 25 +++++++++++++------------ 5 files changed, 41 insertions(+), 38 deletions(-) diff --git a/libsrc/general/mpi_interface.hpp b/libsrc/general/mpi_interface.hpp index d293480f..880abc4b 100644 --- a/libsrc/general/mpi_interface.hpp +++ b/libsrc/general/mpi_interface.hpp @@ -19,15 +19,17 @@ namespace netgen #ifndef PARALLEL typedef int MPI_Comm; - enum { MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 0}; - - inline int MyMPI_GetNTasks (MPI_Comm comm = ng_comm) { return 1; } - inline int MyMPI_GetId (MPI_Comm comm = ng_comm) { return 0; } - #endif /** This is the "standard" communicator that will be used for netgen-objects. **/ extern MPI_Comm ng_comm; + +#ifndef PARALLEL + enum { MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 0}; + inline int MyMPI_GetNTasks (MPI_Comm comm = ng_comm) { return 1; } + inline int MyMPI_GetId (MPI_Comm comm = ng_comm) { return 0; } +#endif + #ifdef PARALLEL @@ -61,6 +63,10 @@ namespace netgen inline MPI_Datatype MyGetMPIType ( ) { return MPI_DOUBLE; } + template <> + inline MPI_Datatype MyGetMPIType ( ) + { return MPI_CHAR; } + inline void MyMPI_Send (int i, int dest, int tag, MPI_Comm comm = ng_comm) { @@ -284,7 +290,7 @@ namespace netgen { int size = s.Size(); MyMPI_Bcast (size, comm); - if (id != 0) s.SetSize (size); + if (MyMPI_GetId(comm) != 0) s.SetSize (size); MPI_Bcast (&s[0], size, MyGetMPIType(), 0, comm); } diff --git a/libsrc/include/nginterface.h b/libsrc/include/nginterface.h index f299efe9..254734ce 100644 --- a/libsrc/include/nginterface.h +++ b/libsrc/include/nginterface.h @@ -37,6 +37,9 @@ // max number of nodes per surface element #define NG_SURFACE_ELEMENT_MAXPOINTS 8 +#ifndef PARALLEL + typedef int MPI_Comm; +#endif namespace netgen { extern MPI_Comm ng_comm; } diff --git a/libsrc/interface/nginterface.cpp b/libsrc/interface/nginterface.cpp index bd3bd712..08be9458 100644 --- a/libsrc/interface/nginterface.cpp +++ b/libsrc/interface/nginterface.cpp @@ -141,7 +141,7 @@ void Ng_LoadMesh (const char * filename, MPI_Comm comm) } istream * infile; - char* buf; // for distributing geometry! + Array buf; // for distributing geometry! int strs; if( id == 0) { @@ -162,8 +162,9 @@ void Ng_LoadMesh (const char * filename, MPI_Comm comm) geom_part << infile->rdbuf(); string geom_part_string = geom_part.str(); strs = geom_part_string.size(); - buf = new char[strs]; - memcpy(buf, geom_part_string.c_str(), strs*sizeof(char)); + // buf = new char[strs]; + buf.SetSize(strs); + memcpy(&buf[0], geom_part_string.c_str(), strs*sizeof(char)); } delete infile; @@ -238,15 +239,15 @@ void Ng_LoadMesh (const char * filename, MPI_Comm comm) } if(!ng_geometry && ntasks>1) { - /** Scatter the geometry-string **/ - MPI_Bcast(&strs, 1, MPI_INT, 0, comm); - if(id!=0) buf = new char[strs]; - MPI_Bcast(buf, strs, MPI_CHAR, 0, comm); +#ifdef PARALLEL + /** Scatter the geometry-string (no dummy-implementation in mpi_interface) **/ + MyMPI_Bcast(buf, comm); +#endif } if(!ng_geometry) { - infile = new istringstream(string((const char*)buf, (size_t)strs)); - delete[] buf; + infile = new istringstream(string((const char*)&buf[0], (size_t)strs)); + // delete[] buf; for (int i = 0; i < geometryregister.Size(); i++) { NetgenGeometry * hgeom = geometryregister[i]->LoadFromMeshFile (*infile); diff --git a/libsrc/meshing/meshclass.cpp b/libsrc/meshing/meshclass.cpp index 40c7c4e7..545a8f51 100644 --- a/libsrc/meshing/meshclass.cpp +++ b/libsrc/meshing/meshclass.cpp @@ -43,8 +43,8 @@ namespace netgen bcnames.SetSize(0); cd2names.SetSize(0); -#ifdef PARALLEL this->comm = netgen :: ng_comm; +#ifdef PARALLEL paralleltop = new ParallelMeshTopology (*this); #endif } @@ -83,12 +83,10 @@ namespace netgen #endif } -#ifdef PARALLEL void Mesh :: SetCommunicator(MPI_Comm acomm) { this->comm = acomm; } -#endif Mesh & Mesh :: operator= (const Mesh & mesh2) { @@ -1327,14 +1325,8 @@ namespace netgen if (archive.Input()) { - int rank, ntasks; -#ifdef PARALLEL - MPI_Comm_size(this->comm, &ntasks); - MPI_Comm_rank(this->comm, &rank); -#else - rank = 0; - ntasks = 1; -#endif + int rank = MyMPI_GetId(GetCommunicator()); + int ntasks = MyMPI_GetNTasks(GetCommunicator()); RebuildSurfaceElementLists(); diff --git a/libsrc/meshing/parallelmesh.cpp b/libsrc/meshing/parallelmesh.cpp index e25bc8d8..f6db82bf 100644 --- a/libsrc/meshing/parallelmesh.cpp +++ b/libsrc/meshing/parallelmesh.cpp @@ -71,9 +71,10 @@ namespace netgen void Mesh :: SendMesh () const { Array sendrequests; - - int id = MyMPI_GetId(GetCommunicator()); - int np = MyMPI_GetNTasks(GetCommunicator()); + + MPI_Comm comm = GetCommunicator(); + int id = MyMPI_GetId(comm); + int ntasks = MyMPI_GetNTasks(comm); int dim = GetDimension(); MyMPI_Bcast(dim, comm); @@ -751,7 +752,7 @@ namespace netgen NgProfiler::RegionTimer reg(timer); int id = MyMPI_GetId(GetCommunicator()); - int np = MyMPI_GetNTasks(GetCommunicator()); + int ntasks = MyMPI_GetNTasks(GetCommunicator()); int dim; MyMPI_Bcast(dim, comm); @@ -1009,9 +1010,9 @@ namespace netgen // call it only for the master ! void Mesh :: Distribute () { - MPI_Comm comm = this->comm; - MPI_Comm_size(comm, &ntasks); - MPI_Comm_rank(comm, &id); + MPI_Comm comm = GetCommunicator(); + int id = MyMPI_GetId(comm); + int ntasks = MyMPI_GetNTasks(comm); if (id != 0 || ntasks == 1 ) return; @@ -1070,7 +1071,7 @@ namespace netgen eptr.Append (eind.Size()); Array epart(ne), npart(nn); - idxtype nparts = ntasks-1; + idxtype nparts = MyMPI_GetNTasks(GetCommunicator())-1; idxtype edgecut; idxtype ncommon = 3; @@ -1275,9 +1276,9 @@ namespace netgen // call it only for the master ! void Mesh :: Distribute (Array & volume_weights , Array & surface_weights, Array & segment_weights) { - MPI_Comm comm = this->comm; - MPI_Comm_size(comm, &ntasks); - MPI_Comm_rank(comm, &id); + MPI_Comm comm = GetCommunicator(); + int id = MyMPI_GetId(comm); + int ntasks = MyMPI_GetNTasks(comm); if (id != 0 || ntasks == 1 ) return; @@ -1367,7 +1368,7 @@ namespace netgen eptr.Append (eind.Size()); Array epart(ne), npart(nn); - idxtype nparts = ntasks-1; + idxtype nparts = MyMPI_GetNTasks(GetCommunicator())-1; idxtype edgecut; From ee24e786affa17ef133be0c6d57e07f84b7de610 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 30 Jan 2019 16:44:22 +0100 Subject: [PATCH 72/98] use global communicator in python-mesh --- libsrc/meshing/python_mesh.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 6d7760a4..11ba4a7c 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -506,6 +506,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) .def(py::init( [] (int dim) { auto mesh = make_shared(); + mesh->SetCommunicator(netgen::ng_comm); mesh -> SetDimension(dim); SetGlobalMesh(mesh); // for visualization mesh -> SetGeometry (nullptr); @@ -533,8 +534,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) istream * infile; #ifdef PARALLEL - MPI_Comm_rank(MPI_COMM_WORLD, &id); - MPI_Comm_size(MPI_COMM_WORLD, &ntasks); + MPI_Comm_rank(netgen::ng_comm, &id); + MPI_Comm_size(netgen::ng_comm, &ntasks); char* buf = nullptr; int strs = 0; From bc77c763ae284cc32c66e0602ec712ffc8a313ea Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 30 Jan 2019 20:53:03 +0100 Subject: [PATCH 73/98] remove couts --- libsrc/meshing/paralleltop.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/libsrc/meshing/paralleltop.cpp b/libsrc/meshing/paralleltop.cpp index 34c51c69..346b5e25 100644 --- a/libsrc/meshing/paralleltop.cpp +++ b/libsrc/meshing/paralleltop.cpp @@ -30,13 +30,9 @@ namespace netgen if ( ntasks == 1 ) return; - cout << "Reset CG, this = " << this << " , mesh: " << &mesh << endl; - int ned = mesh.GetTopology().GetNEdges(); int nfa = mesh.GetTopology().GetNFaces(); - cout << "nnodes : " << mesh.GetNV() << " " << ned << " " << nfa << endl; - if (glob_edge.Size() != ned) { glob_edge.SetSize(ned); @@ -217,8 +213,6 @@ namespace netgen int id = MyMPI_GetId(comm); int ntasks = MyMPI_GetNTasks(comm); - cout << "Update CG, this = " << this << " , mesh: " << &mesh << endl; - Reset(); static int timer = NgProfiler::CreateTimer ("UpdateCoarseGrid"); NgProfiler::RegionTimer reg(timer); From da5c9723d11ad457c1af9a7806bc6fc9c13ef856 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 30 Jan 2019 20:54:25 +0100 Subject: [PATCH 74/98] fix maxsegmentindex being off by one --- libsrc/geom2d/genmesh2d.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/geom2d/genmesh2d.cpp b/libsrc/geom2d/genmesh2d.cpp index 43193e3a..b42440ce 100644 --- a/libsrc/geom2d/genmesh2d.cpp +++ b/libsrc/geom2d/genmesh2d.cpp @@ -457,9 +457,9 @@ namespace netgen for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) if ( (*mesh)[si].si > maxsegmentindex) maxsegmentindex = (*mesh)[si].si; - mesh->SetNBCNames(maxsegmentindex+1); + mesh->SetNBCNames(maxsegmentindex); - for ( int sindex = 0; sindex <= maxsegmentindex; sindex++ ) + for ( int sindex = 0; sindex < maxsegmentindex; sindex++ ) mesh->SetBCName ( sindex, geometry.GetBCName( sindex+1 ) ); for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) From 214b5c452da4047f51dbd4dbab9f63056a870298 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 30 Jan 2019 20:55:45 +0100 Subject: [PATCH 75/98] Wrap MPI-communicator on netgen side --- libsrc/general/mpi_interface.hpp | 94 +++++++++++++++++++++++--------- libsrc/meshing/python_mesh.cpp | 91 ++++++++++++++++++++++++++++--- 2 files changed, 150 insertions(+), 35 deletions(-) diff --git a/libsrc/general/mpi_interface.hpp b/libsrc/general/mpi_interface.hpp index 880abc4b..593d290a 100644 --- a/libsrc/general/mpi_interface.hpp +++ b/libsrc/general/mpi_interface.hpp @@ -18,56 +18,98 @@ namespace netgen using ngcore::ntasks; #ifndef PARALLEL + /** without MPI, we need a dummy typedef **/ typedef int MPI_Comm; #endif /** This is the "standard" communicator that will be used for netgen-objects. **/ extern MPI_Comm ng_comm; -#ifndef PARALLEL - enum { MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 0}; - inline int MyMPI_GetNTasks (MPI_Comm comm = ng_comm) { return 1; } - inline int MyMPI_GetId (MPI_Comm comm = ng_comm) { return 0; } -#endif - - #ifdef PARALLEL - inline int MyMPI_GetNTasks (MPI_Comm comm = ng_comm) { int ntasks; MPI_Comm_size(comm, &ntasks); return ntasks; } - inline int MyMPI_GetId (MPI_Comm comm = ng_comm) { int id; MPI_Comm_rank(comm, &id); return id; } +#else + enum { MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 0}; + inline int MyMPI_GetNTasks (MPI_Comm comm = ng_comm) { return 1; } + inline int MyMPI_GetId (MPI_Comm comm = ng_comm) { return 0; } +#endif +#ifdef PARALLEL + // For python wrapping of communicators + struct PyMPI_Comm { + MPI_Comm comm; + bool owns_comm; + PyMPI_Comm (MPI_Comm _comm, bool _owns_comm = false) : comm(_comm), owns_comm(_owns_comm) { } + PyMPI_Comm (const PyMPI_Comm & c) = delete; + ~PyMPI_Comm () { + if (owns_comm) + MPI_Comm_free(&comm); + } + inline int Rank() const { return MyMPI_GetId(comm); } + inline int Size() const { return MyMPI_GetNTasks(comm); } + }; +#else + // dummy without MPI + struct PyMPI_Comm { + MPI_Comm comm = 0; + PyMPI_Comm (MPI_Comm _comm, bool _owns_comm = false) { } + ~PyMPI_Comm () { } + inline int Rank() const { return 0; } + inline int Size() const { return 1; } + }; +#endif + +#ifdef PARALLEL + template + inline MPI_Datatype MyGetMPIType ( ) + { cerr << "ERROR in GetMPIType() -- no type found" << endl;return 0; } + template <> + inline MPI_Datatype MyGetMPIType ( ) + { return MPI_INT; } + template <> + inline MPI_Datatype MyGetMPIType ( ) + { return MPI_DOUBLE; } + template <> + inline MPI_Datatype MyGetMPIType ( ) + { return MPI_CHAR; } + template<> + inline MPI_Datatype MyGetMPIType ( ) + { return MPI_UINT64_T; } +#else + typedef int MPI_Datatype; + template inline MPI_Datatype MyGetMPIType ( ) { return 0; } +#endif + +#ifdef PARALLEL + inline MPI_Comm MyMPI_SubCommunicator(MPI_Comm comm, Array & procs) + { + MPI_Comm subcomm; + MPI_Group gcomm, gsubcomm; + MPI_Comm_group(comm, &gcomm); + MPI_Group_incl(gcomm, procs.Size(), &(procs[0]), &gsubcomm); + MPI_Comm_create_group(comm, gsubcomm, 6969, &subcomm); + return subcomm; + } +#else + inline MPI_Comm MyMPI_SubCommunicator(MPI_Comm comm, Array & procs) + { return comm; } +#endif + +#ifdef PARALLEL enum { MPI_TAG_CMD = 110 }; enum { MPI_TAG_MESH = 210 }; enum { MPI_TAG_VIS = 310 }; - template - MPI_Datatype MyGetMPIType ( ) - { cerr << "ERROR in GetMPIType() -- no type found" << endl;return 0; } - - template <> - inline MPI_Datatype MyGetMPIType ( ) - { return MPI_INT; } - - template <> - inline MPI_Datatype MyGetMPIType ( ) - { return MPI_DOUBLE; } - - template <> - inline MPI_Datatype MyGetMPIType ( ) - { return MPI_CHAR; } - - inline void MyMPI_Send (int i, int dest, int tag, MPI_Comm comm = ng_comm) { int hi = i; diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 11ba4a7c..dbc498cb 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -17,6 +17,22 @@ namespace netgen { extern bool netgen_executable_started; extern shared_ptr ng_geometry; +#ifdef PARALLEL + /** we need allreduce in python-wrapped communicators **/ + template + inline T MyMPI_AllReduceNG (T d, const MPI_Op & op = MPI_SUM, MPI_Comm comm = ng_comm) + { + T global_d; + MPI_Allreduce ( &d, &global_d, 1, MyGetMPIType(), op, comm); + return global_d; + } +#else + enum { MPI_SUM = 0, MPI_MIN = 1, MPI_MAX = 2 }; + typedef int MPI_Op; + template + inline T MyMPI_AllReduceNG (T d, const MPI_Op & op = MPI_SUM, MPI_Comm comm = ng_comm) + { return d; } +#endif } @@ -503,19 +519,21 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) py::class_>(m, "Mesh") // .def(py::init<>("create empty mesh")) - .def(py::init( [] (int dim) + .def(py::init( [] (int dim, shared_ptr pycomm) { auto mesh = make_shared(); - mesh->SetCommunicator(netgen::ng_comm); + mesh->SetCommunicator(pycomm!=nullptr ? pycomm->comm : netgen::ng_comm); mesh -> SetDimension(dim); SetGlobalMesh(mesh); // for visualization mesh -> SetGeometry (nullptr); return mesh; } ), - py::arg("dim")=3 + py::arg("dim")=3, py::arg("comm")=nullptr ) .def(NGSPickle()) - + .def_property_readonly("comm", [](const Mesh & amesh) + { return make_shared(amesh.GetCommunicator()); }, + "MPI-communicator the Mesh lives in") /* .def("__init__", [](Mesh *instance, int dim) @@ -528,15 +546,25 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) */ .def_property_readonly("_timestamp", &Mesh::GetTimeStamp) + .def("Distribute", [](Mesh & self, shared_ptr pycomm) { + MPI_Comm comm = pycomm!=nullptr ? pycomm->comm : self.GetCommunicator(); + self.SetCommunicator(comm); + if(MyMPI_GetNTasks(comm)==1) return; + if(MyMPI_GetNTasks(comm)==2) throw NgException("Sorry, cannot handle communicators with NP=2!"); + cout << " rank " << MyMPI_GetId(comm) << " of " << MyMPI_GetNTasks(comm) << " called Distribute " << endl; + if(MyMPI_GetId(comm)==0) self.Distribute(); + else self.SendRecvMesh(); + }, py::arg("comm")=nullptr) .def("Load", FunctionPointer ([](Mesh & self, const string & filename) { istream * infile; + MPI_Comm comm = self.GetCommunicator(); + id = MyMPI_GetId(comm); + ntasks = MyMPI_GetNTasks(comm); + #ifdef PARALLEL - MPI_Comm_rank(netgen::ng_comm, &id); - MPI_Comm_size(netgen::ng_comm, &ntasks); - char* buf = nullptr; int strs = 0; if(id==0) { @@ -564,10 +592,10 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) } /** Scatter the geometry-string **/ - MPI_Bcast(&strs, 1, MPI_INT, 0, MPI_COMM_WORLD); + MPI_Bcast(&strs, 1, MPI_INT, 0, comm); if(id!=0) buf = new char[strs]; - MPI_Bcast(buf, strs, MPI_CHAR, 0, MPI_COMM_WORLD); + MPI_Bcast(buf, strs, MPI_CHAR, 0, comm); if(id==0) delete infile; infile = new istringstream(string((const char*)buf, (size_t)strs)); @@ -922,6 +950,51 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) printmessage_importance = importance; return old; })); + + py::class_> (m, "MPI_Comm") + .def_property_readonly ("rank", &PyMPI_Comm::Rank) + .def_property_readonly ("size", &PyMPI_Comm::Size) + // .def_property_readonly ("rank", [](PyMPI_Comm & c) { cout << "rank for " << c.comm << endl; return c.Rank(); }) + // .def_property_readonly ("size", [](PyMPI_Comm & c) { cout << "size for " << c.comm << endl; return c.Size(); }) +#ifdef PARALLEL + .def("Barrier", [](PyMPI_Comm & c) { MPI_Barrier(c.comm); }) + .def("WTime", [](PyMPI_Comm & c) { return MPI_Wtime(); }) +#else + .def("Barrier", [](PyMPI_Comm & c) { }) + .def("WTime", [](PyMPI_Comm & c) { return -1.0; }) +#endif + .def("Sum", [](PyMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_SUM, c.comm); }) + .def("Min", [](PyMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_MIN, c.comm); }) + .def("Max", [](PyMPI_Comm & c, double x) { return MyMPI_AllReduceNG(x, MPI_MAX, c.comm); }) + .def("Sum", [](PyMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_SUM, c.comm); }) + .def("Min", [](PyMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_MIN, c.comm); }) + .def("Max", [](PyMPI_Comm & c, int x) { return MyMPI_AllReduceNG(x, MPI_MAX, c.comm); }) + .def("Sum", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_SUM, c.comm); }) + .def("Min", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MIN, c.comm); }) + .def("Max", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MAX, c.comm); }) + .def("SubComm", [](PyMPI_Comm & c, py::list proc_list) -> shared_ptr { + Array procs; + if (py::extract (proc_list).check()) { + py::list pylist = py::extract (proc_list)(); + procs.SetSize(py::len(pylist)); + for (int i = 0; i < py::len(pylist); i++) + procs[i] = py::extract(pylist[i])(); + } + else { + throw Exception("SubComm needs a list!"); + } + if(!procs.Size()) { + cout << "warning, tried to construct empty communicator, returning MPI_COMM_NULL" << endl; + return make_shared(MPI_COMM_NULL); + } + else if(procs.Size()==2) { + throw Exception("Sorry, NGSolve cannot handle NP=2."); + } + MPI_Comm subcomm = MyMPI_SubCommunicator(c.comm, procs); + return make_shared(subcomm, true); + }, py::arg("procs")); + ; + } PYBIND11_MODULE(libmesh, m) { From 7b5c69f9935d47038e42431a5efbf87568a879fe Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 30 Jan 2019 20:54:25 +0100 Subject: [PATCH 76/98] fix maxsegmentindex being off by one --- libsrc/geom2d/genmesh2d.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/geom2d/genmesh2d.cpp b/libsrc/geom2d/genmesh2d.cpp index 43193e3a..b42440ce 100644 --- a/libsrc/geom2d/genmesh2d.cpp +++ b/libsrc/geom2d/genmesh2d.cpp @@ -457,9 +457,9 @@ namespace netgen for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) if ( (*mesh)[si].si > maxsegmentindex) maxsegmentindex = (*mesh)[si].si; - mesh->SetNBCNames(maxsegmentindex+1); + mesh->SetNBCNames(maxsegmentindex); - for ( int sindex = 0; sindex <= maxsegmentindex; sindex++ ) + for ( int sindex = 0; sindex < maxsegmentindex; sindex++ ) mesh->SetBCName ( sindex, geometry.GetBCName( sindex+1 ) ); for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++) From 17a457c1fc3145992cfa42e8a2675ee60128050b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 31 Jan 2019 18:41:20 +0100 Subject: [PATCH 77/98] timers --- libsrc/meshing/delaunay.cpp | 6 ++++- libsrc/meshing/improve3.cpp | 8 ++++++ libsrc/meshing/meshclass.hpp | 6 ++--- libsrc/meshing/meshfunc.cpp | 6 +++++ libsrc/meshing/meshing3.cpp | 49 +++++++++++++++++------------------ libsrc/meshing/smoothing3.cpp | 2 ++ 6 files changed, 48 insertions(+), 29 deletions(-) diff --git a/libsrc/meshing/delaunay.cpp b/libsrc/meshing/delaunay.cpp index bf0a5174..cf12f536 100644 --- a/libsrc/meshing/delaunay.cpp +++ b/libsrc/meshing/delaunay.cpp @@ -602,7 +602,9 @@ namespace netgen Array & tempels, int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax) { - Array > centers; + static Timer t("Meshing3::Delaunay1"); RegionTimer reg(t); + + Array> centers; Array radi2; Point3d tpmin, tpmax; @@ -783,6 +785,8 @@ namespace netgen void Meshing3 :: Delaunay (Mesh & mesh, int domainnr, const MeshingParameters & mp) { + static Timer t("Meshing3::Delaunay"); RegionTimer reg(t); + int np, ne; PrintMessage (1, "Delaunay meshing"); diff --git a/libsrc/meshing/improve3.cpp b/libsrc/meshing/improve3.cpp index 0dde9ba6..943c4197 100644 --- a/libsrc/meshing/improve3.cpp +++ b/libsrc/meshing/improve3.cpp @@ -22,6 +22,8 @@ namespace netgen void MeshOptimize3d :: CombineImprove (Mesh & mesh, OPTIMIZEGOAL goal) { + static Timer t("MeshOptimize3d::CombineImprove"); RegionTimer reg(t); + int np = mesh.GetNP(); int ne = mesh.GetNE(); @@ -274,6 +276,8 @@ void MeshOptimize3d :: CombineImprove (Mesh & mesh, void MeshOptimize3d :: SplitImprove (Mesh & mesh, OPTIMIZEGOAL goal) { + static Timer t("MeshOptimize3d::SplitImprove"); RegionTimer reg(t); + double bad1, bad2, badmax, badlimit; int cnt = 0; @@ -569,6 +573,8 @@ void MeshOptimize3d :: SplitImprove (Mesh & mesh, void MeshOptimize3d :: SwapImprove (Mesh & mesh, OPTIMIZEGOAL goal, const BitArray * working_elements) { + static Timer t("MeshOptimize3d::SwapImprove"); RegionTimer reg(t); + PointIndex pi3(0), pi4(0), pi5(0), pi6(0); int cnt = 0; @@ -2303,6 +2309,8 @@ void MeshOptimize3d :: SwapImproveSurface (Mesh & mesh, OPTIMIZEGOAL goal, void MeshOptimize3d :: SwapImprove2 (Mesh & mesh, OPTIMIZEGOAL goal) { + static Timer t("MeshOptimize3d::SwapImprove2"); RegionTimer reg(t); + PointIndex pi1(0), pi2(0), pi3(0), pi4(0), pi5(0); Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET); diff --git a/libsrc/meshing/meshclass.hpp b/libsrc/meshing/meshclass.hpp index e855c3f2..e3fe5025 100644 --- a/libsrc/meshing/meshclass.hpp +++ b/libsrc/meshing/meshclass.hpp @@ -221,7 +221,7 @@ namespace netgen DLL_HEADER PointIndex AddPoint (const Point3d & p, int layer = 1); DLL_HEADER PointIndex AddPoint (const Point3d & p, int layer, POINTTYPE type); - int GetNP () const { return points.Size(); } + auto GetNP () const { return points.Size(); } // [[deprecated("Use Point(PointIndex) instead of int !")]] MeshPoint & Point(int i) { return points.Elem(i); } @@ -291,7 +291,7 @@ namespace netgen timestamp = NextTimeStamp(); } - int GetNSE () const { return surfelements.Size(); } + auto GetNSE () const { return surfelements.Size(); } // [[deprecated("Use SurfaceElement(SurfaceElementIndex) instead of int !")]] Element2d & SurfaceElement(int i) { return surfelements.Elem(i); } @@ -316,7 +316,7 @@ namespace netgen // write to pre-allocated container, thread-safe DLL_HEADER void SetVolumeElement (ElementIndex sei, const Element & el); - int GetNE () const { return volelements.Size(); } + auto GetNE () const { return volelements.Size(); } // [[deprecated("Use VolumeElement(ElementIndex) instead of int !")]] Element & VolumeElement(int i) { return volelements.Elem(i); } diff --git a/libsrc/meshing/meshfunc.cpp b/libsrc/meshing/meshfunc.cpp index d1629d62..e3fab9b8 100644 --- a/libsrc/meshing/meshfunc.cpp +++ b/libsrc/meshing/meshfunc.cpp @@ -14,6 +14,8 @@ namespace netgen // extern double teterrpow; MESHING3_RESULT MeshVolume (MeshingParameters & mp, Mesh& mesh3d) { + static Timer t("MeshVolume"); RegionTimer reg(t); + int oldne; int meshed; @@ -639,6 +641,8 @@ namespace netgen Mesh & mesh3d) // const CSGeometry * geometry) { + static Timer t("OptimizeVolume"); RegionTimer reg(t); + int i; PrintMessage (1, "Volume Optimization"); @@ -698,6 +702,8 @@ namespace netgen void RemoveIllegalElements (Mesh & mesh3d) { + static Timer t("RemoveIllegalElements"); RegionTimer reg(t); + int it = 10; int nillegal, oldn; diff --git a/libsrc/meshing/meshing3.cpp b/libsrc/meshing/meshing3.cpp index 16b49c53..e30454d1 100644 --- a/libsrc/meshing/meshing3.cpp +++ b/libsrc/meshing/meshing3.cpp @@ -168,12 +168,17 @@ int Meshing3 :: AddConnectedPair (const INDEX_2 & apair) MESHING3_RESULT Meshing3 :: GenerateMesh (Mesh & mesh, const MeshingParameters & mp) { - static int meshing3_timer = NgProfiler::CreateTimer ("Meshing3::GenerateMesh"); - static int meshing3_timer_a = NgProfiler::CreateTimer ("Meshing3::GenerateMesh a"); - static int meshing3_timer_b = NgProfiler::CreateTimer ("Meshing3::GenerateMesh b"); - static int meshing3_timer_c = NgProfiler::CreateTimer ("Meshing3::GenerateMesh c"); - static int meshing3_timer_d = NgProfiler::CreateTimer ("Meshing3::GenerateMesh d"); - NgProfiler::RegionTimer reg (meshing3_timer); + static Timer t("Meshing3::GenerateMesh"); RegionTimer reg(t); + static Timer meshing3_timer_a("Meshing3::GenerateMesh a", 2); + static Timer meshing3_timer_b("Meshing3::GenerateMesh b", 2); + static Timer meshing3_timer_c("Meshing3::GenerateMesh c", 1); + static Timer meshing3_timer_d("Meshing3::GenerateMesh d", 2); + // static int meshing3_timer = NgProfiler::CreateTimer ("Meshing3::GenerateMesh"); + // static int meshing3_timer_a = NgProfiler::CreateTimer ("Meshing3::GenerateMesh a"); + // static int meshing3_timer_b = NgProfiler::CreateTimer ("Meshing3::GenerateMesh b"); + // static int meshing3_timer_c = NgProfiler::CreateTimer ("Meshing3::GenerateMesh c"); + // static int meshing3_timer_d = NgProfiler::CreateTimer ("Meshing3::GenerateMesh d"); + // NgProfiler::RegionTimer reg (meshing3_timer); Array locpoints; // local points @@ -269,20 +274,16 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp) } const MiniElement2d & bel = adfront->GetFace (baseelem); - const Point3d & p1 = adfront->GetPoint (bel[0]); - const Point3d & p2 = adfront->GetPoint (bel[1]); - const Point3d & p3 = adfront->GetPoint (bel[2]); + const Point<3> p1 = adfront->GetPoint (bel[0]); + const Point<3> p2 = adfront->GetPoint (bel[1]); + const Point<3> p3 = adfront->GetPoint (bel[2]); + - // (*testout) << endl << "base = " << bel << endl; - - - Point3d pmid = Center (p1, p2, p3); + Point<3> pmid = Center (p1, p2, p3); double his = (Dist (p1, p2) + Dist(p1, p3) + Dist(p2, p3)) / 3; - double hshould; - - hshould = mesh.GetH (pmid); - + double hshould = mesh.GetH (pmid); + if (adfront->GetFace (baseelem).GetNP() == 4) hshould = max2 (his, hshould); @@ -292,13 +293,13 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp) double hinner = hmax * (1 + stat.qualclass); double houter = hmax * (1 + 2 * stat.qualclass); - NgProfiler::StartTimer (meshing3_timer_a); + meshing3_timer_a.Start(); stat.qualclass = adfront -> GetLocals (baseelem, locpoints, locfaces, pindex, findex, connectedpairs, houter, hinner, locfacesplit); - NgProfiler::StopTimer (meshing3_timer_a); + meshing3_timer_a.Stop(); // (*testout) << "locfaces = " << endl << locfaces << endl; @@ -320,9 +321,6 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp) } - - - if (testmode) { (*testout) << "baseelem = " << baseelem << " qualclass = " << stat.qualclass << endl; @@ -479,7 +477,8 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp) (*testout) << endl; } - NgProfiler::StartTimer (meshing3_timer_c); + // NgProfiler::StartTimer (meshing3_timer_c); + meshing3_timer_c.Start(); found = ApplyRules (plainpoints, allowpoint, locfaces, locfacesplit, connectedpairs, @@ -489,8 +488,8 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp) if (found >= 0) impossible = 0; if (found < 0) found = 0; - - NgProfiler::StopTimer (meshing3_timer_c); + meshing3_timer_c.Stop(); + // NgProfiler::StopTimer (meshing3_timer_c); if (!found) loktestmode = 0; diff --git a/libsrc/meshing/smoothing3.cpp b/libsrc/meshing/smoothing3.cpp index e16799dd..1353e156 100644 --- a/libsrc/meshing/smoothing3.cpp +++ b/libsrc/meshing/smoothing3.cpp @@ -1353,6 +1353,8 @@ void Mesh :: ImproveMesh (const CSG eometry & geometry, OPTIMIZEGOAL goal) void Mesh :: ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal) { + static Timer t("Mesh::ImproveMesh"); RegionTimer reg(t); + int typ = 1; (*testout) << "Improve Mesh" << "\n"; From 5fafe3c36f437b0e062d65fa2c17511f3bd8f58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 31 Jan 2019 19:11:22 +0100 Subject: [PATCH 78/98] ng_comm --- libsrc/include/nginterface_v2.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 184f3eb2..d731deaf 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -26,6 +26,11 @@ enum NG_ELEMENT_TYPE { enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; #endif +#ifndef PARALLEL + typedef int MPI_Comm; +#endif +namespace netgen { extern MPI_Comm ng_comm; } + namespace netgen { From e880bff515d6f62a2934b4832d5de02cf3469319 Mon Sep 17 00:00:00 2001 From: Lukas Date: Fri, 1 Feb 2019 16:12:30 +0100 Subject: [PATCH 79/98] DLL_HEADER for ng_comm --- libsrc/general/mpi_interface.hpp | 2 +- libsrc/include/nginterface.h | 2 +- libsrc/include/nginterface_v2.hpp | 2 +- libsrc/meshing/global.cpp | 2 +- libsrc/meshing/global.hpp | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libsrc/general/mpi_interface.hpp b/libsrc/general/mpi_interface.hpp index 593d290a..eb79865e 100644 --- a/libsrc/general/mpi_interface.hpp +++ b/libsrc/general/mpi_interface.hpp @@ -23,7 +23,7 @@ namespace netgen #endif /** This is the "standard" communicator that will be used for netgen-objects. **/ - extern MPI_Comm ng_comm; + extern DLL_HEADER MPI_Comm ng_comm; #ifdef PARALLEL inline int MyMPI_GetNTasks (MPI_Comm comm = ng_comm) diff --git a/libsrc/include/nginterface.h b/libsrc/include/nginterface.h index 254734ce..38e38ec2 100644 --- a/libsrc/include/nginterface.h +++ b/libsrc/include/nginterface.h @@ -40,7 +40,7 @@ #ifndef PARALLEL typedef int MPI_Comm; #endif -namespace netgen { extern MPI_Comm ng_comm; } +namespace netgen { extern DLL_HEADER MPI_Comm ng_comm; } // implemented element types: diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index d731deaf..d6d4c5a8 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -29,7 +29,7 @@ enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; #ifndef PARALLEL typedef int MPI_Comm; #endif -namespace netgen { extern MPI_Comm ng_comm; } +namespace netgen { extern DLL_HEADER MPI_Comm ng_comm; } namespace netgen diff --git a/libsrc/meshing/global.cpp b/libsrc/meshing/global.cpp index 988dc8e6..327727be 100644 --- a/libsrc/meshing/global.cpp +++ b/libsrc/meshing/global.cpp @@ -32,7 +32,7 @@ namespace netgen // TraceGlobal glob2("global2"); // global communicator for netgen - MPI_Comm ng_comm = MPI_COMM_WORLD; + DLL_HEADER MPI_Comm ng_comm = MPI_COMM_WORLD; weak_ptr global_mesh; void SetGlobalMesh (shared_ptr m) diff --git a/libsrc/meshing/global.hpp b/libsrc/meshing/global.hpp index 9b1bbac7..c97815e3 100644 --- a/libsrc/meshing/global.hpp +++ b/libsrc/meshing/global.hpp @@ -61,7 +61,7 @@ namespace netgen DLL_HEADER void SetGlobalMesh (shared_ptr m); // global communicator for netgen (dummy if no MPI) - extern MPI_Comm ng_comm; + extern DLL_HEADER MPI_Comm ng_comm; } From 1321fcf3f3962fc6268c6f57827aeba03f102745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Sat, 2 Feb 2019 16:23:46 +0100 Subject: [PATCH 80/98] ResetTime from meshing global --- nglib/nglib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nglib/nglib.cpp b/nglib/nglib.cpp index 5fea184c..54fff096 100644 --- a/nglib/nglib.cpp +++ b/nglib/nglib.cpp @@ -1211,14 +1211,14 @@ namespace netgen } */ - + /* #ifndef WIN32 void ResetTime () { ; } #endif - + */ void MyBeep (int i) From cc732689c2290bed0ee44176290afe165a506036 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Sat, 2 Feb 2019 16:24:07 +0100 Subject: [PATCH 81/98] start modernizing delaunay --- libsrc/gprim/geomobjects.hpp | 3 +- libsrc/meshing/adfront3.hpp | 1 + libsrc/meshing/delaunay.cpp | 59 +++++++++++++++++++++++++----------- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/libsrc/gprim/geomobjects.hpp b/libsrc/gprim/geomobjects.hpp index ad215278..eb2f0030 100644 --- a/libsrc/gprim/geomobjects.hpp +++ b/libsrc/gprim/geomobjects.hpp @@ -270,7 +270,8 @@ namespace netgen for (int i = 0; i < D; i++) { if (p(i) < pmin(i)) pmin(i) = p(i); - else if (p(i) > pmax(i)) pmax(i) = p(i); + /* else */ if (p(i) > pmax(i)) pmax(i) = p(i); + // optimization invalid for empty-box ! } } diff --git a/libsrc/meshing/adfront3.hpp b/libsrc/meshing/adfront3.hpp index 738de122..9b7f3818 100644 --- a/libsrc/meshing/adfront3.hpp +++ b/libsrc/meshing/adfront3.hpp @@ -233,6 +233,7 @@ public: /// const MiniElement2d & GetFace (int i) const { return faces.Get(i).Face(); } + const auto & Faces() const { return faces; } /// void Print () const; /// diff --git a/libsrc/meshing/delaunay.cpp b/libsrc/meshing/delaunay.cpp index cf12f536..5f63d35e 100644 --- a/libsrc/meshing/delaunay.cpp +++ b/libsrc/meshing/delaunay.cpp @@ -41,8 +41,8 @@ namespace netgen PointIndex & operator[] (int i) { return pnums[i]; } PointIndex operator[] (int i) const { return pnums[i]; } - int & NB1(int i) { return nb[i-1]; } - int NB1(int i) const { return nb[i-1]; } + // int & NB1(int i) { return nb[i-1]; } + // int NB1(int i) const { return nb[i-1]; } int & NB(int i) { return nb[i]; } int NB(int i) const { return nb[i]; } @@ -57,35 +57,38 @@ namespace netgen return i; return 3; } - + + /* void GetFace1 (int i, INDEX_3 & face) const { face.I(1) = pnums[deltetfaces[i-1][0]]; face.I(2) = pnums[deltetfaces[i-1][1]]; face.I(3) = pnums[deltetfaces[i-1][2]]; } - + */ void GetFace (int i, INDEX_3 & face) const { face.I(1) = pnums[deltetfaces[i][0]]; face.I(2) = pnums[deltetfaces[i][1]]; face.I(3) = pnums[deltetfaces[i][2]]; } - + + /* INDEX_3 GetFace1 (int i) const { return INDEX_3 (pnums[deltetfaces[i-1][0]], pnums[deltetfaces[i-1][1]], pnums[deltetfaces[i-1][2]]); } - + */ INDEX_3 GetFace (int i) const { return INDEX_3 (pnums[deltetfaces[i][0]], pnums[deltetfaces[i][1]], pnums[deltetfaces[i][2]]); } - + + /* void GetFace1 (int i, Element2d & face) const { // face.SetType(TRIG); @@ -93,6 +96,15 @@ namespace netgen face[1] = pnums[deltetfaces[i-1][1]]; face[2] = pnums[deltetfaces[i-1][2]]; } + */ + void GetFace (int i, Element2d & face) const + { + // face.SetType(TRIG); + face[0] = pnums[deltetfaces[i][0]]; + face[1] = pnums[deltetfaces[i][1]]; + face[2] = pnums[deltetfaces[i][2]]; + } + }; @@ -135,7 +147,7 @@ namespace netgen // get neighbour of element elnr in direction fnr int GetNB (int elnr, int fnr) { - return tets.Get(elnr).NB1(fnr); + return tets.Get(elnr).NB(fnr-1); } // @@ -456,7 +468,7 @@ namespace netgen if (!nbind || !insphere.IsIn (nbind)) { - tempels.Get (celind).GetFace1 (k, face); + tempels.Get (celind).GetFace (k-1, face); Element newel(TET); for (int l = 0; l < 3; l++) @@ -611,6 +623,7 @@ namespace netgen // new: local box + /* mesh.GetBox (pmax, pmin); // lower bound for pmax, upper for pmin for (int i = 1; i <= adfront->GetNF(); i++) { @@ -627,8 +640,20 @@ namespace netgen pmin.SetToMin (mesh.Point (pi)); pmax.SetToMax (mesh.Point (pi)); } + cout << "pmin = " << pmin << ", pmax = " << pmax << endl; + */ + Box<3> bbox(Box<3>::EMPTY_BOX); + + for (auto & face : adfront->Faces()) + for (PointIndex pi : face.Face().PNums()) + bbox.Add (mesh.Point(pi)); + + for (PointIndex pi : mesh.LockedPoints()) + bbox.Add (mesh.Point (pi)); - + pmin = bbox.PMin(); + pmax = bbox.PMax(); + // cout << "bbox = " << bbox << endl; Vec3d vdiag(pmin, pmax); // double r1 = vdiag.Length(); @@ -862,7 +887,7 @@ namespace netgen { Element2d self(TRIG); self.SetIndex (1); - startel.GetFace1 (i, self); + startel.GetFace (i-1, self); tempmesh.AddSurfaceElement (self); } @@ -1293,7 +1318,7 @@ namespace netgen for (int j = 1; j <= 4; j++) { - el.GetFace1 (j, hel); + el.GetFace (j-1, hel); hel.Invert(); hel.NormalizeNumbering(); @@ -1307,8 +1332,8 @@ namespace netgen { INDEX_2 i2 = faceht.Get(i3); - tempels.Elem(i).NB1(j) = i2.I1(); - tempels.Elem(i2.I1()).NB1(i2.I2()) = i; + tempels.Elem(i).NB(j-1) = i2.I1(); + tempels.Elem(i2.I1()).NB(i2.I2()-1) = i; } else { @@ -1468,7 +1493,7 @@ namespace netgen for (int j = 1; j <= 4; j++) { - INDEX_3 i3 = tempels.Get(ei).GetFace1(j); + INDEX_3 i3 = tempels.Get(ei).GetFace(j-1); /* Element2d face; tempels.Get(ei).GetFace(j, face); @@ -1478,8 +1503,8 @@ namespace netgen i3.Sort(); - if (tempels.Get(ei).NB1(j)) - elstack.Append (tempels.Get(ei).NB1(j)); + if (tempels.Get(ei).NB(j-1)) + elstack.Append (tempels.Get(ei).NB(j-1)); /* if (innerfaces.Used(i3)) From 1303e923792c2b9c1f02dac316a3fbb68906d8fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Sun, 3 Feb 2019 06:20:52 +0100 Subject: [PATCH 82/98] modernize Delaunay --- libsrc/meshing/delaunay.cpp | 297 ++++++++++++----------------------- libsrc/meshing/meshclass.hpp | 3 +- 2 files changed, 100 insertions(+), 200 deletions(-) diff --git a/libsrc/meshing/delaunay.cpp b/libsrc/meshing/delaunay.cpp index 5f63d35e..cbd2a73b 100644 --- a/libsrc/meshing/delaunay.cpp +++ b/libsrc/meshing/delaunay.cpp @@ -6,7 +6,6 @@ namespace netgen { - static const int deltetfaces[][3] = { { 1, 2, 3 }, { 2, 0, 3 }, @@ -14,10 +13,6 @@ namespace netgen { 1, 0, 2 } }; - - - - class DelaunayTet { PointIndex pnums[4]; @@ -41,9 +36,6 @@ namespace netgen PointIndex & operator[] (int i) { return pnums[i]; } PointIndex operator[] (int i) const { return pnums[i]; } - // int & NB1(int i) { return nb[i-1]; } - // int NB1(int i) const { return nb[i-1]; } - int & NB(int i) { return nb[i]; } int NB(int i) const { return nb[i]; } @@ -58,29 +50,6 @@ namespace netgen return 3; } - /* - void GetFace1 (int i, INDEX_3 & face) const - { - face.I(1) = pnums[deltetfaces[i-1][0]]; - face.I(2) = pnums[deltetfaces[i-1][1]]; - face.I(3) = pnums[deltetfaces[i-1][2]]; - } - */ - void GetFace (int i, INDEX_3 & face) const - { - face.I(1) = pnums[deltetfaces[i][0]]; - face.I(2) = pnums[deltetfaces[i][1]]; - face.I(3) = pnums[deltetfaces[i][2]]; - } - - /* - INDEX_3 GetFace1 (int i) const - { - return INDEX_3 (pnums[deltetfaces[i-1][0]], - pnums[deltetfaces[i-1][1]], - pnums[deltetfaces[i-1][2]]); - } - */ INDEX_3 GetFace (int i) const { return INDEX_3 (pnums[deltetfaces[i][0]], @@ -88,15 +57,6 @@ namespace netgen pnums[deltetfaces[i][2]]); } - /* - void GetFace1 (int i, Element2d & face) const - { - // face.SetType(TRIG); - face[0] = pnums[deltetfaces[i-1][0]]; - face[1] = pnums[deltetfaces[i-1][1]]; - face[2] = pnums[deltetfaces[i-1][2]]; - } - */ void GetFace (int i, Element2d & face) const { // face.SetType(TRIG); @@ -104,7 +64,6 @@ namespace netgen face[1] = pnums[deltetfaces[i][1]]; face[2] = pnums[deltetfaces[i][2]]; } - }; @@ -113,8 +72,6 @@ namespace netgen - - /* Table to maintain neighbour elements */ @@ -147,7 +104,7 @@ namespace netgen // get neighbour of element elnr in direction fnr int GetNB (int elnr, int fnr) { - return tets.Get(elnr).NB(fnr-1); + return tets.Get(elnr).NB(fnr); } // @@ -193,7 +150,6 @@ namespace netgen - /* connected lists of cosphereical elements */ @@ -265,24 +221,23 @@ namespace netgen Array & freelist, SphereList & list, IndexSet & insphere, IndexSet & closesphere) { + // static Timer t("Meshing3::AddDelaunayPoint"); RegionTimer reg(t); /* find any sphere, such that newp is contained in */ - DelaunayTet el; int cfelind = -1; const Point<3> * pp[4]; Point<3> pc; - double r2; Point3d tpmin, tpmax; tettree.GetIntersecting (newp, newp, treesearch); + double quot,minquot(1e20); - for (int j = 0; j < treesearch.Size(); j++) + for (auto jjj : treesearch) { - int jjj = treesearch[j]; quot = Dist2 (centers.Get(jjj), newp) / radi2.Get(jjj); if((cfelind == -1 || quot < 0.99*minquot) && quot < 1) @@ -296,46 +251,12 @@ namespace netgen } - /* - int i, j, k, l; - if (!felind) - { - cerr << "not in any sphere, 1" << endl; - // old, non tree search - - double mindist = 1e10; - for (j = 1; j <= tempels.Size(); j++) - { - if (tempels.Get(j).PNum(1)) - { - double toofar = - Dist2 (centers.Get(j), newp) - radi2.Get(j); - if (toofar < mindist || toofar < 1e-7) - { - mindist = toofar; - cout << " dist2 = " << Dist2 (centers.Get(j), newp) - << " radi2 = " << radi2.Get(j) << endl; - } - if (toofar < 0) - { - el = tempels.Get(j); - felind = j; - cout << "sphere found !" << endl; - break; - } - } - } - cout << "point is too far from sheres: " << mindist << endl; - } - */ - if (cfelind == -1) { PrintWarning ("Delaunay, point not in any sphere"); return; } - /* insphere: point is in sphere -> delete element closesphere: point is close to sphere -> considered for same center @@ -388,7 +309,7 @@ namespace netgen // check neighbour-tets for (int j = starti; j < nstarti; j++) - for (int k = 1; k <= 4; k++) + for (int k = 0; k < 4; k++) { int helind = insphere.GetArray().Get(j); int nbind = meshnb.GetNB (helind, k); @@ -416,61 +337,48 @@ namespace netgen } else { - /* - Element2d face; - tempels.Get(helind).GetFace (k, face); + INDEX_3 i3 = tempels.Get(helind).GetFace (k); - const Point3d & p1 = mesh.Point (face.PNum(1)); - const Point3d & p2 = mesh.Point (face[1]); - const Point3d & p3 = mesh.Point (face[2]); - */ + const Point<3> & p1 = mesh.Point ( PointIndex (i3.I1()) ); + const Point<3> & p2 = mesh.Point ( PointIndex (i3.I2()) ); + const Point<3> & p3 = mesh.Point ( PointIndex (i3.I3()) ); - INDEX_3 i3 = tempels.Get(helind).GetFace (k-1); - - const Point3d & p1 = mesh.Point ( PointIndex (i3.I1()) ); - const Point3d & p2 = mesh.Point ( PointIndex (i3.I2()) ); - const Point3d & p3 = mesh.Point ( PointIndex (i3.I3()) ); - - - Vec3d v1(p1, p2); - Vec3d v2(p1, p3); - Vec3d n = Cross (v1, v2); + Vec<3> v1 = p2-p1; + Vec<3> v2 = p3-p1; + Vec<3> n = Cross (v1, v2); n /= n.Length(); - if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k-1])) > 0) + if (n * Vec3d (p1, mesh.Point (tempels.Get(helind)[k])) > 0) n *= -1; double dist = n * Vec3d (p1, newp); - if (dist > -1e-10) // 1e-10 { insphere.Add (nbind); changed = 1; } - - } } } } // while (changed) - // (*testout) << "newels: " << endl; - Array newels; + + // Array newels; + Array newels; Element2d face(TRIG); - for (int j = 1; j <= insphere.GetArray().Size(); j++) - for (int k = 1; k <= 4; k++) + for (int celind : insphere.GetArray()) + for (int k = 0; k < 4; k++) { - // int elind = insphere.GetArray().Get(j); - int celind = insphere.GetArray().Get(j); int nbind = meshnb.GetNB (celind, k); if (!nbind || !insphere.IsIn (nbind)) { - tempels.Get (celind).GetFace (k-1, face); + tempels.Get (celind).GetFace (k, face); - Element newel(TET); + // Element newel(TET); + DelaunayTet newel; for (int l = 0; l < 3; l++) newel[l] = face[l]; newel[3] = newpi; @@ -483,7 +391,7 @@ namespace netgen n.Normalize(); if (n * Vec3d(mesh.Point (face[0]), - mesh.Point (tempels.Get(insphere.GetArray().Get(j))[k-1])) + mesh.Point (tempels.Get(celind)[k])) > 0) n *= -1; @@ -504,38 +412,36 @@ namespace netgen meshnb.ResetFaceHT (10*insphere.GetArray().Size()+1); - for (int j = 1; j <= insphere.GetArray().Size(); j++) + for (auto celind : insphere.GetArray()) { - // int elind = - int celind = insphere.GetArray().Get(j); - meshnb.Delete (celind); list.DeleteElement (celind); for (int k = 0; k < 4; k++) tempels.Elem(celind)[k] = -1; - // ((ADTree6&)tettree.Tree()).DeleteElement (celind); tettree.DeleteElement (celind); freelist.Append (celind); } - int hasclose = 0; - for (int j = 1; j <= closesphere.GetArray().Size(); j++) + + + bool hasclose = false; + for (int ind : closesphere.GetArray()) { - int ind = closesphere.GetArray().Get(j); if (!insphere.IsIn(ind) && fabs (Dist2 (centers.Get (ind), newp) - radi2.Get(ind)) < 1e-8 ) - hasclose = 1; + hasclose = true; } for (int j = 1; j <= newels.Size(); j++) { + const auto & newel = newels.Get(j); int nelind; if (!freelist.Size()) { - tempels.Append (newels.Get(j)); + tempels.Append (newel); nelind = tempels.Size(); } else @@ -543,29 +449,29 @@ namespace netgen nelind = freelist.Last(); freelist.DeleteLast(); - tempels.Elem(nelind) = newels.Get(j); + tempels.Elem(nelind) = newel; } meshnb.Add (nelind); list.AddElement (nelind); for (int k = 0; k < 4; k++) - pp[k] = &mesh.Point (newels.Get(j)[k]); + pp[k] = &mesh.Point (newel[k]); if (CalcSphereCenter (&pp[0], pc) ) { PrintSysError ("Delaunay: New tet is flat"); (*testout) << "new tet is flat" << endl; - for (int k = 1; k <= 4; k++) - (*testout) << newels.Get(j).PNum(k) << " "; + for (int k = 0; k < 4; k++) + (*testout) << newel[k] << " "; (*testout) << endl; - for (int k = 1; k <= 4; k++) + for (int k = 0; k < 4; k++) (*testout) << *pp[k-1] << " "; (*testout) << endl; } - r2 = Dist2 (*pp[0], pc); + double r2 = Dist2 (*pp[0], pc); if (hasclose) for (int k = 1; k <= closesphere.GetArray().Size(); k++) { @@ -615,33 +521,11 @@ namespace netgen int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax) { static Timer t("Meshing3::Delaunay1"); RegionTimer reg(t); + static Timer tloop("Meshing3::Delaunay1 loop"); Array> centers; Array radi2; - Point3d tpmin, tpmax; - - - // new: local box - /* - mesh.GetBox (pmax, pmin); // lower bound for pmax, upper for pmin - for (int i = 1; i <= adfront->GetNF(); i++) - { - const MiniElement2d & face = adfront->GetFace(i); - for (PointIndex pi : face.PNums()) - { - pmin.SetToMin (mesh.Point (pi)); - pmax.SetToMax (mesh.Point (pi)); - } - } - - for (PointIndex pi : mesh.LockedPoints()) - { - pmin.SetToMin (mesh.Point (pi)); - pmax.SetToMax (mesh.Point (pi)); - } - cout << "pmin = " << pmin << ", pmax = " << pmax << endl; - */ Box<3> bbox(Box<3>::EMPTY_BOX); for (auto & face : adfront->Faces()) @@ -653,26 +537,24 @@ namespace netgen pmin = bbox.PMin(); pmax = bbox.PMax(); - // cout << "bbox = " << bbox << endl; - Vec3d vdiag(pmin, pmax); + + Vec<3> vdiag = pmax-pmin; // double r1 = vdiag.Length(); - double r1 = sqrt (3.0) * max3(vdiag.X(), vdiag.Y(), vdiag.Z()); - vdiag = Vec3d (r1, r1, r1); + double r1 = sqrt (3.0) * max3(vdiag(0), vdiag(1), vdiag(2)); + vdiag = Vec<3> (r1, r1, r1); //double r2; - Point3d pmin2 = pmin - 8 * vdiag; - Point3d pmax2 = pmax + 8 * vdiag; + Point<3> pmin2 = pmin - 8 * vdiag; + Point<3> pmax2 = pmax + 8 * vdiag; - Point3d cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2); - cp2.X() = pmin2.X(); - cp3.Y() = pmin2.Y(); - cp4.Z() = pmin2.Z(); + Point<3> cp1(pmin2), cp2(pmax2), cp3(pmax2), cp4(pmax2); + cp2(0) = pmin2(0); + cp3(1) = pmin2(1); + cp4(2) = pmin2(2); - - - int np = mesh.GetNP(); + size_t np = mesh.GetNP(); startel[0] = mesh.AddPoint (cp1); startel[1] = mesh.AddPoint (cp2); @@ -682,24 +564,21 @@ namespace netgen // flag points to use for Delaunay: BitArrayChar usep(np); usep.Clear(); - for (int i = 1; i <= adfront->GetNF(); i++) - { - const MiniElement2d & face = adfront->GetFace(i); - for (int j = 0; j < face.GetNP(); j++) - usep.Set (face[j]); - } - for (int i = oldnp + PointIndex::BASE; + for (auto & face : adfront->Faces()) + for (PointIndex pi : face.Face().PNums()) + usep.Set (pi); + + for (size_t i = oldnp + PointIndex::BASE; i < np + PointIndex::BASE; i++) usep.Set (i); - for (int i = 0; i < mesh.LockedPoints().Size(); i++) - usep.Set (mesh.LockedPoints()[i]); - + for (PointIndex pi : mesh.LockedPoints()) + usep.Set (pi); + Array freelist; - int cntp = 0; MeshNB meshnb (tempels, mesh.GetNP() + 5); @@ -716,13 +595,12 @@ namespace netgen list.AddElement (1); Array connected, treesearch; - - tpmin = tpmax = mesh.Point(startel[0]); - for (int k = 1; k < 4; k++) - { - tpmin.SetToMin (mesh.Point (startel[k])); - tpmax.SetToMax (mesh.Point (startel[k])); - } + Box<3> tbox(Box<3>::EMPTY_BOX); + for (size_t k = 0; k < 4; k++) + tbox.Add (mesh.Point(startel[k])); + Point<3> tpmin = tbox.PMin(); + Point<3> tpmax = tbox.PMax(); + tpmax = tpmax + 0.01 * (tpmax - tpmin); tettree.Insert (tpmin, tpmax, 1); @@ -754,6 +632,7 @@ namespace netgen for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++) mixed[pi] = PointIndex ( (prim * pi) % np + PointIndex::BASE ); + tloop.Start(); for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++) { if (pi % 1000 == 0) @@ -782,7 +661,8 @@ namespace netgen connected, treesearch, freelist, list, insphere, closesphere); } - + tloop.Stop(); + for (int i = tempels.Size(); i >= 1; i--) if (tempels.Get(i)[0] <= 0) tempels.DeleteElement (i); @@ -839,26 +719,27 @@ namespace netgen // improve delaunay - mesh by swapping !!!! Mesh tempmesh; - for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) - tempmesh.AddPoint (mesh[pi]); + + for (auto & meshpoint : mesh.Points()) + tempmesh.AddPoint (meshpoint); - for (int i = 1; i <= tempels.Size(); i++) + for (auto & tempel : tempels) { Element el(4); for (int j = 0; j < 4; j++) - el[j] = tempels.Elem(i)[j]; + el[j] = tempel[j]; el.SetIndex (1); - const Point3d & lp1 = mesh.Point (el[0]); - const Point3d & lp2 = mesh.Point (el[1]); - const Point3d & lp3 = mesh.Point (el[2]); - const Point3d & lp4 = mesh.Point (el[3]); - Vec3d v1(lp1, lp2); - Vec3d v2(lp1, lp3); - Vec3d v3(lp1, lp4); + const Point<3> & lp1 = mesh.Point (el[0]); + const Point<3> & lp2 = mesh.Point (el[1]); + const Point<3> & lp3 = mesh.Point (el[2]); + const Point<3> & lp4 = mesh.Point (el[3]); + Vec<3> v1 = lp2-lp1; + Vec<3> v2 = lp3-lp1; + Vec<3> v3 = lp4-lp1; - Vec3d n = Cross (v1, v2); + Vec<3> n = Cross (v1, v2); double vol = n * v3; if (vol > 0) swap (el[2], el[3]); @@ -1261,6 +1142,7 @@ namespace netgen INDEX_3_HASHTABLE boundaryfaces(mesh.GetNOpenElements()/3+1); + /* for (int i = 1; i <= mesh.GetNOpenElements(); i++) { const Element2d & tri = mesh.OpenElement(i); @@ -1268,6 +1150,13 @@ namespace netgen i3.Sort(); boundaryfaces.PrepareSet (i3); } + */ + for (const Element2d & tri : mesh.OpenElements()) + { + INDEX_3 i3 (tri[0], tri[1], tri[2]); + i3.Sort(); + boundaryfaces.PrepareSet (i3); + } boundaryfaces.AllocateElements(); for (int i = 1; i <= mesh.GetNOpenElements(); i++) { @@ -1277,14 +1166,23 @@ namespace netgen boundaryfaces.Set (i3, 1); } + /* for (int i = 0; i < tempels.Size(); i++) for (int j = 0; j < 4; j++) tempels[i].NB(j) = 0; - + */ + for (auto & el : tempels) + for (int j = 0; j < 4; j++) + el.NB(j) = 0; + TABLE elsonpoint(mesh.GetNP()); + /* for (int i = 0; i < tempels.Size(); i++) { const DelaunayTet & el = tempels[i]; + */ + for (const DelaunayTet & el : tempels) + { INDEX_4 i4(el[0], el[1], el[2], el[3]); i4.Sort(); elsonpoint.IncSizePrepare (i4.I1()); @@ -1308,7 +1206,8 @@ namespace netgen INDEX_3_CLOSED_HASHTABLE faceht(100); Element2d hel(TRIG); - for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) + // for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End(); pi++) + for (PointIndex pi : mesh.Points().Range()) { faceht.SetSize (4 * elsonpoint[pi].Size()); for (int ii = 0; ii < elsonpoint[pi].Size(); ii++) diff --git a/libsrc/meshing/meshclass.hpp b/libsrc/meshing/meshclass.hpp index e3fe5025..d1f09b91 100644 --- a/libsrc/meshing/meshclass.hpp +++ b/libsrc/meshing/meshclass.hpp @@ -454,7 +454,8 @@ namespace netgen const Element2d & OpenElement(int i) const { return openelements.Get(i); } - + auto & OpenElements() const { return openelements; } + /// are also quads open elements bool HasOpenQuads () const; From 665acf811d304422f75af05da72d16b3c614b5f8 Mon Sep 17 00:00:00 2001 From: Lukas Date: Mon, 4 Feb 2019 13:12:31 +0100 Subject: [PATCH 83/98] fix typo --- libsrc/meshing/parallelmesh.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libsrc/meshing/parallelmesh.cpp b/libsrc/meshing/parallelmesh.cpp index f6db82bf..3258d2d9 100644 --- a/libsrc/meshing/parallelmesh.cpp +++ b/libsrc/meshing/parallelmesh.cpp @@ -578,8 +578,8 @@ namespace netgen osegs_both.Append(osegs1[l]); } for(int l = 0; l Date: Tue, 5 Feb 2019 09:02:31 +0100 Subject: [PATCH 84/98] take care of tolerance in searchtree --- libsrc/gprim/adtree.cpp | 6 +++--- libsrc/gprim/adtree.hpp | 6 +++--- libsrc/meshing/meshclass.cpp | 36 +++++++++++++++++++++++++----------- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/libsrc/gprim/adtree.cpp b/libsrc/gprim/adtree.cpp index 41237acc..cba845a7 100644 --- a/libsrc/gprim/adtree.cpp +++ b/libsrc/gprim/adtree.cpp @@ -2400,13 +2400,13 @@ namespace netgen Array & pis) const { Point<2*dim> tpmin, tpmax; - + double tol = Tolerance(); for (size_t i = 0; i < dim; i++) { tpmin(i) = boxpmin(i); - tpmax(i) = pmax(i); + tpmax(i) = pmax(i)+tol; - tpmin(i+dim) = pmin(i); + tpmin(i+dim) = pmin(i)-tol; tpmax(i+dim) = boxpmax(i); } diff --git a/libsrc/gprim/adtree.hpp b/libsrc/gprim/adtree.hpp index 174e9d9a..11694b67 100644 --- a/libsrc/gprim/adtree.hpp +++ b/libsrc/gprim/adtree.hpp @@ -570,9 +570,9 @@ public: { tree->DeleteElement(pi); } void GetIntersecting (const Point & pmin, const Point & pmax, Array & pis) const; - - // const T_ADTree<2*dim> & Tree() const { return *tree; }; - // T_ADTree<2*dim> & Tree() { return *tree; }; + double Tolerance() const { return 1e-7 * Dist(boxpmax, boxpmin); } // single precision + const auto & Tree() const { return *tree; }; + auto & Tree() { return *tree; }; }; } diff --git a/libsrc/meshing/meshclass.cpp b/libsrc/meshing/meshclass.cpp index 545a8f51..0d8f5879 100644 --- a/libsrc/meshing/meshclass.cpp +++ b/libsrc/meshing/meshclass.cpp @@ -1680,6 +1680,7 @@ namespace netgen void Mesh :: CalcSurfacesOfNode () { + static Timer t("Mesh::CalcSurfacesOfNode"); RegionTimer reg (t); // surfacesonnode.SetSize (GetNP()); TABLE surfacesonnode(GetNP()); @@ -1864,8 +1865,7 @@ namespace netgen void Mesh :: FindOpenElements (int dom) { - static int timer = NgProfiler::CreateTimer ("Mesh::FindOpenElements"); - NgProfiler::RegionTimer reg (timer); + static Timer t("Mesh::FindOpenElements"); RegionTimer reg (t); int np = GetNP(); int ne = GetNE(); @@ -2717,6 +2717,8 @@ namespace netgen void Mesh :: CalcLocalH (double grading) { + static Timer t("Mesh::CalcLocalH"); RegionTimer reg(t); + if (!lochfunc) { Point3d pmin, pmax; @@ -3242,6 +3244,8 @@ namespace netgen void Mesh :: Compress () { + static Timer t("Mesh::Compress"); RegionTimer reg(t); + Array op2np(GetNP()); Array hpoints; BitArrayChar pused(GetNP()); @@ -3381,7 +3385,7 @@ namespace netgen for (int i = 0; i < lockedpoints.Size(); i++) lockedpoints[i] = op2np[lockedpoints[i]]; - + /* for (int i = 0; i < facedecoding.Size(); i++) facedecoding[i].firstelement = -1; for (int i = surfelements.Size()-1; i >= 0; i--) @@ -3390,7 +3394,8 @@ namespace netgen surfelements[i].next = facedecoding[ind-1].firstelement; facedecoding[ind-1].firstelement = i; } - + */ + RebuildSurfaceElementLists (); CalcSurfacesOfNode(); @@ -3508,6 +3513,8 @@ namespace netgen int Mesh :: CheckOverlappingBoundary () { + static Timer t("Mesh::CheckOverlappingBoundary"); RegionTimer reg(t); + int i, j, k; Point3d pmin, pmax; @@ -4824,9 +4831,10 @@ namespace netgen bool build_searchtree, const bool allowindex) const { - const double pointtol = 1e-12; - netgen::Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol); - netgen::Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol); + // const double pointtol = 1e-12; + // netgen::Point<3> pmin = p - Vec<3> (pointtol, pointtol, pointtol); + // netgen::Point<3> pmax = p + Vec<3> (pointtol, pointtol, pointtol); + if (dimension == 2) { int ne; @@ -4839,8 +4847,11 @@ namespace netgen if (elementsearchtree || build_searchtree) { // update if necessary: - const_cast(*this).BuildElementSearchTree (); - elementsearchtree->GetIntersecting (pmin, pmax, locels); + const_cast(*this).BuildElementSearchTree (); + // double tol = elementsearchtree->Tolerance(); + // netgen::Point<3> pmin = p - Vec<3> (tol, tol, tol); + // netgen::Point<3> pmax = p + Vec<3> (tol, tol, tol); + elementsearchtree->GetIntersecting (p, p, locels); ne = locels.Size(); } else @@ -4882,8 +4893,11 @@ namespace netgen if (elementsearchtree || build_searchtree) { // update if necessary: - const_cast(*this).BuildElementSearchTree (); - elementsearchtree->GetIntersecting (pmin, pmax, locels); + const_cast(*this).BuildElementSearchTree (); + // double tol = elementsearchtree->Tolerance(); + // netgen::Point<3> pmin = p - Vec<3> (tol, tol, tol); + // netgen::Point<3> pmax = p + Vec<3> (tol, tol, tol); + elementsearchtree->GetIntersecting (p, p, locels); ne = locels.Size(); } else From e0e4b10eeed95f44e704231811664e22a21ea936 Mon Sep 17 00:00:00 2001 From: Matthias Hochsteger Date: Tue, 5 Feb 2019 15:44:17 +0100 Subject: [PATCH 85/98] Remove unused variable --- libsrc/core/paje_trace.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libsrc/core/paje_trace.cpp b/libsrc/core/paje_trace.cpp index 508067fd..844710d5 100644 --- a/libsrc/core/paje_trace.cpp +++ b/libsrc/core/paje_trace.cpp @@ -9,7 +9,6 @@ #include "paje_trace.hpp" #include "profiler.hpp" -static constexpr int MAX_TRACE_LINE_SIZE = 50; extern const char *header; namespace ngcore From 8a711031ccdab546f862e2e86952b377b3dbe930 Mon Sep 17 00:00:00 2001 From: Lukas Date: Wed, 6 Feb 2019 14:35:32 +0100 Subject: [PATCH 86/98] replace cout by PrintMessage --- libsrc/meshing/parallelmesh.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libsrc/meshing/parallelmesh.cpp b/libsrc/meshing/parallelmesh.cpp index 3258d2d9..cbaca6d7 100644 --- a/libsrc/meshing/parallelmesh.cpp +++ b/libsrc/meshing/parallelmesh.cpp @@ -984,7 +984,8 @@ namespace netgen stringstream str; str << "p" << id << ": got " << GetNE() << " elements and " << GetNSE() << " surface elements"; - cout << str.str() << endl; + PrintMessage(2, str.str()); + // cout << str.str() << endl; // PrintMessage (2, "Got ", GetNE(), " elements and ", GetNSE(), " surface elements"); // PrintMessage (2, "Got ", GetNSE(), " surface elements"); From d5f1076e173e9e312c4563f7df11ec3fe58b87ff Mon Sep 17 00:00:00 2001 From: Christopher Lackner Date: Wed, 6 Feb 2019 19:13:51 +0100 Subject: [PATCH 87/98] read tet10, pyramid13, prism15 and hex20 from gmsh --- libsrc/general/array.hpp | 7 +- libsrc/include/nginterface.h | 4 +- libsrc/include/nginterface_v2.hpp | 2 +- libsrc/meshing/curvedelems.cpp | 127 ++++++++++++++++++++++++++++ libsrc/meshing/meshclass.cpp | 6 +- libsrc/meshing/meshtype.cpp | 89 ++++++++++++++++++- libsrc/meshing/meshtype.hpp | 15 ++-- libsrc/meshing/python_mesh.cpp | 51 +++-------- libsrc/meshing/secondorder.cpp | 38 +++++++++ libsrc/meshing/topology.hpp | 25 +++++- libsrc/visualization/vsmesh.cpp | 2 +- libsrc/visualization/vssolution.cpp | 11 ++- python/read_gmsh.py | 108 ++++++++++++++++------- 13 files changed, 396 insertions(+), 89 deletions(-) diff --git a/libsrc/general/array.hpp b/libsrc/general/array.hpp index 16bb6e78..df0cd0a5 100644 --- a/libsrc/general/array.hpp +++ b/libsrc/general/array.hpp @@ -243,10 +243,11 @@ namespace netgen } explicit Array(size_t asize) - : FlatArray (asize, new T[asize]) + : FlatArray (asize, asize ? new T[asize] : nullptr) { - allocsize = asize; - ownmem = 1; + allocsize = asize; + if(asize) + ownmem = 1; } /// Generate array in user data diff --git a/libsrc/include/nginterface.h b/libsrc/include/nginterface.h index 38e38ec2..24e90cc1 100644 --- a/libsrc/include/nginterface.h +++ b/libsrc/include/nginterface.h @@ -32,7 +32,7 @@ // max number of nodes per element -#define NG_ELEMENT_MAXPOINTS 12 +#define NG_ELEMENT_MAXPOINTS 20 // max number of nodes per surface element #define NG_SURFACE_ELEMENT_MAXPOINTS 8 @@ -49,7 +49,7 @@ enum NG_ELEMENT_TYPE { NG_SEGM = 1, NG_SEGM3 = 2, NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14, NG_TET = 20, NG_TET10 = 21, - NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, + NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, NG_PRISM15 = 27, NG_PYRAMID13 = 28, NG_HEX = 25, NG_HEX20 = 26 }; diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index d6d4c5a8..962f061c 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -19,7 +19,7 @@ enum NG_ELEMENT_TYPE { NG_SEGM = 1, NG_SEGM3 = 2, NG_TRIG = 10, NG_QUAD=11, NG_TRIG6 = 12, NG_QUAD6 = 13, NG_QUAD8 = 14, NG_TET = 20, NG_TET10 = 21, - NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, + NG_PYRAMID = 22, NG_PRISM = 23, NG_PRISM12 = 24, NG_PRISM15 = 27, NG_PYRAMID13 = 28, NG_HEX = 25, NG_HEX20 = 26 }; diff --git a/libsrc/meshing/curvedelems.cpp b/libsrc/meshing/curvedelems.cpp index a3e7f209..182945d3 100644 --- a/libsrc/meshing/curvedelems.cpp +++ b/libsrc/meshing/curvedelems.cpp @@ -2790,6 +2790,32 @@ namespace netgen break; } + case PRISM15: + { + shapes = 0.0; + T x = xi(0); + T y = xi(1); + T z = xi(2); + T lam = 1-x-y; + T lamz = 1-z; + shapes[0] = (2*x*x-x) * (2*lamz*lamz-lamz); + shapes[1] = (2*y*y-y) * (2*lamz*lamz-lamz); + shapes[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); + shapes[3] = (2*x*x-x) * (2*z*z-z); + shapes[4] = (2*y*y-y) * (2*z*z-z); + shapes[5] = (2*lam*lam-lam) * (2*z*z-z); + shapes[6] = 4 * x * y * (2*lamz*lamz-lamz); + shapes[7] = 4 * x * lam * (2*lamz*lamz-lamz); + shapes[8] = 4 * y * lam * (2*lamz*lamz-lamz); + shapes[9] = x * 4 * z * (1-z); + shapes[10] = y * 4 * z * (1-z); + shapes[11] = lam * 4 * z * (1-z); + shapes[12] = 4 * x * y * (2*z*z-z); + shapes[13] = 4 * x * lam * (2*z*z-z); + shapes[14] = 4 * y * lam * (2*z*z-z); + break; + } + case PYRAMID: { shapes = 0.0; @@ -2839,6 +2865,29 @@ namespace netgen break; } + case PYRAMID13: + { + shapes = 0.0; + T x = xi(0); + T y = xi(1); + T z = xi(2); + z *= 1-1e-12; + shapes[0] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (-2*x - z + 2)*(-2*y - z + 2))*(-0.5*x - 0.5*y - 0.5*z + 0.25); + shapes[1] = (0.5*x - 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(-2*y - z + 2)); + shapes[2] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(2*y + z))*(0.5*x + 0.5*y + 0.5*z - 0.75); + shapes[3] = (-0.5*x + 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*y + z)*(-2*x - z + 2)); + shapes[4] = z*(2*z - 1); + shapes[5] = 2*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + shapes[6] = 4*x*y*(-2*x - 2*z + 2)/(-2*z + 2); + shapes[7] = 2*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + shapes[8] = 4*x*y*(-2*y - 2*z + 2)/(-2*z + 2); + shapes[9] = z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); + shapes[10] = 2*x*z*(-2*y - 2*z + 2)/(-z + 1); + shapes[11] = 4*x*y*z/(-z + 1); + shapes[12] = 2*y*z*(-2*x - 2*z + 2)/(-z + 1); + break; + } + case HEX: { shapes = 0.0; @@ -3300,6 +3349,36 @@ namespace netgen } + case PRISM15: + { + AutoDiff<3,T> x(xi(0), 0); + AutoDiff<3,T> y(xi(1), 1); + AutoDiff<3,T> z(xi(2), 2); + AutoDiff<3,T> ad[15]; + AutoDiff<3,T> lam = 1-x-y; + AutoDiff<3,T> lamz = 1-z; + + ad[0] = (2*x*x-x) * (2*lamz*lamz-lamz); + ad[1] = (2*y*y-y) * (2*lamz*lamz-lamz); + ad[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); + ad[3] = (2*x*x-x) * (2*z*z-z); + ad[4] = (2*y*y-y) * (2*z*z-z); + ad[5] = (2*lam*lam-lam) * (2*z*z-z); + ad[6] = 4 * x * y * (2*lamz*lamz-lamz); + ad[7] = 4 * x * lam * (2*lamz*lamz-lamz); + ad[8] = 4 * y * lam * (2*lamz*lamz-lamz); + ad[9] = x * 4 * z * (1-z); + ad[10] = y * 4 * z * (1-z); + ad[11] = lam * 4 * z * (1-z); + ad[12] = 4 * x * y * (2*z*z-z); + ad[13] = 4 * x * lam * (2*z*z-z); + ad[14] = 4 * y * lam * (2*z*z-z); + + for(int i=0; i<15; i++) + for(int j=0; j<3; j++) + dshapes(i,j) = ad[i].DValue(j); + break; + } case PYRAMID: { // if (typeid(T) == typeid(SIMD)) return; @@ -3397,6 +3476,54 @@ namespace netgen break; } + case PYRAMID13: + { + T x = xi(0); + T y = xi(1); + T z = xi(2); + z *= 1-1e-12; + dshapes(0,0) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(4*y + 2*z + 2*z*(2*y + z - 1)/(-z + 1) - 4); + dshapes(0,1) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(4*x + 2*z + 2*z*(2*x + z - 1)/(-z + 1) - 4); + dshapes(0,2) = 0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(-2*x - z + 2)*(-2*y - z + 2) + (-0.5*x - 0.5*y - 0.5*z + 0.25)*(2*x + 2*y + 2*z + z*(2*x + z - 1)/(-z + 1) + z*(2*y + z - 1)/(-z + 1) + z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) - 5 + (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); + dshapes(1,0) = -0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(-2*y - z + 2) + (0.5*x - 0.5*y - 0.25)*(-4*y - 2*z - 2*z*(2*y + z - 1)/(-z + 1) + 4); + dshapes(1,1) = 0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(2*x + z)*(-2*y - z + 2) + (-4*x - 2*z - 2*z*(2*x + z - 1)/(-z + 1))*(0.5*x - 0.5*y - 0.25); + dshapes(1,2) = (0.5*x - 0.5*y - 0.25)*(-2*x - 2*y - 2*z - z*(2*x + z - 1)/(-z + 1) - z*(2*y + z - 1)/(-z + 1) - z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) + 1 - (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); + dshapes(2,0) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (4*y + 2*z + 2*z*(2*y + z - 1)/(-z + 1))*(0.5*x + 0.5*y + 0.5*z - 0.75); + dshapes(2,1) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (4*x + 2*z + 2*z*(2*x + z - 1)/(-z + 1))*(0.5*x + 0.5*y + 0.5*z - 0.75); + dshapes(2,2) = -0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*x + z)*(2*y + z) + (0.5*x + 0.5*y + 0.5*z - 0.75)*(2*x + 2*y + 2*z + z*(2*x + z - 1)/(-z + 1) + z*(2*y + z - 1)/(-z + 1) + z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) - 1 + (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); + dshapes(3,0) = 0.5*z + 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) - 0.5*(2*y + z)*(-2*x - z + 2) + (-0.5*x + 0.5*y - 0.25)*(-4*y - 2*z - 2*z*(2*y + z - 1)/(-z + 1)); + dshapes(3,1) = -0.5*z - 0.5*z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + 0.5*(2*y + z)*(-2*x - z + 2) + (-0.5*x + 0.5*y - 0.25)*(-4*x - 2*z - 2*z*(2*x + z - 1)/(-z + 1) + 4); + dshapes(3,2) = (-0.5*x + 0.5*y - 0.25)*(-2*x - 2*y - 2*z - z*(2*x + z - 1)/(-z + 1) - z*(2*y + z - 1)/(-z + 1) - z*(2*x + z - 1)*(2*y + z - 1)/((-z + 1)*(-z + 1)) + 1 - (2*x + z - 1)*(2*y + z - 1)/(-z + 1)); + dshapes(4,0) = 0; + dshapes(4,1) = 0; + dshapes(4,2) = 4*z - 1; + dshapes(5,0) = -4*x*(-2*y - 2*z + 2)/(-2*z + 2) + 2*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(5,1) = -4*x*(-2*x - 2*z + 2)/(-2*z + 2); + dshapes(5,2) = -4*x*(-2*x - 2*z + 2)/(-2*z + 2) - 4*x*(-2*y - 2*z + 2)/(-2*z + 2) + 4*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); + dshapes(6,0) = -8*x*y/(-2*z + 2) + 4*y*(-2*x - 2*z + 2)/(-2*z + 2); + dshapes(6,1) = 4*x*(-2*x - 2*z + 2)/(-2*z + 2); + dshapes(6,2) = -8*x*y/(-2*z + 2) + 8*x*y*(-2*x - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); + dshapes(7,0) = -4*y*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(7,1) = -4*y*(-2*x - 2*z + 2)/(-2*z + 2) + 2*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(7,2) = -4*y*(-2*x - 2*z + 2)/(-2*z + 2) - 4*y*(-2*y - 2*z + 2)/(-2*z + 2) + 4*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); + dshapes(8,0) = 4*y*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(8,1) = -8*x*y/(-2*z + 2) + 4*x*(-2*y - 2*z + 2)/(-2*z + 2); + dshapes(8,2) = -8*x*y/(-2*z + 2) + 8*x*y*(-2*y - 2*z + 2)/((-2*z + 2)*(-2*z + 2)); + dshapes(9,0) = -2*z*(-2*y - 2*z + 2)/(-z + 1); + dshapes(9,1) = -2*z*(-2*x - 2*z + 2)/(-z + 1); + dshapes(9,2) = -2*z*(-2*x - 2*z + 2)/(-z + 1) - 2*z*(-2*y - 2*z + 2)/(-z + 1) + z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/((-z + 1)*(-z + 1)) + (-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); + dshapes(10,0) = 2*z*(-2*y - 2*z + 2)/(-z + 1); + dshapes(10,1) = -4*x*z/(-z + 1); + dshapes(10,2) = -4*x*z/(-z + 1) + 2*x*z*(-2*y - 2*z + 2)/((-z + 1)*(-z + 1)) + 2*x*(-2*y - 2*z + 2)/(-z + 1); + dshapes(11,0) = 4*y*z/(-z + 1); + dshapes(11,1) = 4*x*z/(-z + 1); + dshapes(11,2) = 4*x*y*z/((-z + 1)*(-z + 1)) + 4*x*y/(-z + 1); + dshapes(12,0) = -4*y*z/(-z + 1); + dshapes(12,1) = 2*z*(-2*x - 2*z + 2)/(-z + 1); + dshapes(12,2) = -4*y*z/(-z + 1) + 2*y*z*(-2*x - 2*z + 2)/((-z + 1)*(-z + 1)) + 2*y*(-2*x - 2*z + 2)/(-z + 1); + break; + } + case HEX: { // if (typeid(T) == typeid(SIMD)) return; diff --git a/libsrc/meshing/meshclass.cpp b/libsrc/meshing/meshclass.cpp index 0d8f5879..807de27e 100644 --- a/libsrc/meshing/meshclass.cpp +++ b/libsrc/meshing/meshclass.cpp @@ -4712,7 +4712,7 @@ namespace netgen lam(2) > -eps && lam(0) + lam(1) + lam(2) < 1+eps); } - else if (el.GetType() == PRISM) + else if (el.GetType() == PRISM || el.GetType() == PRISM15) { retval = (lam(0) > -eps && lam(1) > -eps && @@ -4720,7 +4720,7 @@ namespace netgen lam(2) < 1+eps && lam(0) + lam(1) < 1+eps); } - else if (el.GetType() == PYRAMID) + else if (el.GetType() == PYRAMID || el.GetType() == PYRAMID13) { retval = (lam(0) > -eps && lam(1) > -eps && @@ -4728,7 +4728,7 @@ namespace netgen lam(0) + lam(2) < 1+eps && lam(1) + lam(2) < 1+eps); } - else if (el.GetType() == HEX) + else if (el.GetType() == HEX || el.GetType() == HEX20) { retval = (lam(0) > -eps && lam(0) < 1+eps && lam(1) > -eps && lam(1) < 1+eps && diff --git a/libsrc/meshing/meshtype.cpp b/libsrc/meshing/meshtype.cpp index 494a3879..b28cc92d 100644 --- a/libsrc/meshing/meshtype.cpp +++ b/libsrc/meshing/meshtype.cpp @@ -1028,6 +1028,8 @@ namespace netgen case 6: typ = PRISM; break; case 8: typ = HEX; break; case 10: typ = TET10; break; + case 13: typ = PYRAMID13; break; + case 15: typ = PRISM15; break; case 20: typ = HEX20; break; default: cerr << "Element::Element: unknown element with " << np << " points" << endl; } @@ -1109,6 +1111,8 @@ namespace netgen case 6: typ = PRISM; break; case 8: typ = HEX; break; case 10: typ = TET10; break; + case 13: typ = PYRAMID13; break; + case 15: typ = PRISM15; break; case 20: typ = HEX20; break; // default: break; @@ -1128,7 +1132,9 @@ namespace netgen case PRISM: np = 6; break; case HEX: np = 8; break; case TET10: np = 10; break; + case PYRAMID13: np = 13; break; case PRISM12: np = 12; break; + case PRISM15: np = 15; break; case HEX20: np = 20; break; default: break; @@ -1958,7 +1964,27 @@ namespace netgen shape(4) = p(2); break; } - + case PYRAMID13: + { + T x = p(0); + T y = p(1); + T z = p(2); + z *= 1-1e-12; + shape[0] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (-2*x - z + 2)*(-2*y - z + 2))*(-0.5*x - 0.5*y - 0.5*z + 0.25); + shape[1] = (0.5*x - 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(-2*y - z + 2)); + shape[2] = (-z + z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*x + z)*(2*y + z))*(0.5*x + 0.5*y + 0.5*z - 0.75); + shape[3] = (-0.5*x + 0.5*y - 0.25)*(-z - z*(2*x + z - 1)*(2*y + z - 1)/(-z + 1) + (2*y + z)*(-2*x - z + 2)); + shape[4] = z*(2*z - 1); + shape[5] = 2*x*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + shape[6] = 4*x*y*(-2*x - 2*z + 2)/(-2*z + 2); + shape[7] = 2*y*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-2*z + 2); + shape[8] = 4*x*y*(-2*y - 2*z + 2)/(-2*z + 2); + shape[9] = z*(-2*x - 2*z + 2)*(-2*y - 2*z + 2)/(-z + 1); + shape[10] = 2*x*z*(-2*y - 2*z + 2)/(-z + 1); + shape[11] = 4*x*y*z/(-z + 1); + shape[12] = 2*y*z*(-2*x - 2*z + 2)/(-z + 1); + break; + } case PRISM: { shape(0) = p(0) * (1-p(2)); @@ -1969,6 +1995,30 @@ namespace netgen shape(5) = (1-p(0)-p(1)) * p(2); break; } + case PRISM15: + { + T x = p(0); + T y = p(1); + T z = p(2); + T lam = 1-x-y; + T lamz = 1-z; + shape[0] = (2*x*x-x) * (2*lamz*lamz-lamz); + shape[1] = (2*y*y-y) * (2*lamz*lamz-lamz); + shape[2] = (2*lam*lam-lam) * (2*lamz*lamz-lamz); + shape[3] = (2*x*x-x) * (2*z*z-z); + shape[4] = (2*y*y-y) * (2*z*z-z); + shape[5] = (2*lam*lam-lam) * (2*z*z-z); + shape[6] = 4 * x * y * (2*lamz*lamz-lamz); + shape[7] = 4 * x * lam * (2*lamz*lamz-lamz); + shape[8] = 4 * y * lam * (2*lamz*lamz-lamz); + shape[9] = x * 4 * z * (1-z); + shape[10] = y * 4 * z * (1-z); + shape[11] = lam * 4 * z * (1-z); + shape[12] = 4 * x * y * (2*z*z-z); + shape[13] = 4 * x * lam * (2*z*z-z); + shape[14] = 4 * y * lam * (2*z*z-z); + break; + } case HEX: { shape(0) = (1-p(0))*(1-p(1))*(1-p(2)); @@ -1981,6 +2031,43 @@ namespace netgen shape(7) = (1-p(0))*( p(1))*( p(2)); break; } + case HEX20: + { + T x = p(0); + T y = p(1); + T z = p(2); + shape[0] = (1-x)*(1-y)*(1-z); + shape[1] = x *(1-y)*(1-z); + shape[2] = x * y *(1-z); + shape[3] = (1-x)* y *(1-z); + shape[4] = (1-x)*(1-y)*(z); + shape[5] = x *(1-y)*(z); + shape[6] = x * y *(z); + shape[7] = (1-x)* y *(z); + + T sigma[8]={(1-x)+(1-y)+(1-z),x+(1-y)+(1-z),x+y+(1-z),(1-x)+y+(1-z), + (1-x)+(1-y)+z,x+(1-y)+z,x+y+z,(1-x)+y+z}; + + static const int e[12][2] = + { + { 0, 1 }, { 2, 3 }, { 3, 0 }, { 1, 2 }, + { 4, 5 }, { 6, 7 }, { 7, 4 }, { 5, 6 }, + { 0, 4 }, { 1, 5 }, { 2, 6 }, { 3, 7 }, + }; + + for (int i = 0; i < 12; i++) + { + T lame = shape[e[i][0]]+shape[e[i][1]]; + T xi = sigma[e[i][1]]-sigma[e[i][0]]; + shape[8+i] = (1-xi*xi)*lame; + } + for (int i = 0; i < 12; i++) + { + shape[e[i][0]] -= 0.5 * shape[8+i]; + shape[e[i][1]] -= 0.5 * shape[8+i]; + } + break; + } default: throw NgException("Element :: GetNewShape not implemented for that element"); } diff --git a/libsrc/meshing/meshtype.hpp b/libsrc/meshing/meshtype.hpp index 1b31d597..df997e36 100644 --- a/libsrc/meshing/meshtype.hpp +++ b/libsrc/meshing/meshtype.hpp @@ -21,7 +21,7 @@ namespace netgen SEGMENT = 1, SEGMENT3 = 2, TRIG = 10, QUAD=11, TRIG6 = 12, QUAD6 = 13, QUAD8 = 14, TET = 20, TET10 = 21, - PYRAMID = 22, PRISM = 23, PRISM12 = 24, + PYRAMID = 22, PRISM = 23, PRISM12 = 24, PRISM15 = 27, PYRAMID13 = 28, HEX = 25, HEX20 = 26 }; @@ -708,16 +708,18 @@ namespace netgen /// uint8_t GetNV() const { - __assume(typ >= TET && typ <= HEX20); + __assume(typ >= TET && typ <= PYRAMID13); switch (typ) { case TET: case TET10: return 4; - case PRISM12: - case PRISM: + case PRISM12: + case PRISM15: + case PRISM: return 6; case PYRAMID: + case PYRAMID13: return 5; case HEX: case HEX20: @@ -795,8 +797,9 @@ namespace netgen { case TET: case TET10: return 4; - case PYRAMID: return 5; - case PRISM: + case PYRAMID: case PYRAMID13: return 5; + case PRISM: + case PRISM15: case PRISM12: return 5; case HEX: case HEX20: return 6; diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index dbc498cb..45929e4b 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -256,44 +256,19 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) py::class_(m, "Element3D") .def(py::init([](int index, py::list vertices) { - Element * newel = nullptr; - if (py::len(vertices) == 4) - { - newel = new Element(TET); - for (int i = 0; i < 4; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); - } - else if (py::len(vertices) == 5) - { - newel = new Element(PYRAMID); - for (int i = 0; i < 5; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); - } - else if (py::len(vertices) == 6) - { - newel = new Element(PRISM); - for (int i = 0; i < 6; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); - } - else if (py::len(vertices) == 8) - { - newel = new Element(HEX); - for (int i = 0; i < 8; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); - } - else if (py::len(vertices) == 20) - { - newel = new Element(HEX20); - for (int i = 0; i < 20; i++) - (*newel)[i] = py::extract(vertices[i])(); - newel->SetIndex(index); - } - else - throw NgException ("cannot create element"); + std::map types = {{4, TET}, + {5, PYRAMID}, + {6, PRISM}, + {8, HEX}, + {10, TET10}, + {13, PYRAMID13}, + {15, PRISM15}, + {20, HEX20}}; + int np = py::len(vertices); + auto newel = new Element(types[np]); + for(int i=0; i(vertices[i]); + newel->SetIndex(index); return newel; }), py::arg("index")=1,py::arg("vertices"), diff --git a/libsrc/meshing/secondorder.cpp b/libsrc/meshing/secondorder.cpp index 6241fd4e..49f91662 100644 --- a/libsrc/meshing/secondorder.cpp +++ b/libsrc/meshing/secondorder.cpp @@ -223,6 +223,29 @@ namespace netgen { 3, 4, 10 }, { 4, 5, 11 }, }; + static int betw_prism15[9][3] = + { + { 0, 1, 6 }, + { 0, 2, 7 }, + { 1, 2, 8 }, + { 0, 3, 9 }, + { 1, 4, 10 }, + { 2, 5, 11 }, + { 3, 4, 12 }, + { 3, 5, 13 }, + { 4, 5, 14 } + }; + static int betw_pyramid[8][3] = + { + { 0, 1, 5 }, + { 3, 2, 6 }, + { 3, 0, 7 }, + { 1, 2, 8 }, + { 0, 4, 9 }, + { 1, 4, 10 }, + { 2, 4, 11 }, + { 3, 4, 12 } + }; static int betw_hex[12][3] = { { 0, 1, 8 }, @@ -259,6 +282,21 @@ namespace netgen onp = 6; break; } + case PRISM15: + { + betw = betw_prism15; + newel.SetType(PRISM15); + onp = 6; + break; + } + case PYRAMID: + case PYRAMID13: + { + betw = betw_pyramid; + newel.SetType(PYRAMID13); + onp = 5; + break; + } case HEX: case HEX20: { diff --git a/libsrc/meshing/topology.hpp b/libsrc/meshing/topology.hpp index 625b15d7..b4e646d2 100644 --- a/libsrc/meshing/topology.hpp +++ b/libsrc/meshing/topology.hpp @@ -212,10 +212,12 @@ inline short int MeshTopology :: GetNVertices (ELEMENT_TYPE et) return 4; case PYRAMID: + case PYRAMID13: return 5; case PRISM: case PRISM12: + case PRISM15: return 6; case HEX: @@ -257,10 +259,15 @@ inline short int MeshTopology :: GetNPoints (ELEMENT_TYPE et) case PYRAMID: return 5; + case PYRAMID13: + return 13; case PRISM: - case PRISM12: return 6; + case PRISM12: + return 12; + case PRISM15: + return 15; case HEX: return 8; @@ -277,7 +284,7 @@ inline short int MeshTopology :: GetNPoints (ELEMENT_TYPE et) inline short int MeshTopology :: GetNEdges (ELEMENT_TYPE et) { - __assume(et >= SEGMENT && et <= HEX); + __assume(et >= SEGMENT && et <= PYRAMID13); switch (et) { case SEGMENT: @@ -298,10 +305,12 @@ inline short int MeshTopology :: GetNEdges (ELEMENT_TYPE et) return 6; case PYRAMID: + case PYRAMID13: return 8; case PRISM: case PRISM12: + case PRISM15: return 9; case HEX: @@ -318,7 +327,7 @@ inline short int MeshTopology :: GetNEdges (ELEMENT_TYPE et) inline short int MeshTopology :: GetNFaces (ELEMENT_TYPE et) { - __assume(et >= SEGMENT && et <= HEX); + __assume(et >= SEGMENT && et <= PYRAMID13); switch (et) { case SEGMENT: @@ -339,10 +348,12 @@ inline short int MeshTopology :: GetNFaces (ELEMENT_TYPE et) return 4; case PYRAMID: + case PYRAMID13: return 5; case PRISM: case PRISM12: + case PRISM15: return 5; case HEX: @@ -443,10 +454,12 @@ const ELEMENT_EDGE * MeshTopology :: GetEdges1 (ELEMENT_TYPE et) return tet_edges; case PYRAMID: + case PYRAMID13: return pyramid_edges; case PRISM: case PRISM12: + case PRISM15: return prism_edges; case HEX: @@ -542,10 +555,12 @@ const ELEMENT_EDGE * MeshTopology :: GetEdges0 (ELEMENT_TYPE et) return tet_edges; case PYRAMID: + case PYRAMID13: return pyramid_edges; case PRISM: case PRISM12: + case PRISM15: return prism_edges; case HEX: @@ -627,9 +642,11 @@ inline const ELEMENT_FACE * MeshTopology :: GetFaces1 (ELEMENT_TYPE et) case PRISM: case PRISM12: + case PRISM15: return prism_faces; case PYRAMID: + case PYRAMID13: return pyramid_faces; case SEGMENT: @@ -710,9 +727,11 @@ inline const ELEMENT_FACE * MeshTopology :: GetFaces0 (ELEMENT_TYPE et) case PRISM: case PRISM12: + case PRISM15: return prism_faces; case PYRAMID: + case PYRAMID13: return pyramid_faces; case SEGMENT: diff --git a/libsrc/visualization/vsmesh.cpp b/libsrc/visualization/vsmesh.cpp index d758c626..a6c5ef4c 100644 --- a/libsrc/visualization/vsmesh.cpp +++ b/libsrc/visualization/vsmesh.cpp @@ -2682,7 +2682,7 @@ namespace netgen for (ElementIndex ei = 0; ei < mesh->GetNE(); ei++) { const Element & el = (*mesh)[ei]; - if (el.GetType() == PYRAMID && !el.IsDeleted()) + if ((el.GetType() == PYRAMID || el.GetType() == PYRAMID13) && !el.IsDeleted()) { int i = ei + 1; diff --git a/libsrc/visualization/vssolution.cpp b/libsrc/visualization/vssolution.cpp index 201f1fba..3b0b61cc 100644 --- a/libsrc/visualization/vssolution.cpp +++ b/libsrc/visualization/vssolution.cpp @@ -2857,6 +2857,7 @@ namespace netgen } case PRISM: case PRISM12: + case PRISM15: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; @@ -2907,6 +2908,7 @@ namespace netgen } case PRISM: case PRISM12: + case PRISM15: { lami[0] = (1-lam3) * (1-lam1-lam2); lami[1] = (1-lam3) * lam1; @@ -2918,6 +2920,7 @@ namespace netgen break; } case PYRAMID: + case PYRAMID13: { if (lam3 > 1-1e-5) { @@ -4019,7 +4022,7 @@ namespace netgen if(vispar.donotclipdomain > 0 && vispar.donotclipdomain == (*mesh)[ei].GetIndex()) continue; ELEMENT_TYPE type = (*mesh)[ei].GetType(); - if (type == HEX || type == PRISM || type == TET || type == TET10 || type == PYRAMID) + if (type == HEX || type == PRISM || type == TET || type == TET10 || type == PYRAMID || type == PYRAMID13 || type == PRISM15 || type == HEX20) { const Element & el = (*mesh)[ei]; @@ -4078,6 +4081,8 @@ namespace netgen switch (type) { case PRISM: + case PRISM12: + case PRISM15: if (ix+iy <= n) { ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); @@ -4088,9 +4093,11 @@ namespace netgen compress[ii] = -1; break; case HEX: + case HEX20: ploc = Point<3> (double(ix) / n, double(iy) / n, double(iz) / n); break; case PYRAMID: + case PYRAMID13: ploc = Point<3> (double(ix) / n * (1-double(iz)/n), double(iy) / n * (1-double(iz)/n), double(iz)/n); @@ -4104,7 +4111,7 @@ namespace netgen locgrid[compress[ii]] = ploc; } - if (type != TET && type != TET10 && type != PRISM) cnt_valid = n3; + if (type != TET && type != TET10 && type != PRISM && type != PRISM12 && type != PRISM15) cnt_valid = n3; locgrid.SetSize(cnt_valid); diff --git a/python/read_gmsh.py b/python/read_gmsh.py index 0617732d..23a7ec52 100644 --- a/python/read_gmsh.py +++ b/python/read_gmsh.py @@ -1,9 +1,10 @@ from netgen.meshing import * - def ReadGmsh(filename): + if not filename.endswith(".msh"): + filename += ".msh" meshdim = 1 - with open(filename + ".msh", 'r') as f: + with open(filename, 'r') as f: while f.readline().split()[0] != "$Elements": pass nelem = int(f.readline()) @@ -16,15 +17,58 @@ def ReadGmsh(filename): meshdim = 3 break - f = open(filename + ".msh", 'r') + f = open(filename, 'r') mesh = Mesh(dim=meshdim) pointmap = {} facedescriptormap = {} - namemap = {} + namemap = { 0 : "default" } materialmap = {} bbcmap = {} + segm = 1 + trig = 2 + quad = 3 + tet = 4 + hex = 5 + prism = 6 + pyramid = 7 + segm3 = 8 # 2nd order line + trig6 = 9 # 2nd order trig + tet10 = 11 # 2nd order tet + point = 15 + quad8 = 16 # 2nd order quad + hex20 = 17 # 2nd order hex + prism15 = 18 # 2nd order prism + pyramid13 = 19 # 2nd order pyramid + segms = [segm, segm3] + trigs = [trig, trig6] + quads = [quad, quad8] + tets = [tet, tet10] + hexes = [hex, hex20] + prisms = [prism, prism15] + pyramids = [pyramid, pyramid13] + elem0d = [point] + elem1d = segms + elem2d = trigs + quads + elem3d = tets + hexes + prisms + pyramids + + num_nodes_map = { segm : 2, + trig : 3, + quad : 4, + tet : 4, + hex : 8, + prism : 6, + pyramid : 5, + segm3 : 3, + trig6 : 6, + tet10 : 10, + point : 1, + quad8 : 8, + hex20 : 20, + prism15 : 18, + pyramid13 : 19 } + while True: line = f.readline() if line == "": @@ -57,29 +101,14 @@ def ReadGmsh(filename): # the first tag is the physical group nr, the second tag is the group nr of the dim tags = [int(line[3 + k]) for k in range(numtags)] - if elmtype == 1: # 2-node line - num_nodes = 2 - elif elmtype == 2: # 3-node trig - num_nodes = 3 - elif elmtype == 3: # 4-node quad - num_nodes = 4 - elif elmtype == 4: # 4-node tet - num_nodes = 4 - elif elmtype == 5: # 8-node hex - num_nodes = 8 - elif elmtype == 6: # 6-node prism - num_nodes = 6 - elif elmtype == 7: # 5-node pyramid - num_nodes = 5 - elif elmtype == 15: # 1-node point - num_nodes = 1 - else: + if elmtype not in num_nodes_map: raise Exception("element type", elmtype, "not implemented") + num_nodes = num_nodes_map[elmtype] nodenums = line[3 + numtags:3 + numtags + num_nodes] nodenums2 = [pointmap[int(nn)] for nn in nodenums] - if elmtype == 1: + if elmtype in elem1d: if meshdim == 3: if tags[1] in bbcmap: index = bbcmap[tags[1]] @@ -117,7 +146,7 @@ def ReadGmsh(filename): mesh.Add(Element1D(index=index, vertices=nodenums2)) - if elmtype in [2, 3]: # 2d elements + if elmtype in elem2d: # 2d elements if meshdim == 3: if tags[1] in facedescriptormap.keys(): index = facedescriptormap[tags[1]] @@ -142,9 +171,17 @@ def ReadGmsh(filename): mesh.SetMaterial(index, "surf" + str(tags[1])) materialmap[tags[1]] = index - mesh.Add(Element2D(index, nodenums2)) + if elmtype in trigs: + ordering = [i for i in range(3)] + if elmtype == trig6: + ordering += [4,5,3] + if elmtype in quads: + ordering = [i for i in range(4)] + if elmtype == quad8: + ordering += [4, 6, 7, 5] + mesh.Add(Element2D(index, [nodenums2[i] for i in ordering])) - if elmtype in [4, 5, 6, 7]: # volume elements + if elmtype in elem3d: # volume elements if tags[1] in materialmap: index = materialmap[tags[1]] else: @@ -157,9 +194,22 @@ def ReadGmsh(filename): nodenums2 = [pointmap[int(nn)] for nn in nodenums] - if elmtype == 4: - mesh.Add(Element3D(index, [nodenums2[0], nodenums2[1], nodenums2[3], nodenums2[2]])) - elif elmtype in [5, 6, 7]: - mesh.Add(Element3D(index, nodenums2)) + if elmtype in tets: + ordering = [0,1,2,3] + if elmtype == tet10: + ordering += [4,6,7,5,9,8] + elif elmtype in hexes: + ordering = [0,1,5,4,3,2,6,7] + if elmtype == hex20: + ordering += [8,16,10,12,13,19,15,14,9,11,18,17] + elif elmtype in prisms: + ordering = [0,2,1,3,5,4] + if elmtype == prism15: + ordering += [7,6,9,8,11,10,13,12,14] + elif elmtype in pyramids: + ordering = [3,2,1,0,4] + if elmtype == pyramid13: + ordering += [10,5,6,8,12,11,9,7] + mesh.Add(Element3D(index, [nodenums2[i] for i in ordering])) return mesh From 04f0f76bd21e622e8afcf941b5168305246d66c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 7 Feb 2019 15:58:53 +0100 Subject: [PATCH 88/98] header dependency --- libsrc/visualization/soldata.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libsrc/visualization/soldata.hpp b/libsrc/visualization/soldata.hpp index 56df5d65..b5f2b793 100644 --- a/libsrc/visualization/soldata.hpp +++ b/libsrc/visualization/soldata.hpp @@ -1,7 +1,7 @@ #ifndef FILE_SOLDATA #define FILE_SOLDATA - +#include // for tAVX namespace netgen { From 33f1e6da88d0c3502ad560cea43764e84a4cb056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 7 Feb 2019 20:26:55 +0100 Subject: [PATCH 89/98] namespace for tAVX --- libsrc/visualization/soldata.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsrc/visualization/soldata.hpp b/libsrc/visualization/soldata.hpp index b5f2b793..de6d8233 100644 --- a/libsrc/visualization/soldata.hpp +++ b/libsrc/visualization/soldata.hpp @@ -103,10 +103,10 @@ namespace netgen #ifdef __SSE__ virtual bool GetMultiSurfValue (size_t selnr, size_t facetnr, size_t npts, - const tAVXd * xref, - const tAVXd * x, - const tAVXd * dxdxref, - tAVXd * values) + const netgen::tAVXd * xref, + const netgen::tAVXd * x, + const netgen::tAVXd * dxdxref, + netgen::tAVXd * values) { cerr << "GetMultiSurfVaue not overloaded for SIMD" << endl; return false; From ead955cf040a9f01743b6c4fd0f8c809f1eedf4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 7 Feb 2019 20:32:01 +0100 Subject: [PATCH 90/98] ngsimd namespace --- libsrc/visualization/soldata.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libsrc/visualization/soldata.hpp b/libsrc/visualization/soldata.hpp index de6d8233..74143fc0 100644 --- a/libsrc/visualization/soldata.hpp +++ b/libsrc/visualization/soldata.hpp @@ -103,10 +103,10 @@ namespace netgen #ifdef __SSE__ virtual bool GetMultiSurfValue (size_t selnr, size_t facetnr, size_t npts, - const netgen::tAVXd * xref, - const netgen::tAVXd * x, - const netgen::tAVXd * dxdxref, - netgen::tAVXd * values) + const ngsimd::tAVXd * xref, + const ngsimd::tAVXd * x, + const ngsimd::tAVXd * dxdxref, + ngsimd::tAVXd * values) { cerr << "GetMultiSurfVaue not overloaded for SIMD" << endl; return false; From 966c2960fb216e373689b8a737792522be6d4de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Thu, 7 Feb 2019 23:09:34 +0100 Subject: [PATCH 91/98] rounding num segments per edge --- libsrc/geom2d/genmesh2d.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libsrc/geom2d/genmesh2d.cpp b/libsrc/geom2d/genmesh2d.cpp index b42440ce..b5e5000a 100644 --- a/libsrc/geom2d/genmesh2d.cpp +++ b/libsrc/geom2d/genmesh2d.cpp @@ -55,7 +55,8 @@ namespace netgen sum += dt / fun; } - int nel = int (sum+1); + int nel = int (sum+0.5); + if (nel == 0) nel = 1; fperel = sum / nel; points.Append (0); @@ -129,6 +130,7 @@ namespace netgen Point3d oldmark3(oldmark(0), oldmark(1), 0); double h = mesh.GetH (Point<3> (oldmark(0), oldmark(1), 0)); + cout << "edge h = " << h << endl; Vec<3> v (1e-4*h, 1e-4*h, 1e-4*h); searchtree.GetIntersecting (oldmark3 - v, oldmark3 + v, locsearch); From 1e6829d8c7ad6516018dbd7b21ce52a654c7be13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 8 Feb 2019 00:36:52 +0100 Subject: [PATCH 92/98] remove output --- libsrc/geom2d/genmesh2d.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libsrc/geom2d/genmesh2d.cpp b/libsrc/geom2d/genmesh2d.cpp index b5e5000a..fde8b16c 100644 --- a/libsrc/geom2d/genmesh2d.cpp +++ b/libsrc/geom2d/genmesh2d.cpp @@ -130,7 +130,6 @@ namespace netgen Point3d oldmark3(oldmark(0), oldmark(1), 0); double h = mesh.GetH (Point<3> (oldmark(0), oldmark(1), 0)); - cout << "edge h = " << h << endl; Vec<3> v (1e-4*h, 1e-4*h, 1e-4*h); searchtree.GetIntersecting (oldmark3 - v, oldmark3 + v, locsearch); From ae2eb4d0d8517467787db8c6595dc6555fd229ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 8 Feb 2019 09:51:38 +0100 Subject: [PATCH 93/98] namespace --- libsrc/include/nginterface_v2.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index 936a053e..b0dcfe89 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -29,12 +29,15 @@ enum NG_REFINEMENT_TYPE { NG_REFINE_H = 0, NG_REFINE_P = 1, NG_REFINE_HP = 2 }; #ifndef PARALLEL typedef int MPI_Comm; #endif -namespace netgen { extern DLL_HEADER MPI_Comm ng_comm; } namespace netgen { - + using namespace std; + using namespace ngcore; + + extern DLL_HEADER MPI_Comm ng_comm; + static constexpr int POINTINDEX_BASE = 1; struct T_EDGE2 From f661e4a30d8b7085e4839bd931ff7df7dffbac57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 8 Feb 2019 14:14:19 +0100 Subject: [PATCH 94/98] distribute --- libsrc/meshing/python_mesh.cpp | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 45929e4b..1c8ce9c5 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -521,15 +521,22 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) */ .def_property_readonly("_timestamp", &Mesh::GetTimeStamp) - .def("Distribute", [](Mesh & self, shared_ptr pycomm) { - MPI_Comm comm = pycomm!=nullptr ? pycomm->comm : self.GetCommunicator(); - self.SetCommunicator(comm); - if(MyMPI_GetNTasks(comm)==1) return; + .def("Distribute", [](shared_ptr self, shared_ptr pycomm) { + MPI_Comm comm = pycomm!=nullptr ? pycomm->comm : self->GetCommunicator(); + self->SetCommunicator(comm); + if(MyMPI_GetNTasks(comm)==1) return self; if(MyMPI_GetNTasks(comm)==2) throw NgException("Sorry, cannot handle communicators with NP=2!"); cout << " rank " << MyMPI_GetId(comm) << " of " << MyMPI_GetNTasks(comm) << " called Distribute " << endl; - if(MyMPI_GetId(comm)==0) self.Distribute(); - else self.SendRecvMesh(); + if(MyMPI_GetId(comm)==0) self->Distribute(); + else self->SendRecvMesh(); + return self; }, py::arg("comm")=nullptr) + .def("Receive", [](shared_ptr pycomm) { + auto mesh = make_shared(); + mesh->SetCommunicator(pycomm->comm); + mesh->SendRecvMesh(); + return mesh; + }) .def("Load", FunctionPointer ([](Mesh & self, const string & filename) { From bab9d41b1b8460645fbf61baa6b9f034827503b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 8 Feb 2019 17:15:02 +0100 Subject: [PATCH 95/98] why was SubComm that complicated ? --- libsrc/meshing/python_mesh.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 1c8ce9c5..c3d3a2fb 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -954,11 +954,21 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) .def("Sum", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_SUM, c.comm); }) .def("Min", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MIN, c.comm); }) .def("Max", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MAX, c.comm); }) - .def("SubComm", [](PyMPI_Comm & c, py::list proc_list) -> shared_ptr { + .def("SubComm", [](PyMPI_Comm & c, py::list proc_list) { + Array procs(py::len(proc_list)); + for (int i = 0; i < procs.Size(); i++) + procs[i] = py::extract(proc_list[i])(); + if (!procs.Size()) + return make_shared(MPI_COMM_NULL); + + MPI_Comm subcomm = MyMPI_SubCommunicator(c.comm, procs); + return make_shared(subcomm, true); + + /* Array procs; if (py::extract (proc_list).check()) { py::list pylist = py::extract (proc_list)(); - procs.SetSize(py::len(pylist)); + procs.SetSize(py::len(pyplist)); for (int i = 0; i < py::len(pylist); i++) procs[i] = py::extract(pylist[i])(); } @@ -974,6 +984,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) } MPI_Comm subcomm = MyMPI_SubCommunicator(c.comm, procs); return make_shared(subcomm, true); + */ }, py::arg("procs")); ; From 8a165ef8f1dea161e104d8fa07aa2d45b933bb6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 8 Feb 2019 20:24:54 +0100 Subject: [PATCH 96/98] subcomms --- libsrc/general/ngpython.hpp | 1 + libsrc/meshing/python_mesh.cpp | 11 +++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/libsrc/general/ngpython.hpp b/libsrc/general/ngpython.hpp index 0604cb00..722709c5 100644 --- a/libsrc/general/ngpython.hpp +++ b/libsrc/general/ngpython.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace py = pybind11; #include #include diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index c3d3a2fb..16d84c63 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -954,13 +954,12 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) .def("Sum", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_SUM, c.comm); }) .def("Min", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MIN, c.comm); }) .def("Max", [](PyMPI_Comm & c, size_t x) { return MyMPI_AllReduceNG(x, MPI_MAX, c.comm); }) - .def("SubComm", [](PyMPI_Comm & c, py::list proc_list) { - Array procs(py::len(proc_list)); + .def("SubComm", [](PyMPI_Comm & c, std::vector proc_list) { + Array procs(proc_list.size()); for (int i = 0; i < procs.Size(); i++) - procs[i] = py::extract(proc_list[i])(); - if (!procs.Size()) - return make_shared(MPI_COMM_NULL); - + procs[i] = proc_list[i]; + if (!procs.Contains(c.Rank())) + throw Exception("rank "+ToString(c.Rank())+" not in subcomm"); MPI_Comm subcomm = MyMPI_SubCommunicator(c.comm, procs); return make_shared(subcomm, true); From 9500f8d8f2f4454512b9078eb5066ccc82e1a86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Fri, 8 Feb 2019 22:12:00 +0100 Subject: [PATCH 97/98] handle 2 ranks case --- libsrc/meshing/parallelmesh.cpp | 69 +++++++++++++++++++++++---------- libsrc/meshing/python_mesh.cpp | 4 +- 2 files changed, 51 insertions(+), 22 deletions(-) diff --git a/libsrc/meshing/parallelmesh.cpp b/libsrc/meshing/parallelmesh.cpp index cbaca6d7..e9c040ef 100644 --- a/libsrc/meshing/parallelmesh.cpp +++ b/libsrc/meshing/parallelmesh.cpp @@ -1073,29 +1073,45 @@ namespace netgen Array epart(ne), npart(nn); idxtype nparts = MyMPI_GetNTasks(GetCommunicator())-1; - idxtype edgecut; - idxtype ncommon = 3; - METIS_PartMeshDual (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &ncommon, &nparts, - NULL, NULL, - &edgecut, &epart[0], &npart[0]); - - /* - METIS_PartMeshNodal (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &nparts, - NULL, NULL, - &edgecut, &epart[0], &npart[0]); - */ - PrintMessage (3, "metis complete"); - // cout << "done" << endl; - - for (int i = 0; i < GetNE(); i++) - VolumeElement(i+1).SetPartition(epart[i] + 1); - for (int i = 0; i < GetNSE(); i++) - SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1); - for (int i = 0; i < GetNSeg(); i++) - LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1); + if (nparts == 1) + { + for (int i = 0; i < GetNE(); i++) + VolumeElement(i+1).SetPartition(1); + for (int i = 0; i < GetNSE(); i++) + SurfaceElement(i+1).SetPartition(1); + for (int i = 0; i < GetNSeg(); i++) + LineSegment(i+1).SetPartition(1); + } + else + + { + idxtype edgecut; + + idxtype ncommon = 3; + METIS_PartMeshDual (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &ncommon, &nparts, + NULL, NULL, + &edgecut, &epart[0], &npart[0]); + + /* + METIS_PartMeshNodal (&ne, &nn, &eptr[0], &eind[0], NULL, NULL, &nparts, + NULL, NULL, + &edgecut, &epart[0], &npart[0]); + */ + PrintMessage (3, "metis complete"); + // cout << "done" << endl; + + for (int i = 0; i < GetNE(); i++) + VolumeElement(i+1).SetPartition(epart[i] + 1); + for (int i = 0; i < GetNSE(); i++) + SurfaceElement(i+1).SetPartition(epart[i+GetNE()] + 1); + for (int i = 0; i < GetNSeg(); i++) + LineSegment(i+1).SetPartition(epart[i+GetNE()+GetNSE()] + 1); + } + + // surface elements attached to volume elements Array boundarypoints (GetNP()); boundarypoints = false; @@ -1370,6 +1386,19 @@ namespace netgen Array epart(ne), npart(nn); idxtype nparts = MyMPI_GetNTasks(GetCommunicator())-1; + + if (nparts == 1) + { + for (int i = 0; i < GetNE(); i++) + VolumeElement(i+1).SetPartition(1); + for (int i = 0; i < GetNSE(); i++) + SurfaceElement(i+1).SetPartition(1); + for (int i = 0; i < GetNSeg(); i++) + LineSegment(i+1).SetPartition(1); + return; + } + + idxtype edgecut; diff --git a/libsrc/meshing/python_mesh.cpp b/libsrc/meshing/python_mesh.cpp index 16d84c63..34b00a0f 100644 --- a/libsrc/meshing/python_mesh.cpp +++ b/libsrc/meshing/python_mesh.cpp @@ -525,8 +525,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m) MPI_Comm comm = pycomm!=nullptr ? pycomm->comm : self->GetCommunicator(); self->SetCommunicator(comm); if(MyMPI_GetNTasks(comm)==1) return self; - if(MyMPI_GetNTasks(comm)==2) throw NgException("Sorry, cannot handle communicators with NP=2!"); - cout << " rank " << MyMPI_GetId(comm) << " of " << MyMPI_GetNTasks(comm) << " called Distribute " << endl; + // if(MyMPI_GetNTasks(comm)==2) throw NgException("Sorry, cannot handle communicators with NP=2!"); + // cout << " rank " << MyMPI_GetId(comm) << " of " << MyMPI_GetNTasks(comm) << " called Distribute " << endl; if(MyMPI_GetId(comm)==0) self->Distribute(); else self->SendRecvMesh(); return self; From 68c320fd53ed22ea323b4c070baff43cec294dc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20Sch=C3=B6berl?= Date: Mon, 11 Feb 2019 07:57:09 +0100 Subject: [PATCH 98/98] less ifdef PARALLEL --- libsrc/include/nginterface_v2.hpp | 3 +-- libsrc/interface/nginterface_v2.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/libsrc/include/nginterface_v2.hpp b/libsrc/include/nginterface_v2.hpp index b0dcfe89..bd432a43 100644 --- a/libsrc/include/nginterface_v2.hpp +++ b/libsrc/include/nginterface_v2.hpp @@ -363,9 +363,8 @@ namespace netgen int * const indices = NULL, int numind = 0) const; -#ifdef PARALLEL + // for MPI-parallel std::tuple GetDistantProcs (int nodetype, int locnum) const; -#endif shared_ptr GetMesh () const { return mesh; } shared_ptr SelectMesh () const; diff --git a/libsrc/interface/nginterface_v2.cpp b/libsrc/interface/nginterface_v2.cpp index 9be47b57..7fe34c1b 100644 --- a/libsrc/interface/nginterface_v2.cpp +++ b/libsrc/interface/nginterface_v2.cpp @@ -1245,11 +1245,11 @@ void Ngx_Mesh::SetSurfaceElementOrders (int enr, int ox, int oy) -#ifdef PARALLEL + std::tuple Ngx_Mesh :: GetDistantProcs (int nodetype, int locnum) const { - +#ifdef PARALLEL switch (nodetype) { case 0: @@ -1270,10 +1270,10 @@ void Ngx_Mesh::SetSurfaceElementOrders (int enr, int ox, int oy) default: return std::tuple(0,nullptr); } - } - +#else + return std::tuple(0,nullptr); #endif - + } }