mirror of
https://github.com/NGSolve/netgen.git
synced 2025-05-10 04:30:48 +05:00
Compare commits
334 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a9e8f2a1c9 | ||
![]() |
b84975586c | ||
![]() |
aa66cd11c4 | ||
![]() |
494b0ae37c | ||
![]() |
f42d0c0be4 | ||
![]() |
b43eb033d2 | ||
![]() |
1fc382867d | ||
![]() |
6ea09e1151 | ||
![]() |
36cbd5fc00 | ||
![]() |
3a9060fc2f | ||
![]() |
109e7ffcf7 | ||
![]() |
1db8ea3500 | ||
![]() |
b05c32675b | ||
![]() |
cb3eb0d355 | ||
![]() |
42294117bd | ||
![]() |
60c1151205 | ||
![]() |
3f28651e63 | ||
![]() |
5a66cbee72 | ||
![]() |
788c782455 | ||
![]() |
12ef984e93 | ||
![]() |
f15ba64a90 | ||
![]() |
3b79dbc8ff | ||
![]() |
7b13db740d | ||
![]() |
78994da199 | ||
![]() |
42c1818784 | ||
![]() |
97f869207e | ||
![]() |
951e20a7e4 | ||
![]() |
8cde49627b | ||
![]() |
36c9201ffc | ||
![]() |
8478ff5078 | ||
![]() |
714158e928 | ||
![]() |
9399f753c4 | ||
![]() |
8944322e60 | ||
![]() |
15bd6cbed0 | ||
![]() |
b8d722d6a8 | ||
![]() |
7aae5369c4 | ||
![]() |
787c6043fa | ||
![]() |
d240203932 | ||
![]() |
0c789fb04f | ||
![]() |
9204b079f6 | ||
![]() |
2778b934e6 | ||
![]() |
627e89d579 | ||
![]() |
bc194027a2 | ||
![]() |
d1a9f7ee3d | ||
![]() |
82befccada | ||
![]() |
9601f70c17 | ||
![]() |
5ab7a4995c | ||
![]() |
8b0b9e507f | ||
![]() |
f236648847 | ||
![]() |
2220fc093f | ||
![]() |
5e742f017c | ||
![]() |
fb399595fa | ||
![]() |
d2f7c24a5e | ||
![]() |
d7ae61e00a | ||
![]() |
058cdce84d | ||
![]() |
15ffcbae8e | ||
![]() |
913ede1cae | ||
![]() |
44fe189bf0 | ||
![]() |
b811162086 | ||
![]() |
12ff6d6f51 | ||
![]() |
b14a9e6d2b | ||
![]() |
d1228b6ce9 | ||
![]() |
7aff94046f | ||
![]() |
a8a75614c0 | ||
![]() |
6f574ec191 | ||
![]() |
20196cd8e9 | ||
![]() |
cf6c702d2c | ||
![]() |
5856001819 | ||
![]() |
49ecbd55ee | ||
![]() |
311ae9e89b | ||
![]() |
5292a09c94 | ||
![]() |
b79128fabf | ||
![]() |
886bb14299 | ||
![]() |
892271fd08 | ||
![]() |
c4985c49e1 | ||
![]() |
06e8764d01 | ||
![]() |
dcd6f6d60d | ||
![]() |
0a1fd5a2e2 | ||
![]() |
5642d435e1 | ||
![]() |
6af9b48bda | ||
![]() |
c0b33db5c0 | ||
![]() |
59e5974a28 | ||
![]() |
1f70e62fc7 | ||
![]() |
b1e840f7d8 | ||
![]() |
1ebc6a0e81 | ||
![]() |
63cb566b8d | ||
![]() |
9bc0273784 | ||
![]() |
c99f26ec12 | ||
![]() |
0b480f1eab | ||
![]() |
eefeca571b | ||
![]() |
58db55c2ff | ||
![]() |
0497dc25fd | ||
![]() |
2838327ba1 | ||
![]() |
566182f977 | ||
![]() |
dd508bf675 | ||
![]() |
643898c5e2 | ||
![]() |
3b3491a597 | ||
![]() |
e926071bb2 | ||
![]() |
ce5f6d695c | ||
![]() |
aca27f6421 | ||
![]() |
3185256ad3 | ||
![]() |
6d6e297a1f | ||
![]() |
bcbd390f7d | ||
![]() |
f117281ea4 | ||
![]() |
3362d91a37 | ||
![]() |
fe21b0bb8b | ||
![]() |
104c576caa | ||
![]() |
2fdc293b9a | ||
![]() |
2b75d091e9 | ||
![]() |
9bc9ee8e7d | ||
![]() |
3c273bf537 | ||
![]() |
990fb0657c | ||
![]() |
7fac77d28e | ||
![]() |
626507f8fb | ||
![]() |
9ab086f819 | ||
![]() |
b7b168e265 | ||
![]() |
9efaac072e | ||
![]() |
4ed519e819 | ||
![]() |
0e1bebaa1d | ||
![]() |
e57cc13047 | ||
![]() |
16962aea69 | ||
![]() |
e0abf93ce1 | ||
![]() |
95e9408db0 | ||
![]() |
4a9188da61 | ||
![]() |
bb37ae1987 | ||
![]() |
100279be6c | ||
![]() |
fd0421d573 | ||
![]() |
7afcaf3406 | ||
![]() |
a2ea0c407a | ||
![]() |
55474772cd | ||
![]() |
fa6f8c53ec | ||
![]() |
a5ce9915d1 | ||
![]() |
75032f9905 | ||
![]() |
00e3a3490b | ||
![]() |
00edc92c00 | ||
![]() |
10a56a9e86 | ||
![]() |
2291221719 | ||
![]() |
ceddf31f87 | ||
![]() |
0a7a206223 | ||
![]() |
c466fe8d07 | ||
![]() |
386edbf75e | ||
![]() |
f87aefbcc9 | ||
![]() |
c0080ae62e | ||
![]() |
1a610b060f | ||
![]() |
a675c42d89 | ||
![]() |
9c9b4ea880 | ||
![]() |
abe18a9b74 | ||
![]() |
209863d79e | ||
![]() |
b5fe5a4fb2 | ||
![]() |
0a8db69aa7 | ||
![]() |
73bcb1bd29 | ||
![]() |
31ed810144 | ||
![]() |
1aa34da6af | ||
![]() |
0e2eee3618 | ||
![]() |
bcc9f43f76 | ||
![]() |
34c3d971b0 | ||
![]() |
386c290dc0 | ||
![]() |
975414c2fe | ||
![]() |
8f73a00d2d | ||
![]() |
b560719a47 | ||
![]() |
07191d6e1b | ||
![]() |
b08a1a5db5 | ||
![]() |
868ee9643f | ||
![]() |
0bb738b29e | ||
![]() |
aa9f93a487 | ||
![]() |
7d0bbdab07 | ||
![]() |
ecc3db6760 | ||
![]() |
b808d84957 | ||
![]() |
36cdde4889 | ||
![]() |
c7adfee5d8 | ||
![]() |
6f8e4e9f5f | ||
![]() |
c3e27a1792 | ||
![]() |
27197f146c | ||
![]() |
519490ecee | ||
![]() |
3bfa6c19fa | ||
![]() |
0c1943c77b | ||
![]() |
32e0026128 | ||
![]() |
9935d877cc | ||
![]() |
8c1882226c | ||
![]() |
75504c3a6d | ||
![]() |
eead94dfc1 | ||
![]() |
ad5c50eef5 | ||
![]() |
a4c6655fa7 | ||
![]() |
516c089c42 | ||
![]() |
ebf4d4d1b8 | ||
![]() |
14c39f8283 | ||
![]() |
1c6d53f387 | ||
![]() |
7570468686 | ||
![]() |
a86d231714 | ||
![]() |
22797971f6 | ||
![]() |
dd6638b1ab | ||
![]() |
7d483dcade | ||
![]() |
3e30ad9b75 | ||
![]() |
44611e668c | ||
![]() |
9e80e5f195 | ||
![]() |
e2a20a44bc | ||
![]() |
69f5e8e572 | ||
![]() |
47ea05dc24 | ||
![]() |
fb41dddf3d | ||
![]() |
22a251e4fd | ||
![]() |
ddf64c8250 | ||
![]() |
629cca9413 | ||
![]() |
45acbbf6ef | ||
![]() |
9a7a9fa445 | ||
![]() |
6debf03402 | ||
![]() |
b981d45069 | ||
![]() |
db9aaef220 | ||
![]() |
141af42887 | ||
![]() |
75823e8244 | ||
![]() |
5b245d4de3 | ||
![]() |
587b766418 | ||
![]() |
e30677169b | ||
![]() |
ab985ba044 | ||
![]() |
8a049799e2 | ||
![]() |
a8309fae1c | ||
![]() |
267830387f | ||
![]() |
96bad51dd3 | ||
![]() |
12f42b30cd | ||
![]() |
1e20c1860b | ||
![]() |
c4dbe60f78 | ||
![]() |
ce3f627e36 | ||
![]() |
10986ffbab | ||
![]() |
3e279da9bf | ||
![]() |
6b662a9634 | ||
![]() |
7f8172aaf6 | ||
![]() |
2ff62bc283 | ||
![]() |
833a177e34 | ||
![]() |
592221ee19 | ||
![]() |
27b8b5e7c8 | ||
![]() |
fb39692f9c | ||
![]() |
61bed581ec | ||
![]() |
f3a2cee15b | ||
![]() |
13d962acdd | ||
![]() |
5e3743df31 | ||
![]() |
156a429898 | ||
![]() |
5c38bef3cf | ||
![]() |
451e59afa2 | ||
![]() |
5b6a659356 | ||
![]() |
9f6c64a4f9 | ||
![]() |
e51918df35 | ||
![]() |
c96eeee117 | ||
![]() |
0ddcfdd0c7 | ||
![]() |
ee6ba53d91 | ||
![]() |
7167b4cff9 | ||
![]() |
99b7533251 | ||
![]() |
449179bcec | ||
![]() |
e279140a4d | ||
![]() |
c20dfbbc39 | ||
![]() |
eaec560618 | ||
![]() |
d79b259ece | ||
![]() |
e94096e008 | ||
![]() |
d73cffd0c7 | ||
![]() |
876331afaf | ||
![]() |
1fb2501b7e | ||
![]() |
7656211b3e | ||
![]() |
827b02d94c | ||
![]() |
fe5a3acc8b | ||
![]() |
73c75240f8 | ||
![]() |
67a67a453d | ||
![]() |
cef04cfd2a | ||
![]() |
b955c377f1 | ||
![]() |
f807be50c2 | ||
![]() |
a504372f82 | ||
![]() |
bb3c3ff565 | ||
![]() |
c096536e32 | ||
![]() |
d014119b19 | ||
![]() |
508136b533 | ||
![]() |
00664898c3 | ||
![]() |
16c49d41eb | ||
![]() |
bda192ba90 | ||
![]() |
7f5df05bb7 | ||
![]() |
725576fc42 | ||
![]() |
18ea280388 | ||
![]() |
a009825d83 | ||
![]() |
fd7e5867b4 | ||
![]() |
79d385dc0b | ||
![]() |
1497bf36cc | ||
![]() |
69f2ea5635 | ||
![]() |
4964691fd9 | ||
![]() |
334c3fe702 | ||
![]() |
72e861be80 | ||
![]() |
2e3264ec69 | ||
![]() |
c032ad58ca | ||
![]() |
1772e01edb | ||
![]() |
0fb5b416ba | ||
![]() |
5103dac8d4 | ||
![]() |
c7800704b0 | ||
![]() |
d9247d094b | ||
![]() |
4f399675ce | ||
![]() |
945bf2b3a3 | ||
![]() |
d72801d19a | ||
![]() |
7f666547c9 | ||
![]() |
325175c88f | ||
![]() |
53b08efc6a | ||
![]() |
cb8c7850ba | ||
![]() |
487942bc22 | ||
![]() |
3c9f98b38d | ||
![]() |
8f762bc33d | ||
![]() |
62d2e4fba5 | ||
![]() |
4fd89120b8 | ||
![]() |
ad99e5fdea | ||
![]() |
ba472f7a11 | ||
![]() |
357ff7badf | ||
![]() |
b6b20be30b | ||
![]() |
e075d32f14 | ||
![]() |
bac10cf1fb | ||
![]() |
7968ae4588 | ||
![]() |
54d59cff1e | ||
![]() |
20e0b3efa5 | ||
![]() |
63986a4e5f | ||
![]() |
304ce7364a | ||
![]() |
f1e06f0a6d | ||
![]() |
5e9d22e496 | ||
![]() |
da743467fb | ||
![]() |
78832cb7c5 | ||
![]() |
151c8da887 | ||
![]() |
d987051f2b | ||
![]() |
000a312dc2 | ||
![]() |
6091669e28 | ||
![]() |
3974191ffa | ||
![]() |
a2d9455627 | ||
![]() |
73822401f1 | ||
![]() |
32f291c66e | ||
![]() |
e7e945a84c | ||
![]() |
f9d7d3a4fd | ||
![]() |
3709ea8f94 | ||
![]() |
af5e003790 | ||
![]() |
163135981e | ||
![]() |
c2f42f2f16 | ||
![]() |
eff5e946f7 | ||
![]() |
690eb2093a | ||
![]() |
15ee1c9fae | ||
![]() |
3329834560 | ||
![]() |
919000a5ef |
64
.clang-format
Normal file
64
.clang-format
Normal file
@ -0,0 +1,64 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: true
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakInheritanceList: AfterColon
|
||||
ColumnLimit: 0
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
Cpp11BracedListStyle: true
|
||||
EmptyLineBeforeAccessModifier: Never
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceBeforeParens: Custom
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterFunctionDefinitionName: true
|
||||
AfterFunctionDeclarationName: true
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
TabWidth: 2
|
||||
UseTab: Never
|
||||
|
@ -32,13 +32,23 @@ push_github:
|
||||
- "echo off"
|
||||
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64"
|
||||
- set CI_DIR=C:\ci\%CI_PIPELINE_ID%
|
||||
- set CLCACHE_BASEDIR=C:\ci\%CI_PIPELINE_ID%
|
||||
- set CCACHE_BASEDIR=C:\ci\%CI_PIPELINE_ID%
|
||||
- set NETGEN_BUILD_DIR=%CI_DIR%\build
|
||||
- set INSTALL_DIR=%CI_DIR%\install
|
||||
- set SRC_DIR=%CI_DIR%\src
|
||||
- set NETGENDIR=%INSTALL_DIR%\bin
|
||||
- set PYTHONPATH=%INSTALL_DIR%\lib\site-packages
|
||||
- set PATH=%NETGENDIR%;%PATH%
|
||||
- echo %PATH%
|
||||
- set PATH=%INSTALL_DIR%\bin;C:\python312;C:\python312\bin;C:\python312\Scripts;C:\tools\;%PATH%
|
||||
- echo %PATH%
|
||||
- set CCACHE_HARDLINK=1
|
||||
- set CCACHE_NOHASHDIR=1
|
||||
- C:\tools\ccache -s
|
||||
- C:\tools\ccache -M 20G
|
||||
- dir C:\python312
|
||||
- python.exe --version
|
||||
- python.exe -m pip install -U netgen-occt netgen-occt-devel
|
||||
- cmake --version
|
||||
|
||||
build_win:
|
||||
<<: *win
|
||||
@ -54,12 +64,14 @@ build_win:
|
||||
- >-
|
||||
cmake %SRC_DIR%
|
||||
-G Ninja
|
||||
-DCMAKE_PREFIX=C:/python312
|
||||
-DPython3_ROOT_DIR=C:/python312
|
||||
-DCMAKE_INSTALL_PREFIX=%INSTALL_DIR%
|
||||
-DCHECK_RANGE=ON
|
||||
-DUSE_CGNS=ON
|
||||
-DUSE_OCC=ON
|
||||
-DUSE_CCACHE=ON
|
||||
-DENABLE_UNIT_TESTS=ON
|
||||
-DENABLE_UNIT_TESTS=OFF
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
- cmake --build . --target install --config Release
|
||||
|
||||
@ -69,11 +81,20 @@ test_win:
|
||||
script:
|
||||
- pip install pytest-check
|
||||
- cd tests\pytest
|
||||
- python test_tutorials.py new_results.json
|
||||
- cd %NETGEN_BUILD_DIR%\netgen
|
||||
- ctest -C Release -V --output-on-failure
|
||||
- cd ..
|
||||
needs: ["build_win"]
|
||||
|
||||
generate_results:
|
||||
<<: *win
|
||||
stage: test
|
||||
script:
|
||||
- pip install pytest-check
|
||||
- cd tests\pytest
|
||||
- python test_tutorials.py new_results.json
|
||||
needs: ["build_win"]
|
||||
when: manual
|
||||
artifacts:
|
||||
paths:
|
||||
- tests/pytest/new_results.json
|
||||
@ -260,7 +281,7 @@ cleanup_mac:
|
||||
needs: ["test_mac"]
|
||||
|
||||
pip_linux:
|
||||
image: quay.io/pypa/manylinux2014_x86_64
|
||||
image: quay.io/pypa/manylinux_2_28_x86_64
|
||||
stage: build
|
||||
tags:
|
||||
- pip
|
||||
@ -276,11 +297,11 @@ pip_windows:
|
||||
- pip
|
||||
- windows
|
||||
script:
|
||||
- .\tests\build_pip.ps1 C:\Python38
|
||||
- .\tests\build_pip.ps1 C:\Python39
|
||||
- .\tests\build_pip.ps1 C:\Python310
|
||||
- .\tests\build_pip.ps1 C:\Python311
|
||||
- .\tests\build_pip.ps1 C:\Python313
|
||||
- .\tests\build_pip.ps1 C:\Python312
|
||||
- .\tests\build_pip.ps1 C:\Python311
|
||||
- .\tests\build_pip.ps1 C:\Python310
|
||||
- .\tests\build_pip.ps1 C:\Python39
|
||||
when: manual
|
||||
|
||||
pip_macos:
|
||||
@ -290,9 +311,9 @@ pip_macos:
|
||||
- macosx
|
||||
- m1
|
||||
script:
|
||||
- ./tests/build_pip_mac.sh 3.8
|
||||
- ./tests/build_pip_mac.sh 3.9
|
||||
- ./tests/build_pip_mac.sh 3.10
|
||||
- ./tests/build_pip_mac.sh 3.11
|
||||
- ./tests/build_pip_mac.sh 3.13
|
||||
- ./tests/build_pip_mac.sh 3.12
|
||||
- ./tests/build_pip_mac.sh 3.11
|
||||
- ./tests/build_pip_mac.sh 3.10
|
||||
- ./tests/build_pip_mac.sh 3.9
|
||||
when: manual
|
||||
|
@ -164,6 +164,7 @@ if(USE_CCACHE)
|
||||
find_program(CCACHE_FOUND NAMES ccache ccache.bat)
|
||||
if(CCACHE_FOUND)
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_FOUND})
|
||||
message(STATUS "Using ccache ${CCACHE_FOUND}")
|
||||
endif(CCACHE_FOUND)
|
||||
endif(USE_CCACHE)
|
||||
|
||||
@ -398,7 +399,12 @@ if (USE_OCC)
|
||||
endif()
|
||||
|
||||
target_link_libraries(occ_libs INTERFACE ${OCC_LIBRARIES})
|
||||
include_directories(${OpenCASCADE_INCLUDE_DIR})
|
||||
get_target_property(occ_include_dir TKernel INTERFACE_INCLUDE_DIRECTORIES)
|
||||
if(NOT occ_include_dir)
|
||||
set(occ_include_dir ${OpenCASCADE_INCLUDE_DIR})
|
||||
endif()
|
||||
target_include_directories(occ_libs INTERFACE ${occ_include_dir})
|
||||
message(STATUS "OpenCasCade include dirs: ${occ_include_dir}")
|
||||
if(NOT OpenCASCADE_BUILD_SHARED_LIBS)
|
||||
if(OpenCASCADE_WITH_FREETYPE)
|
||||
find_library( FREETYPE NAMES freetype HINTS ${OpenCASCADE_LIBRARY_DIR})
|
||||
@ -413,10 +419,12 @@ if (USE_OCC)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(occ_libs INTERFACE Threads::Threads)
|
||||
endif()
|
||||
message(STATUS "OCC DIRS ${OpenCASCADE_INCLUDE_DIR}")
|
||||
if(WIN32 AND USE_GUI)
|
||||
target_link_libraries(nggui PRIVATE occ_libs Ws2_32.lib)
|
||||
target_link_libraries(nggui PRIVATE Ws2_32.lib)
|
||||
endif(WIN32 AND USE_GUI)
|
||||
if(USE_GUI)
|
||||
target_link_libraries(nggui PRIVATE occ_libs)
|
||||
endif(USE_GUI)
|
||||
endif (USE_OCC)
|
||||
|
||||
#######################################################################
|
||||
|
@ -57,7 +57,7 @@ set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_C_COMPILER)
|
||||
set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_CXX_COMPILER)
|
||||
set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_BUILD_TYPE)
|
||||
|
||||
set(SUBPROJECT_CMAKE_ARGS "${SUBPROJECT_CMAKE_ARGS};-DCMAKE_POSITION_INDEPENDENT_CODE=ON" CACHE INTERNAL "")
|
||||
set(SUBPROJECT_CMAKE_ARGS "${SUBPROJECT_CMAKE_ARGS};-DCMAKE_POSITION_INDEPENDENT_CODE=ON;-DCMAKE_POLICY_VERSION_MINIMUM=3.5" CACHE INTERNAL "")
|
||||
|
||||
if(USE_CCACHE)
|
||||
find_program(CCACHE_FOUND NAMES ccache ccache.bat)
|
||||
@ -120,27 +120,14 @@ if(BUILD_OCC)
|
||||
list(APPEND NETGEN_DEPENDENCIES project_occ)
|
||||
set(OpenCascade_ROOT ${OCC_DIR})
|
||||
else(BUILD_OCC)
|
||||
if(WIN32 AND NOT OCC_INCLUDE_DIR AND NOT OpenCASCADE_DIR)
|
||||
# we can download prebuilt occ binaries for windows
|
||||
ExternalProject_Add(win_download_occ
|
||||
${SUBPROJECT_ARGS}
|
||||
URL ${OCC_DOWNLOAD_URL_WIN}
|
||||
UPDATE_COMMAND "" # Disable update
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}
|
||||
)
|
||||
list(APPEND NETGEN_DEPENDENCIES win_download_occ)
|
||||
else()
|
||||
find_package(OpenCascade NAMES OpenCasCade OpenCASCADE opencascade)
|
||||
if(NOT OpenCascade_FOUND)
|
||||
message(FATAL_ERROR "Opencascade not found, either\n\
|
||||
- set OpenCascade_DIR to a directory containting opencascadeConfig.cmake\n\
|
||||
- build OpenCascade automatically by passing -DBUILD_OCC=ON\n\
|
||||
- disable OpenCascade by passing -DUSE_OCC=OFF\n\
|
||||
")
|
||||
endif()
|
||||
find_package(OpenCascade NAMES OpenCasCade OpenCASCADE opencascade)
|
||||
if(NOT OpenCascade_FOUND)
|
||||
message(FATAL_ERROR "Opencascade not found, either\n\
|
||||
- install pip packages netgen-occt-devel netgen-occ\n\
|
||||
- set OpenCascade_DIR to a directory containting opencascadeConfig.cmake\n\
|
||||
- build OpenCascade automatically by passing -DBUILD_OCC=ON\n\
|
||||
- disable OpenCascade by passing -DUSE_OCC=OFF\n\
|
||||
")
|
||||
endif()
|
||||
endif(BUILD_OCC)
|
||||
endif(USE_OCC)
|
||||
@ -164,9 +151,11 @@ if(BUILD_ZLIB)
|
||||
# force linking the static library
|
||||
set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)
|
||||
set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/zlibstatic.lib)
|
||||
elseif(EMSCRIPTEN)
|
||||
set(ZLIB_LIBRARY_RELEASE ${ZLIB_ROOT}/lib/zlibstatic.lib)
|
||||
else(WIN32)
|
||||
set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)
|
||||
set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/libz.a)
|
||||
set(ZLIB_LIBRARY_RELEASE ${ZLIB_ROOT}/lib/libz.a)
|
||||
endif(WIN32)
|
||||
else()
|
||||
include(cmake/external_projects/zlib.cmake)
|
||||
@ -270,6 +259,7 @@ set_vars( NETGEN_CMAKE_ARGS
|
||||
OpenCascade_ROOT
|
||||
ZLIB_INCLUDE_DIRS
|
||||
ZLIB_LIBRARIES
|
||||
ZLIB_LIBRARY_RELEASE
|
||||
ZLIB_ROOT
|
||||
|
||||
NGLIB_LIBRARY_TYPE
|
||||
|
@ -51,12 +51,17 @@ if(APPLE OR WIN32)
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
HINTS ${PYTHON_PREFIX}/lib ${PYTHON_PREFIX}/tcl
|
||||
HINTS
|
||||
${PYTHON_PREFIX}/lib
|
||||
${PYTHON_PREFIX}/tcl
|
||||
${PYTHON_PREFIX}/Frameworks
|
||||
${PYTHON_PREFIX}/Frameworks/Tcl.framework
|
||||
${PYTHON_PREFIX}/Frameworks/Tk.framework
|
||||
)
|
||||
find_library(TCL_STUB_LIBRARY NAMES tclstub85 tclstub8.5 tclstub86 tclstub8.6 ${tcl_find_args})
|
||||
find_library(TK_STUB_LIBRARY NAMES tkstub85 tkstub8.5 tkstub86 tkstub8.6 ${tcl_find_args})
|
||||
find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t ${tcl_find_args})
|
||||
find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t ${tcl_find_args})
|
||||
find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t Tcl ${tcl_find_args})
|
||||
find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t Tk ${tcl_find_args})
|
||||
else()
|
||||
# use system tcl/tk on linux
|
||||
find_package(TclStub REQUIRED)
|
||||
@ -104,6 +109,7 @@ if(APPLE)
|
||||
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS
|
||||
-DTCL_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework/Headers
|
||||
-DTK_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/Headers
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||
${SUBPROJECT_ARGS}
|
||||
)
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 80dc998efced8ceb2be59756668a7e90e8bef917
|
||||
Subproject commit 38bf7b174875c27c1ba98bdf5a9bf13d967f14d4
|
@ -24,7 +24,7 @@ if(EMSCRIPTEN)
|
||||
target_compile_options(ngcore PUBLIC -sNO_DISABLE_EXCEPTION_CATCHING)
|
||||
endif()
|
||||
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" AND USE_PYTHON)
|
||||
# Python packages on Linux are compiled with the old ABI,
|
||||
# make sure that the same ABI is used in plugins aswell
|
||||
try_run(
|
||||
@ -33,19 +33,21 @@ if (CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||
RUN_OUTPUT_VARIABLE use_glibcxx_cxx11_abi
|
||||
)
|
||||
target_compile_definitions(ngcore PUBLIC -D_GLIBCXX_USE_CXX11_ABI=${use_glibcxx_cxx11_abi})
|
||||
if(USE_PYTHON)
|
||||
try_run(
|
||||
ret_val can_compile
|
||||
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/_get_gxx_abi.cpp
|
||||
RUN_OUTPUT_VARIABLE cxx_abi_version
|
||||
)
|
||||
if(${can_compile} AND (${ret_val} EQUAL 0))
|
||||
# Different python modules using pybind11 need to use the same C++ ABI version
|
||||
# for compatibility
|
||||
message(STATUS "GNU C++ ABI version: ${cxx_abi_version}")
|
||||
target_compile_options(ngcore PUBLIC "-fabi-version=${cxx_abi_version}")
|
||||
try_run(
|
||||
ret_val can_compile
|
||||
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/_get_gxx_abi.cpp
|
||||
RUN_OUTPUT_VARIABLE default_cxx_abi_version
|
||||
)
|
||||
if(${can_compile} AND (${ret_val} EQUAL 0))
|
||||
# Different python modules using pybind11 need to use the same C++ ABI version
|
||||
# for compatibility
|
||||
set(cxx_abi_version 17)
|
||||
if(cxx_abi_version LESS default_cxx_abi_version)
|
||||
set(cxx_abi_version ${default_cxx_abi_version})
|
||||
endif()
|
||||
endif(USE_PYTHON)
|
||||
message(STATUS "GNU C++ ABI version: ${cxx_abi_version}")
|
||||
target_compile_options(ngcore PUBLIC "-fabi-version=${cxx_abi_version}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_PYTHON)
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef NETGEN_CORE_ARCHIVE_HPP
|
||||
#define NETGEN_CORE_ARCHIVE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <any>
|
||||
#include <array> // for array
|
||||
#include <complex> // for complex
|
||||
@ -77,7 +78,8 @@ namespace ngcore
|
||||
{
|
||||
template <class T, class Tuple, size_t... Is>
|
||||
T* construct_from_tuple(Tuple&& tuple, std::index_sequence<Is...> ) {
|
||||
return new T{std::get<Is>(std::forward<Tuple>(tuple))...};
|
||||
// return new T{std::get<Is>(std::forward<Tuple>(tuple))...};
|
||||
return new T{std::get<Is>(std::move(tuple))...};
|
||||
}
|
||||
|
||||
template <class T, class Tuple>
|
||||
@ -1135,15 +1137,32 @@ namespace ngcore
|
||||
{ char c; *stream >> c; b = (c=='t'); return *this; }
|
||||
Archive & operator & (std::string & str) override
|
||||
{
|
||||
// Ignore \r (carriage return) characters when reading strings
|
||||
// this is necessary for instance when a file was written on Windows and is read on Unix
|
||||
|
||||
int len;
|
||||
*stream >> len;
|
||||
char ch;
|
||||
stream->get(ch); // '\n'
|
||||
stream->get(ch); // read newline character
|
||||
if(ch == '\r') // windows line endings -> read \n as well
|
||||
stream->get(ch);
|
||||
str.resize(len);
|
||||
if(len)
|
||||
stream->get(&str[0], len+1, '\0');
|
||||
|
||||
// remove all \r characters from the string, check if size changed
|
||||
// if so, read the remaining characters
|
||||
str.erase(std::remove(str.begin(), str.end(), '\r'), str.cend());
|
||||
size_t chars_to_read = len-str.size();
|
||||
while (chars_to_read>0)
|
||||
{
|
||||
auto old_size = str.size();
|
||||
str.resize(len);
|
||||
|
||||
stream->get(&str[old_size], chars_to_read+1, '\0');
|
||||
str.erase(std::remove(str.begin()+old_size, str.end(), '\r'), str.cend());
|
||||
chars_to_read = len - str.size();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Archive & operator & (char *& str) override
|
||||
|
@ -216,6 +216,10 @@ namespace ngcore
|
||||
template <typename T>
|
||||
constexpr T IndexBASE () { return T(0); }
|
||||
|
||||
template <typename T>
|
||||
constexpr T IndexBASE (T ind) { return IndexBASE<T>(); }
|
||||
|
||||
|
||||
|
||||
class IndexFromEnd
|
||||
{
|
||||
@ -278,7 +282,8 @@ namespace ngcore
|
||||
T first, next;
|
||||
public:
|
||||
NETGEN_INLINE T_Range () { ; }
|
||||
NETGEN_INLINE T_Range (T n) : first(0), next(n) {;}
|
||||
// NETGEN_INLINE T_Range (T n) : first(0), next(n) {;}
|
||||
NETGEN_INLINE explicit T_Range (size_t n) : first(IndexBASE<T>()), next(IndexBASE<T>()+n) {;}
|
||||
NETGEN_INLINE T_Range (T f, T n) : first(f), next(n) {;}
|
||||
template <typename T2>
|
||||
NETGEN_INLINE T_Range(T_Range<T2> r2) : first(r2.First()), next(r2.Next()) { ; }
|
||||
@ -296,7 +301,7 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE T_Range Split (size_t nr, int tot) const
|
||||
{
|
||||
T diff = next-first;
|
||||
auto diff = next-first;
|
||||
return T_Range (first + nr * diff / tot,
|
||||
first + (nr+1) * diff / tot);
|
||||
}
|
||||
@ -554,6 +559,13 @@ namespace ngcore
|
||||
// { return CArray<T> (data+pos); }
|
||||
NETGEN_INLINE T * operator+ (size_t pos) const { return data+pos; }
|
||||
|
||||
/// access first element. check by macro NETGEN_CHECK_RANGE
|
||||
T & First () const
|
||||
{
|
||||
NETGEN_CHECK_RANGE(0,0,size);
|
||||
return data[0];
|
||||
}
|
||||
|
||||
/// access last element. check by macro NETGEN_CHECK_RANGE
|
||||
T & Last () const
|
||||
{
|
||||
@ -687,6 +699,7 @@ namespace ngcore
|
||||
size_t allocsize;
|
||||
/// that's the data we have to delete, nullptr for not owning the memory
|
||||
T * mem_to_delete;
|
||||
MemoryTracer mt;
|
||||
|
||||
|
||||
using FlatArray<T,IndexType>::size;
|
||||
@ -708,6 +721,7 @@ namespace ngcore
|
||||
{
|
||||
allocsize = asize;
|
||||
mem_to_delete = data;
|
||||
mt.Alloc(sizeof(T)*asize);
|
||||
}
|
||||
|
||||
|
||||
@ -717,7 +731,10 @@ namespace ngcore
|
||||
{
|
||||
allocsize = asize;
|
||||
if(ownMemory)
|
||||
{
|
||||
mem_to_delete = adata;
|
||||
mt.Alloc(sizeof(T)*asize);
|
||||
}
|
||||
else
|
||||
mem_to_delete = nullptr;
|
||||
}
|
||||
@ -733,8 +750,7 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE Array (Array && a2)
|
||||
{
|
||||
mt.Swap(sizeof(T) * allocsize, a2.mt, sizeof(T) * a2.allocsize);
|
||||
|
||||
mt = std::move(a2.mt);
|
||||
size = a2.size;
|
||||
data = a2.data;
|
||||
allocsize = a2.allocsize;
|
||||
@ -753,6 +769,7 @@ namespace ngcore
|
||||
{
|
||||
allocsize = size;
|
||||
mem_to_delete = data;
|
||||
mt.Alloc(sizeof(T)*size);
|
||||
for (size_t i = 0; i < size; i++)
|
||||
data[i] = a2.data[i];
|
||||
}
|
||||
@ -772,6 +789,7 @@ namespace ngcore
|
||||
{
|
||||
allocsize = size;
|
||||
mem_to_delete = data;
|
||||
mt.Alloc(sizeof(T)*size);
|
||||
/*
|
||||
for (size_t i = 0; i < size; i++)
|
||||
data[i] = a2[i];
|
||||
@ -788,6 +806,7 @@ namespace ngcore
|
||||
{
|
||||
allocsize = size;
|
||||
mem_to_delete = data;
|
||||
mt.Alloc(sizeof(T)*size);
|
||||
size_t cnt = 0;
|
||||
for (auto val : list)
|
||||
data[cnt++] = val;
|
||||
@ -800,6 +819,7 @@ namespace ngcore
|
||||
{
|
||||
allocsize = size;
|
||||
mem_to_delete = data;
|
||||
mt.Alloc(sizeof(T)*size);
|
||||
for(size_t i = 0; i < a2.Size(); i++)
|
||||
data[i] = a2[i];
|
||||
for (size_t i = a2.Size(), j=0; i < size; i++,j++)
|
||||
@ -834,6 +854,9 @@ namespace ngcore
|
||||
NETGEN_INLINE void NothingToDelete ()
|
||||
{
|
||||
mem_to_delete = nullptr;
|
||||
|
||||
// this memory is not managed by the Array anymore, so set the memory usage to 0
|
||||
mt.Free(sizeof(T)*allocsize);
|
||||
}
|
||||
|
||||
/// Change logical size. If necessary, do reallocation. Keeps contents.
|
||||
@ -947,7 +970,7 @@ namespace ngcore
|
||||
|
||||
|
||||
/// Delete element i. Move last element to position i.
|
||||
NETGEN_INLINE void DeleteElement (size_t i)
|
||||
NETGEN_INLINE void DeleteElement (IndexType i)
|
||||
{
|
||||
NETGEN_CHECK_RANGE(i,BASE,BASE+size);
|
||||
data[i-BASE] = std::move(data[size-1]);
|
||||
@ -956,10 +979,10 @@ namespace ngcore
|
||||
|
||||
|
||||
/// Delete element i. Move all remaining elements forward
|
||||
NETGEN_INLINE void RemoveElement (size_t i)
|
||||
NETGEN_INLINE void RemoveElement (IndexType i)
|
||||
{
|
||||
NETGEN_CHECK_RANGE(i, BASE, BASE+size);
|
||||
for(size_t j = i; j < this->size-1; j++)
|
||||
for(size_t j = i-BASE; j+1 < this->size; j++)
|
||||
this->data[j] = this->data[j+1];
|
||||
this->size--;
|
||||
}
|
||||
@ -1011,8 +1034,7 @@ namespace ngcore
|
||||
/// steal array
|
||||
NETGEN_INLINE Array & operator= (Array && a2)
|
||||
{
|
||||
mt.Swap(sizeof(T)*allocsize, a2.mt, sizeof(T)*a2.allocsize);
|
||||
|
||||
mt = std::move(a2.mt);
|
||||
ngcore::Swap (size, a2.size);
|
||||
ngcore::Swap (data, a2.data);
|
||||
ngcore::Swap (allocsize, a2.allocsize);
|
||||
@ -1086,8 +1108,7 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE void Swap (Array & b)
|
||||
{
|
||||
mt.Swap(sizeof(T) * allocsize, b.mt, sizeof(T) * b.allocsize);
|
||||
|
||||
mt = std::move(b.mt);
|
||||
ngcore::Swap (size, b.size);
|
||||
ngcore::Swap (data, b.data);
|
||||
ngcore::Swap (allocsize, b.allocsize);
|
||||
@ -1096,7 +1117,8 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE void StartMemoryTracing () const
|
||||
{
|
||||
mt.Alloc(sizeof(T) * allocsize);
|
||||
if(mem_to_delete)
|
||||
mt.Alloc(sizeof(T) * allocsize);
|
||||
}
|
||||
|
||||
const MemoryTracer& GetMemoryTracer() const { return mt; }
|
||||
@ -1105,7 +1127,6 @@ namespace ngcore
|
||||
|
||||
/// resize array, at least to size minsize. copy contents
|
||||
NETGEN_INLINE void ReSize (size_t minsize);
|
||||
MemoryTracer mt;
|
||||
};
|
||||
|
||||
|
||||
@ -1158,6 +1179,7 @@ namespace ngcore
|
||||
using Array<T>::allocsize;
|
||||
using Array<T>::data;
|
||||
using Array<T>::mem_to_delete;
|
||||
using Array<T>::mt;
|
||||
// using Array<T>::ownmem;
|
||||
|
||||
public:
|
||||
@ -1171,6 +1193,7 @@ namespace ngcore
|
||||
data = new T[asize];
|
||||
allocsize = size;
|
||||
mem_to_delete = data;
|
||||
mt.Alloc(sizeof(T)*asize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1191,6 +1214,7 @@ namespace ngcore
|
||||
ArrayMem(ArrayMem && a2)
|
||||
: Array<T> (a2.Size(), (T*)mem)
|
||||
{
|
||||
mt = std::move(a2.mt);
|
||||
if (a2.mem_to_delete)
|
||||
{
|
||||
mem_to_delete = a2.mem_to_delete;
|
||||
@ -1233,6 +1257,7 @@ namespace ngcore
|
||||
|
||||
ArrayMem & operator= (ArrayMem && a2)
|
||||
{
|
||||
mt = std::move(a2.mt);
|
||||
ngcore::Swap (mem_to_delete, a2.mem_to_delete);
|
||||
ngcore::Swap (allocsize, a2.allocsize);
|
||||
ngcore::Swap (size, a2.size);
|
||||
@ -1528,6 +1553,8 @@ namespace ngcore
|
||||
}
|
||||
|
||||
|
||||
struct HTAHelp { };
|
||||
|
||||
// head-tail array
|
||||
template <size_t S, typename T>
|
||||
class HTArray
|
||||
@ -1535,10 +1562,22 @@ namespace ngcore
|
||||
HTArray<S-1,T> tail;
|
||||
T head;
|
||||
public:
|
||||
HTArray () = default;
|
||||
HTArray (const HTArray &) = default;
|
||||
constexpr HTArray () = default;
|
||||
constexpr HTArray (const HTArray &) = default;
|
||||
template <typename T2>
|
||||
HTArray (const HTArray<S,T2> & a2) : tail(a2.Tail()), head(a2.Head()) { ; }
|
||||
constexpr HTArray (const HTArray<S,T2> & a2) : tail(a2.Tail()), head(a2.Head()) { ; }
|
||||
|
||||
constexpr HTArray (T v) : tail(v), head(v) { } // all the same
|
||||
|
||||
template <class... T2,
|
||||
std::enable_if_t<S==1+sizeof...(T2),bool> = true>
|
||||
constexpr HTArray (const T &v, T2... rest)
|
||||
: tail{HTAHelp(), v,rest...}, head(std::get<S-2>(std::tuple(rest...))) { }
|
||||
|
||||
template <class... T2>
|
||||
constexpr HTArray (HTAHelp h, const T &v, T2... rest)
|
||||
: tail{h, v,rest...}, head(std::get<S-2>(std::tuple(rest...))) { }
|
||||
|
||||
|
||||
HTArray & operator= (const HTArray &) = default;
|
||||
|
||||
@ -1559,10 +1598,15 @@ namespace ngcore
|
||||
{
|
||||
T head;
|
||||
public:
|
||||
HTArray () = default;
|
||||
HTArray (const HTArray &) = default;
|
||||
constexpr HTArray () = default;
|
||||
constexpr HTArray (const HTArray &) = default;
|
||||
template <typename T2>
|
||||
HTArray (const HTArray<1,T2> & a2) : head(a2.Head()) { ; }
|
||||
constexpr HTArray (const HTArray<1,T2> & a2) : head(a2.Head()) { ; }
|
||||
constexpr HTArray (T v) : head(v) { } // all the same
|
||||
template <class... T2>
|
||||
constexpr HTArray (HTAHelp h, const T &v, T2... rest)
|
||||
: head(v) { }
|
||||
|
||||
|
||||
HTArray & operator= (const HTArray &) = default;
|
||||
|
||||
@ -1590,7 +1634,7 @@ namespace ngcore
|
||||
HTArray (const HTArray &) = default;
|
||||
template <typename T2>
|
||||
HTArray (const HTArray<0,T2> & a2) { ; }
|
||||
|
||||
constexpr HTArray (T v) { } // all the same
|
||||
HTArray & operator= (const HTArray &) = default;
|
||||
|
||||
/*
|
||||
|
@ -40,12 +40,13 @@ namespace ngcore
|
||||
if (owns_data)
|
||||
{
|
||||
delete [] data;
|
||||
mt.Free(Addr(size)+1);
|
||||
mt.Free(GetMemoryUsage());
|
||||
}
|
||||
|
||||
size = asize;
|
||||
data = new unsigned char [Addr (size)+1];
|
||||
mt.Alloc(Addr(size)+1);
|
||||
owns_data = true;
|
||||
mt.Alloc(GetMemoryUsage());
|
||||
}
|
||||
|
||||
BitArray & BitArray :: Set () throw()
|
||||
|
@ -49,6 +49,7 @@ public:
|
||||
{
|
||||
ba2.owns_data = false;
|
||||
ba2.data = nullptr;
|
||||
mt = std::move(ba2.mt);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -59,13 +60,17 @@ public:
|
||||
int cnt = 0;
|
||||
for (auto i = list.begin(); i < list.end(); i++, cnt++)
|
||||
if (*i) SetBit(cnt);
|
||||
StartMemoryTracing();
|
||||
}
|
||||
|
||||
/// delete data
|
||||
~BitArray ()
|
||||
{
|
||||
if (owns_data)
|
||||
{
|
||||
delete [] data;
|
||||
mt.Free(GetMemoryUsage());
|
||||
}
|
||||
}
|
||||
|
||||
/// Set size, loose values
|
||||
@ -150,11 +155,11 @@ public:
|
||||
|
||||
NGCORE_API auto * Data() const { return data; }
|
||||
|
||||
const size_t GetMemoryUsage() const { return owns_data ? (size+CHAR_BIT-1)/CHAR_BIT : 0; }
|
||||
const MemoryTracer& GetMemoryTracer() const { return mt; }
|
||||
void StartMemoryTracing() const
|
||||
{
|
||||
if(owns_data)
|
||||
mt.Alloc(Addr(size)+1);
|
||||
mt.Alloc(GetMemoryUsage());
|
||||
}
|
||||
|
||||
private:
|
||||
@ -205,6 +210,31 @@ private:
|
||||
|
||||
NGCORE_API std::ostream & operator<<(std::ostream & s, const BitArray & ba);
|
||||
|
||||
|
||||
|
||||
template <typename IndexType>
|
||||
class TBitArray : public BitArray
|
||||
{
|
||||
public:
|
||||
using BitArray::BitArray;
|
||||
|
||||
void SetBit (IndexType i) { BitArray::SetBit(i-IndexBASE<IndexType>()); }
|
||||
void Clear () { BitArray::Clear(); }
|
||||
void Clear (IndexType i) { BitArray::Clear(i-IndexBASE<IndexType>()); }
|
||||
void SetBitAtomic (IndexType i) { BitArray::SetBitAtomic(i-IndexBASE<IndexType>()); }
|
||||
bool Test (IndexType i) const { return BitArray::Test(i-IndexBASE<IndexType>()); }
|
||||
|
||||
bool operator[] (IndexType i) const { return Test(i); }
|
||||
T_Range<IndexType> Range() const { return { IndexBASE<IndexType>(), IndexBASE<IndexType>()+Size() }; }
|
||||
NGCORE_API TBitArray & Or (const TBitArray & ba2)
|
||||
{
|
||||
BitArray::Or(ba2);
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
|
||||
#endif // NETGEN_CORE_BITARRAY
|
||||
|
@ -23,6 +23,47 @@ namespace ngcore
|
||||
}
|
||||
|
||||
|
||||
Exception :: Exception(std::string_view s1, std::string_view s2)
|
||||
: Exception(std::string(s1)+std::string(s2))
|
||||
{ }
|
||||
|
||||
Exception :: Exception(std::string_view s1, std::string_view s2, std::string_view s3)
|
||||
: Exception(std::string(s1)+std::string(s2)+std::string(s3))
|
||||
{ }
|
||||
|
||||
|
||||
void Exception :: Throw (std::string_view s1)
|
||||
{
|
||||
throw Exception(std::string(s1));
|
||||
}
|
||||
|
||||
void Exception :: Throw (std::string_view s1, std::string_view s2)
|
||||
{
|
||||
throw Exception(std::string(s1)+std::string(s2));
|
||||
}
|
||||
|
||||
void Exception :: Throw (std::string_view s1, std::string_view s2, std::string_view s3)
|
||||
{
|
||||
throw Exception(std::string(s1)+std::string(s2)+std::string(s3));
|
||||
}
|
||||
|
||||
|
||||
RangeException :: RangeException (// const std::string & where,
|
||||
const char * where,
|
||||
ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax) : Exception("")
|
||||
{
|
||||
std::stringstream str;
|
||||
str << where << ": index " << ind << " out of range [" << imin << "," << imax << ")\n";
|
||||
Append (str.str());
|
||||
Append (GetBackTrace());
|
||||
}
|
||||
|
||||
|
||||
void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax)
|
||||
{
|
||||
throw RangeException(s, ind, imin, imax);
|
||||
}
|
||||
|
||||
void ThrowException(const std::string & s)
|
||||
{
|
||||
throw Exception (s);
|
||||
@ -32,6 +73,13 @@ namespace ngcore
|
||||
{
|
||||
throw Exception (s);
|
||||
}
|
||||
|
||||
|
||||
void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b)
|
||||
{
|
||||
throw ngcore::Exception(std::string(s) + ", a="+ToString(a) + ", b="+ToString(b) + GetBackTrace());
|
||||
}
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
|
||||
|
@ -1,11 +1,13 @@
|
||||
#ifndef NETGEN_CORE_EXCEPTION_HPP
|
||||
#define NETGEN_CORE_EXCEPTION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <sstream> // for stringstream
|
||||
#include <stdexcept> // for exception
|
||||
#include <string> // for string
|
||||
|
||||
#include "ngcore_api.hpp" // for NGCORE_API
|
||||
#include "utils.hpp" // for ToString
|
||||
|
||||
|
||||
namespace ngcore
|
||||
@ -32,8 +34,14 @@ namespace ngcore
|
||||
Exception(Exception&&) = default;
|
||||
Exception(const std::string& s); // : m_what(s) {}
|
||||
Exception(const char* s); // : m_what(s) {}
|
||||
Exception(std::string_view s1, std::string_view s2);
|
||||
Exception(std::string_view s1, std::string_view s2, std::string_view s3);
|
||||
~Exception() override = default;
|
||||
|
||||
[[noreturn]] static void Throw (std::string_view s1);
|
||||
[[noreturn]] static void Throw (std::string_view s1, std::string_view s2);
|
||||
[[noreturn]] static void Throw (std::string_view s1, std::string_view s2, std::string_view s3);
|
||||
|
||||
Exception& operator =(const Exception&) = default;
|
||||
Exception& operator =(Exception&&) noexcept = default;
|
||||
|
||||
@ -49,23 +57,26 @@ namespace ngcore
|
||||
const char* what() const noexcept override { return m_what.c_str(); }
|
||||
};
|
||||
|
||||
NGCORE_API void ThrowException(const std::string & s);
|
||||
NGCORE_API void ThrowException(const char * s);
|
||||
[[noreturn]] NGCORE_API void ThrowException(const std::string & s);
|
||||
[[noreturn]] NGCORE_API void ThrowException(const char * s);
|
||||
|
||||
// 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("")
|
||||
RangeException (// const std::string & where,
|
||||
const char * where,
|
||||
ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);
|
||||
/*
|
||||
: Exception("")
|
||||
{
|
||||
std::stringstream str;
|
||||
str << where << ": index " << ind << " out of range [" << imin << "," << imax << ")\n";
|
||||
Append (str.str());
|
||||
Append (GetBackTrace());
|
||||
}
|
||||
|
||||
*/
|
||||
template<typename T>
|
||||
RangeException(const std::string& where, const T& value)
|
||||
{
|
||||
@ -75,9 +86,40 @@ namespace ngcore
|
||||
}
|
||||
};
|
||||
|
||||
[[noreturn]] NGCORE_API void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);
|
||||
[[noreturn]] NGCORE_API void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b);
|
||||
|
||||
|
||||
// Exception used if no simd implementation is available to fall back to standard evaluation
|
||||
class NGCORE_API ExceptionNOSIMD : public Exception
|
||||
{ public: using Exception::Exception; };
|
||||
|
||||
template <typename T>
|
||||
struct IsSafe {
|
||||
constexpr operator bool() const { return false; } };
|
||||
|
||||
namespace detail {
|
||||
template <typename T, typename Tmin, typename Tmax>
|
||||
inline static constexpr void CheckRange(const char * s, const T& n, Tmin first, Tmax next)
|
||||
{
|
||||
if constexpr (!IsSafe<decltype(n)>())
|
||||
if (n<first || n>=next)
|
||||
ThrowRangeException(s, ptrdiff_t(n), ptrdiff_t(first), ptrdiff_t(next));
|
||||
}
|
||||
|
||||
template <typename Ta, typename Tb>
|
||||
inline static constexpr void CheckSame(const char * s, const Ta& a, const Tb& b)
|
||||
{
|
||||
if constexpr (!IsSafe<decltype(a)>() || !IsSafe<decltype(b)>())
|
||||
if(a != b)
|
||||
{
|
||||
if constexpr(std::is_integral_v<decltype(a)> && std::is_same_v<decltype(a),decltype(b)>)
|
||||
ThrowNotTheSameException(s, long(a), long(b)); \
|
||||
else
|
||||
throw Exception(std::string(s) + "\t: not the same, a="+ToString(a) + ", b="+ngcore::ToString(b) + GetBackTrace());
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace ngcore
|
||||
|
||||
#define NETGEN_CORE_NGEXEPTION_STR_HELPER(x) #x
|
||||
@ -87,20 +129,14 @@ namespace ngcore
|
||||
#define NG_EXCEPTION(s) ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t"+std::string(s))
|
||||
|
||||
#if defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
|
||||
#define NETGEN_CHECK_RANGE(value, min, max_plus_one) \
|
||||
{ if ((value)<(min) || (value)>=(max_plus_one)) \
|
||||
throw ngcore::RangeException(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", int(value), int(min), int(max_plus_one)); }
|
||||
#define NETGEN_CHECK_SHAPE(a,b) \
|
||||
{ if(a.Shape() != b.Shape()) \
|
||||
throw ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t: shape don't match"); }
|
||||
#define NETGEN_CHECK_SAME(a,b) \
|
||||
{ if(a != b) \
|
||||
throw ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t: not the same, a="+ToString(a) + ", b="+ToString(b) + GetBackTrace()); }
|
||||
#define NETGEN_CHECK_RANGE(value, min, max_plus_one) ngcore::detail::CheckRange(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", value, min, max_plus_one);
|
||||
#define NETGEN_CHECK_SAME(a,b) ngcore::detail::CheckSame(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", a, b);
|
||||
|
||||
#define NETGEN_NOEXCEPT
|
||||
#else // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
|
||||
#define NETGEN_CHECK_RANGE(value, min, max)
|
||||
#define NETGEN_CHECK_SAME(a,b)
|
||||
#define NETGEN_CHECK_SHAPE(a,b)
|
||||
// #define NETGEN_CHECK_SHAPE(a,b)
|
||||
#define NETGEN_NOEXCEPT noexcept
|
||||
#endif // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
namespace ngcore
|
||||
{
|
||||
using std::string;
|
||||
using std::string_view;
|
||||
using std::endl;
|
||||
Flags :: Flags () { ; }
|
||||
|
||||
@ -209,18 +210,18 @@ namespace ngcore
|
||||
}
|
||||
|
||||
|
||||
double Flags :: GetNumFlag (const string & name, double def) const
|
||||
double Flags :: GetNumFlag (string_view name, double def) const
|
||||
{
|
||||
if (numflags.Used (name))
|
||||
return numflags[name];
|
||||
return numflags[string(name)];
|
||||
else
|
||||
return def;
|
||||
}
|
||||
|
||||
const double * Flags :: GetNumFlagPtr (const string & name) const
|
||||
const double * Flags :: GetNumFlagPtr (string_view name) const
|
||||
{
|
||||
if (numflags.Used (name))
|
||||
return & ((SymbolTable<double>&)numflags)[name];
|
||||
return & ((SymbolTable<double>&)numflags)[string(name)];
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
@ -239,16 +240,16 @@ namespace ngcore
|
||||
return defflags.Used (name);
|
||||
}
|
||||
*/
|
||||
bool Flags :: GetDefineFlag (const string & name) const throw()
|
||||
bool Flags :: GetDefineFlag (string_view name) const throw()
|
||||
{
|
||||
if (!defflags.Used (name)) return false;
|
||||
return defflags[name];
|
||||
if (!defflags.Used (string(name))) return false;
|
||||
return defflags[string(name)];
|
||||
}
|
||||
|
||||
xbool Flags :: GetDefineFlagX (const string & name) const throw()
|
||||
xbool Flags :: GetDefineFlagX (string_view name) const throw()
|
||||
{
|
||||
if (!defflags.Used (name)) return maybe;
|
||||
return bool(defflags[name]);
|
||||
if (!defflags.Used (string(name))) return maybe;
|
||||
return bool(defflags[string(name)]);
|
||||
}
|
||||
|
||||
|
||||
@ -296,32 +297,32 @@ namespace ngcore
|
||||
return empty;
|
||||
}
|
||||
|
||||
bool Flags :: StringFlagDefined (const string & name) const
|
||||
bool Flags :: StringFlagDefined (string_view name) const noexcept
|
||||
{
|
||||
return strflags.Used (name);
|
||||
}
|
||||
|
||||
bool Flags :: NumFlagDefined (const string &name) const
|
||||
bool Flags :: NumFlagDefined (string_view name) const noexcept
|
||||
{
|
||||
return numflags.Used (name);
|
||||
}
|
||||
|
||||
bool Flags :: FlagsFlagDefined (const string &name) const
|
||||
bool Flags :: FlagsFlagDefined (string_view name) const noexcept
|
||||
{
|
||||
return flaglistflags.Used (name);
|
||||
}
|
||||
|
||||
bool Flags :: StringListFlagDefined (const string & name) const
|
||||
bool Flags :: StringListFlagDefined (string_view name) const noexcept
|
||||
{
|
||||
return strlistflags.Used (name);
|
||||
}
|
||||
|
||||
bool Flags :: NumListFlagDefined (const string & name) const
|
||||
bool Flags :: NumListFlagDefined (string_view name) const noexcept
|
||||
{
|
||||
return numlistflags.Used (name);
|
||||
}
|
||||
|
||||
bool Flags :: AnyFlagDefined (const string& name) const
|
||||
bool Flags :: AnyFlagDefined (string_view name) const noexcept
|
||||
{
|
||||
return anyflags.Used(name);
|
||||
}
|
||||
|
@ -125,15 +125,15 @@ namespace ngcore
|
||||
/// Returns std::string flag, default value if not exists
|
||||
std::string GetStringFlag (const std::string & name, std::string def = "") const;
|
||||
/// Returns numerical flag, default value if not exists
|
||||
double GetNumFlag (const std::string & name, double def) const;
|
||||
double GetNumFlag (std::string_view name, double def) const;
|
||||
/// Returns address of numerical flag, null if not exists
|
||||
const double * GetNumFlagPtr (const std::string & name) const;
|
||||
const double * GetNumFlagPtr (std::string_view name) const;
|
||||
/// Returns address of numerical flag, null if not exists
|
||||
double * GetNumFlagPtr (const std::string & name);
|
||||
/// Returns boolean flag
|
||||
// int GetDefineFlag (const char * name) const;
|
||||
bool GetDefineFlag (const std::string & name) const throw();
|
||||
xbool GetDefineFlagX (const std::string & name) const throw();
|
||||
bool GetDefineFlag (std::string_view name) const noexcept;
|
||||
xbool GetDefineFlagX (std::string_view name) const noexcept;
|
||||
/// Returns string list flag, empty array if not exist
|
||||
const Array<std::string> & GetStringListFlag (const std::string & name) const;
|
||||
/// Returns num list flag, empty array if not exist
|
||||
@ -144,16 +144,16 @@ namespace ngcore
|
||||
|
||||
|
||||
/// Test, if string flag is defined
|
||||
bool StringFlagDefined (const std::string & name) const;
|
||||
bool StringFlagDefined (std::string_view name) const noexcept;
|
||||
/// Test, if num flag is defined
|
||||
bool NumFlagDefined (const std::string & name) const;
|
||||
bool NumFlagDefined (std::string_view name) const noexcept;
|
||||
/// Test, if num flag is defined
|
||||
bool FlagsFlagDefined (const std::string & name) const;
|
||||
bool FlagsFlagDefined (std::string_view name) const noexcept;
|
||||
/// Test, if string list flag is defined
|
||||
bool StringListFlagDefined (const std::string & name) const;
|
||||
bool StringListFlagDefined (std::string_view name) const noexcept;
|
||||
/// Test, if num list flag is defined
|
||||
bool NumListFlagDefined (const std::string & name) const;
|
||||
bool AnyFlagDefined (const std::string& name) const;
|
||||
bool NumListFlagDefined (std::string_view name) const noexcept;
|
||||
bool AnyFlagDefined (std::string_view name) const noexcept;
|
||||
|
||||
/// number of string flags
|
||||
int GetNStringFlags () const { return strflags.Size(); }
|
||||
|
@ -5,6 +5,7 @@ functions = [
|
||||
("int", "MPI_Alltoall", "void*", "int", "MPI_Datatype", "void*", "int", "MPI_Datatype", "MPI_Comm"),
|
||||
("int", "MPI_Barrier", "MPI_Comm"),
|
||||
("int", "MPI_Bcast", "void*", "int", "MPI_Datatype", "int", "MPI_Comm"),
|
||||
("int", "MPI_Ibcast", "void*", "int", "MPI_Datatype", "int", "MPI_Comm", "MPI_Request*"),
|
||||
("int", "MPI_Comm_c2f", "MPI_Comm"),
|
||||
("int", "MPI_Comm_create", "MPI_Comm", "MPI_Group", "MPI_Comm*"),
|
||||
("int", "MPI_Comm_create_group", "MPI_Comm", "MPI_Group", "int", "MPI_Comm*"),
|
||||
@ -105,13 +106,13 @@ def generate_declarations():
|
||||
name = f[1]
|
||||
args = ", ".join(get_args(f))
|
||||
code += f"NGCORE_API extern {ret} (*NG_{name})({args});\n"
|
||||
nowrapper_code += f"static const auto NG_{name} = {name};\n"
|
||||
nowrapper_code += f"#define NG_{name} {name}\n"
|
||||
|
||||
for typ, name in constants:
|
||||
if typ.startswith("MPI_"):
|
||||
typ = "NG_" + typ
|
||||
code += f"NGCORE_API extern {typ} NG_{name};\n"
|
||||
nowrapper_code += f"static const decltype({name}) NG_{name} = {name};\n"
|
||||
nowrapper_code += f"#define NG_{name} {name}\n"
|
||||
|
||||
with open("ng_mpi_generated_declarations.hpp", "w") as f:
|
||||
f.write("#ifdef NG_MPI_WRAPPER\n")
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <optional>
|
||||
|
||||
// #include "mpi_wrapper.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
@ -46,16 +47,27 @@ namespace ngcore
|
||||
class IVec
|
||||
{
|
||||
/// data
|
||||
T i[(N>0)?N:1];
|
||||
// T i[(N>0)?N:1];
|
||||
|
||||
HTArray<N,T> i;
|
||||
|
||||
public:
|
||||
///
|
||||
NETGEN_INLINE IVec () { }
|
||||
constexpr NETGEN_INLINE IVec () = default;
|
||||
constexpr NETGEN_INLINE IVec (const IVec & i1) : i(i1.i) { }
|
||||
|
||||
constexpr NETGEN_INLINE IVec (T ai1) : i(ai1) { }
|
||||
|
||||
template <class... T2,
|
||||
std::enable_if_t<N==1+sizeof...(T2),bool> = true>
|
||||
constexpr IVec (const T &v, T2... rest)
|
||||
: i{v,rest...} { }
|
||||
|
||||
/*
|
||||
/// init all
|
||||
NETGEN_INLINE IVec (T ai1)
|
||||
{
|
||||
for (int j = 0; j < N; j++) { i[j] = ai1; }
|
||||
for (int j = 0; j < N; j++) { i[j] = ai1; }
|
||||
}
|
||||
|
||||
/// init i[0], i[1]
|
||||
@ -77,11 +89,13 @@ namespace ngcore
|
||||
/// init i[0], i[1], i[2]
|
||||
NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4, T ai5, T ai6, T ai7, T ai8, T ai9)
|
||||
: i{ai1, ai2, ai3, ai4, ai5, ai6, ai7, ai8, ai9 } { ; }
|
||||
|
||||
*/
|
||||
|
||||
template <typename ARCHIVE>
|
||||
void DoArchive(ARCHIVE& ar)
|
||||
{
|
||||
ar.Do(i, N);
|
||||
// ar.Do(i.begin(), N);
|
||||
ar.Do(i.Ptr(), N);
|
||||
}
|
||||
|
||||
template <int N2, typename T2>
|
||||
@ -286,7 +300,7 @@ namespace ngcore
|
||||
|
||||
|
||||
template <int N, typename TI>
|
||||
NETGEN_INLINE size_t HashValue2 (const IVec<N,TI> & ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<N,TI> & ind, size_t mask)
|
||||
{
|
||||
IVec<N,size_t> lind = ind;
|
||||
size_t sum = 0;
|
||||
@ -297,14 +311,14 @@ namespace ngcore
|
||||
|
||||
/// hash value of 1 int
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue2 (const IVec<1,TI> & ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<1,TI> & ind, size_t mask)
|
||||
{
|
||||
return ind[0] & mask;
|
||||
}
|
||||
|
||||
/// hash value of 2 int
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue2 (const IVec<2,TI> & ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<2,TI> & ind, size_t mask)
|
||||
{
|
||||
IVec<2,size_t> lind = ind;
|
||||
return (113*lind[0]+lind[1]) & mask;
|
||||
@ -312,17 +326,17 @@ namespace ngcore
|
||||
|
||||
/// hash value of 3 int
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue2 (const IVec<3,TI> & ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<3,TI> & ind, size_t mask)
|
||||
{
|
||||
IVec<3,size_t> lind = ind;
|
||||
return (113*lind[0]+59*lind[1]+lind[2]) & mask;
|
||||
}
|
||||
|
||||
NETGEN_INLINE size_t HashValue2 (size_t ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (size_t ind, size_t mask)
|
||||
{
|
||||
return ind & mask;
|
||||
}
|
||||
NETGEN_INLINE size_t HashValue2 (int ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (int ind, size_t mask)
|
||||
{
|
||||
return size_t(ind) & mask;
|
||||
}
|
||||
@ -577,7 +591,27 @@ namespace ngcore
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr inline T InvalidHash() { return T(-1); }
|
||||
|
||||
template <typename T_HASH>
|
||||
struct CHT_trait
|
||||
{
|
||||
constexpr static inline T_HASH Invalid() { return InvalidHash<T_HASH>(); }
|
||||
constexpr static inline size_t HashValue (const T_HASH & hash, size_t mask) { return HashValue2(hash, mask); }
|
||||
};
|
||||
|
||||
template <typename T1, typename T2>
|
||||
struct CHT_trait<std::tuple<T1,T2>>
|
||||
{
|
||||
constexpr static inline std::tuple<T1,T2> Invalid() { return { CHT_trait<T1>::Invalid(), CHT_trait<T2>::Invalid() } ; }
|
||||
constexpr static inline size_t HashValue (const std::tuple<T1,T2> & hash, size_t mask)
|
||||
{
|
||||
return (CHT_trait<T1>::HashValue(std::get<0>(hash), mask) + CHT_trait<T2>::HashValue(std::get<1>(hash),mask)) & mask;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
A closed hash-table.
|
||||
@ -598,14 +632,18 @@ namespace ngcore
|
||||
///
|
||||
Array<T> cont;
|
||||
///
|
||||
T_HASH invalid = -1;
|
||||
// T_HASH invalid = -1;
|
||||
// static constexpr T_HASH invalid = InvalidHash<T_HASH>();
|
||||
static constexpr T_HASH invalid = CHT_trait<T_HASH>::Invalid();
|
||||
public:
|
||||
///
|
||||
ClosedHashTable (size_t asize = 128)
|
||||
: size(RoundUp2(asize)), hash(size), cont(size)
|
||||
{
|
||||
mask = size-1;
|
||||
hash = T_HASH(invalid);
|
||||
// hash = T_HASH(invalid);
|
||||
// hash = InvalidHash<T_HASH>();
|
||||
hash = CHT_trait<T_HASH>::Invalid();
|
||||
}
|
||||
|
||||
ClosedHashTable (ClosedHashTable && ht2) = default;
|
||||
@ -614,7 +652,8 @@ namespace ngcore
|
||||
ClosedHashTable (size_t asize, LocalHeap & lh)
|
||||
: size(RoundUp2(asize)), mask(size-1), hash(size, lh), cont(size, lh)
|
||||
{
|
||||
hash = T_HASH(invalid);
|
||||
// hash = T_HASH(invalid);
|
||||
hash = InvalidHash<T_HASH>();
|
||||
}
|
||||
|
||||
ClosedHashTable & operator= (ClosedHashTable && ht2) = default;
|
||||
@ -639,7 +678,8 @@ namespace ngcore
|
||||
|
||||
size_t Position (const T_HASH ind) const
|
||||
{
|
||||
size_t i = HashValue2(ind, mask);
|
||||
// size_t i = HashValue2(ind, mask);
|
||||
size_t i = CHT_trait<T_HASH>::HashValue(ind, mask);
|
||||
while (true)
|
||||
{
|
||||
if (hash[i] == ind) return i;
|
||||
@ -661,7 +701,8 @@ namespace ngcore
|
||||
{
|
||||
if (UsedElements()*2 > Size()) DoubleSize();
|
||||
|
||||
size_t i = HashValue2 (ind, mask);
|
||||
// size_t i = HashValue2 (ind, mask);
|
||||
size_t i = CHT_trait<T_HASH>::HashValue (ind, mask);
|
||||
|
||||
while (true)
|
||||
{
|
||||
@ -706,6 +747,16 @@ namespace ngcore
|
||||
return (Position (ahash) != size_t(-1));
|
||||
}
|
||||
|
||||
inline std::optional<T> GetIfUsed (const T_HASH & ahash) const
|
||||
{
|
||||
size_t pos = Position (ahash);
|
||||
if (pos != size_t(-1))
|
||||
return cont[pos];
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
void SetData (size_t pos, const T_HASH & ahash, const T & acont)
|
||||
{
|
||||
hash[pos] = ahash;
|
||||
@ -783,6 +834,15 @@ namespace ngcore
|
||||
hash = T_HASH(invalid);
|
||||
used = 0;
|
||||
}
|
||||
|
||||
template <typename ARCHIVE>
|
||||
void DoArchive (ARCHIVE& ar)
|
||||
{
|
||||
ar & hash & cont;
|
||||
ar & size & mask & used;
|
||||
}
|
||||
|
||||
struct EndIterator { };
|
||||
|
||||
class Iterator
|
||||
{
|
||||
@ -800,24 +860,21 @@ namespace ngcore
|
||||
while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;
|
||||
return *this;
|
||||
}
|
||||
bool operator!= (const Iterator & it2) { return nr != it2.nr; }
|
||||
auto operator* () const
|
||||
{
|
||||
T_HASH hash;
|
||||
T val;
|
||||
tab.GetData(nr, hash,val);
|
||||
return std::make_pair(hash,val);
|
||||
}
|
||||
|
||||
bool operator!= (EndIterator it2) { return nr != tab.Size(); }
|
||||
|
||||
auto operator* () const { return tab.GetBoth(nr); }
|
||||
};
|
||||
|
||||
Iterator begin() const { return Iterator(*this, 0); }
|
||||
Iterator end() const { return Iterator(*this, Size()); }
|
||||
EndIterator end() const { return EndIterator(); }
|
||||
};
|
||||
|
||||
template <class T_HASH, class T>
|
||||
ostream & operator<< (ostream & ost,
|
||||
const ClosedHashTable<T_HASH,T> & tab)
|
||||
{
|
||||
/*
|
||||
for (size_t i = 0; i < tab.Size(); i++)
|
||||
if (tab.UsedPos(i))
|
||||
{
|
||||
@ -826,6 +883,9 @@ namespace ngcore
|
||||
tab.GetData (i, key, val);
|
||||
ost << key << ": " << val << ", ";
|
||||
}
|
||||
*/
|
||||
for (auto [key,val] : tab)
|
||||
ost << key << ": " << val << ", ";
|
||||
return ost;
|
||||
}
|
||||
|
||||
@ -1070,6 +1130,106 @@ namespace ngcore
|
||||
return ost;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <class T, class IndexType>
|
||||
class CompressedTable
|
||||
{
|
||||
Table<T, size_t> table;
|
||||
ClosedHashTable<IndexType, size_t> idmap;
|
||||
|
||||
public:
|
||||
CompressedTable (Table<T, size_t> && atable, ClosedHashTable<IndexType, size_t> && aidmap)
|
||||
: table(std::move(atable)), idmap(std::move(aidmap)) { }
|
||||
|
||||
FlatArray<T> operator[](IndexType id) const
|
||||
{
|
||||
if (auto nr = idmap.GetIfUsed(id))
|
||||
return table[*nr];
|
||||
else
|
||||
return { 0, nullptr };
|
||||
}
|
||||
auto & GetTable() { return table; }
|
||||
};
|
||||
|
||||
|
||||
template <class T, typename IndexType>
|
||||
class CompressedTableCreator
|
||||
{
|
||||
protected:
|
||||
int mode; // 1 .. cnt, 2 .. cnt entries, 3 .. fill table
|
||||
size_t nd; // number of entries;
|
||||
ClosedHashTable<IndexType, size_t> idmap;
|
||||
Array<int,size_t> cnt;
|
||||
Table<T,size_t> table;
|
||||
public:
|
||||
CompressedTableCreator()
|
||||
{ nd = 0; mode = 1; }
|
||||
|
||||
CompressedTable<T,IndexType> MoveTable()
|
||||
{
|
||||
return { std::move(table), std::move(idmap) };
|
||||
}
|
||||
|
||||
bool Done () { return mode > 3; }
|
||||
void operator++(int) { SetMode (mode+1); }
|
||||
|
||||
int GetMode () const { return mode; }
|
||||
void SetMode (int amode)
|
||||
{
|
||||
mode = amode;
|
||||
if (mode == 2)
|
||||
{
|
||||
cnt.SetSize(nd);
|
||||
cnt = 0;
|
||||
}
|
||||
if (mode == 3)
|
||||
{
|
||||
table = Table<T,size_t> (cnt);
|
||||
cnt = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Add (IndexType blocknr, const T & data)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
if (!idmap.Used (blocknr))
|
||||
idmap[blocknr] = nd++;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
cnt[idmap.Get(blocknr)]++;
|
||||
break;
|
||||
case 3:
|
||||
size_t cblock = idmap.Get(blocknr);
|
||||
int ci = cnt[cblock]++;
|
||||
table[cblock][ci] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
|
||||
|
@ -35,11 +35,16 @@ namespace ngcore
|
||||
|
||||
class MemoryTracer
|
||||
{
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
#if defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)
|
||||
NGCORE_API static std::vector<std::string> names;
|
||||
NGCORE_API static std::vector<int> parents;
|
||||
|
||||
static int CreateId(const std::string& name)
|
||||
#if defined(NETGEN_CHECK_RANGE)
|
||||
NGCORE_API static std::atomic<size_t> total_memory;
|
||||
mutable size_t allocated_memory = 0;
|
||||
#endif // NETGEN_CHECK_RANGE
|
||||
|
||||
static int CreateId(const std::string& name = "")
|
||||
{
|
||||
int id = names.size();
|
||||
names.push_back(name);
|
||||
@ -48,7 +53,7 @@ namespace ngcore
|
||||
std::cerr << "Allocated " << id << " MemoryTracer objects" << std::endl;
|
||||
return id;
|
||||
}
|
||||
int id;
|
||||
mutable int id = 0;
|
||||
|
||||
public:
|
||||
|
||||
@ -57,8 +62,33 @@ namespace ngcore
|
||||
id = CreateId(name);
|
||||
}
|
||||
|
||||
// not tracing
|
||||
MemoryTracer() : id(0) {}
|
||||
MemoryTracer() { }
|
||||
|
||||
MemoryTracer(const MemoryTracer & tracer)
|
||||
{
|
||||
(*this) = tracer;
|
||||
}
|
||||
|
||||
MemoryTracer(MemoryTracer && tracer)
|
||||
{
|
||||
(*this) = std::move(tracer);
|
||||
}
|
||||
|
||||
MemoryTracer & operator=(const MemoryTracer & tracer) {
|
||||
if(tracer.id)
|
||||
id = CreateId(names[tracer.id]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MemoryTracer & operator=(MemoryTracer && tracer) {
|
||||
ngcore::Swap(id, tracer.id);
|
||||
|
||||
#if defined(NETGEN_CHECK_RANGE)
|
||||
ngcore::Swap(allocated_memory, tracer.allocated_memory);
|
||||
#endif // NETGEN_CHECK_RANGE
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... TRest>
|
||||
MemoryTracer( std::string name, TRest & ... rest )
|
||||
@ -67,38 +97,48 @@ namespace ngcore
|
||||
Track(rest...);
|
||||
}
|
||||
|
||||
#if defined(NETGEN_CHECK_RANGE)
|
||||
// check if all memory was freed when object is destroyed
|
||||
~MemoryTracer()
|
||||
{
|
||||
NETGEN_CHECK_SAME(allocated_memory, 0);
|
||||
}
|
||||
#endif // NETGEN_CHECK_RANGE
|
||||
|
||||
NETGEN_INLINE void Alloc(size_t size) const
|
||||
{
|
||||
#if defined(NETGEN_CHECK_RANGE)
|
||||
// Trace also nameless Memtracer objects if range checks are active
|
||||
if(!id && size)
|
||||
id = CreateId();
|
||||
#endif // NETGEN_CHECK_RANGE
|
||||
|
||||
if(id && trace)
|
||||
trace->AllocMemory(id, size);
|
||||
|
||||
#if defined(NETGEN_CHECK_RANGE)
|
||||
if(id)
|
||||
{
|
||||
allocated_memory += size;
|
||||
total_memory += size;
|
||||
}
|
||||
#endif // NETGEN_CHECK_RANGE
|
||||
}
|
||||
|
||||
void Free(size_t size) const
|
||||
{
|
||||
if(id && trace)
|
||||
trace->FreeMemory(id, size);
|
||||
}
|
||||
|
||||
void Swap(size_t mysize, MemoryTracer& other, size_t other_size) const
|
||||
{
|
||||
if(!trace || (id == 0 && other.id == 0))
|
||||
return;
|
||||
if(id == 0)
|
||||
return trace->ChangeMemory(other.id, mysize - other_size);
|
||||
if(other.id == 0)
|
||||
return trace->ChangeMemory(id, other_size - mysize);
|
||||
|
||||
// first decrease memory, otherwise have artificial/wrong high peak memory usage
|
||||
if(mysize<other_size)
|
||||
{
|
||||
trace->ChangeMemory(other.id, mysize-other_size);
|
||||
trace->ChangeMemory(id, other_size-mysize);
|
||||
}
|
||||
else
|
||||
{
|
||||
trace->ChangeMemory(id, other_size-mysize);
|
||||
trace->ChangeMemory(other.id, mysize-other_size);
|
||||
}
|
||||
#if defined(NETGEN_CHECK_RANGE)
|
||||
if(id)
|
||||
{
|
||||
// check if we have at least size bytes of memory currently allocated (such that allocated_memory doesn't get negative)
|
||||
NETGEN_CHECK_RANGE(allocated_memory, static_cast<ptrdiff_t>(size), std::numeric_limits<ptrdiff_t>::max());
|
||||
allocated_memory -= size;
|
||||
total_memory -= size;
|
||||
#endif // NETGEN_CHECK_RANGE
|
||||
}
|
||||
}
|
||||
|
||||
int GetId() const { return id; }
|
||||
@ -148,7 +188,15 @@ namespace ngcore
|
||||
|
||||
static const std::vector<std::string> & GetNames() { return names; }
|
||||
static const std::vector<int> & GetParents() { return parents; }
|
||||
#else // NETGEN_TRACE_MEMORY
|
||||
static size_t GetTotalMemory()
|
||||
{
|
||||
#if defined(NETGEN_CHECK_RANGE)
|
||||
return total_memory;
|
||||
#else
|
||||
return 0;
|
||||
#endif // NETGEN_CHECK_RANGE
|
||||
}
|
||||
#else // defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)
|
||||
public:
|
||||
MemoryTracer() {}
|
||||
MemoryTracer( std::string /* name */ ) {}
|
||||
@ -157,7 +205,6 @@ namespace ngcore
|
||||
|
||||
void Alloc(size_t /* size */) const {}
|
||||
void Free(size_t /* size */) const {}
|
||||
void Swap(...) const {}
|
||||
int GetId() const { return 0; }
|
||||
|
||||
template <typename... TRest>
|
||||
@ -166,6 +213,7 @@ namespace ngcore
|
||||
static std::string GetName(int /* id */) { return ""; }
|
||||
std::string GetName() const { return ""; }
|
||||
void SetName(std::string /* name */) const {}
|
||||
static size_t GetTotalMemory() { return 0; }
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
};
|
||||
} // namespace ngcore
|
||||
|
@ -72,14 +72,68 @@ namespace ngcore
|
||||
return GetMPIType<T>();
|
||||
}
|
||||
|
||||
class NgMPI_Request
|
||||
{
|
||||
NG_MPI_Request request;
|
||||
public:
|
||||
NgMPI_Request (NG_MPI_Request requ) : request{requ} { }
|
||||
NgMPI_Request (const NgMPI_Request&) = delete;
|
||||
NgMPI_Request (NgMPI_Request&&) = default;
|
||||
~NgMPI_Request () { NG_MPI_Wait (&request, NG_MPI_STATUS_IGNORE); }
|
||||
void Wait() { NG_MPI_Wait (&request, NG_MPI_STATUS_IGNORE); }
|
||||
operator NG_MPI_Request() &&
|
||||
{
|
||||
auto tmp = request;
|
||||
request = NG_MPI_REQUEST_NULL;
|
||||
return tmp;
|
||||
}
|
||||
};
|
||||
|
||||
class NgMPI_Requests
|
||||
{
|
||||
Array<NG_MPI_Request> requests;
|
||||
public:
|
||||
NgMPI_Requests() = default;
|
||||
~NgMPI_Requests() { WaitAll(); }
|
||||
|
||||
void Reset() { requests.SetSize0(); }
|
||||
|
||||
NgMPI_Requests & operator+= (NgMPI_Request && r)
|
||||
{
|
||||
requests += NG_MPI_Request(std::move(r));
|
||||
return *this;
|
||||
}
|
||||
|
||||
NgMPI_Requests & operator+= (NG_MPI_Request r)
|
||||
{
|
||||
requests += r;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void WaitAll()
|
||||
{
|
||||
static Timer t("NgMPI - WaitAll"); RegionTimer reg(t);
|
||||
if (!requests.Size()) return;
|
||||
NG_MPI_Waitall (requests.Size(), requests.Data(), NG_MPI_STATUSES_IGNORE);
|
||||
}
|
||||
|
||||
int WaitAny ()
|
||||
{
|
||||
int nr;
|
||||
NG_MPI_Waitany (requests.Size(), requests.Data(), &nr, NG_MPI_STATUS_IGNORE);
|
||||
return nr;
|
||||
}
|
||||
};
|
||||
|
||||
[[deprecated("use requests.WaitAll instread")]]
|
||||
inline void MyMPI_WaitAll (FlatArray<NG_MPI_Request> requests)
|
||||
{
|
||||
static Timer t("MPI - WaitAll"); RegionTimer reg(t);
|
||||
if (!requests.Size()) return;
|
||||
NG_MPI_Waitall (requests.Size(), requests.Data(), NG_MPI_STATUSES_IGNORE);
|
||||
}
|
||||
|
||||
|
||||
[[deprecated("use requests.WaitAny instread")]]
|
||||
inline int MyMPI_WaitAny (FlatArray<NG_MPI_Request> requests)
|
||||
{
|
||||
int nr;
|
||||
@ -233,25 +287,25 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/** --- non-blocking P2P --- **/
|
||||
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
NG_MPI_Request ISend (T & val, int dest, int tag) const
|
||||
[[nodiscard]] NG_MPI_Request ISend (T & val, int dest, int tag) const
|
||||
{
|
||||
NG_MPI_Request request;
|
||||
NG_MPI_Isend (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
NG_MPI_Request ISend (FlatArray<T> s, int dest, int tag) const
|
||||
[[nodiscard]] NG_MPI_Request ISend (FlatArray<T> s, int dest, int tag) const
|
||||
{
|
||||
NG_MPI_Request request;
|
||||
NG_MPI_Isend (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm, &request);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
NG_MPI_Request IRecv (T & val, int dest, int tag) const
|
||||
[[nodiscard]] NG_MPI_Request IRecv (T & val, int dest, int tag) const
|
||||
{
|
||||
NG_MPI_Request request;
|
||||
NG_MPI_Irecv (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);
|
||||
@ -259,7 +313,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
NG_MPI_Request IRecv (FlatArray<T> s, int src, int tag) const
|
||||
[[nodiscard]] NG_MPI_Request IRecv (FlatArray<T> s, int src, int tag) const
|
||||
{
|
||||
NG_MPI_Request request;
|
||||
NG_MPI_Irecv (s.Data(), s.Size(), GetMPIType<T>(), src, tag, comm, &request);
|
||||
@ -307,9 +361,18 @@ namespace ngcore
|
||||
NG_MPI_Bcast (&s, 1, GetMPIType<T>(), root, comm);
|
||||
}
|
||||
|
||||
|
||||
template <class T, size_t S>
|
||||
void Bcast (std::array<T,S> & d, int root = 0) const
|
||||
{
|
||||
if (size == 1) return;
|
||||
if (S != 0)
|
||||
NG_MPI_Bcast (&d[0], S, GetMPIType<T>(), root, comm);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
void Bcast (Array<T> & d, int root = 0)
|
||||
void Bcast (Array<T> & d, int root = 0) const
|
||||
{
|
||||
if (size == 1) return;
|
||||
|
||||
@ -330,11 +393,31 @@ namespace ngcore
|
||||
NG_MPI_Bcast (&s[0], len, NG_MPI_CHAR, root, comm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T, size_t S>
|
||||
[[nodiscard]] NgMPI_Request IBcast (std::array<T,S> & d, int root = 0) const
|
||||
{
|
||||
NG_MPI_Request request;
|
||||
NG_MPI_Ibcast (&d[0], S, GetMPIType<T>(), root, comm, &request);
|
||||
return request;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
[[nodiscard]] NgMPI_Request IBcast (FlatArray<T> d, int root = 0) const
|
||||
{
|
||||
NG_MPI_Request request;
|
||||
int ds = d.Size();
|
||||
NG_MPI_Ibcast (d.Data(), ds, GetMPIType<T>(), root, comm, &request);
|
||||
return request;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void AllToAll (FlatArray<T> send, FlatArray<T> recv) const
|
||||
{
|
||||
NG_MPI_Alltoall (send.Data(), 1, GetMPIType<T>(),
|
||||
recv.Data(), 1, GetMPIType<T>(), comm);
|
||||
recv.Data(), 1, GetMPIType<T>(), comm);
|
||||
}
|
||||
|
||||
|
||||
@ -343,7 +426,7 @@ namespace ngcore
|
||||
{
|
||||
if (size == 1) return;
|
||||
NG_MPI_Scatter (send.Data(), 1, GetMPIType<T>(),
|
||||
NG_MPI_IN_PLACE, -1, GetMPIType<T>(), 0, comm);
|
||||
NG_MPI_IN_PLACE, -1, GetMPIType<T>(), 0, comm);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -351,7 +434,7 @@ namespace ngcore
|
||||
{
|
||||
if (size == 1) return;
|
||||
NG_MPI_Scatter (NULL, 0, GetMPIType<T>(),
|
||||
&recv, 1, GetMPIType<T>(), 0, comm);
|
||||
&recv, 1, GetMPIType<T>(), 0, comm);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -360,7 +443,7 @@ namespace ngcore
|
||||
recv[0] = T(0);
|
||||
if (size == 1) return;
|
||||
NG_MPI_Gather (NG_MPI_IN_PLACE, 1, GetMPIType<T>(),
|
||||
recv.Data(), 1, GetMPIType<T>(), 0, comm);
|
||||
recv.Data(), 1, GetMPIType<T>(), 0, comm);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -401,16 +484,16 @@ namespace ngcore
|
||||
|
||||
recv_data = DynamicTable<T> (recv_sizes, true);
|
||||
|
||||
Array<NG_MPI_Request> requests;
|
||||
NgMPI_Requests requests;
|
||||
for (int dest = 0; dest < size; dest++)
|
||||
if (dest != rank && send_data[dest].Size())
|
||||
requests.Append (ISend (FlatArray<T>(send_data[dest]), dest, tag));
|
||||
requests += ISend (FlatArray<T>(send_data[dest]), dest, tag);
|
||||
|
||||
for (int dest = 0; dest < size; dest++)
|
||||
if (dest != rank && recv_data[dest].Size())
|
||||
requests.Append (IRecv (FlatArray<T>(recv_data[dest]), dest, tag));
|
||||
requests += IRecv (FlatArray<T>(recv_data[dest]), dest, tag);
|
||||
|
||||
MyMPI_WaitAll (requests);
|
||||
requests.WaitAll();
|
||||
}
|
||||
|
||||
|
||||
@ -453,6 +536,22 @@ namespace ngcore
|
||||
};
|
||||
template <class T, class T2=void>
|
||||
inline NG_MPI_Datatype GetMPIType () { return -1; }
|
||||
|
||||
class NgMPI_Request {
|
||||
public:
|
||||
NgMPI_Request() = default;
|
||||
NgMPI_Request(NgMPI_Request &&) { ; }
|
||||
NgMPI_Request(NG_MPI_Request &&) { ; }
|
||||
};
|
||||
class NgMPI_Requests
|
||||
{
|
||||
public:
|
||||
NgMPI_Requests & operator+= (NgMPI_Request &&) { return *this; }
|
||||
NgMPI_Requests & operator+= (NG_MPI_Request r) { return *this; }
|
||||
void Reset() { ; }
|
||||
void WaitAll() { ; }
|
||||
int WaitAny() { return 0; }
|
||||
};
|
||||
|
||||
class NgMPI_Comm
|
||||
{
|
||||
@ -506,9 +605,18 @@ namespace ngcore
|
||||
template <typename T>
|
||||
void Bcast (T & s, int root = 0) const { ; }
|
||||
|
||||
template <class T, size_t S>
|
||||
void Bcast (std::array<T,S> & d, int root = 0) const {}
|
||||
|
||||
template <class T>
|
||||
void Bcast (Array<T> & d, int root = 0) { ; }
|
||||
void Bcast (Array<T> & d, int root = 0) const { ; }
|
||||
|
||||
template <class T, size_t S>
|
||||
NG_MPI_Request IBcast (std::array<T,S> & d, int root = 0) const { return 0; }
|
||||
|
||||
template <class T>
|
||||
NG_MPI_Request IBcast (FlatArray<T> d, int root = 0) const { return 0; }
|
||||
|
||||
template <typename T>
|
||||
void AllGather (T val, FlatArray<T> recv) const
|
||||
{
|
||||
|
@ -7,16 +7,16 @@
|
||||
|
||||
#include "array.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
#include "pybind11/pytypes.h"
|
||||
|
||||
#ifdef NG_PYTHON
|
||||
#include "pybind11/pytypes.h"
|
||||
#include "python_ngcore.hpp"
|
||||
#endif
|
||||
|
||||
#define MPI4PY_LIMITED_API 1
|
||||
#define MPI4PY_LIMITED_API_SKIP_MESSAGE 1
|
||||
#define MPI4PY_LIMITED_API_SKIP_SESSION 1
|
||||
#include "mpi4py_pycapi.h" // mpi4py < 4.0.0
|
||||
#endif
|
||||
|
||||
#ifdef MSMPI_VER
|
||||
int MPI_Comm_create_group(MPI_Comm arg0, MPI_Group arg1, int arg2,
|
||||
@ -164,7 +164,7 @@ void ng_init_mpi() {
|
||||
imported_mpi4py = true;
|
||||
}
|
||||
PyObject* py_src = src.ptr();
|
||||
auto type = Py_TYPE(py_src);
|
||||
[[maybe_unused]] auto type = Py_TYPE(py_src);
|
||||
if (PyObject_TypeCheck(py_src, &PyMPIComm_Type)) {
|
||||
dst = mpi2ng(*PyMPIComm_Get(py_src));
|
||||
return !PyErr_Occurred();
|
||||
|
@ -5,6 +5,7 @@ NGCORE_API extern int (*NG_MPI_Allreduce)(void*, void*, int, NG_MPI_Datatype, NG
|
||||
NGCORE_API extern int (*NG_MPI_Alltoall)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Barrier)(NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Bcast)(void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Ibcast)(void*, int, NG_MPI_Datatype, int, NG_MPI_Comm, NG_MPI_Request*);
|
||||
NGCORE_API extern int (*NG_MPI_Comm_c2f)(NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Comm_create)(NG_MPI_Comm, NG_MPI_Group, NG_MPI_Comm*);
|
||||
NGCORE_API extern int (*NG_MPI_Comm_create_group)(NG_MPI_Comm, NG_MPI_Group, int, NG_MPI_Comm*);
|
||||
@ -75,79 +76,80 @@ NGCORE_API extern int NG_MPI_THREAD_SINGLE;
|
||||
NGCORE_API extern int NG_MPI_VERSION;
|
||||
NGCORE_API extern void* NG_MPI_IN_PLACE;
|
||||
#else // NG_MPI_WRAPPER
|
||||
static const auto NG_MPI_Wtime = MPI_Wtime;
|
||||
static const auto NG_MPI_Allgather = MPI_Allgather;
|
||||
static const auto NG_MPI_Allreduce = MPI_Allreduce;
|
||||
static const auto NG_MPI_Alltoall = MPI_Alltoall;
|
||||
static const auto NG_MPI_Barrier = MPI_Barrier;
|
||||
static const auto NG_MPI_Bcast = MPI_Bcast;
|
||||
static const auto NG_MPI_Comm_c2f = MPI_Comm_c2f;
|
||||
static const auto NG_MPI_Comm_create = MPI_Comm_create;
|
||||
static const auto NG_MPI_Comm_create_group = MPI_Comm_create_group;
|
||||
static const auto NG_MPI_Comm_free = MPI_Comm_free;
|
||||
static const auto NG_MPI_Comm_group = MPI_Comm_group;
|
||||
static const auto NG_MPI_Comm_rank = MPI_Comm_rank;
|
||||
static const auto NG_MPI_Comm_size = MPI_Comm_size;
|
||||
static const auto NG_MPI_Finalize = MPI_Finalize;
|
||||
static const auto NG_MPI_Gather = MPI_Gather;
|
||||
static const auto NG_MPI_Gatherv = MPI_Gatherv;
|
||||
static const auto NG_MPI_Get_count = MPI_Get_count;
|
||||
static const auto NG_MPI_Get_processor_name = MPI_Get_processor_name;
|
||||
static const auto NG_MPI_Group_incl = MPI_Group_incl;
|
||||
static const auto NG_MPI_Init = MPI_Init;
|
||||
static const auto NG_MPI_Init_thread = MPI_Init_thread;
|
||||
static const auto NG_MPI_Initialized = MPI_Initialized;
|
||||
static const auto NG_MPI_Iprobe = MPI_Iprobe;
|
||||
static const auto NG_MPI_Irecv = MPI_Irecv;
|
||||
static const auto NG_MPI_Isend = MPI_Isend;
|
||||
static const auto NG_MPI_Probe = MPI_Probe;
|
||||
static const auto NG_MPI_Query_thread = MPI_Query_thread;
|
||||
static const auto NG_MPI_Recv = MPI_Recv;
|
||||
static const auto NG_MPI_Recv_init = MPI_Recv_init;
|
||||
static const auto NG_MPI_Reduce = MPI_Reduce;
|
||||
static const auto NG_MPI_Reduce_local = MPI_Reduce_local;
|
||||
static const auto NG_MPI_Request_free = MPI_Request_free;
|
||||
static const auto NG_MPI_Scatter = MPI_Scatter;
|
||||
static const auto NG_MPI_Send = MPI_Send;
|
||||
static const auto NG_MPI_Send_init = MPI_Send_init;
|
||||
static const auto NG_MPI_Startall = MPI_Startall;
|
||||
static const auto NG_MPI_Type_commit = MPI_Type_commit;
|
||||
static const auto NG_MPI_Type_contiguous = MPI_Type_contiguous;
|
||||
static const auto NG_MPI_Type_create_resized = MPI_Type_create_resized;
|
||||
static const auto NG_MPI_Type_create_struct = MPI_Type_create_struct;
|
||||
static const auto NG_MPI_Type_free = MPI_Type_free;
|
||||
static const auto NG_MPI_Type_get_extent = MPI_Type_get_extent;
|
||||
static const auto NG_MPI_Type_indexed = MPI_Type_indexed;
|
||||
static const auto NG_MPI_Type_size = MPI_Type_size;
|
||||
static const auto NG_MPI_Wait = MPI_Wait;
|
||||
static const auto NG_MPI_Waitall = MPI_Waitall;
|
||||
static const auto NG_MPI_Waitany = MPI_Waitany;
|
||||
static const decltype(MPI_COMM_NULL) NG_MPI_COMM_NULL = MPI_COMM_NULL;
|
||||
static const decltype(MPI_COMM_WORLD) NG_MPI_COMM_WORLD = MPI_COMM_WORLD;
|
||||
static const decltype(MPI_CHAR) NG_MPI_CHAR = MPI_CHAR;
|
||||
static const decltype(MPI_CXX_DOUBLE_COMPLEX) NG_MPI_CXX_DOUBLE_COMPLEX = MPI_CXX_DOUBLE_COMPLEX;
|
||||
static const decltype(MPI_C_BOOL) NG_MPI_C_BOOL = MPI_C_BOOL;
|
||||
static const decltype(MPI_DATATYPE_NULL) NG_MPI_DATATYPE_NULL = MPI_DATATYPE_NULL;
|
||||
static const decltype(MPI_DOUBLE) NG_MPI_DOUBLE = MPI_DOUBLE;
|
||||
static const decltype(MPI_FLOAT) NG_MPI_FLOAT = MPI_FLOAT;
|
||||
static const decltype(MPI_INT) NG_MPI_INT = MPI_INT;
|
||||
static const decltype(MPI_SHORT) NG_MPI_SHORT = MPI_SHORT;
|
||||
static const decltype(MPI_UINT64_T) NG_MPI_UINT64_T = MPI_UINT64_T;
|
||||
static const decltype(MPI_LOR) NG_MPI_LOR = MPI_LOR;
|
||||
static const decltype(MPI_MAX) NG_MPI_MAX = MPI_MAX;
|
||||
static const decltype(MPI_MIN) NG_MPI_MIN = MPI_MIN;
|
||||
static const decltype(MPI_SUM) NG_MPI_SUM = MPI_SUM;
|
||||
static const decltype(MPI_REQUEST_NULL) NG_MPI_REQUEST_NULL = MPI_REQUEST_NULL;
|
||||
static const decltype(MPI_STATUSES_IGNORE) NG_MPI_STATUSES_IGNORE = MPI_STATUSES_IGNORE;
|
||||
static const decltype(MPI_STATUS_IGNORE) NG_MPI_STATUS_IGNORE = MPI_STATUS_IGNORE;
|
||||
static const decltype(MPI_ANY_SOURCE) NG_MPI_ANY_SOURCE = MPI_ANY_SOURCE;
|
||||
static const decltype(MPI_ANY_TAG) NG_MPI_ANY_TAG = MPI_ANY_TAG;
|
||||
static const decltype(MPI_MAX_PROCESSOR_NAME) NG_MPI_MAX_PROCESSOR_NAME = MPI_MAX_PROCESSOR_NAME;
|
||||
static const decltype(MPI_PROC_NULL) NG_MPI_PROC_NULL = MPI_PROC_NULL;
|
||||
static const decltype(MPI_ROOT) NG_MPI_ROOT = MPI_ROOT;
|
||||
static const decltype(MPI_SUBVERSION) NG_MPI_SUBVERSION = MPI_SUBVERSION;
|
||||
static const decltype(MPI_THREAD_MULTIPLE) NG_MPI_THREAD_MULTIPLE = MPI_THREAD_MULTIPLE;
|
||||
static const decltype(MPI_THREAD_SINGLE) NG_MPI_THREAD_SINGLE = MPI_THREAD_SINGLE;
|
||||
static const decltype(MPI_VERSION) NG_MPI_VERSION = MPI_VERSION;
|
||||
static const decltype(MPI_IN_PLACE) NG_MPI_IN_PLACE = MPI_IN_PLACE;
|
||||
#define NG_MPI_Wtime MPI_Wtime
|
||||
#define NG_MPI_Allgather MPI_Allgather
|
||||
#define NG_MPI_Allreduce MPI_Allreduce
|
||||
#define NG_MPI_Alltoall MPI_Alltoall
|
||||
#define NG_MPI_Barrier MPI_Barrier
|
||||
#define NG_MPI_Bcast MPI_Bcast
|
||||
#define NG_MPI_Ibcast MPI_Ibcast
|
||||
#define NG_MPI_Comm_c2f MPI_Comm_c2f
|
||||
#define NG_MPI_Comm_create MPI_Comm_create
|
||||
#define NG_MPI_Comm_create_group MPI_Comm_create_group
|
||||
#define NG_MPI_Comm_free MPI_Comm_free
|
||||
#define NG_MPI_Comm_group MPI_Comm_group
|
||||
#define NG_MPI_Comm_rank MPI_Comm_rank
|
||||
#define NG_MPI_Comm_size MPI_Comm_size
|
||||
#define NG_MPI_Finalize MPI_Finalize
|
||||
#define NG_MPI_Gather MPI_Gather
|
||||
#define NG_MPI_Gatherv MPI_Gatherv
|
||||
#define NG_MPI_Get_count MPI_Get_count
|
||||
#define NG_MPI_Get_processor_name MPI_Get_processor_name
|
||||
#define NG_MPI_Group_incl MPI_Group_incl
|
||||
#define NG_MPI_Init MPI_Init
|
||||
#define NG_MPI_Init_thread MPI_Init_thread
|
||||
#define NG_MPI_Initialized MPI_Initialized
|
||||
#define NG_MPI_Iprobe MPI_Iprobe
|
||||
#define NG_MPI_Irecv MPI_Irecv
|
||||
#define NG_MPI_Isend MPI_Isend
|
||||
#define NG_MPI_Probe MPI_Probe
|
||||
#define NG_MPI_Query_thread MPI_Query_thread
|
||||
#define NG_MPI_Recv MPI_Recv
|
||||
#define NG_MPI_Recv_init MPI_Recv_init
|
||||
#define NG_MPI_Reduce MPI_Reduce
|
||||
#define NG_MPI_Reduce_local MPI_Reduce_local
|
||||
#define NG_MPI_Request_free MPI_Request_free
|
||||
#define NG_MPI_Scatter MPI_Scatter
|
||||
#define NG_MPI_Send MPI_Send
|
||||
#define NG_MPI_Send_init MPI_Send_init
|
||||
#define NG_MPI_Startall MPI_Startall
|
||||
#define NG_MPI_Type_commit MPI_Type_commit
|
||||
#define NG_MPI_Type_contiguous MPI_Type_contiguous
|
||||
#define NG_MPI_Type_create_resized MPI_Type_create_resized
|
||||
#define NG_MPI_Type_create_struct MPI_Type_create_struct
|
||||
#define NG_MPI_Type_free MPI_Type_free
|
||||
#define NG_MPI_Type_get_extent MPI_Type_get_extent
|
||||
#define NG_MPI_Type_indexed MPI_Type_indexed
|
||||
#define NG_MPI_Type_size MPI_Type_size
|
||||
#define NG_MPI_Wait MPI_Wait
|
||||
#define NG_MPI_Waitall MPI_Waitall
|
||||
#define NG_MPI_Waitany MPI_Waitany
|
||||
#define NG_MPI_COMM_NULL MPI_COMM_NULL
|
||||
#define NG_MPI_COMM_WORLD MPI_COMM_WORLD
|
||||
#define NG_MPI_CHAR MPI_CHAR
|
||||
#define NG_MPI_CXX_DOUBLE_COMPLEX MPI_CXX_DOUBLE_COMPLEX
|
||||
#define NG_MPI_C_BOOL MPI_C_BOOL
|
||||
#define NG_MPI_DATATYPE_NULL MPI_DATATYPE_NULL
|
||||
#define NG_MPI_DOUBLE MPI_DOUBLE
|
||||
#define NG_MPI_FLOAT MPI_FLOAT
|
||||
#define NG_MPI_INT MPI_INT
|
||||
#define NG_MPI_SHORT MPI_SHORT
|
||||
#define NG_MPI_UINT64_T MPI_UINT64_T
|
||||
#define NG_MPI_LOR MPI_LOR
|
||||
#define NG_MPI_MAX MPI_MAX
|
||||
#define NG_MPI_MIN MPI_MIN
|
||||
#define NG_MPI_SUM MPI_SUM
|
||||
#define NG_MPI_REQUEST_NULL MPI_REQUEST_NULL
|
||||
#define NG_MPI_STATUSES_IGNORE MPI_STATUSES_IGNORE
|
||||
#define NG_MPI_STATUS_IGNORE MPI_STATUS_IGNORE
|
||||
#define NG_MPI_ANY_SOURCE MPI_ANY_SOURCE
|
||||
#define NG_MPI_ANY_TAG MPI_ANY_TAG
|
||||
#define NG_MPI_MAX_PROCESSOR_NAME MPI_MAX_PROCESSOR_NAME
|
||||
#define NG_MPI_PROC_NULL MPI_PROC_NULL
|
||||
#define NG_MPI_ROOT MPI_ROOT
|
||||
#define NG_MPI_SUBVERSION MPI_SUBVERSION
|
||||
#define NG_MPI_THREAD_MULTIPLE MPI_THREAD_MULTIPLE
|
||||
#define NG_MPI_THREAD_SINGLE MPI_THREAD_SINGLE
|
||||
#define NG_MPI_VERSION MPI_VERSION
|
||||
#define NG_MPI_IN_PLACE MPI_IN_PLACE
|
||||
#endif // NG_MPI_WRAPPER
|
||||
|
@ -4,6 +4,7 @@ decltype(NG_MPI_Allreduce) NG_MPI_Allreduce = [](void*, void*, int, NG_MPI_Datat
|
||||
decltype(NG_MPI_Alltoall) NG_MPI_Alltoall = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Barrier) NG_MPI_Barrier = [](NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Bcast) NG_MPI_Bcast = [](void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Ibcast) NG_MPI_Ibcast = [](void*, int, NG_MPI_Datatype, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Comm_c2f) NG_MPI_Comm_c2f = [](NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Comm_create) NG_MPI_Comm_create = [](NG_MPI_Comm, NG_MPI_Group, NG_MPI_Comm*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Comm_create_group) NG_MPI_Comm_create_group = [](NG_MPI_Comm, NG_MPI_Group, int, NG_MPI_Comm*)->int { throw no_mpi(); };
|
||||
|
@ -4,6 +4,7 @@ NG_MPI_Allreduce = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG
|
||||
NG_MPI_Alltoall = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, NG_MPI_Comm arg6)->int { return MPI_Alltoall( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
|
||||
NG_MPI_Barrier = [](NG_MPI_Comm arg0)->int { return MPI_Barrier( ng2mpi(arg0)); };
|
||||
NG_MPI_Bcast = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, NG_MPI_Comm arg4)->int { return MPI_Bcast( arg0, arg1, ng2mpi(arg2), arg3, ng2mpi(arg4)); };
|
||||
NG_MPI_Ibcast = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, NG_MPI_Comm arg4, NG_MPI_Request* arg5)->int { return MPI_Ibcast( arg0, arg1, ng2mpi(arg2), arg3, ng2mpi(arg4), ng2mpi(arg5)); };
|
||||
NG_MPI_Comm_c2f = [](NG_MPI_Comm arg0)->int { return MPI_Comm_c2f( ng2mpi(arg0)); };
|
||||
NG_MPI_Comm_create = [](NG_MPI_Comm arg0, NG_MPI_Group arg1, NG_MPI_Comm* arg2)->int { return MPI_Comm_create( ng2mpi(arg0), ng2mpi(arg1), ng2mpi(arg2)); };
|
||||
NG_MPI_Comm_create_group = [](NG_MPI_Comm arg0, NG_MPI_Group arg1, int arg2, NG_MPI_Comm* arg3)->int { return MPI_Comm_create_group( ng2mpi(arg0), ng2mpi(arg1), arg2, ng2mpi(arg3)); };
|
||||
|
@ -6,7 +6,9 @@
|
||||
|
||||
#include "ng_mpi.hpp"
|
||||
#include "ngstream.hpp"
|
||||
#ifdef NG_PYTHON
|
||||
#include "python_ngcore.hpp"
|
||||
#endif // NG_PYTHON
|
||||
#include "utils.hpp"
|
||||
|
||||
using std::cerr;
|
||||
@ -14,10 +16,12 @@ using std::cout;
|
||||
using std::endl;
|
||||
|
||||
#ifndef NG_MPI_WRAPPER
|
||||
#ifdef NG_PYTHON
|
||||
#define MPI4PY_LIMITED_API 1
|
||||
#define MPI4PY_LIMITED_API_SKIP_MESSAGE 1
|
||||
#define MPI4PY_LIMITED_API_SKIP_SESSION 1
|
||||
#include "mpi4py_pycapi.h" // mpi4py < 4.0.0
|
||||
#endif // NG_PYTHON
|
||||
#endif // NG_MPI_WRAPPER
|
||||
|
||||
namespace ngcore {
|
||||
@ -94,6 +98,7 @@ void InitMPI(std::optional<std::filesystem::path> mpi_lib_path) {
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
#ifdef NG_PYTHON
|
||||
// Use mpi4py to init MPI library and get the vendor name
|
||||
auto mpi4py = py::module::import("mpi4py.MPI");
|
||||
vendor = mpi4py.attr("get_vendor")()[py::int_(0)].cast<std::string>();
|
||||
@ -106,6 +111,7 @@ void InitMPI(std::optional<std::filesystem::path> mpi_lib_path) {
|
||||
mpi_lib =
|
||||
std::make_unique<SharedLibrary>(mpi4py_lib_file, std::nullopt, true);
|
||||
#endif // WIN32
|
||||
#endif // NG_PYTHON
|
||||
}
|
||||
|
||||
std::string ng_lib_name = "";
|
||||
|
@ -22,5 +22,6 @@
|
||||
#include "xbool.hpp"
|
||||
#include "ngstream.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "ranges.hpp"
|
||||
|
||||
#endif // NETGEN_CORE_NGCORE_HPP
|
||||
|
@ -41,6 +41,7 @@ namespace ngcore
|
||||
bool PajeTrace::trace_thread_counter = false;
|
||||
bool PajeTrace::trace_threads = true;
|
||||
bool PajeTrace::mem_tracing_enabled = true;
|
||||
bool PajeTrace::write_paje_file = true;
|
||||
|
||||
PajeTrace :: PajeTrace(int anthreads, std::string aname)
|
||||
{
|
||||
@ -124,7 +125,7 @@ namespace ngcore
|
||||
#endif
|
||||
if(comm.Size()==1)
|
||||
{
|
||||
Write(tracefile_name);
|
||||
Write();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -136,7 +137,7 @@ namespace ngcore
|
||||
event.timer_id += NgProfiler::SIZE*comm.Rank();
|
||||
|
||||
if(comm.Rank() == MPI_PAJE_WRITER)
|
||||
Write(tracefile_name);
|
||||
Write();
|
||||
else
|
||||
SendData();
|
||||
}
|
||||
@ -443,7 +444,16 @@ namespace ngcore
|
||||
|
||||
NGCORE_API PajeTrace *trace;
|
||||
|
||||
void PajeTrace::Write( const std::string & filename )
|
||||
void PajeTrace::Write( )
|
||||
{
|
||||
if(write_paje_file) WritePajeFile( tracefile_name );
|
||||
WriteTimingChart();
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
WriteMemoryChart("");
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
}
|
||||
|
||||
void PajeTrace::WritePajeFile( const std::string & filename )
|
||||
{
|
||||
auto n_events = jobs.size() + timer_events.size();
|
||||
for(auto & vtasks : tasks)
|
||||
@ -849,10 +859,6 @@ namespace ngcore
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteTimingChart();
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
WriteMemoryChart("");
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
paje.WriteEvents();
|
||||
}
|
||||
|
||||
@ -961,10 +967,18 @@ namespace ngcore
|
||||
f.precision(4);
|
||||
f << R"CODE_(
|
||||
<head>
|
||||
<script src="https://d3js.org/d3.v5.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
|
||||
<script src="https://unpkg.com/sunburst-chart"></script>
|
||||
|
||||
<style>body { margin: 0 }</style>
|
||||
<style>
|
||||
body { margin: 0 }
|
||||
.tooltip {
|
||||
white-space: pre-line !important;
|
||||
max-width: 800px !important;
|
||||
word-wrap: break-word !important;
|
||||
padding: 10px !important;
|
||||
}
|
||||
</style>
|
||||
)CODE_";
|
||||
if(!time_or_memory)
|
||||
f << "<title>Maximum Memory Consumption</title>\n";
|
||||
|
@ -25,6 +25,7 @@ namespace ngcore
|
||||
NGCORE_API static bool trace_thread_counter;
|
||||
NGCORE_API static bool trace_threads;
|
||||
NGCORE_API static bool mem_tracing_enabled;
|
||||
NGCORE_API static bool write_paje_file;
|
||||
|
||||
bool tracing_enabled;
|
||||
TTimePoint start_time;
|
||||
@ -32,6 +33,8 @@ namespace ngcore
|
||||
size_t n_memory_events_at_start;
|
||||
|
||||
public:
|
||||
NGCORE_API void Write();
|
||||
NGCORE_API void WritePajeFile( const std::string & filename );
|
||||
NGCORE_API void WriteTimingChart();
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
NGCORE_API void WriteMemoryChart( std::string fname );
|
||||
@ -61,6 +64,11 @@ namespace ngcore
|
||||
max_tracefile_size = max_size;
|
||||
}
|
||||
|
||||
static void SetWritePajeFile( bool write )
|
||||
{
|
||||
write_paje_file = write;
|
||||
}
|
||||
|
||||
std::string tracefile_name;
|
||||
|
||||
struct Job
|
||||
@ -262,8 +270,6 @@ namespace ngcore
|
||||
links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} );
|
||||
}
|
||||
|
||||
void Write( const std::string & filename );
|
||||
|
||||
void SendData(); // MPI parallel data reduction
|
||||
|
||||
};
|
||||
|
@ -116,6 +116,7 @@ namespace ngcore
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
std::vector<std::string> MemoryTracer::names{"all"};
|
||||
std::vector<int> MemoryTracer::parents{-1};
|
||||
std::atomic<size_t> MemoryTracer::total_memory{0};
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
|
||||
} // namespace ngcore
|
||||
|
@ -319,8 +319,9 @@ namespace ngcore
|
||||
.def ("__getitem__",
|
||||
[](TFlat & self, TIND i) -> T&
|
||||
{
|
||||
static constexpr int base = IndexBASE<TIND>();
|
||||
if (i < base || i >= self.Size()+base)
|
||||
// static constexpr int base = IndexBASE<TIND>();
|
||||
auto reli = i - IndexBASE<TIND>();
|
||||
if (reli < 0 || reli >= self.Size())
|
||||
throw py::index_error();
|
||||
return self[i];
|
||||
},
|
||||
@ -328,8 +329,9 @@ namespace ngcore
|
||||
.def ("__setitem__",
|
||||
[](TFlat & self, TIND i, T val) -> T&
|
||||
{
|
||||
static constexpr int base = IndexBASE<TIND>();
|
||||
if (i < base || i >= self.Size()+base)
|
||||
// static constexpr int base = IndexBASE<TIND>();
|
||||
auto reli = i - IndexBASE<TIND>();
|
||||
if (reli < 0 || reli >= self.Size())
|
||||
throw py::index_error();
|
||||
self[i] = val;
|
||||
return self[i];
|
||||
|
@ -141,8 +141,16 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
|
||||
|
||||
.def(py::self | py::self)
|
||||
.def(py::self & py::self)
|
||||
#ifdef __clang__
|
||||
// see https://github.com/pybind/pybind11/issues/1893
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wself-assign-overloaded"
|
||||
#endif
|
||||
.def(py::self |= py::self)
|
||||
.def(py::self &= py::self)
|
||||
#ifdef __clang__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
.def(~py::self)
|
||||
;
|
||||
|
||||
@ -316,6 +324,8 @@ threads : int
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
;
|
||||
|
||||
m.def("GetTotalMemory", MemoryTracer::GetTotalMemory);
|
||||
|
||||
py::class_<Timer<>> (m, "Timer")
|
||||
.def(py::init<const string&>())
|
||||
.def("Start", static_cast<void (Timer<>::*)()const>(&Timer<>::Start), "start timer")
|
||||
|
@ -34,6 +34,8 @@ namespace ngcore {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
// now using has_shared_from_this2 in archive.hpp
|
||||
template <typename T>
|
||||
struct has_shared_from_this
|
||||
{
|
||||
@ -42,6 +44,7 @@ namespace ngcore {
|
||||
typedef decltype( check<T>(sizeof(char)) ) type;
|
||||
static constexpr type value = type();
|
||||
};
|
||||
*/
|
||||
#endif // NETGEN_PYTHON
|
||||
|
||||
|
||||
@ -59,7 +62,7 @@ namespace ngcore {
|
||||
{
|
||||
detail::TCargs<T> args;
|
||||
ar &args;
|
||||
auto nT = detail::constructIfPossible<T>(args);
|
||||
auto nT = detail::constructIfPossible<T>(std::move(args));
|
||||
return typeid(T) == ti ? nT
|
||||
: Archive::Caster<T, Bases>::tryUpcast(ti, nT);
|
||||
};
|
||||
|
@ -61,6 +61,7 @@ namespace ngcore
|
||||
|
||||
|
||||
NETGEN_INLINE auto operator[] (int i) const { return ((int64_t*)(&data))[i]; }
|
||||
NETGEN_INLINE auto & operator[] (int i) { return ((int64_t*)(&data))[i]; }
|
||||
NETGEN_INLINE __m512i Data() const { return data; }
|
||||
NETGEN_INLINE __m512i & Data() { return data; }
|
||||
static SIMD FirstInt() { return { 0, 1, 2, 3, 4, 5, 6, 7 }; }
|
||||
@ -132,6 +133,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
NETGEN_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; }
|
||||
NETGEN_INLINE double & operator[] (int i) { return ((double*)(&data))[i]; }
|
||||
NETGEN_INLINE __m512d Data() const { return data; }
|
||||
NETGEN_INLINE __m512d & Data() { return data; }
|
||||
|
||||
|
@ -45,7 +45,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// INDEX of symbol name, throws exception if unused
|
||||
size_t Index (const std::string & name) const
|
||||
size_t Index (std::string_view 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
|
||||
int CheckIndex (const std::string & name) const
|
||||
int CheckIndex (std::string_view name) const
|
||||
{
|
||||
for (int i = 0; i < names.size(); i++)
|
||||
if (names[i] == name) return i;
|
||||
@ -67,12 +67,12 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// Returns reference to element. exception for unused identifier
|
||||
reference operator[] (const std::string & name)
|
||||
reference operator[] (std::string_view name)
|
||||
{
|
||||
return data[Index (name)];
|
||||
}
|
||||
|
||||
const_reference operator[] (const std::string & name) const
|
||||
const_reference operator[] (std::string_view name) const
|
||||
{
|
||||
return data[Index (name)];
|
||||
}
|
||||
@ -99,7 +99,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// Associates el to the string name, overrides if name is used
|
||||
void Set (const std::string & name, const T & el)
|
||||
void Set (std::string_view name, const T & el)
|
||||
{
|
||||
int i = CheckIndex (name);
|
||||
if (i >= 0)
|
||||
@ -107,15 +107,24 @@ namespace ngcore
|
||||
else
|
||||
{
|
||||
data.push_back(el);
|
||||
names.push_back(name);
|
||||
names.push_back(std::string(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
bool Used (const std::string & name) const
|
||||
{
|
||||
return CheckIndex(name) >= 0;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
bool Used (std::string_view name) const
|
||||
{
|
||||
return CheckIndex(name) >= 0;
|
||||
}
|
||||
|
||||
/// Deletes symboltable
|
||||
inline void DeleteAll ()
|
||||
{
|
||||
|
@ -62,9 +62,9 @@ namespace ngcore
|
||||
return index;
|
||||
}
|
||||
|
||||
NGCORE_API size_t * TablePrefixSum32 (FlatArray<unsigned int> entrysize)
|
||||
NGCORE_API size_t * TablePrefixSum32 (FlatArray<uint32_t> entrysize)
|
||||
{ return TablePrefixSum2 (entrysize); }
|
||||
NGCORE_API size_t * TablePrefixSum64 (FlatArray<size_t> entrysize)
|
||||
NGCORE_API size_t * TablePrefixSum64 (FlatArray<uint64_t> entrysize)
|
||||
{ return TablePrefixSum2 (entrysize); }
|
||||
|
||||
/*
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "ngcore_api.hpp"
|
||||
#include "profiler.hpp"
|
||||
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
|
||||
@ -93,6 +94,7 @@ namespace ngcore
|
||||
Iterator end() const { return Iterator(*this, BASE+size); }
|
||||
};
|
||||
|
||||
/*
|
||||
NGCORE_API extern size_t * TablePrefixSum32 (FlatArray<unsigned int> entrysize);
|
||||
NGCORE_API extern size_t * TablePrefixSum64 (FlatArray<size_t> entrysize);
|
||||
|
||||
@ -105,7 +107,20 @@ namespace ngcore
|
||||
{ return TablePrefixSum32 (FlatArray<unsigned> (entrysize.Size(), (unsigned int*)(std::atomic<int>*)entrysize.Addr(0))); }
|
||||
NETGEN_INLINE size_t * TablePrefixSum (FlatArray<size_t> entrysize)
|
||||
{ return TablePrefixSum64 (entrysize); }
|
||||
*/
|
||||
|
||||
NGCORE_API extern size_t * TablePrefixSum32 (FlatArray<uint32_t> entrysize);
|
||||
NGCORE_API extern size_t * TablePrefixSum64 (FlatArray<uint64_t> entrysize);
|
||||
|
||||
template <typename T> // TODO: enable_if T is integral
|
||||
NETGEN_INLINE size_t * TablePrefixSum (FlatArray<T> entrysize)
|
||||
{
|
||||
if constexpr (sizeof(T) == 4)
|
||||
return TablePrefixSum32 ( { entrysize.Size(), (uint32_t*)(void*)entrysize.Addr(0) });
|
||||
else
|
||||
return TablePrefixSum64 ( { entrysize.Size(), (uint64_t*)(void*)entrysize.Addr(0) });
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
A compact Table container.
|
||||
@ -130,6 +145,7 @@ namespace ngcore
|
||||
{
|
||||
for (size_t i : IntRange(size+1))
|
||||
index[i] = i*entrysize;
|
||||
mt.Alloc(GetMemUsage());
|
||||
}
|
||||
|
||||
/// Construct table of variable entrysize
|
||||
@ -141,6 +157,7 @@ namespace ngcore
|
||||
index = TablePrefixSum (FlatArray<TI> (entrysize.Size(), entrysize.Data()));
|
||||
size_t cnt = index[size];
|
||||
data = new T[cnt];
|
||||
mt.Alloc(GetMemUsage());
|
||||
}
|
||||
|
||||
explicit NETGEN_INLINE Table (const FlatTable<T,IndexType> & tab2)
|
||||
@ -157,6 +174,7 @@ namespace ngcore
|
||||
size_t cnt = index[size];
|
||||
data = new T[cnt];
|
||||
this->AsArray() = tab2.AsArray();
|
||||
mt.Alloc(GetMemUsage());
|
||||
/*
|
||||
for (size_t i = 0; i < cnt; i++)
|
||||
data[i] = tab2.data[i];
|
||||
@ -177,12 +195,14 @@ namespace ngcore
|
||||
data = new T[cnt];
|
||||
for (size_t i = 0; i < cnt; i++)
|
||||
data[i] = tab2.data[i];
|
||||
|
||||
mt.Alloc(GetMemUsage());
|
||||
}
|
||||
|
||||
NETGEN_INLINE Table (Table && tab2)
|
||||
: FlatTable<T,IndexType>(0, nullptr, nullptr)
|
||||
{
|
||||
tab2.mt.Free(tab2.GetMemUsage());
|
||||
mt = std::move(tab2.mt);
|
||||
Swap (size, tab2.size);
|
||||
Swap (index, tab2.index);
|
||||
Swap (data, tab2.data);
|
||||
@ -210,7 +230,7 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE Table & operator= (Table && tab2)
|
||||
{
|
||||
mt.Swap(GetMemUsage(), tab2.mt, tab2.GetMemUsage());
|
||||
mt = std::move(tab2.mt);
|
||||
Swap (size, tab2.size);
|
||||
Swap (index, tab2.index);
|
||||
Swap (data, tab2.data);
|
||||
@ -324,8 +344,8 @@ namespace ngcore
|
||||
case 1:
|
||||
{
|
||||
size_t oldval = nd;
|
||||
while (blocknr+1>nd) {
|
||||
nd.compare_exchange_weak (oldval, blocknr+1);
|
||||
while (blocknr-IndexBASE<IndexType>()+1>nd) {
|
||||
nd.compare_exchange_weak (oldval, blocknr-IndexBASE<IndexType>()+1);
|
||||
oldval = nd;
|
||||
}
|
||||
break;
|
||||
@ -401,7 +421,7 @@ namespace ngcore
|
||||
pcreator = std::make_unique<TableCreator<TEntry, TIndex>>(*cnt);
|
||||
else
|
||||
pcreator = std::make_unique<TableCreator<TEntry, TIndex>>();
|
||||
|
||||
|
||||
auto & creator = *pcreator;
|
||||
|
||||
for ( ; !creator.Done(); creator++)
|
||||
@ -447,7 +467,9 @@ namespace ngcore
|
||||
void Add (size_t blocknr, FlatArray<int> dofs);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
A dynamic table class.
|
||||
|
@ -168,6 +168,12 @@ namespace ngcore
|
||||
trace = nullptr;
|
||||
}
|
||||
num_threads = 1;
|
||||
#ifdef USE_NUMA
|
||||
for (int j = 0; j < num_nodes; j++)
|
||||
numa_free (nodedata[j], sizeof(NodeData));
|
||||
#else
|
||||
delete nodedata[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <cmath>
|
||||
#include <ostream>
|
||||
#include <thread>
|
||||
|
||||
@ -316,6 +317,7 @@ namespace ngcore
|
||||
|
||||
public:
|
||||
SharedLoop (IntRange ar) : r(ar) { cnt = r.begin(); }
|
||||
SharedLoop (size_t s) : SharedLoop (IntRange{s}) { ; }
|
||||
SharedIterator begin() { return SharedIterator (cnt, r.end(), true); }
|
||||
SharedIterator end() { return SharedIterator (cnt, r.end(), false); }
|
||||
};
|
||||
@ -622,6 +624,8 @@ public:
|
||||
Reset (r);
|
||||
}
|
||||
|
||||
SharedLoop2 (size_t s) : SharedLoop2 (IntRange{s}) { }
|
||||
|
||||
void Reset (IntRange r)
|
||||
{
|
||||
for (size_t i = 0; i < ranges.Size(); i++)
|
||||
@ -631,6 +635,9 @@ public:
|
||||
participants.store(0, std::memory_order_relaxed);
|
||||
processed.store(0, std::memory_order_release);
|
||||
}
|
||||
|
||||
void Reset (size_t s) { Reset(IntRange{s}); }
|
||||
|
||||
|
||||
SharedIterator begin()
|
||||
{
|
||||
@ -1010,7 +1017,7 @@ public:
|
||||
int num_nodes = numa_num_configured_nodes();
|
||||
size_t pagesize = numa_pagesize();
|
||||
|
||||
int npages = ceil ( double(s)*sizeof(T) / pagesize );
|
||||
int npages = std::ceil ( double(s)*sizeof(T) / pagesize );
|
||||
|
||||
// cout << "size = " << numa_size << endl;
|
||||
// cout << "npages = " << npages << endl;
|
||||
|
@ -182,7 +182,7 @@ namespace ngcore
|
||||
|
||||
/// square element
|
||||
template <class T>
|
||||
NETGEN_INLINE T sqr (const T a)
|
||||
NETGEN_INLINE constexpr T sqr (const T a)
|
||||
{
|
||||
return a * a;
|
||||
}
|
||||
|
@ -1211,7 +1211,7 @@ namespace netgen
|
||||
PrintMessage (2, "Object ", i, " has ", tams->GetNT(), " triangles");
|
||||
}
|
||||
}
|
||||
catch (exception)
|
||||
catch (const std::exception &)
|
||||
{
|
||||
cerr << "*************************************************************" << endl
|
||||
<< "**** out of memory problem in CSG visualization ****" << endl
|
||||
|
@ -567,7 +567,7 @@ namespace netgen
|
||||
{
|
||||
// int i, j;
|
||||
SegmentIndex si;
|
||||
PointIndex pi;
|
||||
// PointIndex pi;
|
||||
|
||||
NgArray<int> osedges(cntedge);
|
||||
INDEX_2_HASHTABLE<int> osedgesht (cntedge+1);
|
||||
@ -610,7 +610,7 @@ namespace netgen
|
||||
for (int i = 1; i <= osedgesht.GetNBags(); i++)
|
||||
for (int j = 1; j <= osedgesht.GetBagSize(i); j++)
|
||||
{
|
||||
INDEX_2 i2;
|
||||
PointIndices<2> i2;
|
||||
int val;
|
||||
osedgesht.GetData (i, j, i2, val);
|
||||
|
||||
@ -619,8 +619,8 @@ namespace netgen
|
||||
Vec<3> v = p2 - p1;
|
||||
double vlen = v.Length();
|
||||
v /= vlen;
|
||||
for (pi = PointIndex::BASE;
|
||||
pi < mesh.GetNP()+PointIndex::BASE; pi++)
|
||||
for (PointIndex pi = IndexBASE<PointIndex>();
|
||||
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
|
||||
if (pi != i2.I1() && pi != i2.I2())
|
||||
{
|
||||
@ -1371,8 +1371,8 @@ namespace netgen
|
||||
lastpi = PointIndex::INVALID;
|
||||
|
||||
/*
|
||||
for (pi = PointIndex::BASE;
|
||||
pi < mesh.GetNP()+PointIndex::BASE; pi++)
|
||||
for (pi = IndexBASE<PointIndex>();
|
||||
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
if (Dist (mesh[pi], p) < 1e-6)
|
||||
{
|
||||
lastpi = pi;
|
||||
@ -1414,8 +1414,8 @@ namespace netgen
|
||||
if (i == ne)
|
||||
{
|
||||
/*
|
||||
for (pi = PointIndex::BASE;
|
||||
pi < mesh.GetNP()+PointIndex::BASE; pi++)
|
||||
for (pi = IndexBASE<PointIndex>();
|
||||
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
if (Dist(mesh[pi], np) < 1e-6)
|
||||
thispi = pi;
|
||||
*/
|
||||
@ -1539,8 +1539,8 @@ namespace netgen
|
||||
// generate initial point
|
||||
Point<3> p = edgepoints[0];
|
||||
PointIndex pi1 = PointIndex::INVALID;
|
||||
for (pi = PointIndex::BASE;
|
||||
pi < mesh.GetNP()+PointIndex::BASE; pi++)
|
||||
for (PointIndex pi = IndexBASE<PointIndex>();
|
||||
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
|
||||
if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize())
|
||||
{
|
||||
@ -1557,8 +1557,8 @@ namespace netgen
|
||||
|
||||
p = edgepoints.Last();
|
||||
PointIndex pi2 = PointIndex::INVALID;
|
||||
for (pi = PointIndex::BASE;
|
||||
pi < mesh.GetNP()+PointIndex::BASE; pi++)
|
||||
for (pi = IndexBASE<PointIndex>();
|
||||
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
|
||||
if (Dist (mesh[pi], p) < 1e-6*geometry.MaxSize())
|
||||
{
|
||||
@ -1646,7 +1646,7 @@ namespace netgen
|
||||
Mesh & mesh)
|
||||
{
|
||||
int k;
|
||||
PointIndex pi;
|
||||
// PointIndex pi;
|
||||
|
||||
double size = geometry.MaxSize();
|
||||
|
||||
@ -1660,8 +1660,8 @@ namespace netgen
|
||||
|
||||
PointIndex frompi = PointIndex::INVALID;
|
||||
PointIndex topi = PointIndex::INVALID;
|
||||
for (pi = PointIndex::BASE;
|
||||
pi < mesh.GetNP()+PointIndex::BASE; pi++)
|
||||
for (PointIndex pi = IndexBASE<PointIndex>();
|
||||
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
{
|
||||
if (Dist2 (mesh[pi], fromp) <= 1e-16*size)
|
||||
frompi = pi;
|
||||
@ -1714,12 +1714,12 @@ namespace netgen
|
||||
if (oldseg.seginfo == 0)
|
||||
continue;
|
||||
|
||||
int pi1 = oldseg[0];
|
||||
int pi2 = oldseg[1];
|
||||
PointIndex pi1 = oldseg[0];
|
||||
PointIndex pi2 = oldseg[1];
|
||||
|
||||
int npi1 = geometry.identifications.Get(copyedgeidentification)
|
||||
PointIndex npi1 = geometry.identifications.Get(copyedgeidentification)
|
||||
-> GetIdentifiedPoint (mesh, pi1);
|
||||
int npi2 = geometry.identifications.Get(copyedgeidentification)
|
||||
PointIndex npi2 = geometry.identifications.Get(copyedgeidentification)
|
||||
-> GetIdentifiedPoint (mesh, pi2);
|
||||
|
||||
//(*testout) << "copy edge, pts = " << npi1 << " - " << npi2 << endl;
|
||||
@ -1885,12 +1885,10 @@ namespace netgen
|
||||
|
||||
if (seg1.domin != -1 || seg1.domout != -1)
|
||||
{
|
||||
mesh.AddPoint (p1, layer, EDGEPOINT);
|
||||
mesh.AddPoint (p2, layer, EDGEPOINT);
|
||||
seg1[0] = mesh.GetNP()-1;
|
||||
seg1[1] = mesh.GetNP();
|
||||
seg2[1] = mesh.GetNP()-1;
|
||||
seg2[0] = mesh.GetNP();
|
||||
seg1[0] = mesh.AddPoint (p1, layer, EDGEPOINT);
|
||||
seg1[1] = mesh.AddPoint (p2, layer, EDGEPOINT);
|
||||
seg2[0] = seg1[1];
|
||||
seg2[1] = seg1[0];
|
||||
seg1.geominfo[0].trignum = 1;
|
||||
seg1.geominfo[1].trignum = 1;
|
||||
seg2.geominfo[0].trignum = 1;
|
||||
|
@ -35,7 +35,7 @@ namespace netgen
|
||||
auto up = geom.GetUserPoint(i);
|
||||
auto pnum = mesh.AddPoint(up);
|
||||
mesh.Points().Last().Singularity (geom.GetUserPointRefFactor(i));
|
||||
mesh.AddLockedPoint (PointIndex (i+1));
|
||||
mesh.AddLockedPoint (pnum);
|
||||
int index = up.GetIndex();
|
||||
if (index == -1)
|
||||
index = mesh.AddCD3Name (up.GetName())+1;
|
||||
@ -443,7 +443,7 @@ namespace netgen
|
||||
meshing.SetStartTime (starttime);
|
||||
|
||||
double eps = 1e-8 * geom.MaxSize();
|
||||
for (PointIndex pi = PointIndex::BASE; pi < noldp+PointIndex::BASE; pi++)
|
||||
for (PointIndex pi = IndexBASE<PointIndex>(); pi < noldp+IndexBASE<PointIndex>(); pi++)
|
||||
{
|
||||
// if(surf->PointOnSurface(mesh[pi]))
|
||||
meshing.AddPoint (mesh[pi], pi, NULL,
|
||||
@ -473,8 +473,8 @@ namespace netgen
|
||||
{
|
||||
PointGeomInfo gi;
|
||||
gi.trignum = k;
|
||||
meshing.AddBoundaryElement (segments[si][0] + 1 - PointIndex::BASE,
|
||||
segments[si][1] + 1 - PointIndex::BASE,
|
||||
meshing.AddBoundaryElement (segments[si][0] + 1 - IndexBASE<PointIndex>(),
|
||||
segments[si][1] + 1 - IndexBASE<PointIndex>(),
|
||||
gi, gi);
|
||||
}
|
||||
|
||||
@ -718,7 +718,7 @@ namespace netgen
|
||||
|
||||
mesh -> LoadLocalMeshSize (mparam.meshsizefilename);
|
||||
for (auto mspnt : mparam.meshsize_points)
|
||||
mesh -> RestrictLocalH (mspnt.pnt, mspnt.h);
|
||||
mesh -> RestrictLocalH (mspnt.pnt, mspnt.h, mspnt.layer);
|
||||
}
|
||||
|
||||
spoints.SetSize(0);
|
||||
@ -826,6 +826,9 @@ namespace netgen
|
||||
{
|
||||
multithread.task = "Volume meshing";
|
||||
|
||||
for (int i = 0; i < geom.GetNTopLevelObjects(); i++)
|
||||
mesh->SetMaterial (i+1, geom.GetTopLevelObject(i)->GetMaterial().c_str());
|
||||
|
||||
MESHING3_RESULT res =
|
||||
MeshVolume (mparam, *mesh);
|
||||
|
||||
@ -838,10 +841,6 @@ namespace netgen
|
||||
|
||||
MeshQuality3d (*mesh);
|
||||
|
||||
for (int i = 0; i < geom.GetNTopLevelObjects(); i++)
|
||||
mesh->SetMaterial (i+1, geom.GetTopLevelObject(i)->GetMaterial().c_str());
|
||||
|
||||
|
||||
#ifdef STAT_STREAM
|
||||
(*statout) << GetTime() << " & ";
|
||||
#endif
|
||||
|
@ -65,10 +65,10 @@ ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Identification :: GetIdentifiedPoint (class Mesh & mesh, int pi)
|
||||
PointIndex Identification :: GetIdentifiedPoint (class Mesh & mesh, PointIndex pi)
|
||||
{
|
||||
cout << "Identification::GetIdentifiedPoint called for base-class" << endl;
|
||||
return -1;
|
||||
return PointIndex::INVALID;
|
||||
}
|
||||
|
||||
void Identification :: IdentifyPoints (Mesh & mesh)
|
||||
@ -261,8 +261,8 @@ Identifiable (const Point<3> & p1, const Point<3> & p2) const
|
||||
|
||||
|
||||
|
||||
int PeriodicIdentification ::
|
||||
GetIdentifiedPoint (class Mesh & mesh, int pi)
|
||||
PointIndex PeriodicIdentification ::
|
||||
GetIdentifiedPoint (class Mesh & mesh, PointIndex pi)
|
||||
{
|
||||
const Surface *snew;
|
||||
const Point<3> & p = mesh.Point (pi);
|
||||
@ -289,14 +289,14 @@ GetIdentifiedPoint (class Mesh & mesh, int pi)
|
||||
// project to other surface
|
||||
snew->Project (hp);
|
||||
|
||||
int newpi = 0;
|
||||
for (int i = 1; i <= mesh.GetNP(); i++)
|
||||
if (Dist2 (mesh.Point(i), hp) < 1e-12)
|
||||
PointIndex newpi(PointIndex::INVALID);
|
||||
for (PointIndex pi : Range(mesh.Points()))
|
||||
if (Dist2 (mesh.Point(pi), hp) < 1e-12)
|
||||
{
|
||||
newpi = i;
|
||||
newpi = pi;
|
||||
break;
|
||||
}
|
||||
if (!newpi)
|
||||
if (!newpi.IsValid())
|
||||
newpi = mesh.AddPoint (hp);
|
||||
|
||||
if (snew == s2)
|
||||
@ -322,6 +322,7 @@ void PeriodicIdentification :: IdentifyPoints (class Mesh & mesh)
|
||||
mesh.GetBox(p1, p2);
|
||||
auto eps = 1e-6 * (p2-p1).Length();
|
||||
|
||||
/*
|
||||
for (int i = 1; i <= mesh.GetNP(); i++)
|
||||
{
|
||||
Point<3> p = mesh.Point(i);
|
||||
@ -334,13 +335,24 @@ void PeriodicIdentification :: IdentifyPoints (class Mesh & mesh)
|
||||
if (Dist2(mesh.Point(j), pp) < eps)
|
||||
{
|
||||
mesh.GetIdentifications().Add (i, j, nr);
|
||||
/*
|
||||
(*testout) << "Identify points(periodic:), nr = " << nr << ": "
|
||||
<< mesh.Point(i) << " - " << mesh.Point(j) << endl;
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
for (auto pi : Range(mesh.Points()))
|
||||
{
|
||||
Point<3> p = mesh[pi];
|
||||
if (s1->PointOnSurface (p))
|
||||
{
|
||||
Point<3> pp = p;
|
||||
pp = trafo(pp);
|
||||
s2->Project (pp);
|
||||
for (PointIndex pj : Range(mesh.Points()))
|
||||
if (Dist2(mesh[pj], pp) < eps)
|
||||
mesh.GetIdentifications().Add (pi, pj, nr);
|
||||
}
|
||||
}
|
||||
|
||||
mesh.GetIdentifications().SetType(nr,Identifications::PERIODIC);
|
||||
}
|
||||
@ -396,15 +408,15 @@ void PeriodicIdentification :: IdentifyFaces (class Mesh & mesh)
|
||||
|
||||
if (side == 1)
|
||||
{
|
||||
if (mesh.GetIdentifications().Get (seg1[0], seg2[0]) &&
|
||||
mesh.GetIdentifications().Get (seg1[1], seg2[1]))
|
||||
if (mesh.GetIdentifications().Used (seg1[0], seg2[0]) &&
|
||||
mesh.GetIdentifications().Used (seg1[1], seg2[1]))
|
||||
{
|
||||
foundother = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mesh.GetIdentifications().Get (seg1[0], seg2[1]) &&
|
||||
mesh.GetIdentifications().Get (seg1[1], seg2[0]))
|
||||
if (mesh.GetIdentifications().Used (seg1[0], seg2[1]) &&
|
||||
mesh.GetIdentifications().Used (seg1[1], seg2[0]))
|
||||
{
|
||||
foundother = 1;
|
||||
break;
|
||||
@ -412,15 +424,15 @@ void PeriodicIdentification :: IdentifyFaces (class Mesh & mesh)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mesh.GetIdentifications().Get (seg2[0], seg1[0]) &&
|
||||
mesh.GetIdentifications().Get (seg2[1], seg1[1]))
|
||||
if (mesh.GetIdentifications().Used (seg2[0], seg1[0]) &&
|
||||
mesh.GetIdentifications().Used (seg2[1], seg1[1]))
|
||||
{
|
||||
foundother = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mesh.GetIdentifications().Get (seg2[0], seg1[1]) &&
|
||||
mesh.GetIdentifications().Get (seg2[1], seg1[0]))
|
||||
if (mesh.GetIdentifications().Used (seg2[0], seg1[1]) &&
|
||||
mesh.GetIdentifications().Used (seg2[1], seg1[0]))
|
||||
{
|
||||
foundother = 1;
|
||||
break;
|
||||
@ -885,17 +897,21 @@ ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const
|
||||
|
||||
|
||||
|
||||
int CloseSurfaceIdentification ::
|
||||
GetIdentifiedPoint (class Mesh & mesh, int pi)
|
||||
PointIndex CloseSurfaceIdentification ::
|
||||
GetIdentifiedPoint (class Mesh & mesh, PointIndex pi)
|
||||
{
|
||||
const Surface *snew;
|
||||
const Point<3> & p = mesh.Point (pi);
|
||||
|
||||
NgArray<int,PointIndex::BASE> identmap(mesh.GetNP());
|
||||
idmap_type identmap(mesh.GetNP());
|
||||
mesh.GetIdentifications().GetMap (nr, identmap);
|
||||
/*
|
||||
if (identmap.Get(pi))
|
||||
return identmap.Get(pi);
|
||||
|
||||
*/
|
||||
if (identmap[pi].IsValid())
|
||||
return identmap[pi];
|
||||
|
||||
|
||||
if (s1->PointOnSurface (p))
|
||||
snew = s2;
|
||||
@ -1168,15 +1184,15 @@ void CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh)
|
||||
|
||||
if (side == 1)
|
||||
{
|
||||
if (mesh.GetIdentifications().Get (seg1[0], seg2[0]) &&
|
||||
mesh.GetIdentifications().Get (seg1[1], seg2[1]))
|
||||
if (mesh.GetIdentifications().Used (seg1[0], seg2[0]) &&
|
||||
mesh.GetIdentifications().Used (seg1[1], seg2[1]))
|
||||
{
|
||||
foundother = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mesh.GetIdentifications().Get (seg1[0], seg2[1]) &&
|
||||
mesh.GetIdentifications().Get (seg1[1], seg2[0]))
|
||||
if (mesh.GetIdentifications().Used (seg1[0], seg2[1]) &&
|
||||
mesh.GetIdentifications().Used (seg1[1], seg2[0]))
|
||||
{
|
||||
foundother = 1;
|
||||
break;
|
||||
@ -1184,15 +1200,15 @@ void CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mesh.GetIdentifications().Get (seg2[0], seg1[0]) &&
|
||||
mesh.GetIdentifications().Get (seg2[1], seg1[1]))
|
||||
if (mesh.GetIdentifications().Used (seg2[0], seg1[0]) &&
|
||||
mesh.GetIdentifications().Used (seg2[1], seg1[1]))
|
||||
{
|
||||
foundother = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mesh.GetIdentifications().Get (seg2[0], seg1[1]) &&
|
||||
mesh.GetIdentifications().Get (seg2[1], seg1[0]))
|
||||
if (mesh.GetIdentifications().Used (seg2[0], seg1[1]) &&
|
||||
mesh.GetIdentifications().Used (seg2[1], seg1[0]))
|
||||
{
|
||||
foundother = 1;
|
||||
break;
|
||||
@ -1229,7 +1245,7 @@ BuildSurfaceElements (NgArray<Segment> & segs,
|
||||
bool found = 0;
|
||||
int cntquads = 0;
|
||||
|
||||
NgArray<int,PointIndex::BASE> identmap;
|
||||
idmap_type identmap;
|
||||
identmap = 0;
|
||||
|
||||
mesh.GetIdentifications().GetMap (nr, identmap);
|
||||
@ -1650,8 +1666,8 @@ BuildSurfaceElements (NgArray<Segment> & segs,
|
||||
{
|
||||
const Segment & s1 = segs.Get(i1);
|
||||
const Segment & s2 = segs.Get(i2);
|
||||
if (mesh.GetIdentifications().Get (s1[0], s2[1]) &&
|
||||
mesh.GetIdentifications().Get (s1[1], s2[0]))
|
||||
if (mesh.GetIdentifications().Used (s1[0], s2[1]) &&
|
||||
mesh.GetIdentifications().Used (s1[1], s2[0]))
|
||||
{
|
||||
Element2d el(QUAD);
|
||||
el.PNum(1) = s1[0];
|
||||
|
@ -56,7 +56,7 @@ namespace netgen
|
||||
virtual void IdentifyFaces (class Mesh & mesh);
|
||||
|
||||
/// get point on other surface, add entry in mesh identifications
|
||||
virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1);
|
||||
virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1);
|
||||
|
||||
/// copy surfaces, or fill rectangles
|
||||
virtual void BuildSurfaceElements (NgArray<class Segment> & segs,
|
||||
@ -97,7 +97,7 @@ namespace netgen
|
||||
const TABLE<int> & specpoint2surface) const override;
|
||||
|
||||
virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const override;
|
||||
virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1) override;
|
||||
virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1) override;
|
||||
virtual void IdentifyPoints (class Mesh & mesh) override;
|
||||
virtual void IdentifyFaces (class Mesh & mesh) override;
|
||||
virtual void BuildSurfaceElements (NgArray<class Segment> & segs,
|
||||
@ -153,7 +153,7 @@ namespace netgen
|
||||
virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const;
|
||||
virtual int IdentifiableCandidate (const SpecialPoint & sp1) const;
|
||||
virtual int ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const;
|
||||
virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1);
|
||||
virtual PointIndex GetIdentifiedPoint (class Mesh & mesh, PointIndex pi1);
|
||||
const Array<double> & GetSlices () const { return slices; }
|
||||
virtual void IdentifyPoints (class Mesh & mesh);
|
||||
virtual void IdentifyFaces (class Mesh & mesh);
|
||||
|
@ -756,10 +756,8 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
|
||||
{
|
||||
MeshingParameters mp;
|
||||
if(pars) mp = *pars;
|
||||
{
|
||||
py::gil_scoped_acquire aq;
|
||||
CreateMPfromKwargs(mp, kwargs);
|
||||
}
|
||||
CreateMPfromKwargs(mp, kwargs);
|
||||
py::gil_scoped_release gil_rel;
|
||||
auto mesh = make_shared<Mesh>();
|
||||
SetGlobalMesh (mesh);
|
||||
mesh->SetGeometry(geo);
|
||||
@ -770,8 +768,7 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
|
||||
throw Exception("Meshing failed!");
|
||||
return mesh;
|
||||
}, py::arg("mp") = nullptr,
|
||||
meshingparameter_description.c_str(),
|
||||
py::call_guard<py::gil_scoped_release>())
|
||||
meshingparameter_description.c_str())
|
||||
;
|
||||
|
||||
m.def("Save", FunctionPointer
|
||||
|
@ -53,7 +53,7 @@ void SingularEdge :: FindPointsOnEdge (class Mesh & mesh)
|
||||
|
||||
for (SegmentIndex si = 0; si < mesh.GetNSeg(); si++)
|
||||
{
|
||||
INDEX_2 i2 (mesh[si][0], mesh[si][1]);
|
||||
PointIndices<2> i2 (mesh[si][0], mesh[si][1]);
|
||||
/*
|
||||
|
||||
bool onedge = 1;
|
||||
@ -93,8 +93,8 @@ void SingularEdge :: FindPointsOnEdge (class Mesh & mesh)
|
||||
{
|
||||
segms.Append (i2);
|
||||
// PrintMessage (5, "sing segment ", i2.I1(), " - ", i2.I2());
|
||||
points.Append (mesh[ PointIndex (i2.I1())]);
|
||||
points.Append (mesh[ PointIndex (i2.I2())]);
|
||||
points.Append (mesh[i2.I1()]);
|
||||
points.Append (mesh[i2.I2()]);
|
||||
mesh[si].singedge_left = factor;
|
||||
mesh[si].singedge_right = factor;
|
||||
}
|
||||
@ -153,8 +153,8 @@ void SingularPoint :: FindPoints (class Mesh & mesh)
|
||||
NgArray<int> surfk, surf;
|
||||
|
||||
|
||||
for (PointIndex pi = PointIndex::BASE;
|
||||
pi < mesh.GetNP()+PointIndex::BASE; pi++)
|
||||
for (PointIndex pi = IndexBASE<PointIndex>();
|
||||
pi < mesh.GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
{
|
||||
if (mesh[pi].Type() != FIXEDPOINT) continue;
|
||||
const Point<3> p = mesh[pi];
|
||||
|
@ -472,7 +472,8 @@ namespace netgen
|
||||
box = Box3d (Point3d (0,0,0), Point3d (1,1,1));
|
||||
}
|
||||
|
||||
if (zoomall == 2 && ((vispar.centerpoint >= 1 && vispar.centerpoint <= mesh->GetNP()) ||
|
||||
if (zoomall == 2 && ((vispar.centerpoint-IndexBASE<PointIndex>() >= 0 &&
|
||||
vispar.centerpoint-IndexBASE<PointIndex>() < mesh->GetNP()) ||
|
||||
vispar.use_center_coords))
|
||||
{
|
||||
if (vispar.use_center_coords)
|
||||
|
@ -45,9 +45,10 @@ namespace netgen
|
||||
void MakePrismsSingEdge (Mesh & mesh, INDEX_2_HASHTABLE<int> & singedges)
|
||||
{
|
||||
// volume elements
|
||||
for (int i = 1; i <= mesh.GetNE(); i++)
|
||||
// for (int i = 1; i <= mesh.GetNE(); i++)
|
||||
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
|
||||
{
|
||||
Element & el = mesh.VolumeElement(i);
|
||||
Element & el = mesh.VolumeElement(ei);
|
||||
if (el.GetType() != TET) continue;
|
||||
|
||||
for (int j = 1; j <= 3; j++)
|
||||
@ -76,9 +77,9 @@ namespace netgen
|
||||
}
|
||||
|
||||
// surface elements
|
||||
for (int i = 1; i <= mesh.GetNSE(); i++)
|
||||
for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
|
||||
{
|
||||
Element2d & el = mesh.SurfaceElement(i);
|
||||
Element2d & el = mesh.SurfaceElement(sei);
|
||||
if (el.GetType() != TRIG) continue;
|
||||
|
||||
for (int j = 1; j <= 3; j++)
|
||||
@ -110,18 +111,18 @@ namespace netgen
|
||||
*/
|
||||
void MakePrismsClosePoints (Mesh & mesh)
|
||||
{
|
||||
int i, j, k;
|
||||
for (i = 1; i <= mesh.GetNE(); i++)
|
||||
// int i, j, k;
|
||||
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
|
||||
{
|
||||
Element & el = mesh.VolumeElement(i);
|
||||
Element & el = mesh.VolumeElement(ei);
|
||||
if (el.GetType() == TET)
|
||||
{
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (k = j+1; k <= 4; k++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
for (int k = j+1; k <= 4; k++)
|
||||
{
|
||||
INDEX_2 edge(el.PNum(j), el.PNum(k));
|
||||
edge.Sort();
|
||||
if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k)))
|
||||
if (mesh.GetIdentifications().UsedSymmetric (el.PNum(j), el.PNum(k)))
|
||||
{
|
||||
int pi3 = 1, pi4 = 1;
|
||||
while (pi3 == j || pi3 == k) pi3++;
|
||||
@ -145,7 +146,7 @@ namespace netgen
|
||||
{
|
||||
// pyramid, base face = 1,2,3,4
|
||||
|
||||
for (j = 0; j <= 1; j++)
|
||||
for (int j = 0; j <= 1; j++)
|
||||
{
|
||||
PointIndex pi1 = el.PNum( (j+0) % 4 + 1);
|
||||
PointIndex pi2 = el.PNum( (j+1) % 4 + 1);
|
||||
@ -157,8 +158,8 @@ namespace netgen
|
||||
INDEX_2 edge2(pi2, pi3);
|
||||
edge1.Sort();
|
||||
edge2.Sort();
|
||||
if (mesh.GetIdentifications().GetSymmetric (pi1, pi4) &&
|
||||
mesh.GetIdentifications().GetSymmetric (pi2, pi3))
|
||||
if (mesh.GetIdentifications().UsedSymmetric (pi1, pi4) &&
|
||||
mesh.GetIdentifications().UsedSymmetric (pi2, pi3))
|
||||
{
|
||||
//int p3 = el.PNum(pi3);
|
||||
//int p4 = el.PNum(pi4);
|
||||
@ -175,18 +176,18 @@ namespace netgen
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i <= mesh.GetNSE(); i++)
|
||||
for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
|
||||
{
|
||||
Element2d & el = mesh.SurfaceElement(i);
|
||||
Element2d & el = mesh.SurfaceElement(sei);
|
||||
if (el.GetType() != TRIG) continue;
|
||||
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
{
|
||||
k = (j % 3) + 1;
|
||||
int k = (j % 3) + 1;
|
||||
INDEX_2 edge(el.PNum(j), el.PNum(k));
|
||||
edge.Sort();
|
||||
|
||||
if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k)))
|
||||
if (mesh.GetIdentifications().UsedSymmetric (el.PNum(j), el.PNum(k)))
|
||||
{
|
||||
int pi3 = 6-j-k;
|
||||
int p3 = el.PNum(pi3);
|
||||
@ -244,7 +245,7 @@ namespace netgen
|
||||
void RefinePrisms (Mesh & mesh, const CSGeometry * geom,
|
||||
ZRefinementOptions & opt)
|
||||
{
|
||||
int i, j;
|
||||
// int i, j;
|
||||
bool found, change;
|
||||
int cnt = 0;
|
||||
|
||||
@ -261,15 +262,23 @@ namespace netgen
|
||||
|
||||
// if (mesh.GetIdentifications().HasIdentifiedPoints())
|
||||
{
|
||||
INDEX_2_HASHTABLE<int> & identpts =
|
||||
auto & identpts =
|
||||
mesh.GetIdentifications().GetIdentifiedPoints ();
|
||||
|
||||
for (i = 1; i <= identpts.GetNBags(); i++)
|
||||
for (j = 1; j <= identpts.GetBagSize(i); j++)
|
||||
|
||||
/*
|
||||
for (int i = 1; i <= identpts.GetNBags(); i++)
|
||||
for (int j = 1; j <= identpts.GetBagSize(i); j++)
|
||||
{
|
||||
INDEX_2 pair;
|
||||
int idnr;
|
||||
identpts.GetData(i, j, pair, idnr);
|
||||
INDEX_3 pair;
|
||||
int dummy;
|
||||
identpts.GetData(i, j, pair, dummy);
|
||||
*/
|
||||
for (auto [hash, val] : identpts)\
|
||||
{
|
||||
auto [hash_pts, idnr] = hash;
|
||||
auto [pi1, pi2] = hash_pts;
|
||||
// auto idnr = pair[2];
|
||||
|
||||
const CloseSurfaceIdentification * csid =
|
||||
dynamic_cast<const CloseSurfaceIdentification*>
|
||||
(geom->identifications.Get(idnr));
|
||||
@ -280,17 +289,25 @@ namespace netgen
|
||||
if (first_id.Test (idnr))
|
||||
{
|
||||
first_id.Clear(idnr);
|
||||
/*
|
||||
ref_uniform.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels()));
|
||||
ref_singular.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels1()));
|
||||
ref_singular.Append (INDEX_3 (pair.I2(), pair.I1(), csid->RefLevels2()));
|
||||
*/
|
||||
ref_uniform.Append (INDEX_3 (pi1, pi2, csid->RefLevels()));
|
||||
ref_singular.Append (INDEX_3 (pi1, pi2, csid->RefLevels1()));
|
||||
ref_singular.Append (INDEX_3 (pi2, pi1, csid->RefLevels2()));
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//const NgArray<double> & slices = csid->GetSlices();
|
||||
INDEX_4 i4;
|
||||
i4[0] = pair.I1();
|
||||
i4[1] = pair.I2();
|
||||
// i4[0] = pair.I1();
|
||||
// i4[1] = pair.I2();
|
||||
i4[0] = pi1;
|
||||
i4[1] = pi2;
|
||||
i4[2] = idnr;
|
||||
i4[3] = csid->GetSlices().Size();
|
||||
ref_slices.Append (i4);
|
||||
@ -313,7 +330,7 @@ namespace netgen
|
||||
found = 0;
|
||||
// mark prisms due to close surface flags:
|
||||
int oldsize = ref_uniform.Size();
|
||||
for (i = 1; i <= oldsize; i++)
|
||||
for (int i = 1; i <= oldsize; i++)
|
||||
{
|
||||
int pi1 = ref_uniform.Get(i).I1();
|
||||
int pi2 = ref_uniform.Get(i).I2();
|
||||
@ -339,7 +356,7 @@ namespace netgen
|
||||
ref_uniform.Append (INDEX_3(pi2, npi, levels-1));
|
||||
}
|
||||
}
|
||||
for (i = 1; i <= ref_singular.Size(); i++)
|
||||
for (int i = 1; i <= ref_singular.Size(); i++)
|
||||
{
|
||||
int pi1 = ref_singular.Get(i).I1();
|
||||
int pi2 = ref_singular.Get(i).I2();
|
||||
@ -367,7 +384,7 @@ namespace netgen
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 1; i <= ref_slices.Size(); i++)
|
||||
for (int i = 1; i <= ref_slices.Size(); i++)
|
||||
{
|
||||
int pi1 = ref_slices.Get(i)[0];
|
||||
int pi2 = ref_slices.Get(i)[1];
|
||||
@ -413,13 +430,13 @@ namespace netgen
|
||||
|
||||
|
||||
|
||||
for (i = 1; i <= mesh.GetNE(); i++)
|
||||
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
|
||||
{
|
||||
Element & el = mesh.VolumeElement (i);
|
||||
Element & el = mesh.VolumeElement (ei);
|
||||
if (el.GetType() != PRISM)
|
||||
continue;
|
||||
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
{
|
||||
int pi1 = el.PNum(j);
|
||||
int pi2 = el.PNum(j+3);
|
||||
@ -465,14 +482,14 @@ namespace netgen
|
||||
{
|
||||
PrintMessage (5, "start loop");
|
||||
change = 0;
|
||||
for (i = 1; i <= mesh.GetNE(); i++)
|
||||
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
|
||||
{
|
||||
Element & el = mesh.VolumeElement (i);
|
||||
Element & el = mesh.VolumeElement (ei);
|
||||
if (el.GetType() != PRISM)
|
||||
continue;
|
||||
|
||||
bool hasref = 0, hasnonref = 0;
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
{
|
||||
int pi1 = el.PNum(j);
|
||||
int pi2 = el.PNum(j+3);
|
||||
@ -491,7 +508,7 @@ namespace netgen
|
||||
{
|
||||
// cout << "el " << i << " in closure" << endl;
|
||||
change = 1;
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
{
|
||||
int pi1 = el.PNum(j);
|
||||
int pi2 = el.PNum(j+3);
|
||||
@ -518,7 +535,7 @@ namespace netgen
|
||||
|
||||
int oldns = mesh.GetNSeg();
|
||||
|
||||
for (i = 1; i <= oldns; i++)
|
||||
for (int i = 1; i <= oldns; i++)
|
||||
{
|
||||
const Segment & el = mesh.LineSegment(i);
|
||||
|
||||
@ -572,14 +589,14 @@ namespace netgen
|
||||
|
||||
// do refinement
|
||||
int oldne = mesh.GetNE();
|
||||
for (i = 1; i <= oldne; i++)
|
||||
for (ElementIndex ei = 0; ei < oldne; ei++)
|
||||
{
|
||||
Element & el = mesh.VolumeElement (i);
|
||||
Element & el = mesh.VolumeElement (ei);
|
||||
if (el.GetNP() != 6)
|
||||
continue;
|
||||
|
||||
int npi[3];
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
{
|
||||
int pi1 = el.PNum(j);
|
||||
int pi2 = el.PNum(j+3);
|
||||
@ -607,7 +624,7 @@ namespace netgen
|
||||
if (npi[0])
|
||||
{
|
||||
Element nel1(6), nel2(6);
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
{
|
||||
nel1.PNum(j) = el.PNum(j);
|
||||
nel1.PNum(j+3) = npi[j-1];
|
||||
@ -616,7 +633,7 @@ namespace netgen
|
||||
}
|
||||
nel1.SetIndex (el.GetIndex());
|
||||
nel2.SetIndex (el.GetIndex());
|
||||
mesh.VolumeElement (i) = nel1;
|
||||
mesh.VolumeElement (ei) = nel1;
|
||||
mesh.AddVolumeElement (nel2);
|
||||
}
|
||||
}
|
||||
@ -628,15 +645,15 @@ namespace netgen
|
||||
// do surface elements
|
||||
int oldnse = mesh.GetNSE();
|
||||
// cout << "oldnse = " << oldnse << endl;
|
||||
for (i = 1; i <= oldnse; i++)
|
||||
for (SurfaceElementIndex sei = 0; sei < oldnse; sei++)
|
||||
{
|
||||
Element2d & el = mesh.SurfaceElement (i);
|
||||
Element2d & el = mesh.SurfaceElement (sei);
|
||||
if (el.GetType() != QUAD)
|
||||
continue;
|
||||
|
||||
int index = el.GetIndex();
|
||||
int npi[2];
|
||||
for (j = 1; j <= 2; j++)
|
||||
for (int j = 1; j <= 2; j++)
|
||||
{
|
||||
int pi1, pi2;
|
||||
|
||||
@ -669,7 +686,7 @@ namespace netgen
|
||||
if (npi[0])
|
||||
{
|
||||
Element2d nel1(QUAD), nel2(QUAD);
|
||||
for (j = 1; j <= 4; j++)
|
||||
for (int j = 1; j <= 4; j++)
|
||||
{
|
||||
nel1.PNum(j) = el.PNum(j);
|
||||
nel2.PNum(j) = el.PNum(j);
|
||||
@ -690,7 +707,7 @@ namespace netgen
|
||||
nel1.SetIndex (el.GetIndex());
|
||||
nel2.SetIndex (el.GetIndex());
|
||||
|
||||
mesh.SurfaceElement (i) = nel1;
|
||||
mesh.SurfaceElement (sei) = nel1;
|
||||
mesh.AddSurfaceElement (nel2);
|
||||
|
||||
int si = mesh.GetFaceDescriptor (index).SurfNr();
|
||||
@ -716,9 +733,9 @@ namespace netgen
|
||||
|
||||
void CombineSingularPrisms(Mesh& mesh)
|
||||
{
|
||||
for(int i = 1; i<=mesh.GetNE(); i++)
|
||||
for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
|
||||
{
|
||||
Element& el = mesh.VolumeElement(i);
|
||||
Element& el = mesh.VolumeElement(ei);
|
||||
if(el.GetType() != PRISM)
|
||||
continue;
|
||||
if(el.PNum(3) == el.PNum(6))
|
||||
|
@ -2,7 +2,6 @@ target_sources(nglib PRIVATE
|
||||
gzstream.cpp
|
||||
hashtabl.cpp
|
||||
mystring.cpp
|
||||
ngarray.cpp
|
||||
ngbitarray.cpp
|
||||
optmem.cpp
|
||||
parthreads.cpp
|
||||
|
@ -292,7 +292,19 @@ namespace netgen
|
||||
|
||||
|
||||
|
||||
|
||||
BASE_INDEX_3_CLOSED_HASHTABLE ::
|
||||
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size)
|
||||
: hash(RoundUp2(size))
|
||||
{
|
||||
// cout << "orig size = " << size
|
||||
// << ", roundup size = " << hash.Size();
|
||||
size = hash.Size();
|
||||
mask = size-1;
|
||||
// cout << "mask = " << mask << endl;
|
||||
invalid = -1;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
hash[i].I1() = invalid;
|
||||
}
|
||||
|
||||
|
||||
void BASE_INDEX_3_CLOSED_HASHTABLE ::
|
||||
|
@ -414,9 +414,14 @@ public:
|
||||
int BagNr() const { return bagnr; }
|
||||
int Pos() const { return pos; }
|
||||
|
||||
void operator++ (int)
|
||||
Iterator operator++ (int)
|
||||
{
|
||||
Iterator it(ht, bagnr, pos);
|
||||
++(*this);
|
||||
return it;
|
||||
}
|
||||
Iterator& operator++()
|
||||
{
|
||||
// cout << "begin Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl;
|
||||
pos++;
|
||||
while (bagnr < ht.GetNBags() &&
|
||||
pos == ht.GetBagSize(bagnr+1))
|
||||
@ -424,7 +429,12 @@ public:
|
||||
pos = 0;
|
||||
bagnr++;
|
||||
}
|
||||
// cout << "end Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl;
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::pair<INDEX_3, T> operator*()
|
||||
{
|
||||
return std::make_pair(ht.hash[bagnr][pos], ht.cont[bagnr][pos]);
|
||||
}
|
||||
|
||||
bool operator != (int i) const
|
||||
@ -446,6 +456,18 @@ public:
|
||||
return GetNBags();
|
||||
}
|
||||
|
||||
Iterator begin () const
|
||||
{
|
||||
Iterator it(*this, 0, -1);
|
||||
it++;
|
||||
return it;
|
||||
}
|
||||
|
||||
int end() const
|
||||
{
|
||||
return GetNBags();
|
||||
}
|
||||
|
||||
void GetData (const Iterator & it,
|
||||
INDEX_3 & ahash, T & acont) const
|
||||
{
|
||||
@ -839,9 +861,10 @@ inline ostream & operator<< (ostream & ost, const INDEX_2_CLOSED_HASHTABLE<T> &
|
||||
for (int i = 0; i < ht.Size(); i++)
|
||||
if (ht.UsedPos(i))
|
||||
{
|
||||
INDEX_2 hash;
|
||||
T data;
|
||||
ht.GetData0 (i, hash, data);
|
||||
// INDEX_2 hash;
|
||||
// T data;
|
||||
// ht.GetData0 (i, hash, data);
|
||||
auto [hash,data] = ht.GetBoth(i);
|
||||
ost << "hash = " << hash << ", data = " << data << endl;
|
||||
}
|
||||
return ost;
|
||||
@ -858,7 +881,8 @@ protected:
|
||||
size_t mask;
|
||||
|
||||
protected:
|
||||
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size)
|
||||
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size);
|
||||
/*
|
||||
: hash(RoundUp2(size))
|
||||
{
|
||||
// cout << "orig size = " << size
|
||||
@ -870,6 +894,7 @@ protected:
|
||||
for (size_t i = 0; i < size; i++)
|
||||
hash[i].I1() = invalid;
|
||||
}
|
||||
*/
|
||||
|
||||
public:
|
||||
int Size() const
|
||||
@ -1051,9 +1076,12 @@ inline ostream & operator<< (ostream & ost, const INDEX_3_CLOSED_HASHTABLE<T> &
|
||||
for (int i = 0; i < ht.Size(); i++)
|
||||
if (ht.UsedPos(i))
|
||||
{
|
||||
/*
|
||||
INDEX_3 hash;
|
||||
T data;
|
||||
ht.GetData (i, hash, data);
|
||||
ht.GetData (i, hash, data);
|
||||
*/
|
||||
auto [hash, data] = ht.GetBoth();
|
||||
ost << "hash = " << hash << ", data = " << data << endl;
|
||||
}
|
||||
return ost;
|
||||
|
@ -223,6 +223,16 @@ MyStr::MyStr(const string & st)
|
||||
strcpy (str, st.c_str());
|
||||
}
|
||||
|
||||
MyStr::MyStr(string_view sv)
|
||||
{
|
||||
length = unsigned(sv.length());
|
||||
if (length > SHORTLEN)
|
||||
str = new char[length + 1];
|
||||
else
|
||||
str = shortstr;
|
||||
strcpy (str, sv.data());
|
||||
}
|
||||
|
||||
MyStr::MyStr(const filesystem::path & path)
|
||||
: MyStr(path.string())
|
||||
{ }
|
||||
|
@ -60,6 +60,7 @@ public:
|
||||
MyStr(const Point3d& p);
|
||||
MyStr(const Vec3d& p);
|
||||
MyStr(const string & st);
|
||||
MyStr(string_view sv);
|
||||
MyStr(const filesystem::path & st);
|
||||
|
||||
~MyStr();
|
||||
|
@ -1,75 +0,0 @@
|
||||
#ifndef FILE_NGSTD_NgArrayCPP
|
||||
#define FILE_NGSTD_NgArrayCPP
|
||||
// necessary for SGI ????
|
||||
|
||||
/**************************************************************************/
|
||||
/* File: array.cpp */
|
||||
/* Author: Joachim Schoeberl */
|
||||
/* Date: 01. Jun. 95 */
|
||||
/**************************************************************************/
|
||||
|
||||
/*
|
||||
Abstract data type NgArray
|
||||
*/
|
||||
|
||||
#include <mystdlib.h>
|
||||
#include <myadt.hpp>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
//using namespace netgen;
|
||||
|
||||
#ifdef NONE
|
||||
void BASE_Array :: ReSize (int minsize, int elementsize)
|
||||
{
|
||||
cout << "resize, minsize = " << minsize << endl;
|
||||
|
||||
if (inc == -1)
|
||||
throw Exception ("Try to resize fixed size array");
|
||||
|
||||
|
||||
void * p;
|
||||
int nsize = (inc) ? allocsize + inc : 2 * allocsize;
|
||||
if (nsize < minsize) nsize = minsize;
|
||||
|
||||
if (data)
|
||||
{
|
||||
p = new char [nsize * elementsize];
|
||||
|
||||
int mins = (nsize < actsize) ? nsize : actsize;
|
||||
memcpy (p, data, mins * elementsize);
|
||||
|
||||
delete [] static_cast<char*> (data);
|
||||
data = p;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = new char[nsize * elementsize];
|
||||
}
|
||||
|
||||
allocsize = nsize;
|
||||
cout << "resize done" << endl;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void BASE_Array :: RangeCheck (int i) const
|
||||
{
|
||||
if (i < 0 || i >= actsize)
|
||||
throw ArrayRangeException ();
|
||||
}
|
||||
|
||||
void BASE_Array :: CheckNonEmpty () const
|
||||
{
|
||||
if (!actsize)
|
||||
{
|
||||
throw Exception ("NgArray should not be empty");
|
||||
// cerr << "NgArray shouldn't be empty";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif // FILE_NGSTD_NgArrayCPP
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
using namespace ngcore;
|
||||
|
||||
// template <class T, int B1, int B2> class IndirectArray;
|
||||
template <class TA1, class TA2> class NgIndirectArray;
|
||||
@ -111,11 +112,7 @@ namespace netgen
|
||||
/// Access array. BASE-based
|
||||
T & operator[] (TIND i) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (i-BASE < 0 || i-BASE >= size)
|
||||
cout << "array<" << typeid(T).name() << "> out of range, i = " << i << ", s = " << size << endl;
|
||||
#endif
|
||||
|
||||
NETGEN_CHECK_RANGE(i,BASE,size+BASE);
|
||||
return data[i-BASE];
|
||||
}
|
||||
|
||||
@ -130,13 +127,7 @@ namespace netgen
|
||||
/// Access array, one-based (old fashioned)
|
||||
T & Elem (int i)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (i < 1 || i > size)
|
||||
cout << "NgArray<" << typeid(T).name()
|
||||
<< ">::Elem out of range, i = " << i
|
||||
<< ", s = " << size << endl;
|
||||
#endif
|
||||
|
||||
NETGEN_CHECK_RANGE(i,1,size+1);
|
||||
return ((T*)data)[i-1];
|
||||
}
|
||||
|
||||
@ -144,30 +135,21 @@ namespace netgen
|
||||
// [[deprecated("Use operator[] instead")]]
|
||||
const T & Get (int i) const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (i < 1 || i > size)
|
||||
cout << "NgArray<" << typeid(T).name() << ">::Get out of range, i = " << i
|
||||
<< ", s = " << size << endl;
|
||||
#endif
|
||||
|
||||
NETGEN_CHECK_RANGE(i,1,size+1);
|
||||
return ((const T*)data)[i-1];
|
||||
}
|
||||
|
||||
/// Access array, one-based (old fashioned)
|
||||
void Set (int i, const T & el)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
if (i < 1 || i > size)
|
||||
cout << "NgArray<" << typeid(T).name() << ">::Set out of range, i = " << i
|
||||
<< ", s = " << size << endl;
|
||||
#endif
|
||||
|
||||
NETGEN_CHECK_RANGE(i,1,size+1);
|
||||
((T*)data)[i-1] = el;
|
||||
}
|
||||
|
||||
/// access first element
|
||||
T & First () const
|
||||
{
|
||||
NETGEN_CHECK_RANGE(0,0,size);
|
||||
return data[0];
|
||||
}
|
||||
|
||||
@ -175,6 +157,7 @@ namespace netgen
|
||||
/// access last element. check by macro CHECK_RANGE
|
||||
T & Last () const
|
||||
{
|
||||
NETGEN_CHECK_RANGE(size-1,0,size);
|
||||
return data[size-1];
|
||||
}
|
||||
|
||||
@ -345,10 +328,7 @@ namespace netgen
|
||||
/// Delete element i (0-based). Move last element to position i.
|
||||
void Delete (TIND i)
|
||||
{
|
||||
#ifdef CHECK_Array_RANGE
|
||||
RangeCheck (i+1);
|
||||
#endif
|
||||
|
||||
NETGEN_CHECK_RANGE(i,0,size);
|
||||
data[i] = std::move(data[size-1]);
|
||||
size--;
|
||||
// DeleteElement (i+1);
|
||||
@ -358,10 +338,7 @@ namespace netgen
|
||||
/// Delete element i (1-based). Move last element to position i.
|
||||
void DeleteElement (TIND i)
|
||||
{
|
||||
#ifdef CHECK_Array_RANGE
|
||||
RangeCheck (i);
|
||||
#endif
|
||||
|
||||
NETGEN_CHECK_RANGE(i,1,size+1);
|
||||
data[i-1] = std::move(data[size-1]);
|
||||
size--;
|
||||
}
|
||||
|
@ -12,7 +12,6 @@
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
data type NgBitArray
|
||||
|
||||
@ -29,8 +28,11 @@ class NgBitArray
|
||||
unsigned char * data;
|
||||
|
||||
public:
|
||||
|
||||
// [[ deprecated ("use BitArray instead")]]
|
||||
DLL_HEADER NgBitArray ();
|
||||
///
|
||||
// [[ deprecated ("use BitArray instead")]]
|
||||
DLL_HEADER NgBitArray (INDEX asize);
|
||||
///
|
||||
DLL_HEADER ~NgBitArray ();
|
||||
|
@ -108,8 +108,9 @@ namespace netgen
|
||||
if (line.size == line.maxsize)
|
||||
{
|
||||
void * p = new char [(line.maxsize+5) * elsize];
|
||||
|
||||
memcpy (p, line.col, line.maxsize * elsize);
|
||||
|
||||
if (line.maxsize && elsize)
|
||||
memcpy (p, line.col, line.maxsize * elsize);
|
||||
delete [] (char*)line.col;
|
||||
|
||||
line.col = p;
|
||||
|
@ -120,7 +120,7 @@ public:
|
||||
|
||||
/// Creates fixed maximal element size table
|
||||
inline TABLE (const NgFlatArray<int,BASE> & entrysizes)
|
||||
: BASE_TABLE (NgFlatArray<int> (entrysizes.Size(), const_cast<int*>(&entrysizes[BASE])),
|
||||
: BASE_TABLE (NgFlatArray<int> (entrysizes.Size(), entrysizes.Size() ? const_cast<int*>(&entrysizes[BASE]) : nullptr),
|
||||
sizeof(T))
|
||||
{ ; }
|
||||
|
||||
|
@ -114,14 +114,24 @@ class INDEX_2
|
||||
|
||||
public:
|
||||
///
|
||||
// protected:
|
||||
INDEX_2 () { }
|
||||
INDEX_2 (const INDEX_2&) = default;
|
||||
public:
|
||||
INDEX_2 (INDEX_2&&) = default;
|
||||
|
||||
INDEX_2 & operator= (const INDEX_2&) = default;
|
||||
INDEX_2 & operator= (INDEX_2&&) = default;
|
||||
///
|
||||
INDEX_2 (INDEX ai1, INDEX ai2)
|
||||
{ i[0] = ai1; i[1] = ai2; }
|
||||
constexpr INDEX_2 (INDEX ai1, INDEX ai2)
|
||||
: i{ai1, ai2} { }
|
||||
// { i[0] = ai1; i[1] = ai2; }
|
||||
|
||||
///
|
||||
INDEX_2 (const INDEX_2 & in2)
|
||||
{ i[0] = in2.i[0]; i[1] = in2.i[1]; }
|
||||
// constexpr INDEX_2 (const INDEX_2 & in2)
|
||||
// : i{in2.i[0], in2.i[1]} { }
|
||||
|
||||
// { i[0] = in2.i[0]; i[1] = in2.i[1]; }
|
||||
|
||||
///
|
||||
int operator== (const INDEX_2 & in2) const
|
||||
@ -130,7 +140,7 @@ public:
|
||||
///
|
||||
|
||||
|
||||
INDEX_2 Sort ()
|
||||
constexpr INDEX_2 Sort ()
|
||||
{
|
||||
if (i[0] > i[1])
|
||||
{
|
||||
@ -149,7 +159,7 @@ public:
|
||||
return INDEX_2 (i1,i2);
|
||||
}
|
||||
|
||||
|
||||
operator std::array<INDEX,2>() { return { i[0], i[1] }; }
|
||||
///
|
||||
INDEX & I1 () { return i[0]; }
|
||||
///
|
||||
@ -165,7 +175,7 @@ public:
|
||||
///
|
||||
int & operator[] (int j) { return i[j]; }
|
||||
///
|
||||
const int & operator[] (int j) const { return i[j]; }
|
||||
constexpr const int & operator[] (int j) const { return i[j]; }
|
||||
///
|
||||
friend ostream & operator<<(ostream & s, const INDEX_2 & i2);
|
||||
};
|
||||
@ -203,13 +213,12 @@ public:
|
||||
///
|
||||
INDEX_3 () { }
|
||||
///
|
||||
INDEX_3 (INDEX ai1, INDEX ai2, INDEX ai3)
|
||||
{ i[0] = ai1; i[1] = ai2; i[2] = ai3; }
|
||||
|
||||
///
|
||||
INDEX_3 (const INDEX_3 & in2)
|
||||
{ i[0] = in2.i[0]; i[1] = in2.i[1]; i[2] = in2.i[2]; }
|
||||
constexpr INDEX_3 (INDEX ai1, INDEX ai2, INDEX ai3)
|
||||
: i{ai1, ai2, ai3} { }
|
||||
|
||||
///
|
||||
constexpr INDEX_3 (const INDEX_3 & in2)
|
||||
: i{in2.i[0], in2.i[1], in2.i[2]} { }
|
||||
|
||||
static INDEX_3 Sort (INDEX_3 i3)
|
||||
{
|
||||
@ -464,4 +473,37 @@ void MergeSort (int size, T * data, T * help);
|
||||
|
||||
}
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
// template <>
|
||||
// constexpr inline netgen::INDEX_2 InvalidHash<netgen::INDEX_2> () { return netgen::INDEX_2{-1,-1}; }
|
||||
|
||||
|
||||
template <>
|
||||
struct CHT_trait<netgen::INDEX_2>
|
||||
{
|
||||
constexpr static inline netgen::INDEX_2 Invalid() { return { -1, -1 } ; }
|
||||
constexpr static inline size_t HashValue (const netgen::INDEX_2 & hash, size_t mask)
|
||||
{ return HashValue2(IVec<2,netgen::INDEX>(hash[0], hash[1]), mask); }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
/*
|
||||
inline size_t HashValue2 (const netgen::INDEX_2 & ind, size_t mask)
|
||||
{
|
||||
return HashValue2(IVec<2,netgen::INDEX>(ind[0], ind[1]), mask);
|
||||
}
|
||||
*/
|
||||
|
||||
inline size_t HashValue2 (const netgen::INDEX_3 & ind, size_t mask)
|
||||
{
|
||||
return HashValue2(IVec<3,netgen::INDEX>(ind[0], ind[1], ind[2]), mask);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -139,7 +139,9 @@ namespace netgen
|
||||
mark = spline.GetPoint (edgelength);
|
||||
|
||||
{
|
||||
PointIndex pi1 = -1, pi2 = -1;
|
||||
PointIndex pi1{PointIndex::INVALID};
|
||||
PointIndex pi2{PointIndex::INVALID};
|
||||
|
||||
|
||||
Point3d mark3(mark(0), mark(1), 0);
|
||||
Point3d oldmark3(oldmark(0), oldmark(1), 0);
|
||||
@ -157,12 +159,12 @@ namespace netgen
|
||||
if ( mesh[PointIndex(locsearch[k])].GetLayer() == spline.layer)
|
||||
pi2 = locsearch[k];
|
||||
|
||||
if (pi1 == -1)
|
||||
if (!pi1.IsValid())
|
||||
{
|
||||
pi1 = mesh.AddPoint(oldmark3, spline.layer);
|
||||
searchtree.Insert (oldmark3, pi1);
|
||||
}
|
||||
if (pi2 == -1)
|
||||
if (!pi2.IsValid())
|
||||
{
|
||||
pi2 = mesh.AddPoint(mark3, spline.layer);
|
||||
searchtree.Insert (mark3, pi2);
|
||||
@ -278,7 +280,7 @@ namespace netgen
|
||||
mesh2d.AddLockedPoint(npi);
|
||||
Element0d el(npi, npi);
|
||||
el.name = point.name;
|
||||
mesh2d.SetCD2Name(npi, point.name);
|
||||
mesh2d.SetCD2Name(npi-IndexBASE<PointIndex>()+1, point.name);
|
||||
mesh2d.pointelements.Append (el);
|
||||
searchtree.Insert (newp, npi);
|
||||
}
|
||||
@ -292,20 +294,20 @@ namespace netgen
|
||||
Point<2> hnewp = (j == 1) ? splines[i]->StartPI() : splines[i]->EndPI();
|
||||
Point<3> newp(hnewp(0), hnewp(1), 0);
|
||||
int layer = GetSpline(i).layer;
|
||||
int npi = -1;
|
||||
for (PointIndex pi = PointIndex::BASE;
|
||||
pi < mesh2d.GetNP()+PointIndex::BASE; pi++)
|
||||
PointIndex npi(PointIndex::INVALID);
|
||||
for (PointIndex pi = IndexBASE<PointIndex>();
|
||||
pi < mesh2d.GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
if (Dist2 (mesh2d.Point(pi), newp) < 1e-12 * diam2 && mesh2d.Point(pi).GetLayer() == layer)
|
||||
npi = pi;
|
||||
|
||||
if (npi == -1)
|
||||
if (!npi.IsValid())
|
||||
{
|
||||
npi = mesh2d.AddPoint (newp, layer);
|
||||
searchtree.Insert (newp, npi);
|
||||
mesh2d.AddLockedPoint(npi);
|
||||
Element0d el(npi, npi);
|
||||
Element0d el(npi, npi-IndexBASE<PointIndex>()+1);
|
||||
el.name = "";
|
||||
mesh2d.SetCD2Name(npi, "");
|
||||
mesh2d.SetCD2Name(npi-IndexBASE<PointIndex>()+1, "");
|
||||
mesh2d.pointelements.Append (el);
|
||||
}
|
||||
}
|
||||
@ -463,8 +465,8 @@ namespace netgen
|
||||
PointIndex mpi(0);
|
||||
Point<2> gp = geometry.GetPoint(i);
|
||||
Point<3> gp3(gp(0), gp(1), 0);
|
||||
for (PointIndex pi = PointIndex::BASE;
|
||||
pi < mesh->GetNP()+PointIndex::BASE; pi++)
|
||||
for (PointIndex pi = IndexBASE<PointIndex>();
|
||||
pi < mesh->GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
if (Dist2(gp3, (*mesh)[pi]) < mindist)
|
||||
{
|
||||
mpi = pi;
|
||||
@ -521,8 +523,8 @@ namespace netgen
|
||||
{ // tensor product mesh
|
||||
RegionTimer rt(t_tensor);
|
||||
|
||||
NgArray<PointIndex, PointIndex::BASE> nextpi(bnp);
|
||||
NgArray<int, PointIndex::BASE> si1(bnp), si2(bnp);
|
||||
Array<PointIndex, PointIndex> nextpi(bnp);
|
||||
Array<int, PointIndex> si1(bnp), si2(bnp);
|
||||
// PointIndex firstpi;
|
||||
|
||||
nextpi = -1;
|
||||
@ -551,7 +553,8 @@ namespace netgen
|
||||
PointIndex c1(0), c2, c3, c4; // 4 corner points
|
||||
int nex = 1, ney = 1;
|
||||
|
||||
for (PointIndex pi = 1; pi <= si2.Size(); pi++)
|
||||
// for (PointIndex pi = 1; pi <= si2.Size(); pi++)
|
||||
for (PointIndex pi : si2.Range())
|
||||
if (si2[pi] != -1)
|
||||
{ c1 = pi; break; }
|
||||
|
||||
@ -564,13 +567,17 @@ namespace netgen
|
||||
NgArray<PointIndex> pts ( (nex+1) * (ney+1) ); // x ... inner loop
|
||||
pts = -1;
|
||||
|
||||
for (PointIndex pi = c1, i = 0; pi != c2; pi = nextpi[pi], i++)
|
||||
int i = 0;
|
||||
for (PointIndex pi = c1; pi != c2; pi = nextpi[pi], i++)
|
||||
pts[i] = pi;
|
||||
for (PointIndex pi = c2, i = 0; pi != c3; pi = nextpi[pi], i++)
|
||||
i = 0;
|
||||
for (PointIndex pi = c2; pi != c3; pi = nextpi[pi], i++)
|
||||
pts[(nex+1)*i+nex] = pi;
|
||||
for (PointIndex pi = c3, i = 0; pi != c4; pi = nextpi[pi], i++)
|
||||
i = 0;
|
||||
for (PointIndex pi = c3; pi != c4; pi = nextpi[pi], i++)
|
||||
pts[(nex+1)*(ney+1)-i-1] = pi;
|
||||
for (PointIndex pi = c4, i = 0; pi != c1; pi = nextpi[pi], i++)
|
||||
i = 0;
|
||||
for (PointIndex pi = c4; pi != c1; pi = nextpi[pi], i++)
|
||||
pts[(nex+1)*(ney-i)] = pi;
|
||||
|
||||
|
||||
|
@ -401,10 +401,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
|
||||
{
|
||||
MeshingParameters mp;
|
||||
if(pars) mp = *pars;
|
||||
{
|
||||
py::gil_scoped_acquire aq;
|
||||
CreateMPfromKwargs(mp, kwargs);
|
||||
}
|
||||
CreateMPfromKwargs(mp, kwargs);
|
||||
py::gil_scoped_release gil_release;
|
||||
auto mesh = make_shared<Mesh>();
|
||||
mesh->SetGeometry(self);
|
||||
SetGlobalMesh (mesh);
|
||||
@ -414,7 +412,6 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
|
||||
throw Exception("Meshing failed!");
|
||||
return mesh;
|
||||
}, py::arg("mp") = nullopt,
|
||||
py::call_guard<py::gil_scoped_release>(),
|
||||
meshingparameter_description.c_str())
|
||||
.def("_SetDomainTensorMeshing", &SplineGeometry2d::SetDomainTensorMeshing)
|
||||
;
|
||||
@ -427,7 +424,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
|
||||
.def(py::self-py::self)
|
||||
.def(py::self*py::self)
|
||||
.def(py::self+=py::self)
|
||||
.def(py::self-=py::self)
|
||||
// .def(py::self-=py::self) // false clange warning, see https://github.com/pybind/pybind11/issues/1893
|
||||
.def("__isub__", [](Solid2d& lhs, const Solid2d& rhs) { return lhs -= rhs; }, py::is_operator())
|
||||
.def(py::self*=py::self)
|
||||
|
||||
.def("Mat", &Solid2d::Mat)
|
||||
@ -466,10 +464,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
|
||||
{
|
||||
MeshingParameters mp;
|
||||
if(pars) mp = *pars;
|
||||
{
|
||||
py::gil_scoped_acquire aq;
|
||||
CreateMPfromKwargs(mp, kwargs);
|
||||
}
|
||||
py::gil_scoped_release gil_release;
|
||||
auto mesh = make_shared<Mesh>();
|
||||
auto geo = self.GenerateSplineGeometry();
|
||||
mesh->SetGeometry(geo);
|
||||
@ -480,7 +476,6 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
|
||||
throw Exception("Meshing failed!");
|
||||
return mesh;
|
||||
}, py::arg("mp") = nullopt,
|
||||
py::call_guard<py::gil_scoped_release>(),
|
||||
meshingparameter_description.c_str())
|
||||
;
|
||||
|
||||
|
@ -970,7 +970,7 @@ public:
|
||||
Leaf *leaf1 = (Leaf*) ball_leaves.Alloc(); new (leaf1) Leaf();
|
||||
Leaf *leaf2 = (Leaf*) ball_leaves.Alloc(); new (leaf2) Leaf();
|
||||
|
||||
for (auto i : order.Range(isplit))
|
||||
for (auto i : order.Range(0, isplit))
|
||||
leaf1->Add(leaf_index, leaf->p[i], leaf->index[i] );
|
||||
for (auto i : order.Range(isplit, N))
|
||||
leaf2->Add(leaf_index, leaf->p[i], leaf->index[i] );
|
||||
@ -1334,7 +1334,7 @@ public:
|
||||
leaves.Append(leaf2);
|
||||
leaves[leaf1->nr] = leaf1;
|
||||
|
||||
for (auto i : order.Range(isplit))
|
||||
for (auto i : order.Range(0,isplit))
|
||||
leaf1->Add(leaves, leaf_index, leaf->p[i], leaf->index[i] );
|
||||
for (auto i : order.Range(isplit, N))
|
||||
leaf2->Add(leaves, leaf_index, leaf->p[i], leaf->index[i] );
|
||||
|
@ -128,7 +128,7 @@ Point2d CrossPoint (const Line2d & l1, const Line2d & l2)
|
||||
|
||||
|
||||
int CrossPointBarycentric (const Line2d & l1, const Line2d & l2,
|
||||
double & lam1, double & lam2)
|
||||
double & lam1, double & lam2, double eps)
|
||||
{
|
||||
// p = l1.1 + lam1 (l1.2-l1.1) = l2.1 + lam2 (l2.2-l2.1)
|
||||
double a11 = l1.p2.X() - l1.p1.X();
|
||||
@ -140,8 +140,11 @@ int CrossPointBarycentric (const Line2d & l1, const Line2d & l2,
|
||||
double b2 = l2.p1.Y() - l1.p1.Y();
|
||||
|
||||
double det = a11*a22 - a12 * a21;
|
||||
/*
|
||||
if (det == 0)
|
||||
return 1;
|
||||
*/
|
||||
if (fabs (det) < eps * (fabs(a11*a22)+fabs(a12*a21))) return 1;
|
||||
|
||||
lam1 = (a22 * b1 - a12 * b2) / det;
|
||||
lam2 = (a11 * b2 - a21 * b1) / det;
|
||||
|
@ -365,7 +365,7 @@ namespace netgen
|
||||
friend DLL_HEADER Point2d CrossPoint (const Line2d & l1, const Line2d & l2);
|
||||
/// returns 1 iff parallel
|
||||
friend int CrossPointBarycentric (const Line2d & l1, const Line2d & l2,
|
||||
double & lam1, double & lam2);
|
||||
double & lam1, double & lam2, double eps);
|
||||
|
||||
///
|
||||
friend int Parallel (const Line2d & l1, const Line2d & l2, double peps);
|
||||
|
@ -140,7 +140,8 @@ namespace netgen
|
||||
|
||||
operator const T* () const { return x; }
|
||||
|
||||
void DoArchive(Archive& archive)
|
||||
template <typename ARCHIVE>
|
||||
void DoArchive(ARCHIVE& archive)
|
||||
{
|
||||
for(int i=0; i<D; i++)
|
||||
archive & x[i];
|
||||
@ -294,7 +295,8 @@ namespace netgen
|
||||
sol = inv * rhs;
|
||||
}
|
||||
|
||||
void DoArchive(Archive & ar)
|
||||
template <typename ARCHIVE>
|
||||
void DoArchive(ARCHIVE & ar)
|
||||
{
|
||||
ar.Do(x, H*W);
|
||||
}
|
||||
@ -341,8 +343,6 @@ namespace netgen
|
||||
pmin(i) = 1e99;
|
||||
pmax(i) = -1e99;
|
||||
}
|
||||
// pmin = Point<D> (1e99, 1e99, 1e99);
|
||||
// pmax = Point<D> (-1e99, -1e99, -1e99);
|
||||
}
|
||||
|
||||
const Point<D> & PMin () const { return pmin; }
|
||||
@ -442,7 +442,8 @@ namespace netgen
|
||||
pmax = center + factor*(pmax-center);
|
||||
}
|
||||
|
||||
void DoArchive(Archive& archive)
|
||||
template <typename ARCHIVE>
|
||||
void DoArchive(ARCHIVE & archive)
|
||||
{ archive & pmin & pmax; }
|
||||
};
|
||||
|
||||
|
@ -39,24 +39,9 @@ namespace netgen
|
||||
using namespace std;
|
||||
using namespace ngcore;
|
||||
|
||||
// extern DLL_HEADER NgMPI_Comm ng_comm;
|
||||
|
||||
static constexpr int POINTINDEX_BASE = 1;
|
||||
|
||||
/*
|
||||
struct T_EDGE2
|
||||
{
|
||||
// int orient:1;
|
||||
// int nr:31; // 0-based
|
||||
int nr; // 0-based
|
||||
};
|
||||
struct T_FACE2
|
||||
{
|
||||
// int orient:3;
|
||||
// int nr:29; // 0-based
|
||||
int nr; // 0-based
|
||||
};
|
||||
*/
|
||||
typedef int T_EDGE2;
|
||||
typedef int T_FACE2;
|
||||
|
||||
@ -112,28 +97,6 @@ namespace netgen
|
||||
int operator[] (size_t i) const { return ptr[i]-POINTINDEX_BASE; }
|
||||
};
|
||||
|
||||
/*
|
||||
class Ng_Edges
|
||||
{
|
||||
public:
|
||||
size_t num;
|
||||
const T_EDGE2 * ptr;
|
||||
|
||||
size_t Size() const { return num; }
|
||||
int operator[] (size_t i) const { return ptr[i]; }
|
||||
};
|
||||
|
||||
class Ng_Faces
|
||||
{
|
||||
public:
|
||||
size_t num;
|
||||
const T_FACE2 * ptr;
|
||||
|
||||
size_t Size() const { return num; }
|
||||
int operator[] (size_t i) const { return ptr[i]; }
|
||||
};
|
||||
*/
|
||||
|
||||
class Ng_Facets
|
||||
{
|
||||
public:
|
||||
@ -154,12 +117,11 @@ namespace netgen
|
||||
int GetIndex() const { return index-1; }
|
||||
Ng_Points points; // all points
|
||||
Ng_Vertices vertices;
|
||||
// Ng_Edges edges;
|
||||
FlatArray<T_EDGE2> edges;
|
||||
// Ng_Faces faces;
|
||||
FlatArray<T_FACE2> faces;
|
||||
Ng_Facets facets;
|
||||
bool is_curved;
|
||||
int8_t newest_vertex;
|
||||
};
|
||||
|
||||
|
||||
@ -412,6 +374,10 @@ namespace netgen
|
||||
int GetClusterRepEdge (int edi) const;
|
||||
int GetClusterRepFace (int fai) const;
|
||||
int GetClusterRepElement (int eli) const;
|
||||
|
||||
// just copied from nginterface, now 0-based
|
||||
int GetElement_Faces (int elnr, int * faces, int * orient = 0) const;
|
||||
int GetSurfaceElement_Face (int selnr, int * orient = 0) const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -72,13 +72,17 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<0> (size_t nr) const
|
||||
ret.facets.base = POINTINDEX_BASE;
|
||||
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));
|
||||
|
||||
*/
|
||||
ret.mat = mesh->GetRegionName(0, el.index);
|
||||
|
||||
ret.is_curved = false;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -96,6 +100,8 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (size_t nr) const
|
||||
ret.index = el.edgenr;
|
||||
else
|
||||
ret.index = el.si;
|
||||
|
||||
/*
|
||||
if (mesh->GetDimension() == 2)
|
||||
ret.mat = *(mesh->GetBCNamePtr(el.si-1));
|
||||
else
|
||||
@ -105,6 +111,8 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (size_t nr) const
|
||||
else
|
||||
ret.mat = *(mesh->GetMaterialPtr(el.si));
|
||||
}
|
||||
*/
|
||||
ret.mat = mesh->GetRegionName(1, ret.index);
|
||||
|
||||
ret.points.num = el.GetNP();
|
||||
ret.points.ptr = (int*)&(el[0]);
|
||||
@ -116,7 +124,7 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (size_t nr) const
|
||||
ret.edges.num = 1;
|
||||
ret.edges.ptr = mesh->GetTopology().GetSegmentElementEdgesPtr (nr);
|
||||
*/
|
||||
ret.edges.Assign ( FlatArray<T_EDGE2> (1, const_cast<T_EDGE2*>( mesh->GetTopology().GetSegmentElementEdgesPtr (nr))));
|
||||
ret.edges.Assign ( FlatArray<T_EDGE2> (1, const_cast<T_EDGE2*>((const int*) mesh->GetTopology().GetSegmentElementEdgesPtr (nr))));
|
||||
|
||||
/*
|
||||
ret.faces.num = 0;
|
||||
@ -139,7 +147,7 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<1> (size_t nr) const
|
||||
else
|
||||
{
|
||||
ret.facets.num = 2;
|
||||
ret.facets.base = 1;
|
||||
ret.facets.base = POINTINDEX_BASE;
|
||||
ret.facets.ptr = (int*)&(el[0]);
|
||||
}
|
||||
|
||||
@ -172,12 +180,19 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<2> (size_t nr) const
|
||||
ret.edges.num = MeshTopology::GetNEdges (el.GetType());
|
||||
ret.edges.ptr = mesh->GetTopology().GetSurfaceElementEdgesPtr (nr);
|
||||
*/
|
||||
ret.edges.Assign (mesh->GetTopology().GetEdges (SurfaceElementIndex(nr)));
|
||||
|
||||
// ret.edges.Assign (mesh->GetTopology().GetEdges (SurfaceElementIndex(nr)));
|
||||
auto hedges = mesh->GetTopology().GetEdges (SurfaceElementIndex(nr));
|
||||
ret.edges.Assign ( { hedges.Size(), (int*)hedges.Data() } );
|
||||
|
||||
/*
|
||||
ret.faces.num = MeshTopology::GetNFaces (el.GetType());
|
||||
ret.faces.ptr = mesh->GetTopology().GetSurfaceElementFacesPtr (nr);
|
||||
*/
|
||||
ret.faces.Assign ( { 1, const_cast<int*>(mesh->GetTopology().GetSurfaceElementFacesPtr (nr)) });
|
||||
|
||||
// ret.faces.Assign ( { 1, const_cast<int*>(mesh->GetTopology().GetSurfaceElementFacesPtr (nr)) });
|
||||
ret.faces.Assign ( { 1, (int*)(mesh->GetTopology().GetSurfaceElementFacesPtr (nr)) });
|
||||
|
||||
if (mesh->GetDimension() == 3)
|
||||
{
|
||||
ret.facets.num = ret.faces.Size();
|
||||
@ -191,6 +206,7 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<2> (size_t nr) const
|
||||
ret.facets.ptr = ret.edges.Data();
|
||||
}
|
||||
ret.is_curved = el.IsCurved();
|
||||
ret.newest_vertex = el.NewestVertex();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -213,19 +229,25 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<3> (size_t nr) const
|
||||
ret.edges.num = MeshTopology::GetNEdges (el.GetType());
|
||||
ret.edges.ptr = mesh->GetTopology().GetElementEdgesPtr (nr);
|
||||
*/
|
||||
ret.edges.Assign (mesh->GetTopology().GetEdges (ElementIndex(nr)));
|
||||
// ret.edges.Assign (mesh->GetTopology().GetEdges (ElementIndex(nr)));
|
||||
auto hedges = mesh->GetTopology().GetEdges (ElementIndex(nr));
|
||||
ret.edges.Assign ( { hedges.Size(), (int*)hedges.Data() } );
|
||||
|
||||
|
||||
/*
|
||||
ret.faces.num = MeshTopology::GetNFaces (el.GetType());
|
||||
ret.faces.ptr = mesh->GetTopology().GetElementFacesPtr (nr);
|
||||
*/
|
||||
ret.faces.Assign (mesh->GetTopology().GetFaces (ElementIndex(nr)));
|
||||
// ret.faces.Assign (mesh->GetTopology().GetFaces (ElementIndex(nr)));
|
||||
auto hfaces = mesh->GetTopology().GetFaces (ElementIndex(nr));
|
||||
ret.faces.Assign ( { hfaces.Size(), (int*)hfaces.Data() } );
|
||||
|
||||
ret.facets.num = ret.faces.Size();
|
||||
ret.facets.base = 0;
|
||||
ret.facets.ptr = ret.faces.Data();
|
||||
|
||||
ret.is_curved = el.IsCurved();
|
||||
ret.newest_vertex = el.NewestVertex();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -269,10 +291,10 @@ template <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetNNodes<2> ()
|
||||
return mesh->GetTopology().GetNFaces();
|
||||
}
|
||||
|
||||
template <> NGX_INLINE DLL_HEADER const Ng_Node<0> Ngx_Mesh :: GetNode<0> (int vnr) const
|
||||
template <> NGX_INLINE DLL_HEADER const Ng_Node<0> Ngx_Mesh :: GetNode<0> (int vnr_) const
|
||||
{
|
||||
Ng_Node<0> node;
|
||||
vnr++;
|
||||
PointIndex vnr = IndexBASE<PointIndex>() + vnr_;
|
||||
switch (mesh->GetDimension())
|
||||
{
|
||||
case 3:
|
||||
@ -325,8 +347,8 @@ template <> NGX_INLINE DLL_HEADER const Ng_Node<2> Ngx_Mesh :: GetNode<2> (int n
|
||||
{
|
||||
Ng_Node<2> node;
|
||||
node.vertices.ptr = (const int*)mesh->GetTopology().GetFaceVerticesPtr(nr);
|
||||
node.vertices.nv = (node.vertices.ptr[3] == 0) ? 3 : 4;
|
||||
node.surface_el = mesh->GetTopology().GetFace2SurfaceElement (nr+1)-1;
|
||||
node.vertices.nv = (node.vertices.ptr[3]+1 == PointIndex::BASE) ? 3 : 4;
|
||||
node.surface_el = mesh->GetTopology().GetFace2SurfaceElement (nr);
|
||||
return node;
|
||||
}
|
||||
|
||||
@ -337,8 +359,8 @@ NGX_INLINE DLL_HEADER Ng_Buffer<int[2]> Ngx_Mesh :: GetPeriodicVertices(int idnr
|
||||
mesh->GetIdentifications().GetPairs (idnr+1, apairs);
|
||||
for(auto& ind : apairs)
|
||||
{
|
||||
ind.I1()--;
|
||||
ind.I2()--;
|
||||
ind.I1() -= IndexBASE<PointIndex>();
|
||||
ind.I2() -= IndexBASE<PointIndex>();
|
||||
}
|
||||
typedef int ti2[2];
|
||||
return { apairs.Size(), (ti2*)(void*)apairs.Release() };
|
||||
@ -347,12 +369,9 @@ NGX_INLINE DLL_HEADER Ng_Buffer<int[2]> Ngx_Mesh :: GetPeriodicVertices(int idnr
|
||||
|
||||
NGX_INLINE void Ngx_Mesh :: GetParentNodes (int ni, int * parents) const
|
||||
{
|
||||
ni++;
|
||||
if (ni <= mesh->mlbetweennodes.Size())
|
||||
{
|
||||
parents[0] = mesh->mlbetweennodes.Get(ni).I1()-1;
|
||||
parents[1] = mesh->mlbetweennodes.Get(ni).I2()-1;
|
||||
}
|
||||
if (ni < mesh->mlbetweennodes.Size())
|
||||
for (int j = 0; j < 2; j++)
|
||||
parents[j] = mesh->mlbetweennodes[IndexBASE<PointIndex>()+ni][j] - IndexBASE<PointIndex>();
|
||||
else
|
||||
parents[0] = parents[1] = -1;
|
||||
}
|
||||
|
@ -507,7 +507,7 @@ NG_ELEMENT_TYPE Ng_GetSurfaceElement (int ei, int * epi, int * np)
|
||||
{
|
||||
const Segment & seg = mesh->LineSegment (ei);
|
||||
|
||||
if (seg[2] < 0)
|
||||
if (!seg[2].IsValid())
|
||||
{
|
||||
epi[0] = seg[0];
|
||||
epi[1] = seg[1];
|
||||
@ -651,14 +651,14 @@ int Ng_FindElementOfPoint (double * p, double * lami, int build_searchtree,
|
||||
{
|
||||
Point3d p3d(p[0], p[1], p[2]);
|
||||
ind =
|
||||
mesh->GetElementOfPoint(p3d, lami, dummy, build_searchtree != 0);
|
||||
mesh->GetElementOfPoint(p3d, lami, dummy, build_searchtree != 0) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
double lam3[3];
|
||||
Point3d p2d(p[0], p[1], 0);
|
||||
ind =
|
||||
mesh->GetElementOfPoint(p2d, lam3, dummy, build_searchtree != 0);
|
||||
mesh->GetSurfaceElementOfPoint(p2d, lam3, dummy, build_searchtree != 0) + 1;
|
||||
|
||||
if (ind > 0)
|
||||
{
|
||||
@ -697,7 +697,7 @@ int Ng_FindSurfaceElementOfPoint (double * p, double * lami, int build_searchtre
|
||||
{
|
||||
Point3d p3d(p[0], p[1], p[2]);
|
||||
ind =
|
||||
mesh->GetSurfaceElementOfPoint(p3d, lami, dummy, build_searchtree != 0);
|
||||
mesh->GetSurfaceElementOfPoint(p3d, lami, dummy, build_searchtree != 0) + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -866,7 +866,7 @@ NG_ELEMENT_TYPE Ng_GetSegment (int ei, int * epi, int * np)
|
||||
epi[0] = seg[0];
|
||||
epi[1] = seg[1];
|
||||
|
||||
if (seg[2] < 0)
|
||||
if (!seg[2].IsValid())
|
||||
{
|
||||
if (np) *np = 2;
|
||||
return NG_SEGM;
|
||||
@ -1571,10 +1571,11 @@ int Ng_GetSurfaceElement_Face (int selnr, int * orient)
|
||||
{
|
||||
if (mesh->GetDimension() == 3)
|
||||
{
|
||||
SurfaceElementIndex sei = selnr-1;
|
||||
const MeshTopology & topology = mesh->GetTopology();
|
||||
if (orient)
|
||||
*orient = topology.GetSurfaceElementFaceOrientation (selnr);
|
||||
return topology.GetSurfaceElementFace (selnr);
|
||||
return topology.GetFace(sei);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -1605,7 +1606,10 @@ void Ng_GetEdge_Vertices (int ednr, int * vert)
|
||||
{
|
||||
const MeshTopology & topology = mesh->GetTopology();
|
||||
// topology.GetEdgeVertices (ednr, vert[0], vert[1]);
|
||||
tie(vert[0], vert[1]) = topology.GetEdgeVertices(ednr-1);
|
||||
// tie(vert[0], vert[1]) = topology.GetEdgeVertices(ednr-1);
|
||||
auto [v1,v2] = topology.GetEdgeVertices(ednr-1);
|
||||
vert[0] = v1-IndexBASE<PointIndex>()+1;
|
||||
vert[1] = v2-IndexBASE<PointIndex>()+1;
|
||||
}
|
||||
|
||||
|
||||
@ -1736,8 +1740,8 @@ void Ng_GetParentNodes (int ni, int * parents)
|
||||
{
|
||||
if (ni <= mesh->mlbetweennodes.Size())
|
||||
{
|
||||
parents[0] = mesh->mlbetweennodes.Get(ni).I1();
|
||||
parents[1] = mesh->mlbetweennodes.Get(ni).I2();
|
||||
parents[0] = mesh->mlbetweennodes[ni].I1();
|
||||
parents[1] = mesh->mlbetweennodes[ni].I2();
|
||||
}
|
||||
else
|
||||
parents[0] = parents[1] = 0;
|
||||
@ -1749,12 +1753,12 @@ int Ng_GetParentElement (int ei)
|
||||
if (mesh->GetDimension() == 3)
|
||||
{
|
||||
if (ei <= mesh->mlparentelement.Size())
|
||||
return mesh->mlparentelement.Get(ei);
|
||||
return mesh->mlparentelement[ei-1]+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ei <= mesh->mlparentsurfaceelement.Size())
|
||||
return mesh->mlparentsurfaceelement.Get(ei);
|
||||
return mesh->mlparentsurfaceelement[ei-1]+1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1765,7 +1769,7 @@ int Ng_GetParentSElement (int ei)
|
||||
if (mesh->GetDimension() == 3)
|
||||
{
|
||||
if (ei <= mesh->mlparentsurfaceelement.Size())
|
||||
return mesh->mlparentsurfaceelement.Get(ei);
|
||||
return mesh->mlparentsurfaceelement[ei-1]+1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1827,7 +1831,7 @@ void Ng_GetPeriodicVertices (int idnr, int * pairs)
|
||||
|
||||
int Ng_GetNPeriodicEdges (int idnr)
|
||||
{
|
||||
NgArray<int,PointIndex::BASE> map;
|
||||
idmap_type map;
|
||||
//const MeshTopology & top = mesh->GetTopology();
|
||||
int nse = mesh->GetNSeg();
|
||||
|
||||
@ -1854,7 +1858,7 @@ int Ng_GetNPeriodicEdges (int idnr)
|
||||
|
||||
void Ng_GetPeriodicEdges (int idnr, int * pairs)
|
||||
{
|
||||
NgArray<int,PointIndex::BASE> map;
|
||||
idmap_type map;
|
||||
const MeshTopology & top = mesh->GetTopology();
|
||||
int nse = mesh->GetNSeg();
|
||||
|
||||
@ -1945,8 +1949,10 @@ int Ng_GetVertex_Elements( int vnr, int* elems )
|
||||
}
|
||||
|
||||
///// Added by Roman Stainko ....
|
||||
int Ng_GetVertex_SurfaceElements( int vnr, int* elems )
|
||||
int Ng_GetVertex_SurfaceElements( int vnr_, int* elems )
|
||||
{
|
||||
PointIndex vnr = vnr_ + IndexBASE<PointIndex>()-1;
|
||||
|
||||
switch (mesh->GetDimension())
|
||||
{
|
||||
case 3:
|
||||
@ -1994,8 +2000,9 @@ int Ng_GetVertex_NElements( int vnr )
|
||||
}
|
||||
|
||||
///// Added by Roman Stainko ....
|
||||
int Ng_GetVertex_NSurfaceElements( int vnr )
|
||||
int Ng_GetVertex_NSurfaceElements( int vnr_ )
|
||||
{
|
||||
PointIndex vnr = vnr_ + IndexBASE<PointIndex>()-1;
|
||||
switch (mesh->GetDimension())
|
||||
{
|
||||
case 3:
|
||||
@ -2240,17 +2247,14 @@ int Ng_GetClosureNodes (int nt, int nodenr, int nodeset, int * nodes)
|
||||
for (int i = 0; i < el.GetNP(); i++)
|
||||
{
|
||||
nodes[cnt++] = 0;
|
||||
nodes[cnt++] = el[i] - PointIndex::BASE;
|
||||
nodes[cnt++] = el[i] - IndexBASE<PointIndex>();
|
||||
}
|
||||
}
|
||||
|
||||
if (nodeset & 2) // Edges
|
||||
{
|
||||
int edges[12];
|
||||
// int ned;
|
||||
// ned = mesh->GetTopology().GetElementEdges (nodenr+1, edges, 0);
|
||||
int ned = mesh->GetTopology().GetEdges (ElementIndex(nodenr)).Size();
|
||||
for (int i = 0; i < ned; i++)
|
||||
auto edges = mesh->GetTopology().GetEdges (ElementIndex(nodenr));
|
||||
for (int i = 0; i < edges.Size(); i++)
|
||||
{
|
||||
nodes[cnt++] = 1;
|
||||
nodes[cnt++] = edges[i]-1;
|
||||
@ -2325,7 +2329,7 @@ int Ng_GetElementClosureNodes (int dim, int elementnr, int nodeset, int * nodes)
|
||||
for (int i = 0; i < el.GetNP(); i++)
|
||||
{
|
||||
nodes[cnt++] = 0;
|
||||
nodes[cnt++] = el[i] - PointIndex::BASE;
|
||||
nodes[cnt++] = el[i] - IndexBASE<PointIndex>();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2343,7 +2347,7 @@ int Ng_GetElementClosureNodes (int dim, int elementnr, int nodeset, int * nodes)
|
||||
|
||||
if (nodeset & 4) // Faces
|
||||
{
|
||||
int face = mesh->GetTopology().GetSurfaceElementFace (elementnr+1);
|
||||
int face = mesh->GetTopology().GetFace (SurfaceElementIndex(elementnr))+1;
|
||||
nodes[cnt++] = 2;
|
||||
nodes[cnt++] = face-1;
|
||||
}
|
||||
|
@ -725,34 +725,32 @@ namespace netgen
|
||||
|
||||
int Ngx_Mesh :: GetParentElement (int ei) const
|
||||
{
|
||||
ei++;
|
||||
if (mesh->GetDimension() == 3)
|
||||
if (mesh->GetDimension() == 3)
|
||||
{
|
||||
if (ei <= mesh->mlparentelement.Size())
|
||||
return mesh->mlparentelement.Get(ei)-1;
|
||||
if (ei < mesh->mlparentelement.Size())
|
||||
return mesh->mlparentelement[ei];
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
if (ei <= mesh->mlparentsurfaceelement.Size())
|
||||
return mesh->mlparentsurfaceelement.Get(ei)-1;
|
||||
if (ei < mesh->mlparentsurfaceelement.Size())
|
||||
return mesh->mlparentsurfaceelement[ei];
|
||||
}
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int Ngx_Mesh :: GetParentSElement (int ei) const
|
||||
{
|
||||
ei++;
|
||||
if (mesh->GetDimension() == 3)
|
||||
if (mesh->GetDimension() == 3)
|
||||
{
|
||||
if (ei <= mesh->mlparentsurfaceelement.Size())
|
||||
return mesh->mlparentsurfaceelement.Get(ei)-1;
|
||||
if (ei < mesh->mlparentsurfaceelement.Size())
|
||||
return mesh->mlparentsurfaceelement[ei];
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int Ngx_Mesh :: GetNIdentifications () const
|
||||
@ -1013,68 +1011,28 @@ namespace netgen
|
||||
int * const indices, int numind) const
|
||||
|
||||
{
|
||||
switch (mesh->GetDimension())
|
||||
Point<3> p(hp[0], 0., 0.);
|
||||
if(mesh->GetDimension() > 1)
|
||||
p[1] = hp[1];
|
||||
if(mesh->GetDimension() == 3)
|
||||
p[2] = hp[2];
|
||||
|
||||
for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
Point<3> p(hp[0], 0,0);
|
||||
for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
|
||||
{
|
||||
auto & seg = (*mesh)[si];
|
||||
Point<3> p1 = (*mesh)[seg[0]];
|
||||
Point<3> p2 = (*mesh)[seg[1]];
|
||||
double lam = (p(0)-p1(0)) / (p2(0)-p1(0));
|
||||
if (lam >= -1e-10 && lam <= 1+1e-10)
|
||||
{
|
||||
lami[0] = 1-lam;
|
||||
return si;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
Point<3> p(hp[0], hp[1],0);
|
||||
try
|
||||
{
|
||||
auto ind = mesh->GetSurfaceElementOfPoint(p, lami, nullptr,
|
||||
build_searchtree);
|
||||
return ind - 1;
|
||||
}
|
||||
catch(NgException e) // quads not implemented curved yet
|
||||
{
|
||||
for (SegmentIndex si = 0; si < mesh->GetNSeg(); si++)
|
||||
{
|
||||
auto & seg = (*mesh)[si];
|
||||
Point<3> p1 = (*mesh)[seg[0]];
|
||||
Point<3> p2 = (*mesh)[seg[1]];
|
||||
double lam;
|
||||
double r;
|
||||
if (fabs(p2[0]-p1[0]) >= fabs(p2[1]-p1[1]))
|
||||
{
|
||||
lam = (p[0]-p1[0])/(p2[0]-p1[0]);
|
||||
r = p[1] - p1[1] - lam*(p2[1]-p1[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
lam = (p[1]-p1[1])/(p2[1]-p1[1]);
|
||||
r = p[0] - p1[0] - lam*(p2[0]-p1[0]);
|
||||
}
|
||||
if ( lam >= -1e-10 && lam <= 1+1e-10 && fabs(r) <= 1e-10 )
|
||||
{
|
||||
lami[0] = 1-lam;
|
||||
return si;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
default:
|
||||
throw Exception("FindElementOfPoint<1> only implemented for mesh-dimension 1 and 2!");
|
||||
break;
|
||||
auto & seg = (*mesh)[si];
|
||||
Point<3> p1 = (*mesh)[seg[0]];
|
||||
Point<3> p2 = (*mesh)[seg[1]];
|
||||
Vec<3> v1 = p2-p1;
|
||||
Vec<3> v2 = p-p1;
|
||||
double lam = v1*v2 / v1.Length2();
|
||||
double lam2 = (v2 - lam * v1).Length() / v1.Length();
|
||||
|
||||
if (lam >= -1e-10 && lam <= 1+1e-10 && lam2 < 1e-10)
|
||||
{
|
||||
lami[0] = 1-lam;
|
||||
return si;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -1085,37 +1043,26 @@ namespace netgen
|
||||
int * const indices, int numind) const
|
||||
|
||||
{
|
||||
NgArray<int> dummy(numind);
|
||||
for (int i = 0; i < numind; i++) dummy[i] = indices[i]+1;
|
||||
|
||||
Point<3> pp(p[0], p[1], 0.);
|
||||
if(mesh->GetDimension() == 3)
|
||||
pp[2] = p[2];
|
||||
FlatArray<int> ind(numind, indices);
|
||||
double lam3[3];
|
||||
int ind;
|
||||
|
||||
if (mesh->GetDimension() == 2)
|
||||
auto elnr = mesh->GetSurfaceElementOfPoint(pp, lam3, ind, build_searchtree);
|
||||
if(elnr.IsValid())
|
||||
{
|
||||
Point<3> p2d(p[0], p[1], 0);
|
||||
ind = mesh->GetElementOfPoint(p2d, lam3, &dummy, build_searchtree);
|
||||
}
|
||||
else
|
||||
{
|
||||
Point3d p3d(p[0], p[1], p[2]);
|
||||
ind = mesh->GetSurfaceElementOfPoint(p3d, lam3, &dummy, build_searchtree);
|
||||
}
|
||||
|
||||
if (ind > 0)
|
||||
{
|
||||
if(mesh->SurfaceElement(ind).GetType()==QUAD || mesh->SurfaceElement(ind).GetType()==TRIG6)
|
||||
if((*mesh)[elnr].GetType() == QUAD || (*mesh)[elnr].GetType() == TRIG6)
|
||||
{
|
||||
lami[0] = lam3[0];
|
||||
lami[1] = lam3[1];
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
lami[0] = 1-lam3[0]-lam3[1];
|
||||
lami[1] = lam3[0];
|
||||
}
|
||||
}
|
||||
return ind-1;
|
||||
return elnr;
|
||||
}
|
||||
|
||||
|
||||
@ -1126,13 +1073,9 @@ namespace netgen
|
||||
int * const indices, int numind) const
|
||||
|
||||
{
|
||||
NgArray<int> dummy(numind);
|
||||
for (int i = 0; i < numind; i++) dummy[i] = indices[i]+1;
|
||||
|
||||
Point<3> p3d(p[0], p[1], p[2]);
|
||||
int ind =
|
||||
mesh->GetElementOfPoint(p3d, lami, &dummy, build_searchtree);
|
||||
return ind-1;
|
||||
Point<3> pp(p[0], p[1], p[2]);
|
||||
FlatArray<int> ind(numind, indices);
|
||||
return mesh->GetElementOfPoint(pp, lami, ind, build_searchtree);
|
||||
}
|
||||
|
||||
void Ngx_Mesh :: Curve (int order)
|
||||
@ -1249,9 +1192,15 @@ int Ngx_Mesh::GetElementOrder (int enr) const
|
||||
void Ngx_Mesh::GetElementOrders (int enr, int * ox, int * oy, int * oz) const
|
||||
{
|
||||
if (mesh->GetDimension() == 3)
|
||||
mesh->VolumeElement(enr).GetOrder(*ox, *oy, *oz);
|
||||
{
|
||||
ElementIndex ei = IndexBASE<ElementIndex>() + enr-1;
|
||||
mesh->VolumeElement(ei).GetOrder(*ox, *oy, *oz);
|
||||
}
|
||||
else
|
||||
mesh->SurfaceElement(enr).GetOrder(*ox, *oy, *oz);
|
||||
{
|
||||
SurfaceElementIndex sei = IndexBASE<SurfaceElementIndex>() + enr-1;
|
||||
mesh->SurfaceElement(sei).GetOrder(*ox, *oy, *oz);
|
||||
}
|
||||
}
|
||||
|
||||
void Ngx_Mesh::SetElementOrder (int enr, int order)
|
||||
@ -1297,6 +1246,36 @@ int Ngx_Mesh::GetClusterRepElement (int pi) const
|
||||
}
|
||||
|
||||
|
||||
int Ngx_Mesh::GetElement_Faces (int elnr, int * faces, int * orient) const
|
||||
{
|
||||
const MeshTopology & topology = mesh->GetTopology();
|
||||
if (mesh->GetDimension() == 3)
|
||||
{
|
||||
int num = topology.GetElementFaces (elnr+1, faces, orient);
|
||||
for (int i = 0; i < num; i++)
|
||||
faces[i]--;
|
||||
return num;
|
||||
}
|
||||
else
|
||||
{
|
||||
faces[0] = elnr;
|
||||
if (orient) orient[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
int Ngx_Mesh::GetSurfaceElement_Face (int selnr, int * orient) const
|
||||
{
|
||||
if (mesh->GetDimension() == 3)
|
||||
{
|
||||
const MeshTopology & topology = mesh->GetTopology();
|
||||
if (orient)
|
||||
*orient = topology.GetSurfaceElementFaceOrientation (selnr+1);
|
||||
return topology.GetFace (SurfaceElementIndex(selnr));
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//HERBERT: falsche Anzahl von Argumenten
|
||||
|
@ -301,7 +301,7 @@ namespace netgen
|
||||
in >> name;
|
||||
cout << IM(3) << len << " element are in group " << name << endl;
|
||||
int hi, index;
|
||||
int fdnr, ednr;
|
||||
int fdnr=-1, ednr=-1;
|
||||
|
||||
in >> hi >> index >> hi >> hi;
|
||||
int codim = get<1>(element_map[index]);
|
||||
@ -712,7 +712,7 @@ namespace netgen
|
||||
if(!UserFormatRegister::HaveFormat(format))
|
||||
throw Exception("Unknown format: " + format);
|
||||
|
||||
const auto & entry = UserFormatRegister::Get(format);
|
||||
const auto entry = UserFormatRegister::Get(format);
|
||||
if(!entry.read)
|
||||
throw Exception("Reading format " + format + " is not implemented");
|
||||
|
||||
|
@ -53,8 +53,8 @@ void ReadMeditFormat (Mesh & mesh, const filesystem::path & filename, map<tuple<
|
||||
for([[maybe_unused]] auto k : Range(nvert)) {
|
||||
for(auto i : Range(dim))
|
||||
fin >> p[i];
|
||||
fin >> index;
|
||||
mesh.AddPoint(p);
|
||||
fin >> index;
|
||||
mesh.AddPoint(p);
|
||||
}
|
||||
}
|
||||
else if(token == "Edges") {
|
||||
@ -64,10 +64,10 @@ void ReadMeditFormat (Mesh & mesh, const filesystem::path & filename, map<tuple<
|
||||
for([[maybe_unused]] auto k : Range(nedge)) {
|
||||
for(auto i : Range(2))
|
||||
fin >> seg[i];
|
||||
fin >> seg.edgenr;
|
||||
seg.edgenr = getIndex(1, seg.edgenr);
|
||||
seg.si = seg.edgenr;
|
||||
mesh.AddSegment(seg);
|
||||
fin >> seg.edgenr;
|
||||
seg.edgenr = getIndex(1, seg.edgenr);
|
||||
seg.si = seg.edgenr;
|
||||
mesh.AddSegment(seg);
|
||||
}
|
||||
}
|
||||
else if(token == "Triangles") {
|
||||
@ -77,9 +77,9 @@ void ReadMeditFormat (Mesh & mesh, const filesystem::path & filename, map<tuple<
|
||||
for([[maybe_unused]] auto k : Range(ntrig)) {
|
||||
for(auto i : Range(3))
|
||||
fin >> sel[i];
|
||||
fin >> index;
|
||||
sel.SetIndex(getIndex(2, index));
|
||||
mesh.AddSurfaceElement(sel);
|
||||
fin >> index;
|
||||
sel.SetIndex(getIndex(2, index));
|
||||
mesh.AddSurfaceElement(sel);
|
||||
}
|
||||
}
|
||||
else if(token == "Tetrahedra") {
|
||||
@ -89,10 +89,10 @@ void ReadMeditFormat (Mesh & mesh, const filesystem::path & filename, map<tuple<
|
||||
for([[maybe_unused]] auto k : Range(ntet)) {
|
||||
for(auto i : Range(4))
|
||||
fin >> el[i];
|
||||
fin >> index;
|
||||
el.SetIndex(getIndex(3, index));
|
||||
el.Invert();
|
||||
mesh.AddVolumeElement(el);
|
||||
fin >> index;
|
||||
el.SetIndex(getIndex(3, index));
|
||||
el.Invert();
|
||||
mesh.AddVolumeElement(el);
|
||||
}
|
||||
}
|
||||
else if(token == "Corners") {
|
||||
|
@ -215,7 +215,8 @@ namespace netgen
|
||||
// Check if the face is a surface element (boundary face)
|
||||
// if not, add the current volume element and the corresponding face into
|
||||
// the owner list
|
||||
int surfelem = meshtopo.GetFace2SurfaceElement(absfacenr);
|
||||
// int surfelem = meshtopo.GetFace2SurfaceElement1(absfacenr);
|
||||
int surfelem = meshtopo.GetFace2SurfaceElement(absfacenr-1)+1;
|
||||
if(!surfelem)
|
||||
{
|
||||
// If it is a new face which has not been listed before,
|
||||
@ -606,7 +607,7 @@ namespace netgen
|
||||
const_cast<Mesh&> (mesh).Compress();
|
||||
const_cast<Mesh&> (mesh).CalcSurfacesOfNode();
|
||||
const_cast<Mesh&> (mesh).RebuildSurfaceElementLists();
|
||||
const_cast<Mesh&> (mesh).BuildElementSearchTree();
|
||||
const_cast<Mesh&> (mesh).BuildElementSearchTree(3);
|
||||
|
||||
|
||||
int np = mesh.GetNP();
|
||||
|
@ -15,15 +15,103 @@
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
using std::vector;
|
||||
|
||||
struct AbaqusElementType
|
||||
{
|
||||
const char * name;
|
||||
const vector<int> permutation;
|
||||
|
||||
AbaqusElementType(const char * name, const vector<int> & permutation)
|
||||
: name(name), permutation(permutation)
|
||||
{}
|
||||
};
|
||||
|
||||
static inline const AbaqusElementType & GetAbaqusType(int dim, int num_nodes)
|
||||
{
|
||||
// maps num_nodes to AbaqusElementType for each dimension
|
||||
typedef std::map<int, AbaqusElementType> AbaqusElementTypes;
|
||||
static const std::map<int, AbaqusElementType> abaqus_eltypes[3] =
|
||||
{
|
||||
// 1D
|
||||
AbaqusElementTypes{
|
||||
{2, AbaqusElementType{"T2D2", vector{0,1}}},
|
||||
},
|
||||
// 2D
|
||||
AbaqusElementTypes{
|
||||
{3, AbaqusElementType{"CPS3", vector{0,1,2}}},
|
||||
},
|
||||
// 3D
|
||||
AbaqusElementTypes{
|
||||
{4, AbaqusElementType{"C3D4", vector{0,1,3,2}}},
|
||||
{10, AbaqusElementType{"C3D10", vector{0,1,3,2,4,8,6,5,7,9}}},
|
||||
}
|
||||
};
|
||||
|
||||
const auto & eltypes = abaqus_eltypes[dim-1];
|
||||
if (eltypes.count(num_nodes) > 0)
|
||||
return eltypes.at(num_nodes);
|
||||
else
|
||||
throw Exception("unsupported " + ToString(dim)+"d Element type with " + ToString(num_nodes) + " nodes");
|
||||
}
|
||||
|
||||
static void WritePoints ( const Mesh & mesh, ostream & out )
|
||||
{
|
||||
out << "*Node" << endl;
|
||||
for(auto pi : mesh.Points().Range() )
|
||||
{
|
||||
out << pi+1-IndexBASE<PointIndex>() << ", ";
|
||||
auto p = mesh[pi];
|
||||
out << p[0] << ", " << p[1] << ", " << p[2] << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
template <typename ElIndex>
|
||||
static void WriteElement(ostream & out, const Mesh& mesh, ElIndex ei, const vector<int> & permutation, int & el_counter)
|
||||
{
|
||||
el_counter++;
|
||||
auto el = mesh[ei];
|
||||
out << el_counter;
|
||||
for(auto i : Range(el.PNums()))
|
||||
out << ", " << el[permutation[i]]+1-IndexBASE<PointIndex>();
|
||||
out << '\n';
|
||||
}
|
||||
|
||||
template <typename ElIndex, typename Elements>
|
||||
static void WriteElements ( ostream & out, const Mesh & mesh, int dim, const Elements & el_range, int & el_counter)
|
||||
{
|
||||
// map index, num_nodes to elements
|
||||
std::map<std::tuple<int, int>, Array<ElIndex>> elset_map;
|
||||
|
||||
for(auto ei : el_range)
|
||||
{
|
||||
const auto & el = mesh[ei];
|
||||
int index = 0;
|
||||
if constexpr(std::is_same_v<ElIndex,SegmentIndex>)
|
||||
index = el.edgenr;
|
||||
else
|
||||
index = el.GetIndex();
|
||||
elset_map[{index, el.GetNP()}].Append(ei);
|
||||
}
|
||||
|
||||
for(auto & [key, elems] : elset_map)
|
||||
{
|
||||
auto [index, num_nodes] = key;
|
||||
auto name = mesh.GetRegionName(elems[0]);
|
||||
if (name == "") name = "default";
|
||||
PrintMessage (5, index, ": ", name);
|
||||
const auto & eltype = GetAbaqusType(dim, num_nodes) ;
|
||||
out << "*Element, type=" << eltype.name << ", ELSET=" << name << endl;
|
||||
for(auto ei : elems)
|
||||
WriteElement(out, mesh, ei, eltype.permutation, el_counter);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteAbaqusFormat (const Mesh & mesh,
|
||||
const filesystem::path & filename)
|
||||
|
||||
{
|
||||
|
||||
cout << "\nWrite Abaqus Volume Mesh" << endl;
|
||||
PrintMessage (1, "Write Abaqus Mesh");
|
||||
|
||||
ofstream outfile (filename);
|
||||
|
||||
@ -32,96 +120,17 @@ void WriteAbaqusFormat (const Mesh & mesh,
|
||||
|
||||
outfile.precision(8);
|
||||
|
||||
outfile << "*Node" << endl;
|
||||
|
||||
int np = mesh.GetNP();
|
||||
int ne = mesh.GetNE();
|
||||
int i, j, k;
|
||||
|
||||
for (i = 1; i <= np; i++)
|
||||
{
|
||||
outfile << i << ", ";
|
||||
outfile << mesh.Point(i)(0) << ", ";
|
||||
outfile << mesh.Point(i)(1) << ", ";
|
||||
outfile << mesh.Point(i)(2) << "\n";
|
||||
}
|
||||
|
||||
int elemcnt = 0; //element counter
|
||||
int finished = 0;
|
||||
int indcnt = 1; //index counter
|
||||
|
||||
while (!finished)
|
||||
{
|
||||
int actcnt = 0;
|
||||
const Element & el1 = mesh.VolumeElement(1);
|
||||
int non = el1.GetNP();
|
||||
if (non == 4)
|
||||
{
|
||||
outfile << "*Element, type=C3D4, ELSET=PART" << indcnt << endl;
|
||||
}
|
||||
else if (non == 10)
|
||||
{
|
||||
outfile << "*Element, type=C3D10, ELSET=PART" << indcnt << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "unsupported Element type!!!" << endl;
|
||||
}
|
||||
|
||||
for (i = 1; i <= ne; i++)
|
||||
{
|
||||
const Element & el = mesh.VolumeElement(i);
|
||||
|
||||
if (el.GetIndex() == indcnt)
|
||||
{
|
||||
actcnt++;
|
||||
if (el.GetNP() != non)
|
||||
{
|
||||
cout << "different element-types in a subdomain are not possible!!!" << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
elemcnt++;
|
||||
outfile << elemcnt << ", ";
|
||||
if (non == 4)
|
||||
{
|
||||
outfile << el.PNum(1) << ", ";
|
||||
outfile << el.PNum(2) << ", ";
|
||||
outfile << el.PNum(4) << ", ";
|
||||
outfile << el.PNum(3) << "\n";
|
||||
}
|
||||
else if (non == 10)
|
||||
{
|
||||
outfile << el.PNum(1) << ", ";
|
||||
outfile << el.PNum(2) << ", ";
|
||||
outfile << el.PNum(4) << ", ";
|
||||
outfile << el.PNum(3) << ", ";
|
||||
outfile << el.PNum(5) << ", ";
|
||||
outfile << el.PNum(9) << ", ";
|
||||
outfile << el.PNum(7) << ", " << "\n";
|
||||
outfile << el.PNum(6) << ", ";
|
||||
outfile << el.PNum(8) << ", ";
|
||||
outfile << el.PNum(10) << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << "unsupported Element type!!!" << endl;
|
||||
for (j = 1; j <= el.GetNP(); j++)
|
||||
{
|
||||
outfile << el.PNum(j);
|
||||
if (j != el.GetNP()) outfile << ", ";
|
||||
}
|
||||
outfile << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
indcnt++;
|
||||
if (elemcnt == ne) {finished = 1; cout << "all elements found by Index!" << endl;}
|
||||
if (actcnt == 0) {finished = 1;}
|
||||
}
|
||||
int element_counter = 0;
|
||||
WritePoints(mesh, outfile);
|
||||
if(mesh.GetDimension() < 3)
|
||||
WriteElements<SegmentIndex>(outfile, mesh, 1, mesh.LineSegments().Range(), element_counter);
|
||||
WriteElements<SurfaceElementIndex>(outfile, mesh, 2, mesh.SurfaceElements().Range(), element_counter);
|
||||
WriteElements<ElementIndex>(outfile, mesh, 3, mesh.VolumeElements().Range(), element_counter);
|
||||
|
||||
// Write identifications (untested!)
|
||||
if (mesh.GetIdentifications().GetMaxNr())
|
||||
{
|
||||
const auto np = mesh.GetNP();
|
||||
// periodic identification, implementation for
|
||||
// Helmut J. Boehm, TU Vienna
|
||||
|
||||
@ -138,27 +147,27 @@ void WriteAbaqusFormat (const Mesh & mesh,
|
||||
NgArray<INDEX_2> pairs;
|
||||
NgBitArray master(np), help(np);
|
||||
master.Set();
|
||||
for (i = 1; i <= 3; i++)
|
||||
for (int i = 1; i <= 3; i++)
|
||||
{
|
||||
mesh.GetIdentifications().GetPairs (i, pairs);
|
||||
help.Clear();
|
||||
for (j = 1; j <= pairs.Size(); j++)
|
||||
for (int j = 1; j <= pairs.Size(); j++)
|
||||
{
|
||||
help.Set (pairs.Get(j).I1());
|
||||
}
|
||||
master.And (help);
|
||||
}
|
||||
for (i = 1; i <= np; i++)
|
||||
for (int i = 1; i <= np; i++)
|
||||
if (master.Test(i))
|
||||
masternode = i;
|
||||
|
||||
cout << "masternode = " << masternode << " = "
|
||||
<< mesh.Point(masternode) << endl;
|
||||
NgArray<int> minions(3);
|
||||
for (i = 1; i <= 3; i++)
|
||||
for (int i = 1; i <= 3; i++)
|
||||
{
|
||||
mesh.GetIdentifications().GetPairs (i, pairs);
|
||||
for (j = 1; j <= pairs.Size(); j++)
|
||||
for (int j = 1; j <= pairs.Size(); j++)
|
||||
{
|
||||
if (pairs.Get(j).I1() == masternode)
|
||||
minions.Elem(i) = pairs.Get(j).I2();
|
||||
@ -179,12 +188,12 @@ void WriteAbaqusFormat (const Mesh & mesh,
|
||||
<< "**POINT_fixed\n"
|
||||
<< "**\n"
|
||||
<< "*BOUNDARY, OP=NEW\n";
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
outfile << masternode << ", " << j << ",, 0.\n";
|
||||
|
||||
outfile << "**\n"
|
||||
<< "*BOUNDARY, OP=NEW\n";
|
||||
for (j = 1; j <= 3; j++)
|
||||
for (int j = 1; j <= 3; j++)
|
||||
{
|
||||
Vec3d v(mesh.Point(masternode), mesh.Point(minions.Get(j)));
|
||||
double vlen = v.Length();
|
||||
@ -203,18 +212,18 @@ void WriteAbaqusFormat (const Mesh & mesh,
|
||||
|
||||
NgBitArray eliminated(np);
|
||||
eliminated.Clear();
|
||||
for (i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)
|
||||
for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)
|
||||
{
|
||||
mesh.GetIdentifications().GetPairs (i, pairs);
|
||||
if (!pairs.Size())
|
||||
continue;
|
||||
|
||||
for (j = 1; j <= pairs.Size(); j++)
|
||||
for (int j = 1; j <= pairs.Size(); j++)
|
||||
if (pairs.Get(j).I1() != masternode &&
|
||||
!eliminated.Test(pairs.Get(j).I2()))
|
||||
{
|
||||
eliminated.Set (pairs.Get(j).I2());
|
||||
for (k = 1; k <= 3; k++)
|
||||
for (int k = 1; k <= 3; k++)
|
||||
{
|
||||
mpc << "4" << "\n";
|
||||
mpc << pairs.Get(j).I2() << "," << k << ", -1.0, ";
|
||||
@ -227,7 +236,7 @@ void WriteAbaqusFormat (const Mesh & mesh,
|
||||
}
|
||||
|
||||
|
||||
cout << "done" << endl;
|
||||
PrintMessage(1, "done");
|
||||
}
|
||||
|
||||
static RegisterUserFormat reg_abaqus ("Abaqus Format", {".mesh"}, nullopt, WriteAbaqusFormat);
|
||||
|
@ -40,7 +40,7 @@ void WriteDiffPackFormat (const Mesh & mesh,
|
||||
int nse = mesh.GetNSE();
|
||||
NgArray <int> BIname;
|
||||
NgArray <int> BCsinpoint;
|
||||
int i, j, k, l;
|
||||
// int i, j, k, l;
|
||||
|
||||
|
||||
outfile.precision(6);
|
||||
@ -58,18 +58,18 @@ void WriteDiffPackFormat (const Mesh & mesh,
|
||||
" Only one subdomain : dpFALSE\n"
|
||||
" Lattice data ? 0\n\n\n\n";
|
||||
|
||||
for (i = 1; i <= nse; i++)
|
||||
for (int i = 1; i <= nse; i++)
|
||||
{
|
||||
int BI=mesh.GetFaceDescriptor(mesh.SurfaceElement(i).GetIndex()).BCProperty();
|
||||
int nbi=BIname.Size();
|
||||
int found=0;
|
||||
for (j = 1; j <= nbi; j++)
|
||||
for (int j = 1; j <= nbi; j++)
|
||||
if(BI == BIname.Get(j)) found = 1;
|
||||
if( ! found ) BIname.Append(BI);
|
||||
}
|
||||
|
||||
outfile << " " << BIname.Size() << " Boundary indicators: ";
|
||||
for (i =1 ; i <= BIname.Size(); i++)
|
||||
for (int i =1 ; i <= BIname.Size(); i++)
|
||||
outfile << BIname.Get(i) << " ";
|
||||
outfile << "\n\n\n";
|
||||
|
||||
@ -92,7 +92,8 @@ void WriteDiffPackFormat (const Mesh & mesh,
|
||||
}
|
||||
|
||||
|
||||
for (i = 1; i <= np; i++)
|
||||
// for (int i = 1; i <= np; i++)
|
||||
for (PointIndex i : mesh.Points().Range())
|
||||
{
|
||||
const Point3d & p = mesh.Point(i);
|
||||
|
||||
@ -114,14 +115,14 @@ void WriteDiffPackFormat (const Mesh & mesh,
|
||||
NgFlatArray<SurfaceElementIndex> sels = point2sel[i];
|
||||
for (int jj = 0; jj < sels.Size(); jj++)
|
||||
{
|
||||
for (k = 1; k <= mesh[sels[jj]].GetNP(); k++)
|
||||
for (int k = 1; k <= mesh[sels[jj]].GetNP(); k++)
|
||||
{
|
||||
if(mesh[sels[jj]].PNum(k)==i)
|
||||
{
|
||||
int BC=mesh.GetFaceDescriptor(mesh[sels[jj]].GetIndex()).BCProperty();
|
||||
int nbcsp=BCsinpoint.Size();
|
||||
int found = 0;
|
||||
for (l = 1; l <= nbcsp; l++)
|
||||
for (int l = 1; l <= nbcsp; l++)
|
||||
if(BC == BCsinpoint.Get(l)) found = 1;
|
||||
if( ! found ) BCsinpoint.Append(BC);
|
||||
}
|
||||
@ -129,7 +130,7 @@ void WriteDiffPackFormat (const Mesh & mesh,
|
||||
}
|
||||
int nbcsp = BCsinpoint.Size();
|
||||
outfile << "[" << nbcsp << "] ";
|
||||
for (j = 1; j <= nbcsp; j++)
|
||||
for (int j = 1; j <= nbcsp; j++)
|
||||
outfile << BCsinpoint.Get(j) << " ";
|
||||
outfile << "\n";
|
||||
}
|
||||
@ -146,7 +147,7 @@ void WriteDiffPackFormat (const Mesh & mesh,
|
||||
" - the global node numbers of the nodes in the element.\n"
|
||||
"#\n";
|
||||
|
||||
for (i = 1; i <= ne; i++)
|
||||
for (int i = 1; i <= ne; i++)
|
||||
{
|
||||
const Element & el = mesh.VolumeElement(i);
|
||||
outfile.width(5);
|
||||
@ -244,7 +245,8 @@ void WriteDiffPackFormat (const Mesh & mesh,
|
||||
" - the boundary indicators that are set (ON) if any.\n"
|
||||
"#\n";
|
||||
|
||||
for (i = 1; i <= np; i++)
|
||||
// for (i = 1; i <= np; i++)
|
||||
for (PointIndex i : mesh.Points().Range())
|
||||
{
|
||||
const Point3d & p = mesh.Point(i);
|
||||
|
||||
|
@ -66,7 +66,7 @@ void WriteFluentFormat (const Mesh & mesh,
|
||||
int i2, j2;
|
||||
NgArray<INDEX_3> surfaceelp;
|
||||
NgArray<int> surfaceeli;
|
||||
NgArray<int> locels;
|
||||
Array<ElementIndex> locels;
|
||||
|
||||
//no cells=no tets
|
||||
//no faces=2*tets
|
||||
@ -79,7 +79,7 @@ void WriteFluentFormat (const Mesh & mesh,
|
||||
snprintf (str, size(str), "(13 (4 1 %x 2 3)(",noverbface); //hexadecimal!!!
|
||||
outfile << str << endl;
|
||||
|
||||
const_cast<Mesh&> (mesh).BuildElementSearchTree();
|
||||
const_cast<Mesh&> (mesh).BuildElementSearchTree(3);
|
||||
|
||||
for (i = 1; i <= ne; i++)
|
||||
{
|
||||
@ -117,12 +117,9 @@ void WriteFluentFormat (const Mesh & mesh,
|
||||
int eli2 = 0;
|
||||
int stopsig = 0;
|
||||
|
||||
for (i2 = 1; i2 <= nel; i2++)
|
||||
for (auto locind : locels)
|
||||
{
|
||||
locind = locels.Get(i2);
|
||||
//cout << " locind=" << locind << endl;
|
||||
|
||||
Element el2 = mesh.VolumeElement(locind);
|
||||
Element el2 = mesh[locind];
|
||||
//if (inverttets)
|
||||
// el2.Invert();
|
||||
|
||||
@ -130,7 +127,7 @@ void WriteFluentFormat (const Mesh & mesh,
|
||||
{
|
||||
el2.GetFace(j2, face2);
|
||||
|
||||
if (face2.HasFace(face)) {eli2 = locind; stopsig = 1; break;}
|
||||
if (face2.HasFace(face)) {eli2 = locind+1; stopsig = 1; break;}
|
||||
}
|
||||
if (stopsig) break;
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ namespace netgen
|
||||
int np = mesh.GetNP(); /// number of points in mesh
|
||||
int ne = mesh.GetNE(); /// number of 3D elements in mesh
|
||||
int nse = mesh.GetNSE(); /// number of surface elements (BC)
|
||||
int i, j, k, l;
|
||||
// int i, j, k, l;
|
||||
|
||||
|
||||
/*
|
||||
@ -66,8 +66,8 @@ namespace netgen
|
||||
*/
|
||||
|
||||
if ((ne > 0)
|
||||
&& (mesh.VolumeElement(1).GetNP() <= 10)
|
||||
&& (mesh.SurfaceElement(1).GetNP() <= 6))
|
||||
&& (mesh.VolumeElements().First().GetNP() <= 10)
|
||||
&& (mesh.SurfaceElements().First().GetNP() <= 6))
|
||||
{
|
||||
cout << "Write GMSH v2.xx Format \n";
|
||||
cout << "The GMSH v2.xx export is currently available for elements upto 2nd Order\n" << endl;
|
||||
@ -86,7 +86,7 @@ namespace netgen
|
||||
outfile << "$Nodes\n";
|
||||
outfile << np << "\n";
|
||||
|
||||
for (i = 1; i <= np; i++)
|
||||
for (int i = 1; i <= np; i++)
|
||||
{
|
||||
const Point3d & p = mesh.Point(i);
|
||||
outfile << i << " "; /// node number
|
||||
@ -101,13 +101,13 @@ namespace netgen
|
||||
outfile << "$Elements\n";
|
||||
outfile << ne + nse << "\n"; //// number of elements + number of surfaces BC
|
||||
|
||||
for (i = 1; i <= nse; i++)
|
||||
for (auto sei : Range(mesh.SurfaceElements()))
|
||||
{
|
||||
int elType = 0;
|
||||
|
||||
Element2d el = mesh.SurfaceElement(i);
|
||||
Element2d el = mesh[sei]; // .SurfaceElement(i);
|
||||
if(invertsurf) el.Invert();
|
||||
|
||||
|
||||
if(el.GetNP() == 3) elType = GMSH_TRIG; //// GMSH Type for a 3 node triangle
|
||||
if(el.GetNP() == 6) elType = GMSH_TRIG6; //// GMSH Type for a 6 node triangle
|
||||
if(elType == 0)
|
||||
@ -116,7 +116,7 @@ namespace netgen
|
||||
return;
|
||||
}
|
||||
|
||||
outfile << i;
|
||||
outfile << sei-IndexBASE(sei)+1;
|
||||
outfile << " ";
|
||||
outfile << elType;
|
||||
outfile << " ";
|
||||
@ -125,7 +125,7 @@ namespace netgen
|
||||
outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " ";
|
||||
/// that means that physical entity = elementary entity (arbitrary approach)
|
||||
outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " ";
|
||||
for (j = 1; j <= el.GetNP(); j++)
|
||||
for (int j = 1; j <= el.GetNP(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile << el.PNum(triGmsh[j]);
|
||||
@ -133,12 +133,12 @@ namespace netgen
|
||||
outfile << "\n";
|
||||
}
|
||||
|
||||
|
||||
for (i = 1; i <= ne; i++)
|
||||
for (ElementIndex ei : Range(mesh.VolumeElements()))
|
||||
{
|
||||
int i = ei-IndexBASE(ei)+1;
|
||||
int elType = 0;
|
||||
|
||||
Element el = mesh.VolumeElement(i);
|
||||
Element el = mesh[ei];
|
||||
if (inverttets) el.Invert();
|
||||
|
||||
if(el.GetNP() == 4) elType = GMSH_TET; //// GMSH Element type for 4 node tetrahedron
|
||||
@ -160,7 +160,7 @@ namespace netgen
|
||||
outfile << " ";
|
||||
outfile << 100000 + el.GetIndex(); /// volume number
|
||||
outfile << " ";
|
||||
for (j = 1; j <= el.GetNP(); j++)
|
||||
for (int j = 1; j <= el.GetNP(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile << el.PNum(tetGmsh[j]);
|
||||
@ -193,7 +193,7 @@ namespace netgen
|
||||
outfile << "$Nodes\n";
|
||||
outfile << np << "\n";
|
||||
|
||||
for (i = 1; i <= np; i++)
|
||||
for (int i = 1; i <= np; i++)
|
||||
{
|
||||
const Point3d & p = mesh.Point(i);
|
||||
outfile << i << " "; /// node number
|
||||
@ -207,7 +207,7 @@ namespace netgen
|
||||
outfile << "$Elements\n";
|
||||
outfile << nse << "\n";
|
||||
|
||||
for (k = 1; k <= nse; k++)
|
||||
for (int k = 1; k <= nse; k++)
|
||||
{
|
||||
int elType = 0;
|
||||
|
||||
@ -232,7 +232,7 @@ namespace netgen
|
||||
outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " ";
|
||||
/// that means that physical entity = elementary entity (arbitrary approach)
|
||||
outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " ";
|
||||
for (l = 1; l <= el.GetNP(); l++)
|
||||
for (int l = 1; l <= el.GetNP(); l++)
|
||||
{
|
||||
outfile << " ";
|
||||
if((elType == GMSH_TRIG) || (elType == GMSH_TRIG6))
|
||||
|
@ -33,7 +33,7 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
int np = mesh.GetNP();
|
||||
|
||||
// Identic points
|
||||
NgArray<int,PointIndex::BASE> identmap1, identmap2, identmap3;
|
||||
idmap_type identmap1, identmap2, identmap3;
|
||||
mesh.GetIdentifications().GetMap(1, identmap1);
|
||||
mesh.GetIdentifications().GetMap(2, identmap2);
|
||||
mesh.GetIdentifications().GetMap(3, identmap3);
|
||||
@ -52,19 +52,21 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
for (j = 1; j <= 4; j++)
|
||||
for (jj = 1; jj <=4; jj++)
|
||||
{
|
||||
if (identmap1.Elem(el.PNum(j)) == el.PNum(jj))
|
||||
// if (identmap1.Elem(el.PNum(j)) == el.PNum(jj))
|
||||
if (identmap1[el.PNum(j)] == el.PNum(jj))
|
||||
{
|
||||
cout << "\n Error: two points on a tetrahedron identified (1) with each other"
|
||||
<< "\n REFINE MESH !" << endl;
|
||||
return;
|
||||
}
|
||||
if (identmap2.Elem(el.PNum(j)) == el.PNum(jj))
|
||||
// if (identmap2.Elem(el.PNum(j)) == el.PNum(jj))
|
||||
if (identmap2[el.PNum(j)] == el.PNum(jj))
|
||||
{
|
||||
cout << "\n Error: two points on a tetrahedron identified (2) with each other"
|
||||
<< "\n REFINE MESH !" << endl;
|
||||
return;
|
||||
}
|
||||
if (identmap3.Elem(el.PNum(j)) == el.PNum(jj))
|
||||
if (identmap3[el.PNum(j)] == el.PNum(jj))
|
||||
{
|
||||
cout << "\n Error: two points on a tetrahedron identified (3) with each other"
|
||||
<< "\n REFINE MESH !" << endl;
|
||||
@ -271,6 +273,7 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
int npid1 = 0;
|
||||
int npid2 = 0;
|
||||
int npid3 = 0;
|
||||
/*
|
||||
for (i=1; i<=np; i++)
|
||||
{
|
||||
if (identmap1.Elem(i))
|
||||
@ -280,6 +283,10 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
if (identmap3.Elem(i))
|
||||
npid3++;
|
||||
}
|
||||
*/
|
||||
for (auto pi : identmap1) if (pi.IsValid()) npid1++;
|
||||
for (auto pi : identmap2) if (pi.IsValid()) npid1++;
|
||||
for (auto pi : identmap3) if (pi.IsValid()) npid1++;
|
||||
|
||||
outfile << "\n";
|
||||
outfile << "# Boundary triangles\n";
|
||||
@ -302,31 +309,31 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << "\n";
|
||||
if (mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() == bc_at_infinity)
|
||||
outfile << "-2\n\n";
|
||||
else if (identmap1.Elem(el.PNum(1))
|
||||
&&identmap1.Elem(el.PNum(2))
|
||||
&&identmap1.Elem(el.PNum(3)))
|
||||
else if (identmap1[el.PNum(1)].IsValid()
|
||||
&&identmap1[el.PNum(2)].IsValid()
|
||||
&&identmap1[el.PNum(3)].IsValid())
|
||||
{
|
||||
outfile << "-1\n";
|
||||
for (j = 1; j <= 3; j++)
|
||||
outfile << identmap1.Elem(el.PNum(j))<<"\n";
|
||||
outfile << identmap1[el.PNum(j)]<<"\n";
|
||||
outfile << "\n";
|
||||
}
|
||||
else if (identmap2.Elem(el.PNum(1))
|
||||
&&identmap2.Elem(el.PNum(2))
|
||||
&&identmap2.Elem(el.PNum(3)))
|
||||
else if (identmap2[el.PNum(1)].IsValid()
|
||||
&&identmap2[el.PNum(2)].IsValid()
|
||||
&&identmap2[el.PNum(3)].IsValid())
|
||||
{
|
||||
outfile << "-1\n";
|
||||
for (j = 1; j <= 3; j++)
|
||||
outfile << identmap2.Elem(el.PNum(j))<<"\n";
|
||||
outfile << identmap2[el.PNum(j)]<<"\n";
|
||||
outfile << "\n";
|
||||
}
|
||||
else if (identmap3.Elem(el.PNum(1))
|
||||
&&identmap3.Elem(el.PNum(2))
|
||||
&&identmap3.Elem(el.PNum(3)))
|
||||
else if (identmap3[el.PNum(1)].IsValid()
|
||||
&&identmap3[el.PNum(2)].IsValid()
|
||||
&&identmap3[el.PNum(3)].IsValid())
|
||||
{
|
||||
outfile << "-1\n";
|
||||
for (j = 1; j <= 3; j++)
|
||||
outfile << identmap3.Elem(el.PNum(j))<<"\n";
|
||||
outfile << identmap3[el.PNum(j)]<<"\n";
|
||||
outfile << "\n";
|
||||
}
|
||||
else
|
||||
@ -373,10 +380,10 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
outfile << "-2\n\n";
|
||||
cout << "\nWarning: Quadrilateral at infinity found (this should not occur)!"<<endl;
|
||||
}
|
||||
else if ( identmap1.Elem(el.PNum(1)) &&
|
||||
identmap1.Elem(el.PNum(2)) &&
|
||||
identmap1.Elem(el.PNum(3)) &&
|
||||
identmap1.Elem(el.PNum(4)) )
|
||||
else if ( identmap1[el.PNum(1)].IsValid() &&
|
||||
identmap1[el.PNum(2)].IsValid() &&
|
||||
identmap1[el.PNum(3)].IsValid() &&
|
||||
identmap1[el.PNum(4)].IsValid())
|
||||
{
|
||||
outfile << "-1\n";
|
||||
for (j = 1; j <= 4; j++)
|
||||
@ -384,14 +391,14 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
jj = j + ct;
|
||||
if ( jj >= 5 )
|
||||
jj = jj - 4;
|
||||
outfile << identmap1.Elem(el.PNum(jj))<<"\n";
|
||||
outfile << identmap1[el.PNum(jj)]<<"\n";
|
||||
}
|
||||
outfile << "\n";
|
||||
}
|
||||
else if ( identmap2.Elem(el.PNum(1)) &&
|
||||
identmap2.Elem(el.PNum(2)) &&
|
||||
identmap2.Elem(el.PNum(3)) &&
|
||||
identmap2.Elem(el.PNum(4)) )
|
||||
else if ( identmap2[el.PNum(1)].IsValid() &&
|
||||
identmap2[el.PNum(2)].IsValid() &&
|
||||
identmap2[el.PNum(3)].IsValid() &&
|
||||
identmap2[el.PNum(4)].IsValid() )
|
||||
{
|
||||
outfile << "-1\n";
|
||||
for (j = 1; j <= 4; j++)
|
||||
@ -399,14 +406,14 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
jj = j + ct;
|
||||
if ( jj >= 5 )
|
||||
jj = jj - 4;
|
||||
outfile << identmap2.Elem(el.PNum(jj))<<"\n";
|
||||
outfile << identmap2[el.PNum(jj)] <<"\n";
|
||||
}
|
||||
outfile << "\n";
|
||||
}
|
||||
else if ( identmap3.Elem(el.PNum(1)) &&
|
||||
identmap3.Elem(el.PNum(2)) &&
|
||||
identmap3.Elem(el.PNum(3)) &&
|
||||
identmap3.Elem(el.PNum(4)) )
|
||||
else if ( identmap3[el.PNum(1)].IsValid() &&
|
||||
identmap3[el.PNum(2)].IsValid() &&
|
||||
identmap3[el.PNum(3)].IsValid() &&
|
||||
identmap3[el.PNum(4)].IsValid() )
|
||||
{
|
||||
outfile << "-1\n";
|
||||
for (j = 1; j <= 4; j++)
|
||||
@ -414,7 +421,7 @@ void WriteJCMFormat (const Mesh & mesh,
|
||||
jj = j + ct;
|
||||
if ( jj >= 5 )
|
||||
jj = jj - 4;
|
||||
outfile << identmap3.Elem(el.PNum(jj))<<"\n";
|
||||
outfile << identmap3[el.PNum(jj)]<<"\n";
|
||||
}
|
||||
outfile << "\n";
|
||||
}
|
||||
|
@ -366,12 +366,12 @@ namespace netgen
|
||||
uidpid = "UID";
|
||||
|
||||
|
||||
NgArray< NgArray<int,PointIndex::BASE>* > idmaps;
|
||||
NgArray< idmap_type* > idmaps;
|
||||
for(int i=1; i<=mesh.GetIdentifications().GetMaxNr(); i++)
|
||||
{
|
||||
if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)
|
||||
{
|
||||
idmaps.Append(new NgArray<int,PointIndex::BASE>);
|
||||
idmaps.Append(new idmap_type);
|
||||
mesh.GetIdentifications().GetMap(i,*idmaps.Last(),true);
|
||||
}
|
||||
}
|
||||
@ -502,7 +502,7 @@ namespace netgen
|
||||
<< mesh[i](0) << " "
|
||||
<< mesh[i](1) << " "
|
||||
<< mesh[i](2) << " " << id_type[i] << " ";
|
||||
if(i-PointIndex::BASE < point_ids.Size())
|
||||
if(i-IndexBASE<PointIndex>() < point_ids.Size())
|
||||
outfile << point_ids[i];
|
||||
else
|
||||
outfile << "0";
|
||||
@ -1066,13 +1066,13 @@ namespace netgen
|
||||
// for(PointIndex i = mesh.Points().Begin(); i < mesh.Points().End(); i++)
|
||||
for(PointIndex i : mesh.Points().Range())
|
||||
{
|
||||
if(i-PointIndex::BASE < point_ids.Size())
|
||||
if(i-IndexBASE<PointIndex>() < point_ids.Size())
|
||||
{
|
||||
if(uid_to_group_0D[point_ids[i]] >= 0)
|
||||
groups[uid_to_group_0D[point_ids[i]]]->Append(i+1-PointIndex::BASE);
|
||||
groups[uid_to_group_0D[point_ids[i]]]->Append(i+1-IndexBASE<PointIndex>());
|
||||
}
|
||||
else
|
||||
groups[uid_to_group_0D[0]]->Append(i+1-PointIndex::BASE);
|
||||
groups[uid_to_group_0D[0]]->Append(i+1-IndexBASE<PointIndex>());
|
||||
}
|
||||
|
||||
|
||||
|
@ -39,7 +39,7 @@ bool WriteUserFormat (const string & format,
|
||||
if(!UserFormatRegister::HaveFormat(format))
|
||||
return true;
|
||||
|
||||
const auto & entry = UserFormatRegister::Get(format);
|
||||
const auto entry = UserFormatRegister::Get(format);
|
||||
if(!entry.write)
|
||||
return true;
|
||||
|
||||
@ -62,7 +62,7 @@ void WriteNeutralFormat (const Mesh & mesh,
|
||||
int ne = mesh.GetNE();
|
||||
int nse = mesh.GetNSE();
|
||||
int nseg = mesh.GetNSeg();
|
||||
int i, j;
|
||||
// int i, j;
|
||||
|
||||
int inverttets = mparam.inverttets;
|
||||
int invertsurf = mparam.inverttrigs;
|
||||
@ -75,7 +75,7 @@ void WriteNeutralFormat (const Mesh & mesh,
|
||||
|
||||
outfile << np << "\n";
|
||||
|
||||
for (i = 1; i <= np; i++)
|
||||
for (int i = 1; i <= np; i++)
|
||||
{
|
||||
const Point3d & p = mesh.Point(i);
|
||||
|
||||
@ -94,14 +94,18 @@ void WriteNeutralFormat (const Mesh & mesh,
|
||||
if (mesh.GetDimension() == 3)
|
||||
{
|
||||
outfile << ne << "\n";
|
||||
for (i = 1; i <= ne; i++)
|
||||
/*
|
||||
for (int i = 1; i <= ne; i++)
|
||||
{
|
||||
Element el = mesh.VolumeElement(i);
|
||||
*/
|
||||
for (Element el : mesh.VolumeElements())
|
||||
{
|
||||
if (inverttets)
|
||||
el.Invert();
|
||||
outfile.width(4);
|
||||
outfile << el.GetIndex() << " ";
|
||||
for (j = 1; j <= el.GetNP(); j++)
|
||||
for (int j = 1; j <= el.GetNP(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile.width(8);
|
||||
@ -112,14 +116,18 @@ void WriteNeutralFormat (const Mesh & mesh,
|
||||
}
|
||||
|
||||
outfile << nse << "\n";
|
||||
for (i = 1; i <= nse; i++)
|
||||
/*
|
||||
for (int i = 1; i <= nse; i++)
|
||||
{
|
||||
Element2d el = mesh.SurfaceElement(i);
|
||||
*/
|
||||
for (Element2d el : mesh.SurfaceElements())
|
||||
{
|
||||
if (invertsurf)
|
||||
el.Invert();
|
||||
outfile.width(4);
|
||||
outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " ";
|
||||
for (j = 1; j <= el.GetNP(); j++)
|
||||
for (int j = 1; j <= el.GetNP(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile.width(8);
|
||||
@ -583,9 +591,13 @@ void WriteFEPPFormat (const Mesh & mesh,
|
||||
|
||||
|
||||
outfile << ne << "\n";
|
||||
/*
|
||||
for (i = 1; i <= ne; i++)
|
||||
{
|
||||
const Element & el = mesh.VolumeElement(i);
|
||||
*/
|
||||
for (const Element & el : mesh.VolumeElements())
|
||||
{
|
||||
outfile.width(4);
|
||||
outfile << el.GetIndex() << " ";
|
||||
outfile.width(4);
|
||||
@ -677,7 +689,6 @@ void WriteEdgeElementFormat (const Mesh & mesh,
|
||||
int nelements = mesh.GetNE();
|
||||
int nsurfelem = mesh.GetNSE();
|
||||
int nedges = top->GetNEdges();
|
||||
int i, j;
|
||||
|
||||
int inverttets = mparam.inverttets;
|
||||
int invertsurf = mparam.inverttrigs;
|
||||
@ -692,7 +703,7 @@ void WriteEdgeElementFormat (const Mesh & mesh,
|
||||
|
||||
// vertices with coordinates
|
||||
outfile << npoints << "\n";
|
||||
for (i = 1; i <= npoints; i++)
|
||||
for (int i = 1; i <= npoints; i++)
|
||||
{
|
||||
const Point3d & p = mesh.Point(i);
|
||||
|
||||
@ -706,16 +717,24 @@ void WriteEdgeElementFormat (const Mesh & mesh,
|
||||
|
||||
// element - edge - list
|
||||
outfile << nelements << " " << nedges << "\n";
|
||||
/*
|
||||
for (i = 1; i <= nelements; i++)
|
||||
{
|
||||
Element el = mesh.VolumeElement(i);
|
||||
*/
|
||||
for (ElementIndex ei : Range(mesh.VolumeElements()))
|
||||
{
|
||||
int i = ei-IndexBASE(ei)+1;
|
||||
|
||||
Element el = mesh.VolumeElement(ei);
|
||||
|
||||
if (inverttets)
|
||||
el.Invert();
|
||||
outfile.width(4);
|
||||
outfile << el.GetIndex() << " ";
|
||||
outfile.width(8);
|
||||
outfile << el.GetNP();
|
||||
for (j = 1; j <= el.GetNP(); j++)
|
||||
for (int j = 1; j <= el.GetNP(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile.width(8);
|
||||
@ -723,11 +742,11 @@ void WriteEdgeElementFormat (const Mesh & mesh,
|
||||
}
|
||||
|
||||
// top->GetElementEdges(i,edges);
|
||||
auto eledges = top->GetEdges(ElementIndex(i-1));
|
||||
auto eledges = top->GetEdges(ei);
|
||||
outfile << endl << " ";
|
||||
outfile.width(8);
|
||||
outfile << eledges.Size();
|
||||
for (j=1; j <= eledges.Size(); j++)
|
||||
for (int j=1; j <= eledges.Size(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile.width(8);
|
||||
@ -738,7 +757,7 @@ void WriteEdgeElementFormat (const Mesh & mesh,
|
||||
// orientation:
|
||||
top->GetElementEdgeOrientations(i,edges);
|
||||
outfile << " ";
|
||||
for (j=1; j <= edges.Size(); j++)
|
||||
for (int j=1; j <= edges.Size(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile.width(8);
|
||||
@ -749,31 +768,33 @@ void WriteEdgeElementFormat (const Mesh & mesh,
|
||||
|
||||
// surface element - edge - list (with boundary conditions)
|
||||
outfile << nsurfelem << "\n";
|
||||
for (i = 1; i <= nsurfelem; i++)
|
||||
for (int i = 1; i <= nsurfelem; i++)
|
||||
{
|
||||
Element2d el = mesh.SurfaceElement(i);
|
||||
SurfaceElementIndex sei(i-1);
|
||||
Element2d el = mesh[sei];
|
||||
if (invertsurf)
|
||||
el.Invert();
|
||||
outfile.width(4);
|
||||
outfile << mesh.GetFaceDescriptor (el.GetIndex()).BCProperty() << " ";
|
||||
outfile.width(8);
|
||||
outfile << el.GetNP();
|
||||
for (j = 1; j <= el.GetNP(); j++)
|
||||
for (int j = 1; j <= el.GetNP(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile.width(8);
|
||||
outfile << el.PNum(j);
|
||||
}
|
||||
|
||||
top->GetSurfaceElementEdges(i,edges);
|
||||
// top->GetSurfaceElementEdges(i,edges);
|
||||
auto edges = top->GetEdges(sei);
|
||||
outfile << endl << " ";
|
||||
outfile.width(8);
|
||||
outfile << edges.Size();
|
||||
for (j=1; j <= edges.Size(); j++)
|
||||
for (int j=0; j < edges.Size(); j++)
|
||||
{
|
||||
outfile << " ";
|
||||
outfile.width(8);
|
||||
outfile << edges[j-1];
|
||||
outfile << edges[j]+1;
|
||||
}
|
||||
outfile << "\n";
|
||||
}
|
||||
@ -782,7 +803,7 @@ void WriteEdgeElementFormat (const Mesh & mesh,
|
||||
// int v1, v2;
|
||||
// edge - vertex - list
|
||||
outfile << nedges << "\n";
|
||||
for (i=1; i <= nedges; i++)
|
||||
for (int i=1; i <= nedges; i++)
|
||||
{
|
||||
// top->GetEdgeVertices(i,v1,v2);
|
||||
auto [v1,v2] = top->GetEdgeVertices(i-1);
|
||||
|
@ -49,7 +49,8 @@ namespace netgen
|
||||
{
|
||||
data = NULL; height = width = 0;
|
||||
SetSize (m2.Height(), m2.Width());
|
||||
memcpy (data, m2.data, sizeof(double) * Height() * Width());
|
||||
if (Height() && Width())
|
||||
memcpy (data, m2.data, sizeof(double) * (Height() * Width()));
|
||||
}
|
||||
|
||||
DenseMatrix :: ~DenseMatrix ()
|
||||
@ -69,7 +70,7 @@ namespace netgen
|
||||
|
||||
delete[] data;
|
||||
|
||||
if (h*w)
|
||||
if (h && w)
|
||||
data = new double[h*w];
|
||||
else
|
||||
data = NULL;
|
||||
|
@ -12,7 +12,7 @@ target_sources(nglib PRIVATE
|
||||
parallelmesh.cpp paralleltop.cpp basegeom.cpp
|
||||
python_mesh.cpp surfacegeom.cpp
|
||||
debugging.cpp fieldlines.cpp visual_interface.cpp
|
||||
boundarylayer2d.cpp
|
||||
boundarylayer2d.cpp boundarylayer_interpolate.cpp
|
||||
)
|
||||
|
||||
target_link_libraries( nglib PRIVATE $<BUILD_INTERFACE:netgen_metis> $<BUILD_INTERFACE:netgen_python> )
|
||||
|
@ -152,15 +152,15 @@ namespace netgen
|
||||
|
||||
if (allflines)
|
||||
{
|
||||
if (allflines->Used (INDEX_2 (GetGlobalIndex (pi1),
|
||||
GetGlobalIndex (pi2))))
|
||||
if (allflines->Used (PointIndices<2>(GetGlobalIndex (pi1),
|
||||
GetGlobalIndex (pi2))))
|
||||
{
|
||||
cerr << "ERROR Adfront2::AddLine: line exists" << endl;
|
||||
(*testout) << "ERROR Adfront2::AddLine: line exists" << endl;
|
||||
}
|
||||
|
||||
allflines->Set (INDEX_2 (GetGlobalIndex (pi1),
|
||||
GetGlobalIndex (pi2)), 1);
|
||||
allflines->Set (PointIndices<2>(GetGlobalIndex (pi1),
|
||||
GetGlobalIndex (pi2)), 1);
|
||||
}
|
||||
|
||||
return li;
|
||||
@ -194,8 +194,8 @@ namespace netgen
|
||||
|
||||
if (allflines)
|
||||
{
|
||||
allflines->Set (INDEX_2 (GetGlobalIndex (lines[li].L().I1()),
|
||||
GetGlobalIndex (lines[li].L().I2())), 2);
|
||||
allflines->Set (PointIndices<2>(GetGlobalIndex (lines[li].L().I1()),
|
||||
GetGlobalIndex (lines[li].L().I2())), 2);
|
||||
}
|
||||
|
||||
lines[li].Invalidate();
|
||||
@ -282,7 +282,7 @@ namespace netgen
|
||||
NgArray<INDEX> & lindex,
|
||||
double xh)
|
||||
{
|
||||
static Timer timer("adfront2::GetLocals"); RegionTimer reg (timer);
|
||||
// static Timer timer("adfront2::GetLocals"); RegionTimer reg (timer);
|
||||
|
||||
int pstind;
|
||||
Point<3> midp, p0;
|
||||
|
@ -95,7 +95,7 @@ namespace netgen
|
||||
{
|
||||
private:
|
||||
/// Point Indizes
|
||||
INDEX_2 l;
|
||||
INDEX_2 l; // want to replace by std::array<int,2> l;
|
||||
/// quality class
|
||||
int lineclass;
|
||||
/// geometry specific data
|
||||
@ -109,23 +109,12 @@ namespace netgen
|
||||
|
||||
///
|
||||
FrontLine (const INDEX_2 & al)
|
||||
{
|
||||
l = al;
|
||||
lineclass = 1;
|
||||
}
|
||||
|
||||
: l(al), lineclass(1) { }
|
||||
|
||||
///
|
||||
const INDEX_2 & L () const
|
||||
{
|
||||
return l;
|
||||
}
|
||||
|
||||
const auto & L () const { return l; }
|
||||
///
|
||||
int LineClass() const
|
||||
{
|
||||
return lineclass;
|
||||
}
|
||||
int LineClass() const { return lineclass; }
|
||||
|
||||
///
|
||||
void IncrementClass ()
|
||||
@ -141,13 +130,13 @@ namespace netgen
|
||||
///
|
||||
bool Valid () const
|
||||
{
|
||||
return l.I1() != -1;
|
||||
return l[0] != -1;
|
||||
}
|
||||
///
|
||||
void Invalidate ()
|
||||
{
|
||||
l.I1() = -1;
|
||||
l.I2() = -1;
|
||||
l[0] = -1;
|
||||
l[1] = -1;
|
||||
lineclass = 1000;
|
||||
}
|
||||
|
||||
@ -171,21 +160,21 @@ class AdFront2
|
||||
{
|
||||
|
||||
///
|
||||
NgArray<FrontPoint2> points; /// front points
|
||||
NgArray<FrontLine> lines; /// front lines
|
||||
Array<FrontPoint2> points; /// front points
|
||||
Array<FrontLine> lines; /// front lines
|
||||
|
||||
Box3d boundingbox;
|
||||
BoxTree<3> linesearchtree; /// search tree for lines
|
||||
Point3dTree pointsearchtree; /// search tree for points
|
||||
Point3dTree cpointsearchtree; /// search tree for cone points (not used ???)
|
||||
|
||||
NgArray<int> delpointl; /// list of deleted front points
|
||||
NgArray<int> dellinel; /// list of deleted front lines
|
||||
Array<int> delpointl; /// list of deleted front points
|
||||
Array<int> dellinel; /// list of deleted front lines
|
||||
|
||||
int nfl; /// number of front lines;
|
||||
INDEX_2_HASHTABLE<int> * allflines; /// all front lines ever have been
|
||||
|
||||
NgArray<int> invpindex;
|
||||
Array<int> invpindex;
|
||||
|
||||
int minval;
|
||||
int starti;
|
||||
@ -210,8 +199,8 @@ public:
|
||||
///
|
||||
int GetNFL () const { return nfl; }
|
||||
|
||||
const FrontLine & GetLine (int nr) { return lines[nr]; }
|
||||
const FrontPoint2 & GetPoint (int nr) { return points[nr]; }
|
||||
const FrontLine & GetLine (int nr) const { return lines[nr]; }
|
||||
const FrontPoint2 & GetPoint (int nr) const { return points[nr]; }
|
||||
const auto & GetLines () const { return lines; }
|
||||
|
||||
///
|
||||
|
@ -13,7 +13,7 @@ FrontPoint3 :: FrontPoint3 ()
|
||||
globalindex.Invalidate(); // = -1;
|
||||
nfacetopoint = 0;
|
||||
frontnr = 1000;
|
||||
cluster = 0;
|
||||
cluster = PointIndex::INVALID;
|
||||
}
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ FrontPoint3 :: FrontPoint3 (const Point<3> & ap, PointIndex agi)
|
||||
globalindex = agi;
|
||||
nfacetopoint = 0;
|
||||
frontnr = 1000;
|
||||
cluster = 0;
|
||||
cluster = PointIndex::INVALID;
|
||||
}
|
||||
|
||||
|
||||
@ -35,7 +35,7 @@ FrontFace :: FrontFace ()
|
||||
qualclass = 1;
|
||||
oldfront = 0;
|
||||
hashvalue = 0;
|
||||
cluster = 0;
|
||||
cluster = PointIndex::INVALID;
|
||||
}
|
||||
|
||||
FrontFace :: FrontFace (const MiniElement2d & af)
|
||||
@ -71,7 +71,7 @@ AdFront3 :: AdFront3 ()
|
||||
hashtable.Init(&points, &faces);
|
||||
|
||||
facetree = NULL;
|
||||
connectedpairs = NULL;
|
||||
// connectedpairs = NULL;
|
||||
|
||||
rebuildcounter = -1;
|
||||
lasti = 0;
|
||||
@ -82,7 +82,7 @@ AdFront3 :: AdFront3 ()
|
||||
AdFront3 :: ~AdFront3 ()
|
||||
{
|
||||
delete facetree;
|
||||
delete connectedpairs;
|
||||
// delete connectedpairs;
|
||||
}
|
||||
|
||||
void AdFront3 :: GetPoints (NgArray<Point<3> > & apoints) const
|
||||
@ -153,10 +153,10 @@ INDEX AdFront3 :: AddFace (const MiniElement2d & aface)
|
||||
}
|
||||
|
||||
|
||||
int cluster = 0;
|
||||
PointIndex cluster = PointIndex::INVALID;
|
||||
for (i = 1; i <= aface.GetNP(); i++)
|
||||
{
|
||||
if (points[aface.PNum(i)].cluster)
|
||||
if (points[aface.PNum(i)].cluster.IsValid())
|
||||
cluster = points[aface.PNum(i)].cluster;
|
||||
}
|
||||
for (i = 1; i <= aface.GetNP(); i++)
|
||||
@ -182,9 +182,13 @@ void AdFront3 :: DeleteFace (INDEX fi)
|
||||
{
|
||||
nff--;
|
||||
|
||||
/*
|
||||
for (int i = 1; i <= faces.Get(fi).Face().GetNP(); i++)
|
||||
{
|
||||
PointIndex pi = faces.Get(fi).Face().PNum(i);
|
||||
*/
|
||||
for (PointIndex pi : faces.Get(fi).Face().PNums())
|
||||
{
|
||||
points[pi].RemoveFace();
|
||||
if (!points[pi].Valid())
|
||||
delpointl.Append (pi);
|
||||
@ -213,13 +217,13 @@ void AdFront3 :: DeleteFace (INDEX fi)
|
||||
}
|
||||
|
||||
|
||||
INDEX AdFront3 :: AddConnectedPair (const INDEX_2 & apair)
|
||||
INDEX AdFront3 :: AddConnectedPair (PointIndices<2> apair)
|
||||
{
|
||||
if (!connectedpairs)
|
||||
connectedpairs = new TABLE<int, PointIndex::BASE> (GetNP());
|
||||
connectedpairs = make_unique<DynamicTable<PointIndex, PointIndex>> (GetNP());
|
||||
|
||||
connectedpairs->Add (apair.I1(), apair.I2());
|
||||
connectedpairs->Add (apair.I2(), apair.I1());
|
||||
connectedpairs->Add (apair[0], apair[1]);
|
||||
connectedpairs->Add (apair[1], apair[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -231,11 +235,11 @@ void AdFront3 :: CreateTrees ()
|
||||
PointIndex pi;
|
||||
Point3d pmin, pmax;
|
||||
|
||||
for (pi = PointIndex::BASE;
|
||||
pi < GetNP()+PointIndex::BASE; pi++)
|
||||
for (pi = IndexBASE<PointIndex>();
|
||||
pi < GetNP()+IndexBASE<PointIndex>(); pi++)
|
||||
{
|
||||
const Point<3> & p = GetPoint(pi);
|
||||
if (pi == PointIndex::BASE)
|
||||
if (pi == IndexBASE<PointIndex>())
|
||||
{
|
||||
pmin = p;
|
||||
pmax = p;
|
||||
@ -323,12 +327,12 @@ void AdFront3 :: RebuildInternalTables ()
|
||||
{
|
||||
const MiniElement2d & el = faces.Get(i).Face();
|
||||
|
||||
int mini = points[el.PNum(1)].cluster;
|
||||
int maxi = mini;
|
||||
PointIndex mini = points[el.PNum(1)].cluster;
|
||||
PointIndex maxi = mini;
|
||||
|
||||
for (int j = 2; j <= 3; j++)
|
||||
{
|
||||
int ci = points[el.PNum(j)].cluster;
|
||||
PointIndex ci = points[el.PNum(j)].cluster;
|
||||
if (ci < mini) mini = ci;
|
||||
if (ci > maxi) maxi = ci;
|
||||
}
|
||||
@ -366,7 +370,7 @@ void AdFront3 :: RebuildInternalTables ()
|
||||
cntcl++;
|
||||
*/
|
||||
|
||||
NgArray<double, PointIndex::BASE> clvol (np);
|
||||
Array<double, PointIndex> clvol (np);
|
||||
clvol = 0.0;
|
||||
|
||||
for (int i = 1; i <= faces.Size(); i++)
|
||||
@ -397,21 +401,18 @@ void AdFront3 :: RebuildInternalTables ()
|
||||
|
||||
|
||||
|
||||
int negvol = 0;
|
||||
for (int i = PointIndex::BASE;
|
||||
i < clvol.Size()+PointIndex::BASE; i++)
|
||||
{
|
||||
if (clvol[i] < 0)
|
||||
negvol = 1;
|
||||
}
|
||||
bool negvol = false;
|
||||
for (auto i : clvol.Range())
|
||||
if (clvol[i] < 0)
|
||||
negvol = true;
|
||||
|
||||
if (negvol)
|
||||
{
|
||||
for (int i = 1; i <= faces.Size(); i++)
|
||||
faces.Elem(i).cluster = 1;
|
||||
faces.Elem(i).cluster = IndexBASE<PointIndex>();
|
||||
// for (PointIndex pi = points.Begin(); pi < points.End(); pi++)
|
||||
for (PointIndex pi : points.Range())
|
||||
points[pi].cluster = 1;
|
||||
points[pi].cluster = IndexBASE<PointIndex>();
|
||||
}
|
||||
|
||||
if (hashon)
|
||||
@ -424,8 +425,6 @@ void AdFront3 :: RebuildInternalTables ()
|
||||
|
||||
int AdFront3 :: SelectBaseElement ()
|
||||
{
|
||||
int i, hi, fstind;
|
||||
|
||||
/*
|
||||
static int minval = -1;
|
||||
static int lasti = 0;
|
||||
@ -450,12 +449,12 @@ int AdFront3 :: SelectBaseElement ()
|
||||
}
|
||||
*/
|
||||
|
||||
fstind = 0;
|
||||
int fstind = 0;
|
||||
|
||||
for (i = lasti+1; i <= faces.Size() && !fstind; i++)
|
||||
for (int i = lasti+1; i <= faces.Size() && !fstind; i++)
|
||||
if (faces.Elem(i).Valid())
|
||||
{
|
||||
hi = faces.Get(i).QualClass() +
|
||||
int hi = faces.Get(i).QualClass() +
|
||||
points[faces.Get(i).Face().PNum(1)].FrontNr() +
|
||||
points[faces.Get(i).Face().PNum(2)].FrontNr() +
|
||||
points[faces.Get(i).Face().PNum(3)].FrontNr();
|
||||
@ -471,10 +470,10 @@ int AdFront3 :: SelectBaseElement ()
|
||||
if (!fstind)
|
||||
{
|
||||
minval = INT_MAX;
|
||||
for (i = 1; i <= faces.Size(); i++)
|
||||
for (int i = 1; i <= faces.Size(); i++)
|
||||
if (faces.Elem(i).Valid())
|
||||
{
|
||||
hi = faces.Get(i).QualClass() +
|
||||
int hi = faces.Get(i).QualClass() +
|
||||
points[faces.Get(i).Face().PNum(1)].FrontNr() +
|
||||
points[faces.Get(i).Face().PNum(2)].FrontNr() +
|
||||
points[faces.Get(i).Face().PNum(3)].FrontNr();
|
||||
@ -495,10 +494,10 @@ int AdFront3 :: SelectBaseElement ()
|
||||
|
||||
|
||||
int AdFront3 :: GetLocals (int fstind,
|
||||
NgArray<Point3d, PointIndex::BASE> & locpoints,
|
||||
NgArray<MiniElement2d> & locfaces, // local index
|
||||
NgArray<PointIndex, PointIndex::BASE> & pindex,
|
||||
NgArray<INDEX> & findex,
|
||||
Array<Point3d, PointIndex> & locpoints,
|
||||
Array<MiniElement2d> & locfaces, // local index
|
||||
Array<PointIndex, PointIndex> & pindex,
|
||||
Array<INDEX> & findex,
|
||||
INDEX_2_HASHTABLE<int> & getconnectedpairs,
|
||||
float xh,
|
||||
float relh,
|
||||
@ -515,7 +514,7 @@ int AdFront3 :: GetLocals (int fstind,
|
||||
hashcreated=1;
|
||||
}
|
||||
|
||||
INDEX i, j;
|
||||
INDEX i;
|
||||
PointIndex pstind;
|
||||
Point3d midp, p0;
|
||||
|
||||
@ -529,7 +528,7 @@ int AdFront3 :: GetLocals (int fstind,
|
||||
locfaces3.SetSize(0);
|
||||
findex2.SetSize(0);
|
||||
|
||||
int cluster = faces.Get(fstind).cluster;
|
||||
PointIndex cluster = faces.Get(fstind).cluster;
|
||||
|
||||
pstind = faces.Get(fstind).Face().PNum(1);
|
||||
p0 = points[pstind].P();
|
||||
@ -596,28 +595,37 @@ int AdFront3 :: GetLocals (int fstind,
|
||||
|
||||
|
||||
invpindex.SetSize (points.Size());
|
||||
/*
|
||||
for (i = 1; i <= locfaces.Size(); i++)
|
||||
for (j = 1; j <= locfaces.Get(i).GetNP(); j++)
|
||||
{
|
||||
PointIndex pi = locfaces.Get(i).PNum(j);
|
||||
invpindex[pi] = PointIndex::INVALID;
|
||||
}
|
||||
*/
|
||||
for (auto & f : locfaces)
|
||||
for (int j = 1; j <= f.GetNP(); j++)
|
||||
{
|
||||
PointIndex pi = f.PNum(j);
|
||||
invpindex[pi] = PointIndex::INVALID;
|
||||
}
|
||||
|
||||
for (i = 1; i <= locfaces.Size(); i++)
|
||||
// for (i = 1; i <= locfaces.Size(); i++)
|
||||
for (auto & f : locfaces)
|
||||
{
|
||||
for (j = 1; j <= locfaces.Get(i).GetNP(); j++)
|
||||
// for (j = 1; j <= locfaces.Get(i).GetNP(); j++)
|
||||
for (int j = 1; j <= f.GetNP(); j++)
|
||||
{
|
||||
PointIndex pi = locfaces.Get(i).PNum(j);
|
||||
// PointIndex pi = locfaces.Get(i).PNum(j);
|
||||
PointIndex pi = f.PNum(j);
|
||||
if (!invpindex[pi].IsValid())
|
||||
{
|
||||
pindex.Append (pi);
|
||||
locpoints.Append (points[pi].P());
|
||||
invpindex[pi] = pindex.Size()-1+PointIndex::BASE;
|
||||
invpindex[pi] = pindex.Size()-1+IndexBASE<PointIndex>();
|
||||
}
|
||||
// locfaces.Elem(i).PNum(j) = locpoints.Append (points[pi].P());
|
||||
// }
|
||||
// else
|
||||
locfaces.Elem(i).PNum(j) = invpindex[pi];
|
||||
// locfaces.Elem(i).PNum(j) = invpindex[pi];
|
||||
f.PNum(j) = invpindex[pi];
|
||||
}
|
||||
}
|
||||
|
||||
@ -625,22 +633,27 @@ int AdFront3 :: GetLocals (int fstind,
|
||||
|
||||
if (connectedpairs)
|
||||
{
|
||||
for (i = 1; i <= locpoints.Size(); i++)
|
||||
// for (i = 1; i <= locpoints.Size(); i++)
|
||||
for (auto i : locpoints.Range())
|
||||
{
|
||||
int pind = pindex.Get(i);
|
||||
if (pind >= 1 && pind <= connectedpairs->Size ())
|
||||
PointIndex pind = pindex[i]; // .Get(i);
|
||||
// if (pind.IsValid() && pind <= connectedpairs->Size ())
|
||||
if (connectedpairs->Range().Contains(pind))
|
||||
{
|
||||
for (j = 1; j <= connectedpairs->EntrySize(pind); j++)
|
||||
// for (int j = 1; j <= connectedpairs->EntrySize(pind); j++)
|
||||
for (auto j : (*connectedpairs)[pind].Range())
|
||||
{
|
||||
int oi = connectedpairs->Get(pind, j);
|
||||
int other = invpindex.Get(oi);
|
||||
if (other >= 1 && other <= pindex.Size() &&
|
||||
pindex.Get(other) == oi)
|
||||
//PointIndex oi = connectedpairs->Get(pind, j);
|
||||
PointIndex oi = (*connectedpairs)[pind][j];
|
||||
PointIndex other = invpindex[oi];
|
||||
// if (other >= 1 && other <= pindex.Size() &&
|
||||
if (pindex.Range().Contains(other) &&
|
||||
pindex[other] == oi)
|
||||
{
|
||||
// INDEX_2 coned(i, other);
|
||||
// coned.Sort();
|
||||
// (*testout) << "connected: " << locpoints.Get(i) << "-" << locpoints.Get(other) << endl;
|
||||
getconnectedpairs.Set (INDEX_2::Sort (i, other), 1);
|
||||
getconnectedpairs.Set (PointIndices<2>::Sort (i, other), 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -667,10 +680,10 @@ int AdFront3 :: GetLocals (int fstind,
|
||||
|
||||
// returns all points connected with fi
|
||||
void AdFront3 :: GetGroup (int fi,
|
||||
NgArray<MeshPoint, PointIndex::BASE> & grouppoints,
|
||||
NgArray<MiniElement2d> & groupelements,
|
||||
NgArray<PointIndex, PointIndex::BASE> & pindex,
|
||||
NgArray<INDEX> & findex)
|
||||
Array<MeshPoint, PointIndex> & grouppoints,
|
||||
Array<MiniElement2d> & groupelements,
|
||||
Array<PointIndex, PointIndex> & pindex,
|
||||
Array<INDEX> & findex)
|
||||
{
|
||||
// static NgArray<char> pingroup;
|
||||
int changed;
|
||||
@ -734,8 +747,9 @@ void AdFront3 :: GetGroup (int fi,
|
||||
if (points[pi].Valid())
|
||||
{
|
||||
grouppoints.Append (points[pi].P());
|
||||
pindex.Append (pi);
|
||||
invpindex[pi] = pindex.Size();
|
||||
pindex.Append (pi);
|
||||
// invpindex[pi] = pindex.Size();
|
||||
invpindex[pi] = pindex.Size()-1 + IndexBASE<PointIndex>();
|
||||
}
|
||||
|
||||
for (int i = 1; i <= faces.Size(); i++)
|
||||
@ -787,6 +801,54 @@ void AdFront3 :: SetStartFront (int /* baseelnp */)
|
||||
*/
|
||||
}
|
||||
|
||||
bool AdFront3 :: PointInsideGroup(const Array<PointIndex, PointIndex> &grouppindex,
|
||||
const Array<MiniElement2d> &groupfaces) const
|
||||
{
|
||||
for(auto pi : Range(points))
|
||||
{
|
||||
const auto& p = points[pi].P();
|
||||
bool found = false;
|
||||
for(const auto& f : groupfaces)
|
||||
{
|
||||
for(auto i : Range(3))
|
||||
if(grouppindex[f.PNum(i+1)] == pi)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(found)
|
||||
continue;
|
||||
|
||||
// "random" direction
|
||||
Vec<3> dir = { 0.123871, 0.15432,-0.43989 };
|
||||
DenseMatrix a(3), ainv(3);
|
||||
Vector b(3), u(3);
|
||||
|
||||
int count = 0;
|
||||
for(const auto& f : groupfaces)
|
||||
{
|
||||
const auto& p1 = points[grouppindex[f.PNum(1)]].P();
|
||||
auto v1 = points[grouppindex[f.PNum(2)]].P() - p1;
|
||||
auto v2 = points[grouppindex[f.PNum(3)]].P() - p1;
|
||||
for(auto i : Range(3))
|
||||
{
|
||||
a(i,0) = v1[i];
|
||||
a(i,1) = v2[i];
|
||||
a(i,2) = -dir[i];
|
||||
b(i) = p[i] - p1[i];
|
||||
}
|
||||
CalcInverse (a, ainv);
|
||||
ainv.Mult (b, u);
|
||||
if (u(0) >= 0 && u(1) >= 0 && u(0)+u(1) <= 1 &&
|
||||
u(2) > 0)
|
||||
count++;
|
||||
}
|
||||
if (count % 2 == 1)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdFront3 :: Inside (const Point<3> & p) const
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ class FrontPoint3
|
||||
/// distance to original boundary
|
||||
int frontnr;
|
||||
///
|
||||
int cluster;
|
||||
PointIndex cluster;
|
||||
public:
|
||||
///
|
||||
FrontPoint3 ();
|
||||
@ -95,7 +95,8 @@ public:
|
||||
const PointIndex PNum (int i) const { return pnum[i-1]; }
|
||||
PointIndex & PNum (int i) { return pnum[i-1]; }
|
||||
const PointIndex PNumMod (int i) const { return pnum[(i-1)%np]; }
|
||||
auto PNums() const { return NgFlatArray<const PointIndex> (np, &pnum[0]); }
|
||||
auto PNums() { return FlatArray<PointIndex> (np, &pnum[0]); }
|
||||
auto PNums() const { return FlatArray<const PointIndex> (np, &pnum[0]); }
|
||||
void Delete () { deleted = true; for (PointIndex & p : pnum) p.Invalidate(); }
|
||||
bool IsDeleted () const { return deleted; }
|
||||
};
|
||||
@ -125,7 +126,7 @@ private:
|
||||
///
|
||||
int hashvalue;
|
||||
///
|
||||
int cluster;
|
||||
PointIndex cluster;
|
||||
|
||||
public:
|
||||
///
|
||||
@ -172,7 +173,7 @@ public:
|
||||
///
|
||||
friend class AdFront3;
|
||||
|
||||
int Cluster () const { return cluster; }
|
||||
PointIndex Cluster () const { return cluster; }
|
||||
};
|
||||
|
||||
|
||||
@ -182,14 +183,17 @@ public:
|
||||
class AdFront3
|
||||
{
|
||||
///
|
||||
NgArray<FrontPoint3, PointIndex::BASE, PointIndex> points;
|
||||
// NgArray<FrontPoint3, PointIndex::BASE, PointIndex> points;
|
||||
Array<FrontPoint3, PointIndex> points
|
||||
;
|
||||
///
|
||||
NgArray<FrontFace> faces;
|
||||
///
|
||||
NgArray<PointIndex> delpointl;
|
||||
Array<PointIndex> delpointl;
|
||||
|
||||
/// which points are connected to pi ?
|
||||
TABLE<int, PointIndex::BASE> * connectedpairs;
|
||||
// TABLE<PointIndex, PointIndex::BASE> * connectedpairs;
|
||||
unique_ptr<DynamicTable<PointIndex, PointIndex>> connectedpairs;
|
||||
|
||||
/// number of total front faces;
|
||||
int nff;
|
||||
@ -214,8 +218,8 @@ class AdFront3
|
||||
int lasti;
|
||||
/// minimal selection-value of baseelements
|
||||
int minval;
|
||||
NgArray<PointIndex, PointIndex::BASE, PointIndex> invpindex;
|
||||
NgArray<char, PointIndex::BASE> pingroup;
|
||||
Array<PointIndex, PointIndex> invpindex;
|
||||
Array<char, PointIndex> pingroup;
|
||||
|
||||
///
|
||||
class BoxTree<3> * facetree;
|
||||
@ -236,9 +240,9 @@ public:
|
||||
///
|
||||
int GetNF() const
|
||||
{ return nff; }
|
||||
///
|
||||
/// 1-based
|
||||
const MiniElement2d & GetFace (int i) const
|
||||
{ return faces.Get(i).Face(); }
|
||||
{ return faces[i-1].Face(); }
|
||||
const auto & Faces() const { return faces; }
|
||||
///
|
||||
void Print () const;
|
||||
@ -262,15 +266,18 @@ public:
|
||||
void GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax,
|
||||
NgArray<int> & ifaces) const;
|
||||
|
||||
bool PointInsideGroup(const Array<PointIndex, PointIndex> &grouppindex,
|
||||
const Array<MiniElement2d>& groupfaces) const;
|
||||
|
||||
///
|
||||
void GetFaceBoundingBox (int i, Box3d & box) const;
|
||||
|
||||
///
|
||||
int GetLocals (int baseelement,
|
||||
NgArray<Point3d, PointIndex::BASE> & locpoints,
|
||||
NgArray<MiniElement2d> & locfaces, // local index
|
||||
NgArray<PointIndex, PointIndex::BASE> & pindex,
|
||||
NgArray<INDEX> & findex,
|
||||
Array<Point3d, PointIndex> & locpoints,
|
||||
Array<MiniElement2d> & locfaces, // local index
|
||||
Array<PointIndex, PointIndex> & pindex,
|
||||
Array<INDEX> & findex,
|
||||
INDEX_2_HASHTABLE<int> & connectedpairs,
|
||||
float xh,
|
||||
float relh,
|
||||
@ -278,10 +285,10 @@ public:
|
||||
|
||||
///
|
||||
void GetGroup (int fi,
|
||||
NgArray<MeshPoint, PointIndex::BASE> & grouppoints,
|
||||
NgArray<MiniElement2d> & groupelements,
|
||||
NgArray<PointIndex, PointIndex::BASE> & pindex,
|
||||
NgArray<INDEX> & findex);
|
||||
Array<MeshPoint, PointIndex> & grouppoints,
|
||||
Array<MiniElement2d> & groupelements,
|
||||
Array<PointIndex, PointIndex> & pindex,
|
||||
Array<INDEX> & findex);
|
||||
|
||||
///
|
||||
void DeleteFace (INDEX fi);
|
||||
@ -290,14 +297,14 @@ public:
|
||||
///
|
||||
INDEX AddFace (const MiniElement2d & e);
|
||||
///
|
||||
INDEX AddConnectedPair (const INDEX_2 & pair);
|
||||
INDEX AddConnectedPair (PointIndices<2> pair);
|
||||
///
|
||||
void IncrementClass (INDEX fi)
|
||||
{ faces.Elem(fi).IncrementQualClass(); }
|
||||
{ faces[fi-1].IncrementQualClass(); }
|
||||
|
||||
///
|
||||
void ResetClass (INDEX fi)
|
||||
{ faces.Elem(fi).ResetQualClass(); }
|
||||
{ faces[fi-1].ResetQualClass(); }
|
||||
|
||||
///
|
||||
void SetStartFront (int baseelnp = 0);
|
||||
|
@ -8,25 +8,26 @@ namespace netgen
|
||||
{
|
||||
struct PointTree
|
||||
{
|
||||
BoxTree<3> tree;
|
||||
std::map<int, BoxTree<3>> tree;
|
||||
Box<3> bounding_box;
|
||||
|
||||
PointTree( Box<3> bb ) : tree(bb) {}
|
||||
PointTree( Box<3> bb ) : bounding_box(bb) {}
|
||||
|
||||
void Insert(Point<3> p, PointIndex n)
|
||||
void Insert(Point<3> p, PointIndex n, int index)
|
||||
{
|
||||
tree.Insert(p, p, n);
|
||||
if(tree.count(index) == 0)
|
||||
tree.emplace(index, bounding_box);
|
||||
tree.at(index).Insert(p, p, n);
|
||||
}
|
||||
|
||||
PointIndex Find(Point<3> p) const
|
||||
PointIndex Find(Point<3> p, int index) const
|
||||
{
|
||||
ArrayMem<int, 1> points;
|
||||
tree.GetIntersecting(p, p, points);
|
||||
tree.at(index).GetIntersecting(p, p, points);
|
||||
if(points.Size()==0)
|
||||
throw Exception("cannot find mapped point " + ToString(p));
|
||||
return points[0];
|
||||
}
|
||||
|
||||
double GetTolerance() { return tree.GetTolerance(); }
|
||||
};
|
||||
|
||||
DLL_HEADER GeometryRegisterArray geometryregister;
|
||||
@ -213,22 +214,24 @@ namespace netgen
|
||||
}
|
||||
}
|
||||
|
||||
struct Line
|
||||
{
|
||||
Point<3> p0, p1;
|
||||
inline double Length() const { return (p1-p0).Length(); }
|
||||
inline double Dist(const Line& other) const
|
||||
namespace {
|
||||
struct Line
|
||||
{
|
||||
Vec<3> n = p1-p0;
|
||||
Vec<3> q = other.p1-other.p0;
|
||||
double nq = n*q;
|
||||
Point<3> p = p0 + 0.5*n;
|
||||
double lambda = (p-other.p0)*n / (nq + 1e-10);
|
||||
if (lambda >= 0 && lambda <= 1)
|
||||
return (p-other.p0-lambda*q).Length();
|
||||
return 1e99;
|
||||
}
|
||||
};
|
||||
Point<3> p0, p1;
|
||||
inline double Length() const { return (p1-p0).Length(); }
|
||||
inline double Dist(const Line& other) const
|
||||
{
|
||||
Vec<3> n = p1-p0;
|
||||
Vec<3> q = other.p1-other.p0;
|
||||
double nq = n*q;
|
||||
Point<3> p = p0 + 0.5*n;
|
||||
double lambda = (p-other.p0)*n / (nq + 1e-10);
|
||||
if (lambda >= 0 && lambda <= 1)
|
||||
return (p-other.p0-lambda*q).Length();
|
||||
return 1e99;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void NetgenGeometry :: Clear()
|
||||
{
|
||||
@ -471,7 +474,7 @@ namespace netgen
|
||||
}
|
||||
|
||||
for(const auto& mspnt : mparam.meshsize_points)
|
||||
mesh.RestrictLocalH(mspnt.pnt, mspnt.h);
|
||||
mesh.RestrictLocalH(mspnt.pnt, mspnt.h, mspnt.layer);
|
||||
|
||||
mesh.LoadLocalMeshSize(mparam.meshsizefilename);
|
||||
}
|
||||
@ -581,17 +584,17 @@ namespace netgen
|
||||
|
||||
Array<PointIndex> vert2meshpt(vertices.Size());
|
||||
vert2meshpt = PointIndex::INVALID;
|
||||
|
||||
for(auto & vert : vertices)
|
||||
{
|
||||
auto pi = mesh.AddPoint(vert->GetPoint(), vert->properties.layer);
|
||||
tree.Insert(mesh[pi], pi);
|
||||
vert2meshpt[vert->nr] = pi;
|
||||
mesh[pi].Singularity(vert->properties.hpref);
|
||||
mesh[pi].SetType(FIXEDPOINT);
|
||||
|
||||
Element0d el(pi, pi);
|
||||
|
||||
Element0d el(pi, pi-IndexBASE<PointIndex>()+1);
|
||||
el.name = vert->properties.GetName();
|
||||
mesh.SetCD3Name(pi, el.name);
|
||||
mesh.SetCD3Name(pi-IndexBASE<PointIndex>()+1, el.name);
|
||||
mesh.pointelements.Append (el);
|
||||
}
|
||||
|
||||
@ -616,8 +619,8 @@ namespace netgen
|
||||
endp = vert2meshpt[edge->GetEndVertex().nr];
|
||||
|
||||
// ignore collapsed edges
|
||||
if(startp == endp && edge->GetLength() < 1e-10 * bounding_box.Diam())
|
||||
continue;
|
||||
if(edge->IsDegenerated())
|
||||
continue;
|
||||
|
||||
// ----------- Add Points to mesh and create segments -----
|
||||
auto & pnums = all_pnums[edgenr];
|
||||
@ -716,7 +719,8 @@ namespace netgen
|
||||
for(auto i : Range(edge_points))
|
||||
{
|
||||
auto pi = mesh.AddPoint(edge_points[i], edge->properties.layer);
|
||||
tree.Insert(mesh[pi], pi);
|
||||
if(edge->identifications.Size())
|
||||
tree.Insert(mesh[pi], pi, edge->nr);
|
||||
pnums[i+1] = pi;
|
||||
}
|
||||
|
||||
@ -757,7 +761,7 @@ namespace netgen
|
||||
p_other = (*ident.trafo)(mesh[pi]);
|
||||
else
|
||||
static_cast<GeometryEdge*>(ident.to)->ProjectPoint(p_other, nullptr);
|
||||
auto pi_other = tree.Find(p_other);
|
||||
auto pi_other = tree.Find(p_other, ident.to->nr);
|
||||
identifications.Add(pi, pi_other, ident.name, ident.type);
|
||||
}
|
||||
}
|
||||
@ -866,7 +870,7 @@ namespace netgen
|
||||
for(auto pi : s.PNums())
|
||||
if(!is_point_in_tree[pi])
|
||||
{
|
||||
tree.Insert(mesh[pi], pi);
|
||||
tree.Insert(mesh[pi], pi, -1);
|
||||
is_point_in_tree[pi] = true;
|
||||
}
|
||||
|
||||
@ -936,8 +940,8 @@ namespace netgen
|
||||
edges[mapped_edges[edgenr]]->ProjectPoint(p2, nullptr);
|
||||
edges[mapped_edges[edgenr]]->ProjectPoint(p3, nullptr);
|
||||
}
|
||||
sel[2] = tree.Find(p2);
|
||||
sel[3] = tree.Find(p3);
|
||||
sel[2] = tree.Find(p2, -1);
|
||||
sel[3] = tree.Find(p3, -1);
|
||||
|
||||
// find mapped segment to set PointGeomInfo correctly
|
||||
Segment s_other;
|
||||
@ -1017,7 +1021,7 @@ namespace netgen
|
||||
if(mesh[pi].Type() == SURFACEPOINT && pi_to_face[pi]==-1)
|
||||
{
|
||||
pi_to_face[pi] = face->nr;
|
||||
tree.Insert(mesh[pi], pi);
|
||||
tree.Insert(mesh[pi], pi, -1);
|
||||
pi_of_face[face->nr].Append(pi);
|
||||
}
|
||||
}
|
||||
@ -1085,7 +1089,7 @@ namespace netgen
|
||||
else
|
||||
edge->ProjectPoint(p, nullptr);
|
||||
}
|
||||
tree.Insert(p, pi);
|
||||
tree.Insert(p, pi, -1);
|
||||
is_point_in_tree[pi] = true;
|
||||
}
|
||||
}
|
||||
@ -1097,7 +1101,7 @@ namespace netgen
|
||||
{
|
||||
auto pi = seg[i];
|
||||
if(!pmap[pi].IsValid())
|
||||
pmap[tree.Find(mesh[pi])] = pi;
|
||||
pmap[tree.Find(mesh[pi], -1)] = pi;
|
||||
|
||||
// store uv values (might be different values for same point in case of internal edges)
|
||||
double u = seg.epgeominfo[i].u;
|
||||
@ -1216,6 +1220,7 @@ namespace netgen
|
||||
{
|
||||
PrintMessage(3, "Optimization step ", i);
|
||||
meshopt.SetFaceIndex(k+1);
|
||||
meshopt.SetMetricWeight (mparam.elsizeweight);
|
||||
int innerstep = 0;
|
||||
for(auto optstep : mparam.optimize2d)
|
||||
{
|
||||
@ -1244,8 +1249,7 @@ namespace netgen
|
||||
|
||||
void NetgenGeometry :: FinalizeMesh(Mesh& mesh) const
|
||||
{
|
||||
if(solids.Size())
|
||||
for (int i = 0; i < mesh.GetNDomains(); i++)
|
||||
for (int i = 0; i < std::min(solids.Size(), (size_t)mesh.GetNDomains()); i++)
|
||||
if (auto name = solids[i]->properties.name)
|
||||
mesh.SetMaterial (i+1, *name);
|
||||
|
||||
@ -1311,6 +1315,13 @@ namespace netgen
|
||||
if(multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHEDGES)
|
||||
return 0;
|
||||
|
||||
if(dimension == 1)
|
||||
{
|
||||
FinalizeMesh(*mesh);
|
||||
mesh->SetDimension(1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE)
|
||||
{
|
||||
MeshSurface(*mesh, mparam);
|
||||
|
@ -86,6 +86,9 @@ namespace netgen
|
||||
protected:
|
||||
GeometryVertex *start, *end;
|
||||
public:
|
||||
// Neighboring domains in 2d
|
||||
// In 3d unused, EXCEPT for free floating edges in a domain,
|
||||
// then both are pointing to the containing domain
|
||||
int domin=-1, domout=-1;
|
||||
|
||||
GeometryEdge( GeometryVertex &start_, GeometryVertex &end_ )
|
||||
@ -187,7 +190,10 @@ namespace netgen
|
||||
};
|
||||
|
||||
class DLL_HEADER GeometrySolid : public GeometryShape
|
||||
{ };
|
||||
{
|
||||
public:
|
||||
Array<GeometryEdge*> free_edges; // edges with no adjacent face
|
||||
};
|
||||
|
||||
class DLL_HEADER NetgenGeometry
|
||||
{
|
||||
@ -212,11 +218,18 @@ namespace netgen
|
||||
size_t GetNVertices() const { return vertices.Size(); }
|
||||
size_t GetNEdges() const { return edges.Size(); }
|
||||
size_t GetNFaces() const { return faces.Size(); }
|
||||
size_t GetNSolids() const { return solids.Size(); }
|
||||
|
||||
const GeometrySolid & GetSolid(int i) const { return *solids[i]; }
|
||||
const GeometryFace & GetFace(int i) const { return *faces[i]; }
|
||||
const GeometryEdge & GetEdge(int i) const { return *edges[i]; }
|
||||
const GeometryVertex & GetVertex(int i) const { return *vertices[i]; }
|
||||
|
||||
auto Solids() const { return FlatArray{solids}; }
|
||||
auto Faces() const { return FlatArray{faces}; }
|
||||
auto Edges() const { return FlatArray{edges}; }
|
||||
auto Vertices() const { return FlatArray{vertices}; }
|
||||
|
||||
virtual Array<const GeometryVertex*> GetFaceVertices(const GeometryFace& face) const { return Array<const GeometryVertex*>{}; }
|
||||
|
||||
void Clear();
|
||||
@ -258,7 +271,7 @@ namespace netgen
|
||||
|
||||
virtual void ProjectPointEdge (int surfind, int surfind2, Point<3> & p, EdgePointGeomInfo* gi = nullptr) const
|
||||
{
|
||||
if(gi && gi->edgenr < edges.Size())
|
||||
if(gi && gi->edgenr < edges.Size() && gi->edgenr >= 0)
|
||||
edges[gi->edgenr]->ProjectPoint(p, gi);
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,95 +1,112 @@
|
||||
#ifndef NETGEN_BOUNDARYLAYER_HPP
|
||||
#define NETGEN_BOUNDARYLAYER_HPP
|
||||
|
||||
#include <core/array.hpp>
|
||||
#include <mystdlib.h>
|
||||
#include <meshing.hpp>
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
///
|
||||
DLL_HEADER extern void InsertVirtualBoundaryLayer (Mesh & mesh);
|
||||
DLL_HEADER extern void InsertVirtualBoundaryLayer (Mesh& mesh);
|
||||
|
||||
/// Create a typical prismatic boundary layer on the given
|
||||
/// Create a typical prismatic boundary layer on the given
|
||||
/// surfaces
|
||||
|
||||
class BoundaryLayerParameters
|
||||
struct SpecialBoundaryPoint
|
||||
{
|
||||
public:
|
||||
// parameters by Philippose ..
|
||||
Array<int> surfid;
|
||||
Array<double> heights;
|
||||
map<string, string> new_mat;
|
||||
BitArray domains;
|
||||
bool outside = false; // set the boundary layer on the outside
|
||||
bool grow_edges = false;
|
||||
bool limit_growth_vectors = true;
|
||||
double limit_safety = 0.3; // alloow only 30% of the growth vector length
|
||||
bool sides_keep_surfaceindex = false;
|
||||
bool keep_surfaceindex = false;
|
||||
Array<size_t> project_boundaries;
|
||||
struct GrowthGroup
|
||||
{
|
||||
Array<int> faces;
|
||||
Vec<3> growth_vector;
|
||||
Array<PointIndex> new_points;
|
||||
|
||||
GrowthGroup (FlatArray<int> faces_, FlatArray<Vec<3>> normals);
|
||||
GrowthGroup (const GrowthGroup&) = default;
|
||||
GrowthGroup () = default;
|
||||
};
|
||||
Array<GrowthGroup> growth_groups;
|
||||
Vec<3> separating_direction;
|
||||
|
||||
SpecialBoundaryPoint (const std::map<int, Vec<3>>& normals);
|
||||
SpecialBoundaryPoint () = default;
|
||||
};
|
||||
|
||||
DLL_HEADER void GenerateBoundaryLayer (Mesh & mesh,
|
||||
const BoundaryLayerParameters & blp);
|
||||
DLL_HEADER void GenerateBoundaryLayer (Mesh& mesh,
|
||||
const BoundaryLayerParameters& blp);
|
||||
|
||||
DLL_HEADER int /* new_domain_number */ GenerateBoundaryLayer2 (Mesh & mesh, int domain, const Array<double> & thicknesses, bool should_make_new_domain=true, const Array<int> & boundaries=Array<int>{});
|
||||
DLL_HEADER int /* new_domain_number */ GenerateBoundaryLayer2 (Mesh& mesh, int domain, const Array<double>& thicknesses, bool should_make_new_domain = true, const Array<int>& boundaries = Array<int>{});
|
||||
|
||||
class BoundaryLayerTool
|
||||
{
|
||||
public:
|
||||
BoundaryLayerTool(Mesh & mesh_, const BoundaryLayerParameters & params_);
|
||||
void Perform();
|
||||
public:
|
||||
BoundaryLayerTool (Mesh& mesh_, const BoundaryLayerParameters& params_);
|
||||
void ProcessParameters ();
|
||||
void Perform ();
|
||||
|
||||
protected:
|
||||
Mesh & mesh;
|
||||
MeshTopology & topo;
|
||||
BoundaryLayerParameters params;
|
||||
Array<Vec<3>, PointIndex> growthvectors;
|
||||
Table<SurfaceElementIndex, PointIndex> p2sel;
|
||||
Mesh& mesh;
|
||||
MeshTopology& topo;
|
||||
BoundaryLayerParameters params;
|
||||
Array<Vec<3>, PointIndex> growthvectors;
|
||||
std::map<PointIndex, Vec<3>> non_bl_growth_vectors;
|
||||
Table<SurfaceElementIndex, PointIndex> p2sel;
|
||||
|
||||
BitArray domains, is_edge_moved, is_boundary_projected, is_boundary_moved;
|
||||
Array<SegmentIndex> moved_segs;
|
||||
int max_edge_nr, nfd_old, ndom_old;
|
||||
Array<int> new_mat_nrs;
|
||||
BitArray moved_surfaces;
|
||||
int np, nseg, nse, ne;
|
||||
double height;
|
||||
BitArray domains, is_edge_moved, is_boundary_projected, is_boundary_moved;
|
||||
Array<SegmentIndex> moved_segs;
|
||||
int max_edge_nr, nfd_old, ndom_old;
|
||||
Array<int> new_mat_nrs;
|
||||
BitArray moved_surfaces;
|
||||
int np, nseg, nse, ne;
|
||||
PointIndex first_new_pi;
|
||||
double total_height;
|
||||
Array<POINTTYPE, PointIndex> point_types;
|
||||
|
||||
bool have_single_segments;
|
||||
Array<Segment> segments, new_segments;
|
||||
// These parameters are derived from given BoundaryLayerParameters and the Mesh
|
||||
Array<double> par_heights;
|
||||
Array<int> par_surfid;
|
||||
bool insert_only_volume_elements;
|
||||
map<string, string> par_new_mat;
|
||||
bool have_material_map = false;
|
||||
Array<size_t> par_project_boundaries;
|
||||
|
||||
Array<double> surfacefacs;
|
||||
Array<int> si_map;
|
||||
Array<double, PointIndex> limits;
|
||||
bool have_single_segments;
|
||||
Array<Segment> old_segments, free_segments, segments, new_segments, new_segments_on_moved_bnd;
|
||||
Array<Element2d, SurfaceElementIndex> new_sels, new_sels_on_moved_bnd;
|
||||
Array<Array<PointIndex>, PointIndex> mapto;
|
||||
Array<PointIndex, PointIndex> mapfrom;
|
||||
|
||||
// major steps called in Perform()
|
||||
void CreateNewFaceDescriptors();
|
||||
void CreateFaceDescriptorsSides();
|
||||
void CalculateGrowthVectors();
|
||||
Array<Array<pair<SegmentIndex, int>>, SegmentIndex> BuildSegMap();
|
||||
Array<double> surfacefacs;
|
||||
Array<int> si_map;
|
||||
|
||||
BitArray ProjectGrowthVectorsOnSurface();
|
||||
void InterpolateSurfaceGrowthVectors();
|
||||
void InterpolateGrowthVectors();
|
||||
void LimitGrowthVectorLengths();
|
||||
std::map<PointIndex, SpecialBoundaryPoint> special_boundary_points;
|
||||
std::map<PointIndex, std::tuple<Vec<3>*, double>> growth_vector_map;
|
||||
|
||||
void InsertNewElements(FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap, const BitArray & in_surface_direction);
|
||||
void SetDomInOut();
|
||||
void SetDomInOutSides();
|
||||
void AddSegments();
|
||||
void FixVolumeElements();
|
||||
// major steps called in Perform()
|
||||
void CreateNewFaceDescriptors ();
|
||||
void CreateFaceDescriptorsSides ();
|
||||
void CalculateGrowthVectors ();
|
||||
Array<Array<pair<SegmentIndex, int>>, SegmentIndex> BuildSegMap ();
|
||||
|
||||
// utility functions
|
||||
array<Point<3>, 2> GetMappedSeg( PointIndex pi );
|
||||
ArrayMem<Point<3>, 4> GetFace( SurfaceElementIndex sei );
|
||||
ArrayMem<Point<3>, 4> GetMappedFace( SurfaceElementIndex sei );
|
||||
ArrayMem<Point<3>, 4> GetMappedFace( SurfaceElementIndex sei, int face );
|
||||
BitArray ProjectGrowthVectorsOnSurface ();
|
||||
void InterpolateSurfaceGrowthVectors ();
|
||||
void InterpolateGrowthVectors ();
|
||||
void LimitGrowthVectorLengths ();
|
||||
void FixSurfaceElements ();
|
||||
|
||||
Vec<3> getNormal(const Element2d & el)
|
||||
{
|
||||
auto v0 = mesh[el[0]];
|
||||
return Cross(mesh[el[1]]-v0, mesh[el[2]]-v0).Normalize();
|
||||
}
|
||||
void InsertNewElements (FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap, const BitArray& in_surface_direction);
|
||||
void SetDomInOut ();
|
||||
void SetDomInOutSides ();
|
||||
void AddSegments ();
|
||||
void AddSurfaceElements ();
|
||||
|
||||
Vec<3> getEdgeTangent(PointIndex pi, int edgenr);
|
||||
Vec<3> getNormal (const Element2d& el)
|
||||
{
|
||||
auto v0 = mesh[el[0]];
|
||||
return Cross(mesh[el[1]] - v0, mesh[el[2]] - v0).Normalize();
|
||||
}
|
||||
|
||||
Vec<3> getEdgeTangent (PointIndex pi, int edgenr, FlatArray<Segment*> segs);
|
||||
};
|
||||
|
||||
} // namespace netgen
|
||||
|
@ -1,5 +1,5 @@
|
||||
#include <mystdlib.h>
|
||||
#include "meshing.hpp"
|
||||
#include "boundarylayer.hpp"
|
||||
#include "meshing2.hpp"
|
||||
#include "../geom2d/csg2d.hpp"
|
||||
|
||||
@ -243,10 +243,6 @@ namespace netgen
|
||||
|
||||
Array<SegmentIndex> segments;
|
||||
|
||||
// surface index map
|
||||
Array<int> si_map(mesh.GetNFD()+2);
|
||||
si_map = -1;
|
||||
|
||||
// int fd_old = mesh.GetNFD();
|
||||
|
||||
int max_edge_nr = -1;
|
||||
@ -254,8 +250,8 @@ namespace netgen
|
||||
|
||||
for(const auto& seg : line_segments)
|
||||
{
|
||||
if(seg.epgeominfo[0].edgenr > max_edge_nr)
|
||||
max_edge_nr = seg.epgeominfo[0].edgenr;
|
||||
if(seg.edgenr > max_edge_nr)
|
||||
max_edge_nr = seg.edgenr;
|
||||
if(seg.domin > max_domain)
|
||||
max_domain = seg.domin;
|
||||
if(seg.domout > max_domain)
|
||||
@ -263,6 +259,7 @@ namespace netgen
|
||||
}
|
||||
|
||||
int new_domain = max_domain+1;
|
||||
int new_edge_nr = max_edge_nr+1;
|
||||
|
||||
BitArray active_boundaries(max_edge_nr+1);
|
||||
BitArray active_segments(nseg);
|
||||
@ -283,12 +280,15 @@ namespace netgen
|
||||
}
|
||||
|
||||
{
|
||||
FaceDescriptor new_fd(0, 0, 0, -1);
|
||||
FaceDescriptor new_fd(0, 0, 0, -1);
|
||||
new_fd.SetBCProperty(new_domain);
|
||||
// int new_fd_index =
|
||||
mesh.AddFaceDescriptor(new_fd);
|
||||
if(should_make_new_domain)
|
||||
mesh.SetBCName(new_domain-1, "mapped_" + mesh.GetBCName(domain-1));
|
||||
{
|
||||
mesh.SetMaterial(new_domain, "layer_" + mesh.GetMaterial(domain));
|
||||
mesh.SetBCName(new_edge_nr - 1, "moved");
|
||||
}
|
||||
}
|
||||
|
||||
for(auto segi : Range(line_segments))
|
||||
@ -329,7 +329,7 @@ namespace netgen
|
||||
auto current_si = si;
|
||||
|
||||
auto first = current_seg[0];
|
||||
auto current = -1;
|
||||
PointIndex current(PointIndex::INVALID);
|
||||
auto next = current_seg[1];
|
||||
|
||||
if(points_done.Test(first))
|
||||
@ -354,7 +354,7 @@ namespace netgen
|
||||
current_si = sj;
|
||||
current_seg = mesh[sj];
|
||||
|
||||
next = current_seg[0] + current_seg[1] - current;
|
||||
next = current_seg[0]-current + current_seg[1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -493,7 +493,7 @@ namespace netgen
|
||||
if(growthvectors[pi].Length2() == 0.0)
|
||||
continue;
|
||||
|
||||
PointIndex pi1 = seg0[0] + seg0[1] - pi;
|
||||
PointIndex pi1 = seg0[0] - pi + seg0[1];
|
||||
auto p1 = mesh[pi1];
|
||||
auto p = mesh[pi];
|
||||
|
||||
@ -584,13 +584,15 @@ namespace netgen
|
||||
auto p2 = [](Point<3> p) { return Point<2>{p[0], p[1]}; };
|
||||
|
||||
auto seg = line_segments[segi];
|
||||
double alpha,beta;
|
||||
intersect( p2(mesh[seg[0]]), p2(mesh[seg[0]]+total_thickness*growthvectors[seg[0]]), p2(mesh[seg[1]]), p2(mesh[seg[1]]+total_thickness*growthvectors[seg[1]]), alpha, beta );
|
||||
|
||||
if(beta>0 && alpha>0 && alpha<1.1)
|
||||
growth[seg[0]] = min(growth[seg[0]], 0.8*alpha);
|
||||
if(alpha>0 && beta>0 && beta<1.1)
|
||||
growth[seg[1]] = min(growth[seg[1]], 0.8*beta);
|
||||
double alpha=0.0;
|
||||
double beta=0.0;
|
||||
if (intersect(p2(mesh[seg[0]]), p2(mesh[seg[0]] + total_thickness * growthvectors[seg[0]]), p2(mesh[seg[1]]), p2(mesh[seg[1]] + total_thickness * growthvectors[seg[1]]), alpha, beta))
|
||||
{
|
||||
if (beta > 0 && alpha > 0 && alpha < 1.1)
|
||||
growth[seg[0]] = min(growth[seg[0]], 0.8 * alpha);
|
||||
if (alpha > 0 && beta > 0 && beta < 1.1)
|
||||
growth[seg[1]] = min(growth[seg[1]], 0.8 * beta);
|
||||
}
|
||||
|
||||
for (auto segj : Range(mesh.LineSegments()))
|
||||
if(segi!=segj)
|
||||
@ -616,8 +618,6 @@ namespace netgen
|
||||
}
|
||||
}
|
||||
|
||||
map<pair<PointIndex, PointIndex>, int> seg2edge;
|
||||
|
||||
// insert new elements ( and move old ones )
|
||||
for(auto si : moved_segs)
|
||||
{
|
||||
@ -627,8 +627,6 @@ namespace netgen
|
||||
auto & pm0 = mapto[seg[0]];
|
||||
auto & pm1 = mapto[seg[1]];
|
||||
|
||||
// auto newindex = si_map[domain];
|
||||
|
||||
Segment s = seg;
|
||||
s.geominfo[0] = {};
|
||||
s.geominfo[1] = {};
|
||||
@ -636,10 +634,10 @@ namespace netgen
|
||||
s[1] = pm1.Last();
|
||||
s[2] = PointIndex::INVALID;
|
||||
auto pair = s[0] < s[1] ? make_pair(s[0], s[1]) : make_pair(s[1], s[0]);
|
||||
if(seg2edge.find(pair) == seg2edge.end())
|
||||
seg2edge[pair] = ++max_edge_nr;
|
||||
s.edgenr = seg2edge[pair];
|
||||
s.si = seg.si;
|
||||
s.edgenr = new_edge_nr;
|
||||
s.epgeominfo[0].edgenr = -1;
|
||||
s.epgeominfo[1].edgenr = -1;
|
||||
s.si = s.edgenr;
|
||||
mesh.AddSegment(s);
|
||||
|
||||
for ( auto i : Range(thicknesses))
|
||||
|
497
libsrc/meshing/boundarylayer_interpolate.cpp
Normal file
497
libsrc/meshing/boundarylayer_interpolate.cpp
Normal file
@ -0,0 +1,497 @@
|
||||
#include "boundarylayer.hpp"
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
struct Neighbor
|
||||
{
|
||||
PointIndex pi;
|
||||
SurfaceElementIndex sei;
|
||||
double weight;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
Array<ArrayMem<detail::Neighbor, 20>>
|
||||
BuildNeighbors (FlatArray<PointIndex> points, const Mesh& mesh)
|
||||
{
|
||||
auto p2sel = mesh.CreatePoint2SurfaceElementTable();
|
||||
|
||||
Array<ArrayMem<detail::Neighbor, 20>> neighbors(points.Size());
|
||||
|
||||
ArrayMem<double, 20> angles;
|
||||
ArrayMem<double, 20> inv_dists;
|
||||
for (auto i : points.Range())
|
||||
{
|
||||
auto& p_neighbors = neighbors[i];
|
||||
auto pi = points[i];
|
||||
angles.SetSize(0);
|
||||
inv_dists.SetSize(0);
|
||||
for (auto sei : p2sel[pi])
|
||||
{
|
||||
const auto& sel = mesh[sei];
|
||||
for (auto pi1 : sel.PNums())
|
||||
{
|
||||
if (pi1 == pi)
|
||||
continue;
|
||||
auto pi2 = pi1;
|
||||
for (auto pi_ : sel.PNums())
|
||||
{
|
||||
if (pi_ != pi && pi_ != pi1)
|
||||
{
|
||||
pi2 = pi_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
p_neighbors.Append({pi1, sei, 0.0});
|
||||
inv_dists.Append(1.0 / (mesh[pi1] - mesh[pi]).Length());
|
||||
auto dot = (mesh[pi1] - mesh[pi]).Normalize() * (mesh[pi2] - mesh[pi]).Normalize();
|
||||
angles.Append(acos(dot));
|
||||
}
|
||||
}
|
||||
double sum_inv_dist = 0.0;
|
||||
for (auto inv_dist : inv_dists)
|
||||
sum_inv_dist += inv_dist;
|
||||
double sum_angle = 0.0;
|
||||
for (auto angle : angles)
|
||||
sum_angle += angle;
|
||||
|
||||
double sum_weight = 0.0;
|
||||
for (auto i : Range(inv_dists))
|
||||
{
|
||||
p_neighbors[i].weight =
|
||||
inv_dists[i] * angles[i] / sum_inv_dist / sum_angle;
|
||||
sum_weight += p_neighbors[i].weight;
|
||||
}
|
||||
for (auto i : Range(inv_dists))
|
||||
p_neighbors[i].weight /= sum_weight;
|
||||
}
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
void BoundaryLayerTool ::InterpolateGrowthVectors ()
|
||||
{
|
||||
point_types.SetSize(mesh.GetNP());
|
||||
for (auto p : mesh.Points().Range())
|
||||
point_types[p] = mesh[p].Type();
|
||||
|
||||
int new_max_edge_nr = max_edge_nr;
|
||||
for (const auto& seg : segments)
|
||||
if (seg.edgenr > new_max_edge_nr)
|
||||
new_max_edge_nr = seg.edgenr;
|
||||
for (const auto& seg : new_segments)
|
||||
if (seg.edgenr > new_max_edge_nr)
|
||||
new_max_edge_nr = seg.edgenr;
|
||||
|
||||
auto getGW = [&] (PointIndex pi) -> Vec<3> {
|
||||
if (growth_vector_map.count(pi) == 0)
|
||||
growth_vector_map[pi] = {&growthvectors[pi], total_height};
|
||||
auto [gw, height] = growth_vector_map[pi];
|
||||
return height * (*gw);
|
||||
};
|
||||
auto addGW = [&] (PointIndex pi, Vec<3> vec) {
|
||||
if (growth_vector_map.count(pi) == 0)
|
||||
growth_vector_map[pi] = {&growthvectors[pi], total_height};
|
||||
auto [gw, height] = growth_vector_map[pi];
|
||||
*gw += 1.0 / height * vec;
|
||||
};
|
||||
|
||||
// interpolate tangential component of growth vector along edge
|
||||
if (max_edge_nr >= new_max_edge_nr)
|
||||
return;
|
||||
|
||||
auto edgenr2seg = ngcore::CreateSortedTable<Segment*, int>(
|
||||
Range(segments.Size() + new_segments.Size()),
|
||||
[&] (auto& table, size_t segi) {
|
||||
auto& seg = segi < segments.Size()
|
||||
? segments[segi]
|
||||
: new_segments[segi - segments.Size()];
|
||||
table.Add(seg.edgenr, &seg);
|
||||
},
|
||||
new_max_edge_nr + 1);
|
||||
auto point2seg = ngcore::CreateSortedTable<Segment*, PointIndex>(
|
||||
Range(segments.Size() + new_segments.Size()),
|
||||
[&] (auto& table, size_t segi) {
|
||||
auto& seg = segi < segments.Size()
|
||||
? segments[segi]
|
||||
: new_segments[segi - segments.Size()];
|
||||
table.Add(seg[0], &seg);
|
||||
table.Add(seg[1], &seg);
|
||||
},
|
||||
mesh.GetNP());
|
||||
|
||||
for (auto edgenr : Range(1, new_max_edge_nr + 1))
|
||||
{
|
||||
// "inner" edges between two flat faces are not treated as edges for interpolation
|
||||
bool no_angles = true;
|
||||
ArrayMem<SurfaceElementIndex, 4> faces;
|
||||
|
||||
for (auto* p_seg : edgenr2seg[edgenr])
|
||||
{
|
||||
auto& seg = *p_seg;
|
||||
faces.SetSize(0);
|
||||
// if (seg[0] <= p2sel.Size())
|
||||
if (seg[0] < IndexBASE<PointIndex>() + p2sel.Size())
|
||||
{
|
||||
for (auto sei : p2sel[seg[0]])
|
||||
if (moved_surfaces.Test(mesh[sei].GetIndex()) && p2sel[seg[1]].Contains(sei))
|
||||
faces.Append(sei);
|
||||
}
|
||||
|
||||
if (faces.Size() == 2 && mesh[faces[0]].GetIndex() != mesh[faces[1]].GetIndex())
|
||||
{
|
||||
auto n0 = getNormal(mesh[faces[0]]);
|
||||
auto n1 = getNormal(mesh[faces[1]]);
|
||||
if (n0 * n1 < 0.99)
|
||||
no_angles = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
no_angles = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (no_angles && faces.Size() == 2 && have_material_map)
|
||||
if (par_new_mat[mesh.GetBCName(mesh[faces[0]].GetIndex() - 1)] != par_new_mat[mesh.GetBCName(mesh[faces[1]].GetIndex() - 1)])
|
||||
no_angles = false;
|
||||
|
||||
if (no_angles)
|
||||
{
|
||||
for (auto* p_seg : edgenr2seg[edgenr])
|
||||
for (auto pi : p_seg->PNums())
|
||||
{
|
||||
if (pi >= first_new_pi)
|
||||
continue;
|
||||
if (point_types[pi] == EDGEPOINT)
|
||||
point_types[pi] = SURFACEPOINT;
|
||||
else if (point_types[pi] == FIXEDPOINT)
|
||||
{
|
||||
// Check at edge corners if all adjacent surface elements have roughly the same normal.
|
||||
// If so, also treat this point as surface point for growth vector interpolation
|
||||
Vec<3> n = 0.0;
|
||||
for (auto si : p2sel[pi])
|
||||
n += getNormal(mesh[si]);
|
||||
n.Normalize();
|
||||
bool is_corner = false;
|
||||
for (auto si : p2sel[pi])
|
||||
if (getNormal(mesh[si]) * n < 0.99)
|
||||
is_corner = true;
|
||||
if (!is_corner)
|
||||
point_types[pi] = SURFACEPOINT;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto edgenr : Range(max_edge_nr + 1, new_max_edge_nr + 1))
|
||||
{
|
||||
double edge_len = 0.;
|
||||
bool any_grows = false;
|
||||
|
||||
auto is_end_point = [&] (PointIndex pi) {
|
||||
auto segs = point2seg[pi];
|
||||
if (segs.Size() == 1)
|
||||
return true;
|
||||
auto first_edgenr = (*segs[0]).edgenr;
|
||||
for (auto* p_seg : segs)
|
||||
if (p_seg->edgenr != first_edgenr)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
Array<PointIndex> points;
|
||||
for (auto* p_seg : edgenr2seg[edgenr])
|
||||
{
|
||||
auto& seg = *p_seg;
|
||||
|
||||
if (getGW(seg[0]).Length2() != 0 || getGW(seg[1]).Length2() != 0)
|
||||
any_grows = true;
|
||||
|
||||
if (points.Size() == 0)
|
||||
for (auto i : Range(2))
|
||||
if (is_end_point(seg[i]))
|
||||
{
|
||||
points.Append(seg[i]);
|
||||
points.Append(seg[1 - i]);
|
||||
edge_len += (mesh[seg[1]] - mesh[seg[0]]).Length();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!any_grows)
|
||||
{
|
||||
PrintMessage(1, "BLayer: skip interpolating growth vectors at edge ", edgenr + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!points.Size())
|
||||
{
|
||||
if (debugparam.debugoutput)
|
||||
cerr << "Could not find startpoint for edge " << edgenr << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
std::set<PointIndex> points_set;
|
||||
points_set.insert(points[0]);
|
||||
points_set.insert(points[1]);
|
||||
|
||||
bool point_found = true;
|
||||
while (point_found)
|
||||
{
|
||||
if (is_end_point(points.Last()))
|
||||
break;
|
||||
point_found = false;
|
||||
for (auto* p_seg : point2seg[points.Last()])
|
||||
{
|
||||
const auto& seg = *p_seg;
|
||||
if (seg.edgenr != edgenr)
|
||||
continue;
|
||||
auto plast = points.Last();
|
||||
if (plast != seg[0] && plast != seg[1])
|
||||
continue;
|
||||
auto pnew = plast == seg[0] ? seg[1] : seg[0];
|
||||
if (pnew == points[0] && points.Size() > 1)
|
||||
{
|
||||
}
|
||||
if (points_set.count(pnew) > 0 && (pnew != points[0] || points.Size() == 2))
|
||||
continue;
|
||||
edge_len += (mesh[points.Last()] - mesh[pnew]).Length();
|
||||
points.Append(pnew);
|
||||
points_set.insert(pnew);
|
||||
point_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!point_found)
|
||||
{
|
||||
if (debugparam.debugoutput)
|
||||
{
|
||||
cerr << "Could not find connected list of line segments for edge "
|
||||
<< edgenr << endl;
|
||||
cerr << "current points: " << endl
|
||||
<< points << endl;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (getGW(points[0]).Length2() == 0 && getGW(points.Last()).Length2() == 0)
|
||||
continue;
|
||||
|
||||
// tangential part of growth vectors
|
||||
auto t1 = (mesh[points[1]] - mesh[points[0]]).Normalize();
|
||||
auto gt1 = getGW(points[0]) * t1 * t1;
|
||||
auto t2 =
|
||||
(mesh[points.Last()] - mesh[points[points.Size() - 2]]).Normalize();
|
||||
auto gt2 = getGW(points.Last()) * t2 * t2;
|
||||
|
||||
double len = 0.;
|
||||
for (auto i : IntRange(1, points.Size() - 1))
|
||||
{
|
||||
auto pi = points[i];
|
||||
len += (mesh[pi] - mesh[points[i - 1]]).Length();
|
||||
auto t = getEdgeTangent(pi, edgenr, point2seg[pi]);
|
||||
auto lam = len / edge_len;
|
||||
auto interpol = (1 - lam) * (gt1 * t) * t + lam * (gt2 * t) * t;
|
||||
addGW(pi, interpol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BoundaryLayerTool ::InterpolateSurfaceGrowthVectors ()
|
||||
{
|
||||
static Timer tall("InterpolateSurfaceGrowthVectors");
|
||||
RegionTimer rtall(tall);
|
||||
static Timer tsmooth("InterpolateSurfaceGrowthVectors-Smoothing");
|
||||
auto np_old = this->np;
|
||||
[[maybe_unused]] auto np = mesh.GetNP();
|
||||
|
||||
auto hasMoved = [&] (PointIndex pi) {
|
||||
return (pi - IndexBASE<PointIndex>() >= np_old) || mapto[pi].Size() > 0 || special_boundary_points.count(pi);
|
||||
};
|
||||
|
||||
std::set<PointIndex> points_set;
|
||||
for (const auto& sel : mesh.SurfaceElements())
|
||||
{
|
||||
for (auto pi : sel.PNums())
|
||||
if (point_types[pi] == SURFACEPOINT && hasMoved(pi))
|
||||
points_set.insert(pi);
|
||||
}
|
||||
|
||||
Array<PointIndex> points;
|
||||
for (auto pi : points_set)
|
||||
points.Append(pi);
|
||||
QuickSort(points);
|
||||
|
||||
// smooth tangential part of growth vectors from edges to surface elements
|
||||
Array<Vec<3>, PointIndex> corrections(mesh.GetNP());
|
||||
corrections = 0.0;
|
||||
RegionTimer rtsmooth(tsmooth);
|
||||
auto neighbors = BuildNeighbors(points, mesh);
|
||||
|
||||
Array<Vec<3>, SurfaceElementIndex> surf_normals(mesh.GetNSE());
|
||||
for (auto sei : mesh.SurfaceElements().Range())
|
||||
surf_normals[sei] = getNormal(mesh[sei]);
|
||||
|
||||
BitArray interpolate_tangent(mesh.GetNP() + 1);
|
||||
interpolate_tangent = false;
|
||||
for (auto pi : points)
|
||||
{
|
||||
for (auto sei : p2sel[pi])
|
||||
if (is_boundary_moved[mesh[sei].GetIndex()])
|
||||
interpolate_tangent.SetBit(pi);
|
||||
}
|
||||
|
||||
constexpr int N_STEPS = 64;
|
||||
for ([[maybe_unused]] auto i : Range(N_STEPS))
|
||||
{
|
||||
for (auto i : points.Range())
|
||||
{
|
||||
auto pi = points[i];
|
||||
auto& p_neighbors = neighbors[i];
|
||||
|
||||
ArrayMem<Vec<3>, 20> g_vectors;
|
||||
double max_len = 0.0;
|
||||
double sum_len = 0.0;
|
||||
|
||||
// average only tangent component on new bl points, average whole growth
|
||||
// vector otherwise
|
||||
bool do_average_tangent = true;
|
||||
for (const auto& s : p_neighbors)
|
||||
{
|
||||
auto gw_other = growthvectors[s.pi] + corrections[s.pi];
|
||||
if (do_average_tangent)
|
||||
{
|
||||
auto n = surf_normals[s.sei];
|
||||
gw_other = gw_other - (gw_other * n) * n;
|
||||
}
|
||||
auto v = gw_other;
|
||||
auto len = v.Length2();
|
||||
sum_len += len;
|
||||
max_len = max(max_len, len);
|
||||
g_vectors.Append(v);
|
||||
}
|
||||
|
||||
if (max_len == 0.0)
|
||||
continue;
|
||||
|
||||
double lambda = 0;
|
||||
if (i > N_STEPS / 4.)
|
||||
lambda = 2.0 * (i - N_STEPS / 4.) / (N_STEPS / 2.);
|
||||
lambda = min(1.0, lambda);
|
||||
|
||||
auto& correction = corrections[pi];
|
||||
correction = 0.0;
|
||||
for (const auto i : p_neighbors.Range())
|
||||
{
|
||||
auto v = g_vectors[i];
|
||||
double weight = lambda * p_neighbors[i].weight + (1.0 - lambda) * v.Length2() / sum_len;
|
||||
correction += weight * v;
|
||||
}
|
||||
|
||||
if (!do_average_tangent)
|
||||
correction -= growthvectors[pi];
|
||||
}
|
||||
}
|
||||
|
||||
for (auto pi : points)
|
||||
growthvectors[pi] += corrections[pi];
|
||||
}
|
||||
|
||||
void BoundaryLayerTool ::FixSurfaceElements ()
|
||||
{
|
||||
static Timer tall("FixSurfaceElements");
|
||||
RegionTimer rtall(tall);
|
||||
[[maybe_unused]] auto np_old = this->np;
|
||||
[[maybe_unused]] auto np = mesh.GetNP();
|
||||
|
||||
non_bl_growth_vectors.clear();
|
||||
|
||||
auto getGW = [&] (PointIndex pi) -> Vec<3> {
|
||||
// return growthvectors[pi];
|
||||
if (growth_vector_map.count(pi) == 0)
|
||||
{
|
||||
non_bl_growth_vectors[pi] = .0;
|
||||
growth_vector_map[pi] = {&non_bl_growth_vectors[pi], 1.0};
|
||||
}
|
||||
auto [gw, height] = growth_vector_map[pi];
|
||||
return height * (*gw);
|
||||
};
|
||||
|
||||
auto addGW = [&] (PointIndex pi, Vec<3> vec) {
|
||||
if (growth_vector_map.count(pi) == 0)
|
||||
{
|
||||
non_bl_growth_vectors[pi] = .0;
|
||||
growth_vector_map[pi] = {&non_bl_growth_vectors[pi], 1.0};
|
||||
}
|
||||
auto [gw, height] = growth_vector_map[pi];
|
||||
*gw += 1.0 / height * vec;
|
||||
};
|
||||
|
||||
std::set<PointIndex> points_set;
|
||||
// only smooth over old surface elements
|
||||
for (SurfaceElementIndex sei : Range(nse))
|
||||
{
|
||||
const auto& sel = mesh[sei];
|
||||
if (sel.GetNP() == 3 && is_boundary_moved[sel.GetIndex()])
|
||||
for (auto pi : sel.PNums())
|
||||
if (point_types[pi] == SURFACEPOINT)
|
||||
points_set.insert(pi);
|
||||
}
|
||||
|
||||
Array<PointIndex> points;
|
||||
for (auto pi : points_set)
|
||||
points.Append(pi);
|
||||
QuickSort(points);
|
||||
|
||||
Array<Vec<3>, PointIndex> corrections(mesh.GetNP());
|
||||
corrections = 0.0;
|
||||
|
||||
auto neighbors = BuildNeighbors(points, mesh);
|
||||
|
||||
constexpr int N_STEPS = 32;
|
||||
for ([[maybe_unused]] auto i : Range(N_STEPS))
|
||||
{
|
||||
for (auto i : points.Range())
|
||||
{
|
||||
auto pi = points[i];
|
||||
auto& p_neighbors = neighbors[i];
|
||||
|
||||
ArrayMem<Vec<3>, 20> g_vectors;
|
||||
double max_len = 0.0;
|
||||
double sum_len = 0.0;
|
||||
|
||||
for (const auto& s : p_neighbors)
|
||||
{
|
||||
auto v = getGW(s.pi) + corrections[s.pi];
|
||||
auto len = v.Length2();
|
||||
sum_len += len;
|
||||
max_len = max(max_len, len);
|
||||
g_vectors.Append(v);
|
||||
}
|
||||
|
||||
if (max_len == 0.0)
|
||||
continue;
|
||||
|
||||
double lambda = 0;
|
||||
if (i > N_STEPS / 4.)
|
||||
lambda = 2.0 * (i - N_STEPS / 4.) / (N_STEPS / 2.);
|
||||
lambda = min(1.0, lambda);
|
||||
|
||||
auto& correction = corrections[pi];
|
||||
correction = 0.0;
|
||||
for (const auto i : p_neighbors.Range())
|
||||
{
|
||||
auto v = g_vectors[i];
|
||||
double weight = lambda * p_neighbors[i].weight + (1.0 - lambda) * v.Length2() / sum_len;
|
||||
correction += weight * v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto pi : points)
|
||||
addGW(pi, corrections[pi]);
|
||||
}
|
||||
|
||||
} // namespace netgen
|
780
libsrc/meshing/boundarylayer_limiter.hpp
Normal file
780
libsrc/meshing/boundarylayer_limiter.hpp
Normal file
@ -0,0 +1,780 @@
|
||||
#include "boundarylayer.hpp"
|
||||
#include <core/array.hpp>
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
struct Intersection_
|
||||
{
|
||||
bool is_intersecting = false;
|
||||
double lam0 = -1, lam1 = -1;
|
||||
Point<3> p;
|
||||
double bary[3];
|
||||
operator bool() const { return is_intersecting; }
|
||||
};
|
||||
|
||||
struct GrowthVectorLimiter
|
||||
{
|
||||
typedef std::array<Point<3>, 2> Seg;
|
||||
typedef std::array<Point<3>, 3> Trig;
|
||||
|
||||
BoundaryLayerTool& tool;
|
||||
const BoundaryLayerParameters& params;
|
||||
Mesh& mesh;
|
||||
double height;
|
||||
Array<double, PointIndex> limits;
|
||||
FlatArray<Vec<3>, PointIndex> growthvectors;
|
||||
BitArray changed_domains;
|
||||
unique_ptr<BoxTree<3>> tree;
|
||||
Array<PointIndex, PointIndex> map_from;
|
||||
Table<SurfaceElementIndex, PointIndex> p2sel;
|
||||
|
||||
GrowthVectorLimiter (BoundaryLayerTool& tool_)
|
||||
: tool(tool_), params(tool_.params), mesh(tool_.mesh), height(tool_.total_height), growthvectors(tool_.growthvectors), map_from(mesh.Points().Size())
|
||||
{
|
||||
changed_domains = tool.domains;
|
||||
if (!params.outside)
|
||||
changed_domains.Invert();
|
||||
|
||||
map_from = tool.mapfrom;
|
||||
p2sel = ngcore::CreateSortedTable<SurfaceElementIndex, PointIndex>(
|
||||
tool.new_sels.Range(),
|
||||
[&] (auto& table, SurfaceElementIndex ei) {
|
||||
for (PointIndex pi : tool.new_sels[ei].PNums())
|
||||
table.Add(pi, ei);
|
||||
},
|
||||
mesh.GetNP());
|
||||
}
|
||||
|
||||
auto SurfaceElementsRange () { return Range(tool.nse + tool.new_sels.Size()); }
|
||||
|
||||
void WriteErrorMesh (string name)
|
||||
{
|
||||
if (!debugparam.write_mesh_on_error)
|
||||
return;
|
||||
Mesh out_mesh;
|
||||
out_mesh = mesh;
|
||||
for (auto [pi, data] : tool.growth_vector_map)
|
||||
{
|
||||
auto [gw, height] = data;
|
||||
out_mesh[pi] += limits[pi] * height * (*gw);
|
||||
}
|
||||
out_mesh.Save(name);
|
||||
}
|
||||
|
||||
const auto& Get (SurfaceElementIndex sei)
|
||||
{
|
||||
if (sei < tool.nse)
|
||||
return mesh[sei];
|
||||
return tool.new_sels[sei - tool.nse];
|
||||
}
|
||||
|
||||
std::pair<double, double> GetMinMaxLimit (SurfaceElementIndex sei)
|
||||
{
|
||||
const auto& sel = Get(sei);
|
||||
double min_limit = GetLimit(sel[0]);
|
||||
double max_limit = min_limit;
|
||||
for (auto i : IntRange(1, sel.GetNP()))
|
||||
{
|
||||
auto limit = GetLimit(sel[i]);
|
||||
min_limit = min(min_limit, limit);
|
||||
max_limit = max(max_limit, limit);
|
||||
}
|
||||
return {min_limit, max_limit};
|
||||
}
|
||||
|
||||
double GetLimit (PointIndex pi)
|
||||
{
|
||||
if (pi < tool.first_new_pi)
|
||||
return limits[pi];
|
||||
return limits[map_from[pi]];
|
||||
}
|
||||
|
||||
bool SetLimit (PointIndex pi, double new_limit)
|
||||
{
|
||||
double& limit = (pi < tool.first_new_pi) ? limits[pi] : limits[map_from[pi]];
|
||||
if (limit <= new_limit)
|
||||
return false;
|
||||
limit = new_limit;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ScaleLimit (PointIndex pi, double factor)
|
||||
{
|
||||
double& limit = (pi < tool.first_new_pi) ? limits[pi] : limits[map_from[pi]];
|
||||
return SetLimit(pi, limit * factor);
|
||||
}
|
||||
|
||||
Vec<3> GetVector (PointIndex pi_to, double shift = 1., bool apply_limit = false)
|
||||
{
|
||||
auto [gw, height] = tool.growth_vector_map[pi_to];
|
||||
if (apply_limit)
|
||||
shift *= GetLimit(pi_to);
|
||||
return shift * height * (*gw);
|
||||
}
|
||||
|
||||
Point<3> GetPoint (PointIndex pi_to, double shift = 1., bool apply_limit = false)
|
||||
{
|
||||
if (pi_to < tool.first_new_pi || tool.growth_vector_map.count(pi_to) == 0)
|
||||
return mesh[pi_to];
|
||||
|
||||
return mesh[pi_to] + GetVector(pi_to, shift, apply_limit);
|
||||
}
|
||||
|
||||
Point<3> GetMappedPoint (PointIndex pi_from, double shift = 1., bool apply_limit = false)
|
||||
{
|
||||
auto pi_to = tool.mapto[pi_from].Last();
|
||||
return GetPoint(pi_to, shift, apply_limit);
|
||||
}
|
||||
|
||||
Seg GetMappedSeg (PointIndex pi_from, double shift = 1.)
|
||||
{
|
||||
return {mesh[pi_from], GetMappedPoint(pi_from, shift)};
|
||||
}
|
||||
|
||||
Seg GetSeg (PointIndex pi_to, double shift = 1., bool apply_limit = false)
|
||||
{
|
||||
return {GetPoint(pi_to, 0), GetPoint(pi_to, shift, apply_limit)};
|
||||
}
|
||||
|
||||
Trig GetTrig (SurfaceElementIndex sei, double shift = 0.0, bool apply_limit = false)
|
||||
{
|
||||
auto sel = Get(sei);
|
||||
Trig trig;
|
||||
for (auto i : Range(3))
|
||||
trig[i] = GetPoint(sel[i], shift, apply_limit);
|
||||
return trig;
|
||||
}
|
||||
|
||||
Trig GetMappedTrig (SurfaceElementIndex sei, double shift = 0.0)
|
||||
{
|
||||
auto sel = Get(sei);
|
||||
Trig trig;
|
||||
for (auto i : Range(3))
|
||||
trig[i] = GetMappedPoint(sel[i], shift);
|
||||
return trig;
|
||||
}
|
||||
|
||||
Trig GetSideTrig (SurfaceElementIndex sei, int index, double shift = 0.0, bool grow_first_vertex = true)
|
||||
{
|
||||
auto trig = GetMappedTrig(sei, 0.0);
|
||||
auto sel = Get(sei);
|
||||
auto index1 = (index + 1) % 3;
|
||||
if (!grow_first_vertex)
|
||||
index1 = (index + 2) % 3;
|
||||
trig[index] = GetMappedPoint(sel[index1], shift, true);
|
||||
return trig;
|
||||
}
|
||||
|
||||
array<Trig, 4> GetSideTrigs (SurfaceElementIndex sei, int i0, double shift = 0.0)
|
||||
{
|
||||
auto trig = GetMappedTrig(sei, 0.0);
|
||||
array<Trig, 4> trigs{trig, trig, trig, trig};
|
||||
|
||||
auto sel = Get(sei);
|
||||
auto i1 = (i0 + 1) % 3;
|
||||
auto i2 = (i0 + 2) % 3;
|
||||
auto p1 = GetMappedPoint(sel[i1], shift, true);
|
||||
auto p2 = GetMappedPoint(sel[i2], shift, true);
|
||||
|
||||
// create four trigs to span the quad from i1,i2 and their shifted points
|
||||
// i1, i2, shifted i1
|
||||
trigs[0][i0] = p1;
|
||||
|
||||
// i1, i2, shifted i2
|
||||
trigs[1][i0] = p2;
|
||||
|
||||
// i1, shifted i1, shifted i2
|
||||
trigs[2][i0] = p1;
|
||||
trigs[2][i2] = p2;
|
||||
|
||||
// i2, shifted i1, shifted i2
|
||||
trigs[2][i0] = p2;
|
||||
trigs[2][i1] = p1;
|
||||
|
||||
return trigs;
|
||||
}
|
||||
|
||||
static constexpr double INTERSECTION_SAFETY = .9;
|
||||
bool LimitGrowthVector (PointIndex pi_to, SurfaceElementIndex sei, double trig_shift, double seg_shift, bool check_prism_sides = false)
|
||||
{
|
||||
auto pi_from = map_from[pi_to];
|
||||
if (!pi_from.IsValid())
|
||||
return false;
|
||||
|
||||
for (auto pi : Get(sei).PNums())
|
||||
{
|
||||
if (pi == pi_from)
|
||||
return false;
|
||||
if (map_from[pi] == pi_from)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (check_prism_sides || trig_shift > .0)
|
||||
{
|
||||
auto [trig_min_limit, trig_max_limit] = GetMinMaxLimit(sei);
|
||||
if (GetLimit(pi_to) < trig_min_limit)
|
||||
return false;
|
||||
|
||||
auto getTrigs = [&] (double scaling = 1.0) -> ArrayMem<Trig, 3> {
|
||||
ArrayMem<Trig, 12> trigs;
|
||||
if (check_prism_sides)
|
||||
for (auto i : Range(3))
|
||||
for (auto trig : GetSideTrigs(sei, i, scaling * trig_shift))
|
||||
trigs.Append(trig);
|
||||
else
|
||||
trigs.Append(GetTrig(sei, scaling * trig_shift, true));
|
||||
return trigs;
|
||||
};
|
||||
|
||||
if (!check_prism_sides)
|
||||
{
|
||||
// If the growth vectors of all points are pointing in the same direction,
|
||||
// an intersection means, we also have an intersection with a prism side face
|
||||
// this is an extra check and handled later
|
||||
auto seg = GetSeg(pi_to, 1.0, false);
|
||||
auto gw = seg[1] - seg[0];
|
||||
|
||||
bool have_same_growth_direction = true;
|
||||
for (auto pi : Get(sei).PNums())
|
||||
{
|
||||
auto p_seg = GetSeg(pi, 1.0, false);
|
||||
auto p_gw = p_seg[1] - p_seg[0];
|
||||
have_same_growth_direction &= (gw * p_gw) > 0;
|
||||
}
|
||||
if (have_same_growth_direction)
|
||||
return false;
|
||||
}
|
||||
|
||||
double scaling = 1.0;
|
||||
while (true)
|
||||
{
|
||||
bool have_intersection = false;
|
||||
auto seg = GetSeg(pi_to, scaling * seg_shift, true);
|
||||
for (auto trig : getTrigs(scaling))
|
||||
have_intersection |= isIntersectingTrig(seg, trig);
|
||||
if (!have_intersection)
|
||||
break;
|
||||
scaling *= 0.9;
|
||||
}
|
||||
if (scaling == 1.0)
|
||||
return false;
|
||||
|
||||
double new_limit = scaling * max(GetLimit(pi_to), trig_max_limit);
|
||||
SetLimit(pi_to, new_limit);
|
||||
for (auto pi : Get(sei).PNums())
|
||||
SetLimit(pi, new_limit);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto seg = GetSeg(pi_to, seg_shift, false);
|
||||
auto trig = GetTrig(sei, 0.0);
|
||||
auto intersection = isIntersectingTrig(seg, trig);
|
||||
// checking with original surface elements -> allow only half the distance
|
||||
auto new_seg_limit = 0.40 * intersection.lam0 * seg_shift;
|
||||
if (intersection && new_seg_limit < GetLimit(pi_from))
|
||||
return SetLimit(pi_from, new_seg_limit);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void EqualizeLimits (double factor = .5)
|
||||
{
|
||||
static Timer t("GrowthVectorLimiter::EqualizeLimits");
|
||||
PrintMessage(5, "GrowthVectorLimiter - equalize limits");
|
||||
RegionTimer reg(t);
|
||||
if (factor == 0.0)
|
||||
return;
|
||||
// for (PointIndex pi : IntRange(tool.np, mesh.GetNP()))
|
||||
for (PointIndex pi : mesh.Points().Range().Modify(tool.np, 0))
|
||||
{
|
||||
// auto pi_from = map_from[pi];
|
||||
std::set<PointIndex> pis;
|
||||
for (auto sei : p2sel[pi])
|
||||
for (auto pi_ : tool.new_sels[sei].PNums())
|
||||
pis.insert(pi_);
|
||||
ArrayMem<double, 20> limits;
|
||||
for (auto pi1 : pis)
|
||||
{
|
||||
auto limit = GetLimit(pi1);
|
||||
if (limit > 0.0)
|
||||
limits.Append(GetLimit(pi1));
|
||||
}
|
||||
|
||||
if (limits.Size() == 0)
|
||||
continue;
|
||||
|
||||
double average = 0.0;
|
||||
for (auto l : limits)
|
||||
average += l;
|
||||
average /= limits.Size();
|
||||
|
||||
SetLimit(pi, factor * average + (1.0 - factor) * GetLimit(pi));
|
||||
}
|
||||
}
|
||||
|
||||
void LimitSelfIntersection (double safety = 1.4)
|
||||
{
|
||||
static Timer t("GrowthVectorLimiter::LimitSelfIntersection");
|
||||
PrintMessage(5, "GrowthVectorLimiter - self intersection");
|
||||
RegionTimer reg(t);
|
||||
// check for self-intersection within new elements (prisms/hexes)
|
||||
auto isIntersecting = [&] (SurfaceElementIndex sei, double shift) {
|
||||
// checks if surface element is self intersecting when growing with factor
|
||||
// shift
|
||||
|
||||
// ignore new surface elements, side trigs are only built
|
||||
// from original surface elements
|
||||
if (sei >= tool.nse)
|
||||
return false;
|
||||
const auto sel = Get(sei);
|
||||
auto np = sel.GetNP();
|
||||
for (auto i : Range(np))
|
||||
{
|
||||
if (sel[i] >= tool.first_new_pi)
|
||||
return false;
|
||||
if (tool.mapto[sel[i]].Size() == 0)
|
||||
return false;
|
||||
}
|
||||
for (auto i : Range(np))
|
||||
{
|
||||
auto seg = GetMappedSeg(sel[i], shift * limits[sel[i]]);
|
||||
for (auto fi : Range(np - 2))
|
||||
{
|
||||
for (auto side : {true, false})
|
||||
{
|
||||
auto trig = GetSideTrig(sei, i + fi, 1.0, side);
|
||||
if (isIntersectingPlane(seg, trig))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
for (SurfaceElementIndex sei : mesh.SurfaceElements().Range())
|
||||
{
|
||||
auto sel = mesh[sei];
|
||||
if (sei >= tool.nse)
|
||||
continue;
|
||||
if (!tool.moved_surfaces[sel.GetIndex()])
|
||||
continue;
|
||||
if (sel.GetNP() == 4)
|
||||
continue;
|
||||
|
||||
// const auto& fd = mesh.GetFaceDescriptor(sel.GetIndex());
|
||||
auto np = sel.GetNP();
|
||||
|
||||
double shift = 1.0;
|
||||
const double step_factor = 0.9;
|
||||
while (isIntersecting(sei, shift * safety))
|
||||
{
|
||||
shift *= step_factor;
|
||||
double max_limit = 0;
|
||||
for (auto i : Range(np))
|
||||
max_limit = max(max_limit, limits[sel[i]]);
|
||||
for (auto i : Range(np))
|
||||
if (max_limit == limits[sel[i]])
|
||||
ScaleLimit(sel[i], step_factor);
|
||||
// if (max_limit < 0.01) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checks if a segment is intersecting a plane, spanned by three points, lam
|
||||
// will be set s.t. p_intersect = seg[0] + lam * (seg[1]-seg[0])
|
||||
Intersection_ isIntersectingPlane (const Seg& seg,
|
||||
const Trig& trig)
|
||||
{
|
||||
auto t1 = trig[1] - trig[0];
|
||||
auto t2 = trig[2] - trig[0];
|
||||
auto n = Cross(t1, t2);
|
||||
auto v0n = (seg[0] - trig[0]) * n;
|
||||
auto v1n = (seg[1] - trig[0]) * n;
|
||||
|
||||
Intersection_ intersection;
|
||||
intersection.lam0 = -v0n / (v1n - v0n);
|
||||
intersection.p = seg[0] + intersection.lam0 * (seg[1] - seg[0]);
|
||||
intersection.is_intersecting = (v0n * v1n < 0) && (intersection.lam0 > -1e-8) && (intersection.lam0 < 1 + 1e-8);
|
||||
|
||||
return intersection;
|
||||
}
|
||||
|
||||
Intersection_ isIntersectingTrig (const Seg& seg, const Trig& trig)
|
||||
{
|
||||
auto intersection = isIntersectingPlane(seg, trig);
|
||||
if (!intersection)
|
||||
return intersection;
|
||||
|
||||
auto p = seg[0] + intersection.lam0 * (seg[1] - seg[0]) - trig[0];
|
||||
|
||||
Vec3d col1 = trig[1] - trig[0];
|
||||
Vec3d col2 = trig[2] - trig[0];
|
||||
Vec3d col3 = Cross(col1, col2);
|
||||
Vec3d rhs = p;
|
||||
Vec3d bary;
|
||||
SolveLinearSystem(col1, col2, col3, rhs, bary);
|
||||
|
||||
intersection.lam1 = 0;
|
||||
double eps = 1e-4;
|
||||
if (bary.X() >= -eps && bary.Y() >= -eps && bary.X() + bary.Y() <= 1 + eps)
|
||||
{
|
||||
intersection.bary[0] = bary.X();
|
||||
intersection.bary[1] = bary.Y();
|
||||
intersection.bary[2] = 1.0 - bary.X() - bary.Y();
|
||||
}
|
||||
else
|
||||
intersection.is_intersecting = false;
|
||||
return intersection;
|
||||
}
|
||||
|
||||
Intersection_ isIntersectingTrig (PointIndex pi_from, PointIndex pi_to, SurfaceElementIndex sei, double shift = 0.0)
|
||||
{
|
||||
// JS: where is that GetSeg function ?
|
||||
return isIntersectingTrig(GetSeg(pi_from, pi_to), GetTrig(sei, shift));
|
||||
}
|
||||
|
||||
void BuildSearchTree (double trig_shift)
|
||||
{
|
||||
static Timer t("BuildSearchTree");
|
||||
RegionTimer rt(t);
|
||||
Box<3> bbox(Box<3>::EMPTY_BOX);
|
||||
for (PointIndex pi : mesh.Points().Range())
|
||||
{
|
||||
bbox.Add(mesh[pi]);
|
||||
bbox.Add(GetPoint(pi, 1.1));
|
||||
}
|
||||
|
||||
tree = make_unique<BoxTree<3>>(bbox);
|
||||
|
||||
for (auto sei : SurfaceElementsRange())
|
||||
{
|
||||
const auto& sel = Get(sei);
|
||||
// auto sel_index = sel.GetIndex();
|
||||
|
||||
Box<3> box(Box<3>::EMPTY_BOX);
|
||||
for (auto pi : sel.PNums())
|
||||
{
|
||||
box.Add(GetPoint(pi, 0.));
|
||||
box.Add(GetPoint(pi, trig_shift * GetLimit(pi)));
|
||||
}
|
||||
tree->Insert(box, sei);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TFunc>
|
||||
void FindTreeIntersections (double trig_shift, double seg_shift, TFunc f, TBitArray<PointIndex>* relevant_points = nullptr)
|
||||
{
|
||||
static Timer t("GrowthVectorLimiter::FindTreeIntersections");
|
||||
RegionTimer rt(t);
|
||||
BuildSearchTree(trig_shift);
|
||||
auto np_new = mesh.Points().Size();
|
||||
// int counter = 0;
|
||||
for (auto i : IntRange(tool.np, np_new))
|
||||
{
|
||||
PointIndex pi_to = i + IndexBASE<PointIndex>();
|
||||
PointIndex pi_from = map_from[pi_to];
|
||||
if (!pi_from.IsValid())
|
||||
throw Exception("Point not mapped");
|
||||
|
||||
if (relevant_points && !relevant_points->Test(pi_to) && !relevant_points->Test(pi_from))
|
||||
continue;
|
||||
|
||||
Box<3> box(Box<3>::EMPTY_BOX);
|
||||
// auto seg = GetSeg(pi_to, seg_shift);
|
||||
|
||||
box.Add(GetPoint(pi_to, 0));
|
||||
box.Add(GetPoint(pi_to, GetLimit(pi_from)));
|
||||
tree->GetFirstIntersecting(box.PMin(), box.PMax(), [&] (SurfaceElementIndex sei) {
|
||||
const auto& sel = Get(sei);
|
||||
if (sel.PNums().Contains(pi_from))
|
||||
return false;
|
||||
if (sel.PNums().Contains(pi_to))
|
||||
return false;
|
||||
// counter++;
|
||||
f(pi_to, sei);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void FixIntersectingSurfaceTrigs ()
|
||||
{
|
||||
static Timer t("GrowthVectorLimiter::FixIntersectingSurfaceTrigs");
|
||||
RegionTimer reg(t);
|
||||
// check if surface trigs are intersecting each other
|
||||
bool changed = true;
|
||||
std::set<PointIndex> special_points;
|
||||
|
||||
if (tool.insert_only_volume_elements)
|
||||
for (auto [pi, special_point] : tool.special_boundary_points)
|
||||
{
|
||||
special_points.insert(pi);
|
||||
for (auto& group : special_point.growth_groups)
|
||||
special_points.insert(group.new_points.Last());
|
||||
}
|
||||
|
||||
auto skip_trig = [&] (const Element2d& tri) {
|
||||
if (!tool.insert_only_volume_elements)
|
||||
return false;
|
||||
for (auto pi : tri.PNums())
|
||||
if (special_points.find(pi) != special_points.end())
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
while (changed)
|
||||
{
|
||||
changed = false;
|
||||
Point3d pmin, pmax;
|
||||
mesh.GetBox(pmin, pmax);
|
||||
BoxTree<3, SurfaceElementIndex> setree(pmin, pmax);
|
||||
|
||||
for (auto sei : SurfaceElementsRange())
|
||||
{
|
||||
const Element2d& tri = Get(sei);
|
||||
|
||||
if (skip_trig(tri))
|
||||
continue;
|
||||
|
||||
Box<3> box(Box<3>::EMPTY_BOX);
|
||||
for (PointIndex pi : tri.PNums())
|
||||
box.Add(GetPoint(pi, 1.0, true));
|
||||
|
||||
box.Increase(1e-3 * box.Diam());
|
||||
setree.Insert(box, sei);
|
||||
}
|
||||
|
||||
for (auto sei : SurfaceElementsRange())
|
||||
{
|
||||
const Element2d& tri = Get(sei);
|
||||
|
||||
if (skip_trig(tri))
|
||||
continue;
|
||||
|
||||
Box<3> box(Box<3>::EMPTY_BOX);
|
||||
for (PointIndex pi : tri.PNums())
|
||||
box.Add(GetPoint(pi, 1.0, true));
|
||||
|
||||
setree.GetFirstIntersecting(box.PMin(), box.PMax(), [&] (size_t sej) {
|
||||
const Element2d& tri2 = Get(sej);
|
||||
|
||||
if (mesh[tri[0]].GetLayer() != mesh[tri2[0]].GetLayer())
|
||||
return false;
|
||||
|
||||
netgen::Point<3> tri1_points[3], tri2_points[3];
|
||||
const netgen::Point<3>*trip1[3], *trip2[3];
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
trip1[k] = &tri1_points[k];
|
||||
trip2[k] = &tri2_points[k];
|
||||
}
|
||||
auto set_points = [&] () {
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
tri1_points[k] = GetPoint(tri[k], 1.0, true);
|
||||
tri2_points[k] = GetPoint(tri2[k], 1.0, true);
|
||||
}
|
||||
};
|
||||
|
||||
set_points();
|
||||
|
||||
int counter = 0;
|
||||
while (IntersectTriangleTriangle(&trip1[0], &trip2[0]))
|
||||
{
|
||||
changed = true;
|
||||
PointIndex pi_max_limit = PointIndex::INVALID;
|
||||
for (PointIndex pi :
|
||||
{tri[0], tri[1], tri[2], tri2[0], tri2[1], tri2[2]})
|
||||
if (pi >= tool.first_new_pi && (!pi_max_limit.IsValid() || GetLimit(pi) > GetLimit(pi_max_limit)))
|
||||
pi_max_limit = map_from[pi];
|
||||
|
||||
if (!pi_max_limit.IsValid())
|
||||
break;
|
||||
|
||||
ScaleLimit(pi_max_limit, 0.9);
|
||||
set_points();
|
||||
counter++;
|
||||
if (GetLimit(pi_max_limit) < 1e-10)
|
||||
{
|
||||
WriteErrorMesh("error_blayer_self_intersection_pi" + ToString(pi_max_limit) + ".vol.gz");
|
||||
throw NgException("Stop meshing in boundary layer thickness limitation: overlapping regions detected at elements " + ToString(tri) + " and " + ToString(tri2));
|
||||
}
|
||||
if (debugparam.debugoutput && counter > 20)
|
||||
{
|
||||
cerr << "Limit intersecting surface elements: too many "
|
||||
"limitation steps, sels: "
|
||||
<< Get(sei) << '\t' << Get(sej) << endl;
|
||||
for (auto si : {sei, sej})
|
||||
{
|
||||
auto sel = Get(si);
|
||||
cerr << "Limits: ";
|
||||
for (auto pi : sel.PNums())
|
||||
cerr << GetLimit(pi) << ",\t";
|
||||
cerr << endl;
|
||||
for (auto pi : sel.PNums())
|
||||
cerr << GetPoint(pi, 1.0, true) << "\t";
|
||||
cerr << endl;
|
||||
}
|
||||
cerr << "pi_max_limit " << pi_max_limit << endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LimitOriginalSurface (double safety)
|
||||
{
|
||||
static Timer t("GrowthVectorLimiter::LimitOriginalSurface");
|
||||
RegionTimer reg(t);
|
||||
PrintMessage(5, "GrowthVectorLimiter - original surface");
|
||||
// limit to not intersect with other (original) surface elements
|
||||
double trig_shift = 0;
|
||||
double seg_shift = safety;
|
||||
FindTreeIntersections(
|
||||
trig_shift, seg_shift, [&] (PointIndex pi_to, SurfaceElementIndex sei) {
|
||||
if (sei >= tool.nse)
|
||||
return; // ignore new surface elements in first pass
|
||||
LimitGrowthVector(pi_to, sei, trig_shift, seg_shift);
|
||||
});
|
||||
}
|
||||
|
||||
void LimitBoundaryLayer (double safety = 1.1)
|
||||
{
|
||||
static Timer t("GrowthVectorLimiter::LimitBoundaryLayer");
|
||||
PrintMessage(5, "GrowthVectorLimiter - boundary layer");
|
||||
// now limit again with shifted surface elements
|
||||
double trig_shift = safety;
|
||||
double seg_shift = safety;
|
||||
size_t limit_counter = 1;
|
||||
|
||||
TBitArray<PointIndex> relevant_points, relevant_points_next;
|
||||
relevant_points.SetSize(mesh.Points().Size() + 1);
|
||||
relevant_points_next.SetSize(mesh.Points().Size() + 1);
|
||||
relevant_points.Set();
|
||||
|
||||
while (limit_counter)
|
||||
{
|
||||
RegionTimer reg(t);
|
||||
size_t find_counter = 0;
|
||||
limit_counter = 0;
|
||||
relevant_points_next.Clear();
|
||||
FindTreeIntersections(
|
||||
trig_shift, seg_shift, [&] (PointIndex pi_to, SurfaceElementIndex sei) {
|
||||
find_counter++;
|
||||
auto sel = Get(sei);
|
||||
|
||||
if (LimitGrowthVector(pi_to, sei, trig_shift, seg_shift))
|
||||
{
|
||||
limit_counter++;
|
||||
relevant_points_next.SetBit(pi_to);
|
||||
relevant_points_next.SetBit(map_from[pi_to]);
|
||||
for (auto pi : sel.PNums())
|
||||
{
|
||||
relevant_points_next.SetBit(pi);
|
||||
if (pi >= tool.first_new_pi)
|
||||
relevant_points_next.SetBit(map_from[pi]);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto pi : sel.PNums())
|
||||
{
|
||||
if (pi >= tool.first_new_pi)
|
||||
return;
|
||||
if (tool.mapto[pi].Size() == 0)
|
||||
return;
|
||||
}
|
||||
if (LimitGrowthVector(pi_to, sei, trig_shift, seg_shift, true))
|
||||
limit_counter++;
|
||||
},
|
||||
&relevant_points);
|
||||
relevant_points = relevant_points_next;
|
||||
}
|
||||
}
|
||||
|
||||
void CheckLimits (int line)
|
||||
{
|
||||
auto check_point = [&] (PointIndex pi) {
|
||||
if (limits[pi] < 1e-8)
|
||||
{
|
||||
WriteErrorMesh("error_blayer_intersection_pi" + ToString(pi) + ".vol.gz");
|
||||
throw NgException(__FILE__ + ToString(line) + ": Stop meshing in boundary layer thickness limitation: overlapping regions detected at point " + ToString(pi));
|
||||
}
|
||||
};
|
||||
|
||||
for (auto pi : Range(growthvectors))
|
||||
check_point(pi);
|
||||
|
||||
if (!tool.insert_only_volume_elements)
|
||||
for (auto& [special_pi, special_point] : tool.special_boundary_points)
|
||||
check_point(special_pi);
|
||||
}
|
||||
|
||||
void Perform ()
|
||||
{
|
||||
limits.SetSize(mesh.Points().Size());
|
||||
limits = 1.0;
|
||||
if (tool.special_boundary_points.size())
|
||||
{
|
||||
auto point_to_sel = tool.mesh.CreatePoint2SurfaceElementTable();
|
||||
for (auto& [pi, special_point] : tool.special_boundary_points)
|
||||
{
|
||||
auto maxh = mesh.GetH(mesh[pi]);
|
||||
auto new_limit = min(0.3 * maxh / tool.total_height, 1.0);
|
||||
if (new_limit < 1.0)
|
||||
{
|
||||
limits[pi] = new_limit;
|
||||
for (auto sei : point_to_sel[pi])
|
||||
for (auto pi_ : Get(sei).PNums())
|
||||
limits[pi_] = new_limit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::array safeties = {0.5, 1.1, 1.5, 1.5};
|
||||
|
||||
// No smoothing in the last pass, to avoid generating new intersections
|
||||
std::array smoothing_factors = {0.8, 0.7, 0.5, 0.0};
|
||||
|
||||
for (auto i_pass : Range(safeties.size()))
|
||||
{
|
||||
PrintMessage(4, "GrowthVectorLimiter pass ", i_pass);
|
||||
double safety = safeties[i_pass];
|
||||
CheckLimits(__LINE__);
|
||||
// intersect segment with original surface elements
|
||||
LimitOriginalSurface(2.1);
|
||||
CheckLimits(__LINE__);
|
||||
// intersect prisms with themself
|
||||
LimitSelfIntersection(1.3 * safety);
|
||||
CheckLimits(__LINE__);
|
||||
// intesect segment with prism
|
||||
LimitBoundaryLayer(safety);
|
||||
CheckLimits(__LINE__);
|
||||
|
||||
for ([[maybe_unused]] auto i : Range(10))
|
||||
EqualizeLimits(smoothing_factors[i_pass]);
|
||||
CheckLimits(__LINE__);
|
||||
|
||||
if (i_pass == safeties.size() - 1)
|
||||
FixIntersectingSurfaceTrigs();
|
||||
CheckLimits(__LINE__);
|
||||
}
|
||||
|
||||
for (auto i : Range(growthvectors))
|
||||
growthvectors[i] *= limits[i];
|
||||
|
||||
for (auto& [special_pi, special_point] : tool.special_boundary_points)
|
||||
{
|
||||
for (auto& group : special_point.growth_groups)
|
||||
{
|
||||
group.growth_vector *= limits[special_pi];
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace netgen
|
@ -1,6 +1,10 @@
|
||||
HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom,
|
||||
NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint)
|
||||
// typename INDEX_2_HASHTABLE<int> HT_EDGEPOINT_DOM;
|
||||
typedef ClosedHashTable<tuple<int, PointIndex>, int> HT_EDGEPOINT_DOM;
|
||||
|
||||
|
||||
HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom,
|
||||
TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)
|
||||
{
|
||||
int ep1(0), ep2(0), ep3(0), ep4(0), cp1(0), cp2(0), cp3(0), cp4(0), fp1, fp2, fp3, fp4;
|
||||
int isedge1(0), isedge2(0), isedge3(0), isedge4(0), isedge5(0), isedge6(0);
|
||||
@ -10,6 +14,7 @@ HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
HPREF_ELEMENT_TYPE type = HP_NONE;
|
||||
|
||||
int debug = 0;
|
||||
/*
|
||||
for (int j = 0;j < 4; j++)
|
||||
{
|
||||
if (el.pnums[j] == 444) debug++;
|
||||
@ -18,7 +23,7 @@ HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
if (el.pnums[j] == 281) debug++;
|
||||
}
|
||||
if (debug < 4) debug = 0;
|
||||
|
||||
*/
|
||||
|
||||
// *testout << "new el" << endl;
|
||||
|
||||
@ -55,12 +60,12 @@ HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
cp3 = cornerpoint.Test (el.pnums[pi3]);
|
||||
cp4 = cornerpoint.Test (el.pnums[pi4]);
|
||||
|
||||
isedge1 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[k]));
|
||||
isedge2 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi3]));
|
||||
isedge3 = edges.Used (INDEX_2::Sort (el.pnums[j], el.pnums[pi4]));
|
||||
isedge4 = edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi3]));
|
||||
isedge5 = edges.Used (INDEX_2::Sort (el.pnums[k], el.pnums[pi4]));
|
||||
isedge6 = edges.Used (INDEX_2::Sort (el.pnums[pi3], el.pnums[pi4]));
|
||||
isedge1 = edges.Used (PointIndices<2>::Sort (el.pnums[j], el.pnums[k]));
|
||||
isedge2 = edges.Used (PointIndices<2>::Sort (el.pnums[j], el.pnums[pi3]));
|
||||
isedge3 = edges.Used (PointIndices<2>::Sort (el.pnums[j], el.pnums[pi4]));
|
||||
isedge4 = edges.Used (PointIndices<2>::Sort (el.pnums[k], el.pnums[pi3]));
|
||||
isedge5 = edges.Used (PointIndices<2>::Sort (el.pnums[k], el.pnums[pi4]));
|
||||
isedge6 = edges.Used (PointIndices<2>::Sort (el.pnums[pi3], el.pnums[pi4]));
|
||||
|
||||
if (debug)
|
||||
{
|
||||
@ -75,13 +80,13 @@ HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
for (int j = 0; j < 4; j++) isface[j] = false;
|
||||
for (int l = 0; l < 4; l++)
|
||||
{
|
||||
INDEX_3 i3(0,0,0);
|
||||
PointIndices<3> i3(PointIndex::INVALID, PointIndex::INVALID, PointIndex::INVALID);
|
||||
switch (l)
|
||||
{
|
||||
case 0: i3.I1() = el.pnums[k]; i3.I2() = el.pnums[pi3]; i3.I3() = el.pnums[pi4]; break;
|
||||
case 1: i3.I1() = el.pnums[j]; i3.I2() = el.pnums[pi3]; i3.I3() = el.pnums[pi4]; break;
|
||||
case 2: i3.I1() = el.pnums[j]; i3.I2() = el.pnums[k]; i3.I3() = el.pnums[pi4]; break;
|
||||
case 3: i3.I1() = el.pnums[j]; i3.I2() = el.pnums[k]; i3.I3() = el.pnums[pi3]; break;
|
||||
case 0: i3[0] = el.pnums[k]; i3[1] = el.pnums[pi3]; i3[2] = el.pnums[pi4]; break;
|
||||
case 1: i3[0] = el.pnums[j]; i3[1] = el.pnums[pi3]; i3[2] = el.pnums[pi4]; break;
|
||||
case 2: i3[0] = el.pnums[j]; i3[1] = el.pnums[k]; i3[2] = el.pnums[pi4]; break;
|
||||
case 3: i3[0] = el.pnums[j]; i3[1] = el.pnums[k]; i3[2] = el.pnums[pi3]; break;
|
||||
}
|
||||
i3.Sort();
|
||||
if (faces.Used (i3))
|
||||
@ -101,15 +106,15 @@ HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
isfedge1 = isfedge2 = isfedge3 = isfedge4 = isfedge5 = isfedge6 = 0;
|
||||
for (int l = 0; l < 6; l++)
|
||||
{
|
||||
INDEX_2 i2(0,0);
|
||||
PointIndices<2> i2(PointIndex::INVALID, PointIndex::INVALID);
|
||||
switch (l)
|
||||
{
|
||||
case 0: i2.I1() = el.pnums[j]; i2.I2() = el[k]; break;
|
||||
case 1: i2.I1() = el.pnums[j]; i2.I2() = el.pnums[pi3]; break;
|
||||
case 2: i2.I1() = el.pnums[j]; i2.I2() = el.pnums[pi4]; break;
|
||||
case 3: i2.I1() = el.pnums[k]; i2.I2() = el.pnums[pi3]; break;
|
||||
case 4: i2.I1() = el.pnums[k]; i2.I2() = el.pnums[pi4]; break;
|
||||
case 5: i2.I1() = el.pnums[pi3]; i2.I2() = el.pnums[pi4]; break;
|
||||
case 0: i2[0] = el.pnums[j]; i2[1] = el[k]; break;
|
||||
case 1: i2[0] = el.pnums[j]; i2[1] = el.pnums[pi3]; break;
|
||||
case 2: i2[0] = el.pnums[j]; i2[1] = el.pnums[pi4]; break;
|
||||
case 3: i2[0] = el.pnums[k]; i2[1] = el.pnums[pi3]; break;
|
||||
case 4: i2[0] = el.pnums[k]; i2[1] = el.pnums[pi4]; break;
|
||||
case 5: i2[0] = el.pnums[pi3]; i2[1] = el.pnums[pi4]; break;
|
||||
}
|
||||
i2.Sort();
|
||||
if (face_edges.Used (i2))
|
||||
@ -141,7 +146,7 @@ HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
fp1 = fp2 = fp3 = fp4 = 0;
|
||||
for (int l = 0; l < 4; l++)
|
||||
{
|
||||
int pti(0);
|
||||
PointIndex pti = PointIndex::INVALID;
|
||||
switch (l)
|
||||
{
|
||||
case 0: pti = el.pnums[j]; break;
|
||||
@ -547,7 +552,7 @@ HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
|
||||
if (type != HP_NONE)
|
||||
{
|
||||
int pnums[4];
|
||||
PointIndex pnums[4];
|
||||
pnums[0] = el.pnums[j];
|
||||
pnums[1] = el.pnums[k];
|
||||
pnums[2] = el.pnums[pi3];
|
||||
@ -585,9 +590,9 @@ HPREF_ELEMENT_TYPE ClassifyTet(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
|
||||
|
||||
|
||||
HPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom,
|
||||
NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint)
|
||||
HPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom,
|
||||
TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)
|
||||
{
|
||||
|
||||
HPREF_ELEMENT_TYPE type = HP_NONE;
|
||||
@ -621,7 +626,7 @@ HPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE<int> & edg
|
||||
const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (PRISM);
|
||||
for(int k=0;k<9;k++)
|
||||
{
|
||||
INDEX_2 i2 = INDEX_2 :: Sort(el.PNum(p[eledges[k][0]-1]),el.PNum(p[eledges[k][1]-1]));
|
||||
PointIndices<2> i2 = PointIndices<2> :: Sort(el.PNum(p[eledges[k][0]-1]),el.PNum(p[eledges[k][1]-1]));
|
||||
if (edges.Used(i2)) edge_sing[k] = 2;
|
||||
else edge_sing[k] = face_edges.Used(i2);
|
||||
}
|
||||
@ -629,16 +634,17 @@ HPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE<int> & edg
|
||||
const ELEMENT_FACE * elfaces = MeshTopology::GetFaces1 (PRISM);
|
||||
for (int k=0;k<5;k++)
|
||||
{
|
||||
INDEX_3 i3;
|
||||
PointIndices<3> i3;
|
||||
|
||||
if(k<2)
|
||||
i3 = INDEX_3::Sort(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1],
|
||||
el.pnums[p[elfaces[k][2]-1]-1]);
|
||||
i3 = PointIndices<3>::Sort(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1],
|
||||
el.pnums[p[elfaces[k][2]-1]-1]);
|
||||
else
|
||||
{
|
||||
INDEX_4 i4 = INDEX_4(el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1], el.pnums[p[elfaces[k][2]-1]-1],el.pnums[p[elfaces[k][3]-1]-1]);
|
||||
PointIndices<4> i4 (el.pnums[p[elfaces[k][0]-1]-1], el.pnums[p[elfaces[k][1]-1]-1],
|
||||
el.pnums[p[elfaces[k][2]-1]-1],el.pnums[p[elfaces[k][3]-1]-1]);
|
||||
i4.Sort();
|
||||
i3 = INDEX_3(i4.I1(), i4.I2(), i4.I3());
|
||||
i3 = PointIndices<3>(i4[0], i4[1], i4[2]);
|
||||
}
|
||||
|
||||
if (faces.Used (i3))
|
||||
@ -808,7 +814,7 @@ HPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE<int> & edg
|
||||
|
||||
if(type != HP_NONE)
|
||||
{
|
||||
int pnums[6];
|
||||
PointIndex pnums[6];
|
||||
for(int j=0;j<6;j++) pnums[j] = el.PNum (p[j]);
|
||||
for(int k=0;k<6;k++) el.pnums[k] = pnums[k];
|
||||
}
|
||||
@ -821,18 +827,20 @@ HPREF_ELEMENT_TYPE ClassifyPrism(HPRefElement & el, INDEX_2_HASHTABLE<int> & edg
|
||||
}
|
||||
|
||||
|
||||
// #ifdef SABINE
|
||||
HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom,
|
||||
NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd)
|
||||
// #ifdef SABINE
|
||||
|
||||
|
||||
HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom,
|
||||
TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint, int dim, const FaceDescriptor & fd)
|
||||
|
||||
{
|
||||
HPREF_ELEMENT_TYPE type = HP_NONE;
|
||||
|
||||
int pnums[3];
|
||||
PointIndex pnums[3];
|
||||
int p[3];
|
||||
|
||||
INDEX_3 i3 (el.pnums[0], el.pnums[1], el.pnums[2]);
|
||||
PointIndices<3> i3 (el.pnums[0], el.pnums[1], el.pnums[2]);
|
||||
i3.Sort();
|
||||
bool sing_face = faces.Used (i3);
|
||||
|
||||
@ -881,7 +889,7 @@ HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edge
|
||||
{
|
||||
int ep1=p[eledges[k][0]-1];
|
||||
int ep2=p[eledges[k][1]-1];
|
||||
INDEX_2 i2(el.PNum(ep1),el.PNum(ep2));
|
||||
PointIndices<2> i2(el.PNum(ep1),el.PNum(ep2));
|
||||
|
||||
if(edges.Used(i2))
|
||||
{
|
||||
@ -924,14 +932,14 @@ HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edge
|
||||
int ep1=p[eledges[k][0]-1];
|
||||
int ep2=p[eledges[k][1]-1];
|
||||
|
||||
INDEX_2 i2 = INDEX_2::Sort(el.PNum(ep1),el.PNum(ep2));
|
||||
PointIndices<2> i2 = PointIndices<2>::Sort(el.PNum(ep1),el.PNum(ep2));
|
||||
|
||||
if(edges.Used(i2))
|
||||
{
|
||||
if(edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep1-1])) ||
|
||||
edgepoint_dom.Used(INDEX_2(-1,pnums[ep1-1])) ||
|
||||
edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[ep2-1])) ||
|
||||
edgepoint_dom.Used(INDEX_2(-1,pnums[ep2-1])))
|
||||
if(edgepoint_dom.Used( { fd.SurfNr(),pnums[ep1-1] } ) ||
|
||||
edgepoint_dom.Used( { -1,pnums[ep1-1] } ) ||
|
||||
edgepoint_dom.Used( { fd.SurfNr(), pnums[ep2-1]} ) ||
|
||||
edgepoint_dom.Used( { -1,pnums[ep2-1] } ))
|
||||
{
|
||||
edge_sing[k]=2;
|
||||
point_sing[ep1-1] = 2;
|
||||
@ -946,11 +954,11 @@ HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edge
|
||||
|
||||
for (int k=0;k<3;k++)
|
||||
if (edgepoint.Test(pnums[k]) &&
|
||||
(dim==3 || edgepoint_dom.Used(INDEX_2(fd.SurfNr(),pnums[k])) || edgepoint_dom.Used(INDEX_2(-1,pnums[k]))))
|
||||
(dim==3 || edgepoint_dom.Used( { fd.SurfNr(),pnums[k] } ) || edgepoint_dom.Used( { -1,pnums[k] } )))
|
||||
//edgepoint, but not member of sing_edge on trig -> cp
|
||||
{
|
||||
INDEX_2 i2a=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+1)%3]));
|
||||
INDEX_2 i2b=INDEX_2::Sort(el.PNum(p[k]), el.PNum(p[(k+2)%3]));
|
||||
PointIndices<2> i2a = PointIndices<2>::Sort(el.PNum(p[k]), el.PNum(p[(k+1)%3]));
|
||||
PointIndices<2> i2b = PointIndices<2>::Sort(el.PNum(p[k]), el.PNum(p[(k+2)%3]));
|
||||
|
||||
if(!edges.Used(i2a) && !edges.Used(i2b))
|
||||
point_sing[p[k]-1] = 3;
|
||||
@ -1299,9 +1307,9 @@ HPREF_ELEMENT_TYPE ClassifyTrig(HPRefElement & el, INDEX_2_HASHTABLE<int> & edge
|
||||
return(type);
|
||||
}
|
||||
#endif
|
||||
HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom,
|
||||
NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint, int dim, const FaceDescriptor & fd)
|
||||
HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom,
|
||||
TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint, int dim, const FaceDescriptor & fd)
|
||||
{
|
||||
HPREF_ELEMENT_TYPE type = HP_NONE;
|
||||
|
||||
@ -1319,10 +1327,10 @@ HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edge
|
||||
|
||||
if (dim == 2)
|
||||
{
|
||||
ep1 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j)));
|
||||
ep2 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+1)));
|
||||
ep3 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+2)));
|
||||
ep4 = edgepoint_dom.Used (INDEX_2 (el.GetIndex(), el.PNumMod(j+3)));
|
||||
ep1 = edgepoint_dom.Used ( { el.GetIndex(), el.PNumMod(j) } );
|
||||
ep2 = edgepoint_dom.Used ( { el.GetIndex(), el.PNumMod(j+1) } );
|
||||
ep3 = edgepoint_dom.Used ( { el.GetIndex(), el.PNumMod(j+2) });
|
||||
ep4 = edgepoint_dom.Used ( { el.GetIndex(), el.PNumMod(j+3) });
|
||||
}
|
||||
|
||||
cp1 = cornerpoint.Test (el.PNumMod (j));
|
||||
@ -1335,7 +1343,7 @@ HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edge
|
||||
ep3 |= cp3;
|
||||
ep4 |= cp4;
|
||||
|
||||
int p[4] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2), el.PNumMod(j+4)};
|
||||
PointIndex p[4] = { el.PNumMod (j), el.PNumMod (j+1), el.PNumMod (j+2), el.PNumMod(j+4)};
|
||||
//int epp[4] = { ep1, ep2, ep3, ep4};
|
||||
int cpp[4] = { cp1, cp2, cp3, cp4};
|
||||
for(int k=0;k<0;k++)
|
||||
@ -1350,8 +1358,7 @@ HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edge
|
||||
|
||||
if(dim ==3)
|
||||
{
|
||||
INDEX_2 i2;
|
||||
i2 = INDEX_2(el.PNumMod (j), el.PNumMod (j+1));
|
||||
PointIndices<2> i2 = PointIndices<2>(el.PNumMod (j), el.PNumMod (j+1));
|
||||
// i2.Sort();
|
||||
isedge1 = edges.Used (i2);
|
||||
i2.Sort();
|
||||
@ -1649,9 +1656,9 @@ HPREF_ELEMENT_TYPE ClassifyQuad(HPRefElement & el, INDEX_2_HASHTABLE<int> & edge
|
||||
}
|
||||
|
||||
|
||||
HPREF_ELEMENT_TYPE ClassifyHex(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom,
|
||||
NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint)
|
||||
HPREF_ELEMENT_TYPE ClassifyHex(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom,
|
||||
TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)
|
||||
{
|
||||
HPREF_ELEMENT_TYPE type = HP_NONE;
|
||||
|
||||
@ -1754,9 +1761,10 @@ HPREF_ELEMENT_TYPE ClassifyHex(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges
|
||||
|
||||
|
||||
|
||||
HPREF_ELEMENT_TYPE ClassifyHex7 (HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom,
|
||||
NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint)
|
||||
HPREF_ELEMENT_TYPE ClassifyHex7 (HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom,
|
||||
TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint,
|
||||
INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)
|
||||
{
|
||||
// HPREF_ELEMENT_TYPE type = HP_NONE;
|
||||
|
||||
@ -1793,9 +1801,10 @@ HPREF_ELEMENT_TYPE ClassifyHex7 (HPRefElement & el, INDEX_2_HASHTABLE<int> & edg
|
||||
|
||||
|
||||
|
||||
HPREF_ELEMENT_TYPE ClassifySegm(HPRefElement & hpel, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom,
|
||||
NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint)
|
||||
HPREF_ELEMENT_TYPE ClassifySegm(HPRefElement & hpel, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom,
|
||||
TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint,
|
||||
INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)
|
||||
{
|
||||
|
||||
int cp1 = cornerpoint.Test (hpel[0]);
|
||||
@ -1836,9 +1845,10 @@ HPREF_ELEMENT_TYPE ClassifySegm(HPRefElement & hpel, INDEX_2_HASHTABLE<int> & ed
|
||||
}
|
||||
|
||||
|
||||
HPREF_ELEMENT_TYPE ClassifyPyramid(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoint_dom,
|
||||
NgBitArray & cornerpoint, NgBitArray & edgepoint, INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, NgArray<int, PointIndex::BASE> & facepoint)
|
||||
HPREF_ELEMENT_TYPE ClassifyPyramid(HPRefElement & el, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoint_dom,
|
||||
TBitArray<PointIndex> & cornerpoint, TBitArray<PointIndex> & edgepoint,
|
||||
INDEX_3_HASHTABLE<int> & faces, INDEX_2_HASHTABLE<int> & face_edges,
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint)
|
||||
{
|
||||
// *testout << "classify pyramid, pnums = ";
|
||||
// for (int i = 0; i < 5; i++) *testout << el.pnums[i] << " ";
|
||||
|
@ -23,6 +23,7 @@ namespace netgen
|
||||
// static int timer2 = NgProfiler::CreateTimer ("clusters2");
|
||||
// static int timer3 = NgProfiler::CreateTimer ("clusters3");
|
||||
RegionTimer reg (timer);
|
||||
constexpr auto PI0 = IndexBASE<PointIndex>();
|
||||
|
||||
const MeshTopology & top = mesh.GetTopology();
|
||||
|
||||
@ -86,16 +87,18 @@ namespace netgen
|
||||
[&] (auto myrange)
|
||||
{
|
||||
NgArray<int> nnums; // , ednums, fanums;
|
||||
for (int i_ : myrange)
|
||||
for (auto i_ : myrange)
|
||||
{
|
||||
int i = i_+1;
|
||||
const Element & el = mesh.VolumeElement(i);
|
||||
int i = i_-IndexBASE<ElementIndex>()+1;
|
||||
const Element & el = mesh.VolumeElement(i_);
|
||||
ELEMENT_TYPE typ = el.GetType();
|
||||
|
||||
// top.GetElementEdges (i, ednums);
|
||||
auto ednums = top.GetEdges (ElementIndex(i_));
|
||||
// auto ednums = top.GetEdges (ElementIndex(i_));
|
||||
auto ednums = top.GetEdges (i_);
|
||||
// top.GetElementFaces (i, fanums);
|
||||
auto fanums = top.GetFaces (ElementIndex(i_));
|
||||
// auto fanums = top.GetFaces (ElementIndex(i_));
|
||||
auto fanums = top.GetFaces (i_);
|
||||
|
||||
int elnv = top.GetNVertices (typ);
|
||||
int elned = ednums.Size();
|
||||
@ -103,7 +106,7 @@ namespace netgen
|
||||
|
||||
nnums.SetSize(elnv+elned+elnfa+1);
|
||||
for (int j = 0; j < elnv; j++)
|
||||
nnums[j] = el[j]+1-PointIndex::BASE;
|
||||
nnums[j] = el[j]+1-PI0;
|
||||
for (int j = 0; j < elned; j++)
|
||||
nnums[elnv+j] = nv+ednums[j]+1;
|
||||
for (int j = 0; j < elnfa; j++)
|
||||
@ -131,7 +134,7 @@ namespace netgen
|
||||
|
||||
nnums.SetSize(elnv+elned+1);
|
||||
for (int j = 1; j <= elnv; j++)
|
||||
nnums.Elem(j) = el.PNum(j)+1-PointIndex::BASE;
|
||||
nnums.Elem(j) = el.PNum(j)+1-PI0;
|
||||
for (int j = 1; j <= elned; j++)
|
||||
nnums.Elem(elnv+j) = nv+ednums.Elem(j);
|
||||
nnums.Elem(elnv+elned+1) = fanum;
|
||||
@ -140,29 +143,31 @@ namespace netgen
|
||||
cluster_reps.Elem(nnums[j]) = nnums[j];
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
ngcore::ParallelForRange
|
||||
(mesh.SurfaceElements().Range(),
|
||||
[&] (auto myrange)
|
||||
{
|
||||
NgArrayMem<int,9> nnums; // , ednums;
|
||||
for (int i_ : myrange)
|
||||
for (SurfaceElementIndex i_ : myrange)
|
||||
{
|
||||
int i = i_+1;
|
||||
const Element2d & el = mesh.SurfaceElement(i);
|
||||
// int i = i_+1;
|
||||
const Element2d & el = mesh[i_]; // .SurfaceElement(i);
|
||||
ELEMENT_TYPE typ = el.GetType();
|
||||
|
||||
// top.GetSurfaceElementEdges (i, ednums);
|
||||
auto ednums = top.GetEdges (SurfaceElementIndex(i_));
|
||||
auto ednums = top.GetEdges (i_);
|
||||
// cout << "ednums = " << ednums << endl;
|
||||
|
||||
int fanum = top.GetSurfaceElementFace (i);
|
||||
int fanum = top.GetFace(i_)+1;
|
||||
|
||||
int elnv = top.GetNVertices (typ);
|
||||
int elned = ednums.Size();
|
||||
|
||||
nnums.SetSize(elnv+elned+1);
|
||||
for (int j = 0; j < elnv; j++)
|
||||
nnums[j] = el[j]+1-PointIndex::BASE;
|
||||
nnums[j] = el[j]+1-PI0;
|
||||
for (int j = 0; j < elned; j++)
|
||||
nnums[elnv+j] = nv+ednums[j]+1;
|
||||
nnums[elnv+elned] = fanum;
|
||||
@ -219,7 +224,6 @@ namespace netgen
|
||||
{ 2, 3, 1, 1, 4, 5, 1, 6, 4, 5, 5, 4, 7, 7, 7 };
|
||||
|
||||
// int cnt = 0;
|
||||
|
||||
do
|
||||
{
|
||||
static Timer t("update cluster, identify");
|
||||
@ -229,7 +233,9 @@ namespace netgen
|
||||
|
||||
for (int i = 1; i <= ne; i++)
|
||||
{
|
||||
const Element & el = mesh.VolumeElement(i);
|
||||
ElementIndex ei(i-1);
|
||||
|
||||
const Element & el = mesh[ei];
|
||||
ELEMENT_TYPE typ = el.GetType();
|
||||
|
||||
const int * clustertab = NULL;
|
||||
@ -247,23 +253,23 @@ namespace netgen
|
||||
break;
|
||||
case TET:
|
||||
case TET10:
|
||||
if (cluster_reps.Get(el.PNum(1)+1-PointIndex::BASE) ==
|
||||
cluster_reps.Get(el.PNum(2)+1-PointIndex::BASE))
|
||||
if (cluster_reps.Get(el.PNum(1)+1-PI0) ==
|
||||
cluster_reps.Get(el.PNum(2)+1-PI0))
|
||||
clustertab = tet_cluster12;
|
||||
else if (cluster_reps.Get(el.PNum(1)+1-PointIndex::BASE) ==
|
||||
cluster_reps.Get(el.PNum(3)+1-PointIndex::BASE))
|
||||
else if (cluster_reps.Get(el.PNum(1)+1-PI0) ==
|
||||
cluster_reps.Get(el.PNum(3)+1-PI0))
|
||||
clustertab = tet_cluster13;
|
||||
else if (cluster_reps.Get(el.PNum(1)+1-PointIndex::BASE) ==
|
||||
cluster_reps.Get(el.PNum(4)+1-PointIndex::BASE))
|
||||
else if (cluster_reps.Get(el.PNum(1)+1-PI0) ==
|
||||
cluster_reps.Get(el.PNum(4)+1-PI0))
|
||||
clustertab = tet_cluster14;
|
||||
else if (cluster_reps.Get(el.PNum(2)+1-PointIndex::BASE) ==
|
||||
cluster_reps.Get(el.PNum(3)+1-PointIndex::BASE))
|
||||
else if (cluster_reps.Get(el.PNum(2)+1-PI0) ==
|
||||
cluster_reps.Get(el.PNum(3)+1-PI0))
|
||||
clustertab = tet_cluster23;
|
||||
else if (cluster_reps.Get(el.PNum(2)+1-PointIndex::BASE) ==
|
||||
cluster_reps.Get(el.PNum(4)+1-PointIndex::BASE))
|
||||
else if (cluster_reps.Get(el.PNum(2)+1-PI0) ==
|
||||
cluster_reps.Get(el.PNum(4)+1-PI0))
|
||||
clustertab = tet_cluster24;
|
||||
else if (cluster_reps.Get(el.PNum(3)+1-PointIndex::BASE) ==
|
||||
cluster_reps.Get(el.PNum(4)+1-PointIndex::BASE))
|
||||
else if (cluster_reps.Get(el.PNum(3)+1-PI0) ==
|
||||
cluster_reps.Get(el.PNum(4)+1-PI0))
|
||||
clustertab = tet_cluster34;
|
||||
|
||||
else
|
||||
@ -277,8 +283,8 @@ namespace netgen
|
||||
{
|
||||
// top.GetElementEdges (i, ednums);
|
||||
// top.GetElementFaces (i, fanums);
|
||||
auto ednums = top.GetEdges (ElementIndex(i-1));
|
||||
auto fanums = top.GetFaces (ElementIndex(i-1));
|
||||
auto ednums = top.GetEdges (ei);
|
||||
auto fanums = top.GetFaces (ei);
|
||||
|
||||
int elnv = top.GetNVertices (typ);
|
||||
int elned = ednums.Size();
|
||||
@ -286,7 +292,7 @@ namespace netgen
|
||||
|
||||
nnums.SetSize(elnv+elned+elnfa+1);
|
||||
for (int j = 0; j < elnv; j++)
|
||||
nnums[j] = el[j]+1-PointIndex::BASE;
|
||||
nnums[j] = el[j]+1-IndexBASE<PointIndex>();
|
||||
for (int j = 0; j < elned; j++)
|
||||
nnums[elnv+j] = nv+ednums[j]+1;
|
||||
for (int j = 0; j < elnfa; j++)
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <mystdlib.h>
|
||||
|
||||
#include "meshing.hpp"
|
||||
|
||||
// #include "../general/autodiff.hpp"
|
||||
|
||||
|
||||
@ -405,18 +404,24 @@ namespace netgen
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static NgArray<shared_ptr<RecPol>> jacpols2;
|
||||
|
||||
void CurvedElements::buildJacPols()
|
||||
struct JacobiRecPols
|
||||
{
|
||||
if (!jacpols2.Size())
|
||||
{
|
||||
jacpols2.SetSize (100);
|
||||
for (int i = 0; i < 100; i++)
|
||||
jacpols2[i] = make_shared<JacobiRecPol> (100, i, 2);
|
||||
}
|
||||
}
|
||||
static constexpr size_t N = 100;
|
||||
ArrayMem<unique_ptr<JacobiRecPol>, N> jacpols;
|
||||
|
||||
JacobiRecPols()
|
||||
{
|
||||
jacpols.SetSize (N);
|
||||
for (int i = 0; i < N; i++)
|
||||
jacpols[i] = make_unique<JacobiRecPol>(N, i, 2);
|
||||
}
|
||||
|
||||
const unique_ptr<JacobiRecPol> & operator[] (int i) {
|
||||
return jacpols[i];
|
||||
}
|
||||
};
|
||||
|
||||
static JacobiRecPols jacpols2;
|
||||
|
||||
// compute face bubbles up to order n, 0 < y, y-x < 1, x+y < 1
|
||||
template <class Tx, class Ty, class Ts>
|
||||
@ -608,7 +613,7 @@ namespace netgen
|
||||
|
||||
if (aorder <= 1)
|
||||
{
|
||||
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
|
||||
for (ElementIndex ei : mesh.VolumeElements().Range())
|
||||
if (mesh[ei].GetType() == TET10)
|
||||
ishighorder = 1;
|
||||
return;
|
||||
@ -710,7 +715,6 @@ namespace netgen
|
||||
|
||||
ComputeGaussRule (aorder+4, xi, weight); // on (0,1)
|
||||
|
||||
buildJacPols();
|
||||
PrintMessage (3, "Curving edges");
|
||||
|
||||
if (mesh.GetDimension() == 3 || rational)
|
||||
@ -1189,9 +1193,10 @@ namespace netgen
|
||||
// if (el.GetType() == TRIG && order >= 3)
|
||||
if (top.GetFaceType(facenr+1) == TRIG && order >= 3)
|
||||
{
|
||||
NgArrayMem<int, 3> verts(3);
|
||||
top.GetFaceVertices (facenr+1, verts);
|
||||
|
||||
// NgArrayMem<PointIndex, 3> verts(3);
|
||||
// top.GetFaceVertices (facenr+1, verts);
|
||||
auto verts = top.GetFaceVertices(facenr);
|
||||
|
||||
int fnums[] = { 0, 1, 2 };
|
||||
/*
|
||||
if (el[fnums[0]] > el[fnums[1]]) swap (fnums[0], fnums[1]);
|
||||
@ -1273,7 +1278,7 @@ namespace netgen
|
||||
with MPI and an interior surface element between volume elements assigned to different
|
||||
procs, only one of them has the surf-el
|
||||
**/
|
||||
SurfaceElementIndex sei = top.GetFace2SurfaceElement (f+1)-1;
|
||||
SurfaceElementIndex sei = top.GetFace2SurfaceElement(f);
|
||||
if (sei != SurfaceElementIndex(-1)) {
|
||||
PointGeomInfo gi = mesh[sei].GeomInfoPi(1);
|
||||
// use improved initial guess
|
||||
@ -1661,12 +1666,21 @@ namespace netgen
|
||||
if (info.order > 1)
|
||||
{
|
||||
const MeshTopology & top = mesh.GetTopology();
|
||||
|
||||
|
||||
/*
|
||||
top.GetSurfaceElementEdges (elnr+1, info.edgenrs);
|
||||
for (int i = 0; i < info.edgenrs.Size(); i++)
|
||||
info.edgenrs[i]--;
|
||||
info.facenr = top.GetSurfaceElementFace (elnr+1)-1;
|
||||
|
||||
*/
|
||||
/*
|
||||
auto edgs = top.GetEdges(SurfaceElementIndex(elnr));
|
||||
info.edgenrs.SetSize(edgs.Size());
|
||||
for (auto [i,nr] : Enumerate(edgs))
|
||||
info.edgenrs[i] = nr;
|
||||
*/
|
||||
info.SetEdges (top.GetEdges(SurfaceElementIndex(elnr)));
|
||||
|
||||
info.facenr = top.GetFace(elnr);
|
||||
for (int i = 0; i < info.edgenrs.Size(); i++)
|
||||
info.ndof += edgecoeffsindex[info.edgenrs[i]+1] - edgecoeffsindex[info.edgenrs[i]];
|
||||
info.ndof += facecoeffsindex[info.facenr+1] - facecoeffsindex[info.facenr];
|
||||
@ -1742,11 +1756,14 @@ namespace netgen
|
||||
if (info.order > 1)
|
||||
{
|
||||
const MeshTopology & top = mesh.GetTopology();
|
||||
|
||||
|
||||
/*
|
||||
top.GetSurfaceElementEdges (elnr+1, info.edgenrs);
|
||||
for (int i = 0; i < info.edgenrs.Size(); i++)
|
||||
info.edgenrs[i]--;
|
||||
info.facenr = top.GetSurfaceElementFace (elnr+1)-1;
|
||||
*/
|
||||
info.SetEdges(top.GetEdges(SurfaceElementIndex(elnr)));
|
||||
info.facenr = top.GetFace(elnr);
|
||||
|
||||
|
||||
bool firsttry = true;
|
||||
@ -2433,7 +2450,7 @@ namespace netgen
|
||||
const HPRefElement & hpref_el =
|
||||
(*mesh.hpelements) [mesh[elnr].GetHpElnr()];
|
||||
|
||||
return mesh.coarsemesh->GetCurvedElements().IsElementCurved (hpref_el.coarse_elnr);
|
||||
return mesh.coarsemesh->GetCurvedElements().IsElementCurved (ElementIndex(hpref_el.coarse_elnr));
|
||||
}
|
||||
|
||||
const Element & el = mesh[elnr];
|
||||
@ -2485,7 +2502,7 @@ namespace netgen
|
||||
const HPRefElement & hpref_el =
|
||||
(*mesh.hpelements) [mesh[elnr].GetHpElnr()];
|
||||
|
||||
return mesh.coarsemesh->GetCurvedElements().IsElementHighOrder (hpref_el.coarse_elnr);
|
||||
return mesh.coarsemesh->GetCurvedElements().IsElementHighOrder (ElementIndex(hpref_el.coarse_elnr));
|
||||
}
|
||||
|
||||
const Element & el = mesh[elnr];
|
||||
@ -2549,7 +2566,8 @@ namespace netgen
|
||||
for (int j = 0; j < 3; j++)
|
||||
coarse_xi(j) += hpref_el.param[i][j] * lami[i];
|
||||
|
||||
mesh.coarsemesh->GetCurvedElements().CalcElementTransformation (coarse_xi, hpref_el.coarse_elnr, x, &dxdxic /* , curved */);
|
||||
mesh.coarsemesh->GetCurvedElements().
|
||||
CalcElementTransformation (coarse_xi, ElementIndex(hpref_el.coarse_elnr), x, &dxdxic /* , curved */);
|
||||
|
||||
if (dxdxi)
|
||||
*dxdxi = dxdxic * trans;
|
||||
@ -4186,11 +4204,14 @@ namespace netgen
|
||||
if (info.order > 1)
|
||||
{
|
||||
const MeshTopology & top = mesh.GetTopology();
|
||||
|
||||
|
||||
/*
|
||||
top.GetSurfaceElementEdges (elnr+1, info.edgenrs);
|
||||
for (int i = 0; i < info.edgenrs.Size(); i++)
|
||||
info.edgenrs[i]--;
|
||||
info.facenr = top.GetSurfaceElementFace (elnr+1)-1;
|
||||
*/
|
||||
info.SetEdges(top.GetEdges(elnr));
|
||||
info.facenr = top.GetFace (elnr);
|
||||
|
||||
|
||||
bool firsttry = true;
|
||||
@ -4348,7 +4369,7 @@ namespace netgen
|
||||
const double * xi, size_t sxi,
|
||||
double * x, size_t sx,
|
||||
double * dxdxi, size_t sdxdxi);
|
||||
|
||||
|
||||
|
||||
template void CurvedElements ::
|
||||
CalcMultiPointSurfaceTransformation<2> (SurfaceElementIndex elnr, int npts,
|
||||
@ -4578,7 +4599,7 @@ namespace netgen
|
||||
}
|
||||
|
||||
mesh.coarsemesh->GetCurvedElements().
|
||||
CalcMultiPointElementTransformation (hpref_el.coarse_elnr, n,
|
||||
CalcMultiPointElementTransformation (ElementIndex(hpref_el.coarse_elnr), n,
|
||||
&coarse_xi[0], 3,
|
||||
x, sx,
|
||||
dxdxi, sdxdxi);
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include <gprim/geomobjects.hpp>
|
||||
|
||||
#include "meshtype.hpp"
|
||||
#include "meshclass.hpp"
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
@ -38,7 +39,6 @@ class CurvedElements
|
||||
bool rational;
|
||||
|
||||
bool ishighorder;
|
||||
void buildJacPols();
|
||||
|
||||
public:
|
||||
DLL_HEADER CurvedElements (const Mesh & amesh);
|
||||
@ -56,8 +56,6 @@ public:
|
||||
|
||||
void DoArchive(Archive& ar)
|
||||
{
|
||||
if(ar.Input())
|
||||
buildJacPols();
|
||||
ar & edgeorder & faceorder & edgecoeffsindex & facecoeffsindex & edgecoeffs & facecoeffs
|
||||
& edgeweight & order & rational & ishighorder;
|
||||
}
|
||||
@ -212,7 +210,7 @@ private:
|
||||
Mat<3> hdxdxi;
|
||||
Vec<3> hcoefs[10]; // enough for second order tets
|
||||
|
||||
void SetEdges (FlatArray<int> edges)
|
||||
void SetEdges (FlatArray<T_EDGE> edges)
|
||||
{
|
||||
nedges = edges.Size();
|
||||
for (int i = 0; i < edges.Size(); i++)
|
||||
@ -222,7 +220,7 @@ private:
|
||||
auto GetEdges() const
|
||||
{ return FlatArray(nedges, edgenrs); }
|
||||
|
||||
void SetFaces (FlatArray<int> faces)
|
||||
void SetFaces (FlatArray<T_FACE> faces)
|
||||
{
|
||||
nfaces = faces.Size();
|
||||
for (int i = 0; i < faces.Size(); i++)
|
||||
@ -251,6 +249,14 @@ private:
|
||||
int ndof;
|
||||
NgArrayMem<int,4> edgenrs;
|
||||
int facenr;
|
||||
|
||||
void SetEdges (FlatArray<T_EDGE> edges)
|
||||
{
|
||||
edgenrs.SetSize(edges.Size());
|
||||
for (int i = 0; i < edges.Size(); i++)
|
||||
edgenrs[i] = edges[i];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
|
@ -1,8 +1,9 @@
|
||||
#include <meshing.hpp>
|
||||
#include "debugging.hpp"
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
unique_ptr<Mesh> GetOpenElements( const Mesh & m, int dom = 0 )
|
||||
unique_ptr<Mesh> GetOpenElements( const Mesh & m, int dom, bool only_quads )
|
||||
{
|
||||
static Timer t("GetOpenElements"); RegionTimer rt(t);
|
||||
auto mesh = make_unique<Mesh>();
|
||||
@ -36,13 +37,14 @@ namespace netgen
|
||||
mesh->SetMaterial(2, "2_points");
|
||||
mesh->SetMaterial(3, "3_points");
|
||||
mesh->SetMaterial(4, "4_points");
|
||||
mesh->Compress();
|
||||
|
||||
mesh->ClearSurfaceElements();
|
||||
|
||||
for (auto & el : openelements)
|
||||
mesh->AddSurfaceElement( el );
|
||||
if(!only_quads || el.GetNP() == 4)
|
||||
mesh->AddSurfaceElement( el );
|
||||
|
||||
mesh->Compress();
|
||||
return mesh;
|
||||
}
|
||||
|
||||
@ -95,6 +97,127 @@ namespace netgen
|
||||
return mesh_ptr;
|
||||
}
|
||||
|
||||
void CheckMesh (const Mesh& mesh, MESHING_STEP step)
|
||||
{
|
||||
if (step == MESHCONST_OPTVOLUME)
|
||||
{
|
||||
bool have_error = false;
|
||||
for (auto el : mesh.VolumeElements())
|
||||
{
|
||||
double volume = el.Volume(mesh.Points());
|
||||
if (volume < 0)
|
||||
{
|
||||
have_error = true;
|
||||
cout << "volume of element " << el << " is negative: " << volume << endl;
|
||||
}
|
||||
}
|
||||
if (have_error)
|
||||
throw Exception("Negative volume");
|
||||
|
||||
CheckElementsAroundEdges(mesh);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void CheckElementsAroundEdges (const Mesh& mesh)
|
||||
{
|
||||
static Mesh last_good_mesh;
|
||||
|
||||
Array<std::tuple<PointIndex, PointIndex>> edges;
|
||||
auto elementsonnode = mesh.CreatePoint2ElementTable();
|
||||
BuildEdgeList(mesh, elementsonnode, edges);
|
||||
mesh.BoundaryEdge(1, 2); // trigger build of boundary edges
|
||||
|
||||
ArrayMem<ElementIndex, 20> hasbothpoints;
|
||||
for (auto [pi0, pi1] : edges)
|
||||
{
|
||||
if (mesh.BoundaryEdge(pi0, pi1))
|
||||
continue;
|
||||
|
||||
hasbothpoints.SetSize(0);
|
||||
for (ElementIndex ei : elementsonnode[pi0])
|
||||
if (mesh[ei].PNums().Contains(pi1))
|
||||
hasbothpoints.Append(ei);
|
||||
|
||||
bool skip = false;
|
||||
for (ElementIndex ei : hasbothpoints)
|
||||
{
|
||||
if (mesh[ei].GetType() != TET)
|
||||
{
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (skip)
|
||||
continue;
|
||||
|
||||
int nsuround = hasbothpoints.Size();
|
||||
ArrayMem<PointIndex, 50> suroundpts(nsuround + 1);
|
||||
suroundpts = PointIndex::INVALID;
|
||||
ArrayMem<bool, 50> tetused(nsuround);
|
||||
tetused = false;
|
||||
tetused[0] = true;
|
||||
|
||||
auto el = mesh[hasbothpoints[0]];
|
||||
PointIndex pi2 = PointIndex::INVALID;
|
||||
PointIndex pi3 = PointIndex::INVALID;
|
||||
for (auto pi : el.PNums())
|
||||
if (pi != pi0 && pi != pi1)
|
||||
{
|
||||
pi3 = pi2;
|
||||
pi2 = pi;
|
||||
}
|
||||
suroundpts[0] = pi2;
|
||||
suroundpts[1] = pi3;
|
||||
|
||||
for (auto i : Range(2, nsuround + 1))
|
||||
{
|
||||
PointIndex oldpi = suroundpts[i - 1];
|
||||
PointIndex newpi = PointIndex::INVALID;
|
||||
|
||||
for (int k = 0; k < nsuround && !newpi.IsValid(); k++)
|
||||
if (!tetused[k])
|
||||
{
|
||||
const Element& nel = mesh[hasbothpoints[k]];
|
||||
for (int k2 = 0; k2 < 4 && !newpi.IsValid(); k2++)
|
||||
if (nel[k2] == oldpi)
|
||||
{
|
||||
newpi = nel[0] - pi0 + nel[1] - pi1 + nel[2] - oldpi + nel[3];
|
||||
tetused[k] = true;
|
||||
suroundpts[i] = newpi;
|
||||
|
||||
ArrayMem<PointIndex, 4> nelpts{nel[0], nel[1], nel[2], nel[3]};
|
||||
ArrayMem<PointIndex, 4> check_points{pi0, pi1, oldpi, newpi};
|
||||
QuickSort(check_points);
|
||||
QuickSort(nelpts);
|
||||
if (check_points != nelpts)
|
||||
{
|
||||
cout << __FILE__ << ":" << __LINE__ << "\tFound error" << endl;
|
||||
cout << "i = " << i << endl;
|
||||
cout << "oldpi = " << oldpi << endl;
|
||||
cout << "newpi = " << newpi << endl;
|
||||
cout << "Elements: " << endl;
|
||||
cout << "nel " << nel << endl;
|
||||
for (auto ei : hasbothpoints)
|
||||
cout << mesh[ei] << endl;
|
||||
cout << endl;
|
||||
cout << "check_points: " << check_points << endl;
|
||||
cout << "nelpts: " << nelpts << endl;
|
||||
cout << "hasbothpoints: " << hasbothpoints << endl;
|
||||
cout << "suroundpts: " << suroundpts << endl;
|
||||
throw Exception("Found error");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (suroundpts.Last() != suroundpts[0])
|
||||
{
|
||||
cout << __FILE__ << ":" << __LINE__ << "\tFound error" << endl;
|
||||
cout << "hasbothpoints: " << hasbothpoints << endl;
|
||||
cout << "suroundpts: " << suroundpts << endl;
|
||||
for (auto ei : hasbothpoints)
|
||||
cout << mesh[ei] << endl;
|
||||
throw Exception("Found error");
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace netgen
|
||||
|
@ -1,12 +1,17 @@
|
||||
#include "meshclass.hpp"
|
||||
#include "meshfunc.hpp"
|
||||
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
unique_ptr<Mesh> GetOpenElements( const Mesh & m, int dom = 0 );
|
||||
unique_ptr<Mesh> GetOpenElements( const Mesh & m, int dom = 0, bool only_quads = false );
|
||||
|
||||
unique_ptr<Mesh> FilterMesh( const Mesh & m, FlatArray<PointIndex> points, FlatArray<SurfaceElementIndex> sels = Array<SurfaceElementIndex>{}, FlatArray<ElementIndex> els = Array<ElementIndex>{} );
|
||||
|
||||
// Checks if the mesh is valid. This is called automatically on various places if debugparam.slowchecks is set
|
||||
void CheckMesh( const Mesh & m, MESHING_STEP meshing_step );
|
||||
|
||||
|
||||
// Sometimes during SwapImprove we discover topological errors in the mesh. For instance, an edge is adjacent to 8 tets around it, but
|
||||
// the 8 "other" points of the tets don't form a closed path around the edge. Instead there are 2 sets of 4 points/tets each, which are not connected.
|
||||
// This function checks for such errors and returns true if any are found.
|
||||
void CheckElementsAroundEdges( const Mesh & m );
|
||||
}
|
||||
|
@ -34,21 +34,19 @@ namespace netgen
|
||||
int NB(int i) const { return nb[i]; }
|
||||
|
||||
|
||||
int FaceNr (INDEX_3 & face) const // which face nr is it ?
|
||||
int FaceNr (const PointIndices<3> & face) const // which face nr is it ?
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
if (pnums[i] != face.I1() &&
|
||||
pnums[i] != face.I2() &&
|
||||
pnums[i] != face.I3())
|
||||
if (pnums[i] != face[0] && pnums[i] != face[1] && pnums[i] != face[2])
|
||||
return i;
|
||||
return 3;
|
||||
}
|
||||
|
||||
INDEX_3 GetFace (int i) const
|
||||
PointIndices<3> GetFace (int i) const
|
||||
{
|
||||
return INDEX_3 (pnums[deltetfaces[i][0]],
|
||||
pnums[deltetfaces[i][1]],
|
||||
pnums[deltetfaces[i][2]]);
|
||||
return { pnums[deltetfaces[i][0]],
|
||||
pnums[deltetfaces[i][1]],
|
||||
pnums[deltetfaces[i][2]] };
|
||||
}
|
||||
|
||||
void GetFace (int i, Element2d & face) const
|
||||
@ -374,10 +372,10 @@ namespace netgen
|
||||
}
|
||||
else
|
||||
{
|
||||
INDEX_3 i3 = tempels.Get(helind).GetFace (k);
|
||||
const Point<3> & p1 = mesh[PointIndex (i3.I1())];
|
||||
const Point<3> & p2 = mesh[PointIndex (i3.I2())];
|
||||
const Point<3> & p3 = mesh[PointIndex (i3.I3())];
|
||||
PointIndices<3> i3 = tempels.Get(helind).GetFace (k);
|
||||
const Point<3> & p1 = mesh[i3[0]];
|
||||
const Point<3> & p2 = mesh[i3[1]];
|
||||
const Point<3> & p3 = mesh[i3[2]];
|
||||
|
||||
Vec<3> n = Cross (p2-p1, p3-p1);
|
||||
n /= n.Length();
|
||||
@ -564,7 +562,7 @@ namespace netgen
|
||||
|
||||
|
||||
|
||||
void Delaunay1 (Mesh & mesh, const MeshingParameters & mp, AdFront3 * adfront,
|
||||
void Delaunay1 (Mesh & mesh, int domainnr, const MeshingParameters & mp, const AdFront3 & adfront,
|
||||
NgArray<DelaunayTet> & tempels,
|
||||
int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax)
|
||||
{
|
||||
@ -575,7 +573,7 @@ namespace netgen
|
||||
|
||||
Box<3> bbox(Box<3>::EMPTY_BOX);
|
||||
|
||||
for (auto & face : adfront->Faces())
|
||||
for (auto & face : adfront.Faces())
|
||||
for (PointIndex pi : face.Face().PNums())
|
||||
bbox.Add (mesh.Point(pi));
|
||||
|
||||
@ -612,17 +610,27 @@ namespace netgen
|
||||
Array<bool, PointIndex> usep(np);
|
||||
usep = false;
|
||||
|
||||
for (auto & face : adfront->Faces())
|
||||
for (auto & face : adfront.Faces())
|
||||
for (PointIndex pi : face.Face().PNums())
|
||||
usep[pi] = true;
|
||||
|
||||
|
||||
/*
|
||||
for (size_t i = oldnp + PointIndex::BASE;
|
||||
i < np + PointIndex::BASE; i++)
|
||||
*/
|
||||
for (auto i : mesh.Points().Range().Modify(oldnp, -4))
|
||||
usep[i] = true;
|
||||
|
||||
for (PointIndex pi : mesh.LockedPoints())
|
||||
usep[pi] = true;
|
||||
|
||||
// mark points of free edge segments (no adjacent face)
|
||||
for (auto & seg : mesh.LineSegments())
|
||||
if(seg.domin == domainnr && seg.domout == domainnr)
|
||||
{
|
||||
usep[seg[0]] = true;
|
||||
usep[seg[1]] = true;
|
||||
}
|
||||
|
||||
NgArray<int> freelist;
|
||||
|
||||
@ -666,7 +674,7 @@ namespace netgen
|
||||
IndexSet closesphere(mesh.GetNP());
|
||||
|
||||
// "random" reordering of points (speeds a factor 3 - 5 !!!)
|
||||
NgArray<PointIndex, PointIndex::BASE, PointIndex> mixed(np);
|
||||
Array<PointIndex, PointIndex> mixed(np);
|
||||
// int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 };
|
||||
// int prims[] = { 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
|
||||
int prims[] = { 211, 223, 227, 229, 233, 239, 241, 251, 257, 263 };
|
||||
@ -677,24 +685,25 @@ namespace netgen
|
||||
while (np % prims[i] == 0) i++;
|
||||
prim = prims[i];
|
||||
}
|
||||
|
||||
|
||||
// for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++)
|
||||
for (PointIndex pi : mesh.Points().Range().Modify(0, -4))
|
||||
mixed[pi] = PointIndex ( (prim * pi) % np + PointIndex::BASE );
|
||||
// mixed[pi] = PointIndex ( (prim * pi) % np + PointIndex::BASE );
|
||||
mixed[pi] = (prim * (pi-IndexBASE<PointIndex>()+1)) % np + IndexBASE<PointIndex>() ;
|
||||
|
||||
Array<DelaunayTet> newels;
|
||||
// for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++)
|
||||
for (PointIndex pi : mesh.Points().Range().Modify(0, -4))
|
||||
{
|
||||
if (pi % 1000 == 0)
|
||||
if ((pi-IndexBASE<PointIndex>()) % 1000 == 0)
|
||||
{
|
||||
if (pi % 10000 == 0)
|
||||
if ((pi-IndexBASE<PointIndex>()) % 10000 == 0)
|
||||
PrintDot ('+');
|
||||
else
|
||||
PrintDot ('.');
|
||||
}
|
||||
|
||||
multithread.percent = 100.0 * pi / np;
|
||||
multithread.percent = 100.0 * (pi-IndexBASE<PointIndex>()) / np;
|
||||
if (multithread.terminate)
|
||||
break;
|
||||
|
||||
@ -714,7 +723,7 @@ namespace netgen
|
||||
}
|
||||
|
||||
for (int i = tempels.Size(); i >= 1; i--)
|
||||
if (tempels.Get(i)[0] <= 0)
|
||||
if (!tempels.Get(i)[0].IsValid())
|
||||
tempels.DeleteElement (i);
|
||||
|
||||
PrintDot ('\n');
|
||||
@ -740,7 +749,7 @@ namespace netgen
|
||||
{
|
||||
static Timer tdegenerated("Delaunay - remove degenerated"); RegionTimer rt(tdegenerated);
|
||||
|
||||
NgBitArray badnode(points.Size());
|
||||
TBitArray<PointIndex> badnode(points.Size());
|
||||
badnode.Clear();
|
||||
|
||||
int ndeg = 0;
|
||||
@ -762,13 +771,15 @@ namespace netgen
|
||||
|
||||
double h = v1.Length() + v2.Length() + v3.Length();
|
||||
if (fabs (vol) < 1e-8 * (h * h * h) &&
|
||||
(el[0] <= np && el[1] <= np &&
|
||||
el[2] <= np && el[3] <= np) ) // old: 1e-12
|
||||
(el[0] < IndexBASE<PointIndex>()+np &&
|
||||
el[1] < IndexBASE<PointIndex>()+np &&
|
||||
el[2] < IndexBASE<PointIndex>()+np &&
|
||||
el[3] < IndexBASE<PointIndex>()+np) ) // old: 1e-12
|
||||
{
|
||||
badnode.Set(el[0]);
|
||||
badnode.Set(el[1]);
|
||||
badnode.Set(el[2]);
|
||||
badnode.Set(el[3]);
|
||||
badnode.SetBitAtomic(el[0]);
|
||||
badnode.SetBitAtomic(el[1]);
|
||||
badnode.SetBitAtomic(el[2]);
|
||||
badnode.SetBitAtomic(el[3]);
|
||||
ndeg++;
|
||||
(*testout) << "vol = " << vol << " h = " << h << endl;
|
||||
}
|
||||
@ -798,7 +809,7 @@ namespace netgen
|
||||
static Timer topenel("Delaunay - find openel"); RegionTimer rt(topenel);
|
||||
|
||||
// find surface triangles which are no face of any tet
|
||||
BitArray bnd_points( mesh.GetNP() + PointIndex::BASE );
|
||||
TBitArray<PointIndex> bnd_points( mesh.GetNP() );
|
||||
bnd_points.Clear();
|
||||
|
||||
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
|
||||
@ -840,16 +851,17 @@ namespace netgen
|
||||
tets_with_3_bnd_points.SetSize(cnt);
|
||||
|
||||
static Timer t1("Build face table"); t1.Start();
|
||||
ngcore::ClosedHashTable< ngcore::IVec<3>, int > face_table( 4*cnt + 3 );
|
||||
for(auto ei : tets_with_3_bnd_points)
|
||||
for(auto j : Range(4))
|
||||
// ngcore::ClosedHashTable< ngcore::IVec<3>, int > face_table( 4*cnt + 3 );
|
||||
ngcore::ClosedHashTable< PointIndices<3>, int > face_table( 4*cnt + 3 );
|
||||
for (auto ei : tets_with_3_bnd_points)
|
||||
for (auto j : Range(4))
|
||||
{
|
||||
auto i3_ = tempels[ei].GetFace (j);
|
||||
ngcore::IVec<3> i3 = {i3_[0], i3_[1], i3_[2]};
|
||||
if(bnd_points[i3[0]] && bnd_points[i3[1]] && bnd_points[i3[2]])
|
||||
PointIndices<3> i3 = tempels[ei].GetFace (j);
|
||||
// ngcore::IVec<3> i3 = {i3_[0], i3_[1], i3_[2]};
|
||||
if(bnd_points[i3[0]] && bnd_points[i3[1]] && bnd_points[i3[2]])
|
||||
{
|
||||
i3.Sort();
|
||||
face_table.Set( i3, true );
|
||||
i3.Sort();
|
||||
face_table.Set( i3, true );
|
||||
}
|
||||
}
|
||||
t1.Stop();
|
||||
@ -860,7 +872,8 @@ namespace netgen
|
||||
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
|
||||
{
|
||||
const Element2d & tri = mesh.OpenElement(i);
|
||||
ngcore::IVec<3> i3(tri[0], tri[1], tri[2]);
|
||||
// ngcore::IVec<3,PointIndex> i3(tri[0], tri[1], tri[2]);
|
||||
PointIndices<3> i3(tri[0], tri[1], tri[2]);
|
||||
i3.Sort();
|
||||
if(!face_table.Used(i3))
|
||||
openels.Append(i);
|
||||
@ -878,7 +891,7 @@ namespace netgen
|
||||
table.Add(tri[2], openel_i);
|
||||
}, mesh.GetNP());
|
||||
|
||||
ngcore::BitArray badnode(mesh.GetNP()+PointIndex::BASE);
|
||||
TBitArray<PointIndex> badnode(mesh.GetNP());
|
||||
badnode.Clear();
|
||||
|
||||
ngcore::ParallelForRange(openels.Size(), [&] (auto myrange) {
|
||||
@ -912,7 +925,7 @@ namespace netgen
|
||||
{
|
||||
auto & tri_other = mesh.OpenElement(i_other);
|
||||
PointIndex pi2 = tri[(edge+2)%3];
|
||||
PointIndex pi3 = tri_other[0]+tri_other[1]+tri_other[2] - pi0 - pi1;
|
||||
PointIndex pi3 = tri_other[0]-pi0+tri_other[1]-pi1+tri_other[2];
|
||||
if(pi2>pi3)
|
||||
Swap(pi2, pi3);
|
||||
|
||||
@ -936,8 +949,8 @@ namespace netgen
|
||||
double h = v1.Length() + v2.Length() + v3.Length();
|
||||
if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-12
|
||||
{
|
||||
badnode.SetBitAtomic(pi2);
|
||||
badnode.SetBitAtomic(pi3);
|
||||
badnode.SetBitAtomic(pi2);
|
||||
badnode.SetBitAtomic(pi3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -1005,7 +1018,7 @@ namespace netgen
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
pp[j] = &mesh.Point(el[j]);
|
||||
tetpi[j] = el[j];
|
||||
tetpi[j] = el[j]-IndexBASE<PointIndex>()+1;
|
||||
}
|
||||
|
||||
Point3d tetpmin(*pp[0]);
|
||||
@ -1034,7 +1047,7 @@ namespace netgen
|
||||
for (int k = 1; k <= 3; k++)
|
||||
{
|
||||
tripp[k-1] = &mesh.Point (tri.PNum(k));
|
||||
tripi[k-1] = tri.PNum(k);
|
||||
tripi[k-1] = tri.PNum(k)-IndexBASE<PointIndex>()+1;
|
||||
}
|
||||
|
||||
if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi))
|
||||
@ -1077,7 +1090,7 @@ namespace netgen
|
||||
}
|
||||
}
|
||||
|
||||
void DelaunayRemoveOuter( const Mesh & mesh, NgArray<DelaunayTet> & tempels, AdFront3 * adfront )
|
||||
void DelaunayRemoveOuter( const Mesh & mesh, NgArray<DelaunayTet> & tempels, const AdFront3 & adfront )
|
||||
{
|
||||
static Timer trem_outer("Delaunay - remove outer"); RegionTimer rt(trem_outer);
|
||||
|
||||
@ -1101,7 +1114,7 @@ namespace netgen
|
||||
*/
|
||||
for (const Element2d & tri : mesh.OpenElements())
|
||||
{
|
||||
INDEX_3 i3 (tri[0], tri[1], tri[2]);
|
||||
PointIndices<3> i3 (tri[0], tri[1], tri[2]);
|
||||
i3.Sort();
|
||||
boundaryfaces.PrepareSet (i3);
|
||||
}
|
||||
@ -1109,7 +1122,7 @@ namespace netgen
|
||||
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
|
||||
{
|
||||
const Element2d & tri = mesh.OpenElement(i);
|
||||
INDEX_3 i3 (tri[0], tri[1], tri[2]);
|
||||
PointIndices<3> i3 (tri[0], tri[1], tri[2]);
|
||||
i3.Sort();
|
||||
boundaryfaces.Set (i3, 1);
|
||||
}
|
||||
@ -1122,16 +1135,13 @@ namespace netgen
|
||||
for (auto & el : tempels)
|
||||
for (int j = 0; j < 4; j++)
|
||||
el.NB(j) = 0;
|
||||
|
||||
TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP());
|
||||
|
||||
/*
|
||||
for (int i = 0; i < tempels.Size(); i++)
|
||||
{
|
||||
const DelaunayTet & el = tempels[i];
|
||||
*/
|
||||
TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP());
|
||||
|
||||
for (const DelaunayTet & el : tempels)
|
||||
{
|
||||
INDEX_4 i4(el[0], el[1], el[2], el[3]);
|
||||
PointIndices<4> i4(el[0], el[1], el[2], el[3]);
|
||||
i4.Sort();
|
||||
elsonpoint.IncSizePrepare (i4.I1());
|
||||
elsonpoint.IncSizePrepare (i4.I2());
|
||||
@ -1142,12 +1152,30 @@ namespace netgen
|
||||
for (int i = 0; i < tempels.Size(); i++)
|
||||
{
|
||||
const DelaunayTet & el = tempels[i];
|
||||
INDEX_4 i4(el[0], el[1], el[2], el[3]);
|
||||
PointIndices<4> i4(el[0], el[1], el[2], el[3]);
|
||||
i4.Sort();
|
||||
elsonpoint.Add (i4.I1(), i+1);
|
||||
elsonpoint.Add (i4.I2(), i+1);
|
||||
}
|
||||
*/
|
||||
|
||||
TableCreator<int, PointIndex> creator(mesh.GetNP());
|
||||
while (!creator.Done())
|
||||
{
|
||||
for (int i = 0; i < tempels.Size(); i++)
|
||||
{
|
||||
const DelaunayTet & el = tempels[i];
|
||||
PointIndices<4> i4(el[0], el[1], el[2], el[3]);
|
||||
i4.Sort();
|
||||
creator.Add (i4[0], i+1);
|
||||
creator.Add (i4[1], i+1);
|
||||
}
|
||||
creator++;
|
||||
}
|
||||
auto elsonpoint = creator.MoveTable();
|
||||
|
||||
|
||||
|
||||
// cout << "elsonpoint mem: ";
|
||||
// elsonpoint.PrintMemInfo(cout);
|
||||
|
||||
@ -1171,7 +1199,7 @@ namespace netgen
|
||||
|
||||
if (hel[0] == pi)
|
||||
{
|
||||
INDEX_3 i3(hel[0], hel[1], hel[2]);
|
||||
PointIndices<3> i3(hel[0], hel[1], hel[2]);
|
||||
|
||||
if (!boundaryfaces.Used (i3))
|
||||
{
|
||||
@ -1186,7 +1214,7 @@ namespace netgen
|
||||
{
|
||||
hel.Invert();
|
||||
hel.NormalizeNumbering();
|
||||
INDEX_3 i3i(hel[0], hel[1], hel[2]);
|
||||
PointIndices<3> i3i(hel[0], hel[1], hel[2]);
|
||||
INDEX_2 i2(i, j);
|
||||
faceht.Set (i3i, i2);
|
||||
}
|
||||
@ -1270,7 +1298,7 @@ namespace netgen
|
||||
|
||||
|
||||
auto ne = tempels.Size();
|
||||
NgBitArray inner(ne), outer(ne);
|
||||
BitArray inner(ne+1), outer(ne+1);
|
||||
inner.Clear();
|
||||
outer.Clear();
|
||||
NgArray<int> elstack;
|
||||
@ -1315,7 +1343,7 @@ namespace netgen
|
||||
|
||||
Point3d ci = Center (p1, p2, p3, p4);
|
||||
|
||||
inside = adfront->Inside (ci);
|
||||
inside = adfront.Inside (ci);
|
||||
|
||||
/*
|
||||
cout << "startel: " << i << endl;
|
||||
@ -1335,9 +1363,9 @@ namespace netgen
|
||||
if (!inner.Test(ei) && !outer.Test(ei))
|
||||
{
|
||||
if (inside)
|
||||
inner.Set(ei);
|
||||
inner.SetBit(ei);
|
||||
else
|
||||
outer.Set(ei);
|
||||
outer.SetBit(ei);
|
||||
|
||||
|
||||
for (int j = 1; j <= 4; j++)
|
||||
@ -1397,7 +1425,7 @@ namespace netgen
|
||||
// if (adfront->Inside (ci) != adfront->Inside (Center (ci, p1)))
|
||||
// cout << "ERROR: outer test unclear !!!" << endl;
|
||||
|
||||
if (inner.Test(i) != adfront->Inside (ci))
|
||||
if (inner.Test(i) != adfront.Inside (ci))
|
||||
{
|
||||
/*
|
||||
cout << "ERROR: outer test wrong !!!"
|
||||
@ -1425,10 +1453,10 @@ namespace netgen
|
||||
|
||||
}
|
||||
|
||||
if (adfront->Inside(ci))
|
||||
if (adfront.Inside(ci))
|
||||
outer.Clear(i);
|
||||
else
|
||||
outer.Set(i);
|
||||
outer.SetBit(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1554,7 +1582,7 @@ namespace netgen
|
||||
|
||||
int np = mesh.GetNP();
|
||||
|
||||
Delaunay1 (mesh, mp, adfront, tempels, oldnp, startel, pmin, pmax);
|
||||
Delaunay1 (mesh, domainnr, mp, *adfront, tempels, oldnp, startel, pmin, pmax);
|
||||
|
||||
{
|
||||
// improve delaunay - mesh by swapping !!!!
|
||||
@ -1657,7 +1685,7 @@ namespace netgen
|
||||
NgArray<int> openels;
|
||||
DelaunayRemoveTwoTriaTets(mesh, tempels, openels);
|
||||
DelaunayRemoveIntersecting(mesh, tempels, openels, pmin, pmax);
|
||||
DelaunayRemoveOuter(mesh, tempels, adfront);
|
||||
DelaunayRemoveOuter(mesh, tempels, *adfront);
|
||||
|
||||
for (int i = 0; i < tempels.Size(); i++)
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ namespace netgen
|
||||
if(p1<p0)
|
||||
Swap(p0,p1);
|
||||
|
||||
IVec<2> hash = {p0,p1};
|
||||
PointIndices<2> hash = {p0,p1};
|
||||
|
||||
auto pos = edge_to_trig.Position(hash);
|
||||
if (pos == -1) return -1;
|
||||
@ -53,7 +53,7 @@ namespace netgen
|
||||
if(p1<p0)
|
||||
Swap(p0,p1);
|
||||
|
||||
IVec<2> hash = {p0,p1};
|
||||
PointIndices<2> hash = {p0,p1};
|
||||
auto pos = edge_to_trig.Position(hash);
|
||||
if (pos == -1)
|
||||
edge_to_trig[hash] = {eli, -1};
|
||||
@ -80,7 +80,7 @@ namespace netgen
|
||||
if(p1<p0)
|
||||
Swap(p0,p1);
|
||||
|
||||
IVec<2> hash = {p0,p1};
|
||||
PointIndices<2> hash = {p0,p1};
|
||||
auto pos = edge_to_trig.Position(hash);
|
||||
auto i2 = edge_to_trig.GetData(pos);
|
||||
|
||||
@ -93,7 +93,7 @@ namespace netgen
|
||||
}
|
||||
|
||||
|
||||
void DelaunayMesh::AppendTrig( int pi0, int pi1, int pi2 )
|
||||
void DelaunayMesh::AppendTrig( PointIndex pi0, PointIndex pi1, PointIndex pi2 )
|
||||
{
|
||||
DelaunayTrig el;
|
||||
el[0] = pi0;
|
||||
@ -174,7 +174,8 @@ namespace netgen
|
||||
{
|
||||
const auto trig = trigs[i_trig];
|
||||
|
||||
if(trig[0]==-1)
|
||||
// if(trig[0]==-1)
|
||||
if(!trig[0].IsValid())
|
||||
continue;
|
||||
|
||||
double rad2 = trig.Radius2();
|
||||
@ -254,9 +255,9 @@ namespace netgen
|
||||
const DelaunayTrig & trig = trigs[j];
|
||||
for (int k = 0; k < 3; k++)
|
||||
{
|
||||
int p1 = trig[k];
|
||||
int p2 = trig[(k+1)%3];
|
||||
IVec<2> edge{p1,p2};
|
||||
PointIndex p1 = trig[k];
|
||||
PointIndex p2 = trig[(k+1)%3];
|
||||
PointIndices<2> edge{p1,p2};
|
||||
edge.Sort();
|
||||
bool found = false;
|
||||
for (int l = 0; l < edges.Size(); l++)
|
||||
@ -309,9 +310,9 @@ namespace netgen
|
||||
for (int j : intersecting)
|
||||
{
|
||||
UnsetNeighbours(j);
|
||||
trigs[j][0] = -1;
|
||||
trigs[j][1] = -1;
|
||||
trigs[j][2] = -1;
|
||||
trigs[j][0] = PointIndex::INVALID;
|
||||
trigs[j][1] = PointIndex::INVALID;
|
||||
trigs[j][2] = PointIndex::INVALID;
|
||||
}
|
||||
|
||||
for (auto edge : edges)
|
||||
@ -331,7 +332,8 @@ namespace netgen
|
||||
|
||||
for (DelaunayTrig & trig : trigs)
|
||||
{
|
||||
if (trig[0] < 0) continue;
|
||||
// if (trig[0] < 0) continue;
|
||||
if (!trig[0].IsValid()) continue;
|
||||
|
||||
Vec<3> n = Cross (P3(points[trig[1]])-P3(points[trig[0]]),
|
||||
P3(points[trig[2]])-P3(points[trig[0]]));
|
||||
@ -427,7 +429,7 @@ namespace netgen
|
||||
}
|
||||
tcut.Stop();
|
||||
|
||||
mesh.LocalHFunction().FindInnerBoxes (&adfront, NULL);
|
||||
mesh.LocalHFunction().FindInnerBoxes (adfront, NULL);
|
||||
|
||||
npoints.SetSize(0);
|
||||
mesh.LocalHFunction().GetInnerPoints (npoints);
|
||||
@ -521,7 +523,7 @@ namespace netgen
|
||||
loch2.CutBoundary (bbox);
|
||||
}
|
||||
|
||||
loch2.FindInnerBoxes (&adfront, NULL);
|
||||
loch2.FindInnerBoxes (adfront, NULL);
|
||||
|
||||
// outer points : smooth mesh-grading
|
||||
npoints.SetSize(0);
|
||||
@ -587,7 +589,7 @@ namespace netgen
|
||||
|
||||
t2.Start();
|
||||
Array<PointIndex> old_points;
|
||||
BitArray add_point(mesh.Points().Size()+1);
|
||||
TBitArray<PointIndex> add_point(mesh.Points().Size()+1);
|
||||
Array<PointIndex> addpoints;
|
||||
add_point.Clear();
|
||||
/*
|
||||
@ -708,7 +710,8 @@ namespace netgen
|
||||
|
||||
for (auto & trig : dmesh.GetElements())
|
||||
{
|
||||
if (trig[0] < 0) continue;
|
||||
// if (trig[0] < 0) continue;
|
||||
if (!trig[0].IsValid()) continue;
|
||||
|
||||
Element2d el(trig[0], trig[1], trig[2]);
|
||||
el.SetIndex (1);
|
||||
@ -719,7 +722,7 @@ namespace netgen
|
||||
while(!conforming)
|
||||
{
|
||||
conforming = true;
|
||||
BitArray marked_points(tempmesh.Points().Size()+1);
|
||||
TBitArray<PointIndex> marked_points(tempmesh.Points().Size()+1);
|
||||
marked_points = false;
|
||||
// Check for trigs cutting a boundary edge (non-conforming mesh)
|
||||
auto point_to_trigs = tempmesh.CreatePoint2SurfaceElementTable( 0 );
|
||||
@ -776,7 +779,7 @@ namespace netgen
|
||||
auto & el0 = tempmesh[cutting_trigs[0]];
|
||||
auto & el1 = tempmesh[cutting_trigs[1]];
|
||||
|
||||
pi1 = el1[0]+el1[1]+el1[2] - pi2-pi3;
|
||||
pi1 = el1[0]-pi2+el1[1]-pi3+el1[2];
|
||||
|
||||
if(marked_points.Test(pi1)) continue;
|
||||
|
||||
@ -801,16 +804,16 @@ namespace netgen
|
||||
// Mark edges and trigs as inside or outside, starting with boundary edges
|
||||
enum POSITION { UNKNOWN, BOUNDARY, INSIDE, OUTSIDE };
|
||||
Array<POSITION, SurfaceElementIndex> trig_pos(tempmesh.SurfaceElements().Size());
|
||||
ngcore::ClosedHashTable<IVec<2>, POSITION> edge_pos(3*tempmesh.SurfaceElements().Size());
|
||||
ngcore::ClosedHashTable<PointIndices<2>, POSITION> edge_pos(3*tempmesh.SurfaceElements().Size());
|
||||
trig_pos = UNKNOWN;
|
||||
|
||||
for (auto & seg : tempmesh.LineSegments())
|
||||
{
|
||||
ArrayMem<SurfaceElementIndex, 2> els;
|
||||
IVec<2> edge{seg[0], seg[1]};
|
||||
PointIndices<2> edge{seg[0], seg[1]};
|
||||
edge.Sort();
|
||||
edge_pos[edge] = BOUNDARY;
|
||||
|
||||
|
||||
for(auto sei : point_to_trigs[seg[0]])
|
||||
for( auto i : Range(3))
|
||||
if(tempmesh[sei][i] == seg[1])
|
||||
@ -819,7 +822,7 @@ namespace netgen
|
||||
for(auto sei : els)
|
||||
{
|
||||
auto & el = tempmesh[sei];
|
||||
PointIndex pi2 = el[0]+el[1]+el[2] - seg[0] - seg[1];
|
||||
PointIndex pi2 = el[0]-seg[0]+el[1]-seg[1]+el[2];
|
||||
bool is_left = ::netgen::Area(P2(tempmesh[seg[0]]), P2(tempmesh[seg[1]]), P2(tempmesh[pi2]))>0.0;
|
||||
POSITION pos;
|
||||
|
||||
@ -828,8 +831,8 @@ namespace netgen
|
||||
else
|
||||
pos = OUTSIDE;
|
||||
|
||||
IVec<2> e1{seg[0], pi2};
|
||||
IVec<2> e2{seg[1], pi2};
|
||||
PointIndices<2> e1{seg[0], pi2};
|
||||
PointIndices<2> e2{seg[1], pi2};
|
||||
e1.Sort();
|
||||
e2.Sort();
|
||||
if(!edge_pos.Used(e1))
|
||||
@ -857,7 +860,7 @@ namespace netgen
|
||||
// any edge of unknown trig already marked?
|
||||
for(auto i : IntRange(3))
|
||||
{
|
||||
IVec<2> edge{el[(i+1)%3], el[(i+2)%3]};
|
||||
PointIndices<2> edge{el[(i+1)%3], el[(i+2)%3]};
|
||||
edge.Sort();
|
||||
if(edge_pos.Used(edge) && edge_pos[edge]!=BOUNDARY)
|
||||
{
|
||||
@ -871,7 +874,7 @@ namespace netgen
|
||||
if(trig_pos[sei] != UNKNOWN)
|
||||
for(auto i : IntRange(3))
|
||||
{
|
||||
IVec<2> edge{el[(i+1)%3], el[(i+2)%3]};
|
||||
PointIndices<2> edge{el[(i+1)%3], el[(i+2)%3]};
|
||||
edge.Sort();
|
||||
if(!edge_pos.Used(edge) || edge_pos[edge]==BOUNDARY)
|
||||
edge_pos[edge] = trig_pos[sei];
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user