mirror of
https://github.com/NGSolve/netgen.git
synced 2025-05-10 04:30:48 +05:00
Compare commits
188 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 |
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
|
||||
|
@ -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)
|
||||
|
@ -109,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}
|
||||
)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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(0., 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);
|
||||
|
@ -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
|
||||
|
@ -50,7 +50,7 @@ namespace ngcore
|
||||
|
||||
RangeException :: RangeException (// const std::string & where,
|
||||
const char * where,
|
||||
int ind, int imin, int imax) : Exception("")
|
||||
ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax) : Exception("")
|
||||
{
|
||||
std::stringstream str;
|
||||
str << where << ": index " << ind << " out of range [" << imin << "," << imax << ")\n";
|
||||
@ -59,7 +59,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
|
||||
void ThrowRangeException(const char * s, int ind, int imin, int imax)
|
||||
void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax)
|
||||
{
|
||||
throw RangeException(s, ind, imin, imax);
|
||||
}
|
||||
@ -75,7 +75,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
|
||||
void ThrowNotTheSameException(const char * s, long int a, long int b)
|
||||
void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b)
|
||||
{
|
||||
throw ngcore::Exception(std::string(s) + ", a="+ToString(a) + ", b="+ToString(b) + GetBackTrace());
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef NETGEN_CORE_EXCEPTION_HPP
|
||||
#define NETGEN_CORE_EXCEPTION_HPP
|
||||
|
||||
#include <cstddef>
|
||||
#include <sstream> // for stringstream
|
||||
#include <stdexcept> // for exception
|
||||
#include <string> // for string
|
||||
@ -66,7 +67,7 @@ namespace ngcore
|
||||
/// where it occurs, index, minimal and maximal indices
|
||||
RangeException (// const std::string & where,
|
||||
const char * where,
|
||||
int ind, int imin, int imax);
|
||||
ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);
|
||||
/*
|
||||
: Exception("")
|
||||
{
|
||||
@ -85,8 +86,8 @@ namespace ngcore
|
||||
}
|
||||
};
|
||||
|
||||
[[noreturn]] NGCORE_API void ThrowRangeException(const char * s, int ind, int imin, int imax);
|
||||
[[noreturn]] NGCORE_API void ThrowNotTheSameException(const char * s, long int a, long int b);
|
||||
[[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
|
||||
@ -98,24 +99,24 @@ namespace ngcore
|
||||
constexpr operator bool() const { return false; } };
|
||||
|
||||
namespace detail {
|
||||
template <typename T>
|
||||
inline static void CheckRange(const char * s, const T& n, int first, int next)
|
||||
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, int(n), first, next);
|
||||
ThrowRangeException(s, ptrdiff_t(n), ptrdiff_t(first), ptrdiff_t(next));
|
||||
}
|
||||
|
||||
template <typename Ta, typename Tb>
|
||||
inline static void CheckSame(const char * s, const Ta& a, const Tb& b)
|
||||
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_same<decltype(a),size_t>() && std::is_same<decltype(b),size_t>())
|
||||
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"+ToString(a) + ", b="+ngcore::ToString(b) + GetBackTrace());
|
||||
throw Exception(std::string(s) + "\t: not the same, a="+ToString(a) + ", b="+ngcore::ToString(b) + GetBackTrace());
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
@ -128,7 +129,7 @@ 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) ngcore::detail::CheckRange(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", value, int(min), int(max_plus_one));
|
||||
#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
|
||||
|
@ -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*"),
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <optional>
|
||||
|
||||
// #include "mpi_wrapper.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
@ -299,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;
|
||||
@ -310,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;
|
||||
@ -325,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;
|
||||
}
|
||||
@ -590,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.
|
||||
@ -611,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;
|
||||
@ -627,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;
|
||||
@ -652,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;
|
||||
@ -674,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)
|
||||
{
|
||||
@ -719,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;
|
||||
@ -796,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
|
||||
{
|
||||
@ -813,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))
|
||||
{
|
||||
@ -839,6 +883,9 @@ namespace ngcore
|
||||
tab.GetData (i, key, val);
|
||||
ost << key << ": " << val << ", ";
|
||||
}
|
||||
*/
|
||||
for (auto [key,val] : tab)
|
||||
ost << key << ": " << val << ", ";
|
||||
return ost;
|
||||
}
|
||||
|
||||
@ -1083,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
|
||||
{
|
||||
#if defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)
|
||||
#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,6 +188,14 @@ namespace ngcore
|
||||
|
||||
static const std::vector<std::string> & GetNames() { return names; }
|
||||
static const std::vector<int> & GetParents() { return parents; }
|
||||
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() {}
|
||||
@ -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
|
||||
{
|
||||
|
@ -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*);
|
||||
@ -81,6 +82,7 @@ NGCORE_API extern void* NG_MPI_IN_PLACE;
|
||||
#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
|
||||
|
@ -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)); };
|
||||
|
@ -22,5 +22,6 @@
|
||||
#include "xbool.hpp"
|
||||
#include "ngstream.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "ranges.hpp"
|
||||
|
||||
#endif // NETGEN_CORE_NGCORE_HPP
|
||||
|
@ -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];
|
||||
|
@ -324,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")
|
||||
|
@ -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; }
|
||||
|
||||
|
@ -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.
|
||||
|
@ -317,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); }
|
||||
};
|
||||
@ -623,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++)
|
||||
@ -632,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()
|
||||
{
|
||||
|
@ -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);
|
||||
}
|
||||
@ -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;
|
||||
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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,14 +111,14 @@ 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();
|
||||
@ -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);
|
||||
@ -175,14 +176,14 @@ 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();
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -263,14 +264,21 @@ namespace netgen
|
||||
{
|
||||
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_3 pair;
|
||||
int dummy;
|
||||
identpts.GetData(i, j, pair, dummy);
|
||||
auto idnr = pair[2];
|
||||
*/
|
||||
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));
|
||||
@ -281,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);
|
||||
@ -314,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();
|
||||
@ -340,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();
|
||||
@ -368,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];
|
||||
@ -414,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);
|
||||
@ -466,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);
|
||||
@ -492,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);
|
||||
@ -519,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);
|
||||
|
||||
@ -573,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);
|
||||
@ -608,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];
|
||||
@ -617,7 +633,7 @@ namespace netgen
|
||||
}
|
||||
nel1.SetIndex (el.GetIndex());
|
||||
nel2.SetIndex (el.GetIndex());
|
||||
mesh.VolumeElement (i) = nel1;
|
||||
mesh.VolumeElement (ei) = nel1;
|
||||
mesh.AddVolumeElement (nel2);
|
||||
}
|
||||
}
|
||||
@ -629,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;
|
||||
|
||||
@ -670,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);
|
||||
@ -691,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();
|
||||
@ -717,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))
|
||||
|
@ -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 ::
|
||||
|
@ -861,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;
|
||||
@ -880,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
|
||||
@ -892,6 +894,7 @@ protected:
|
||||
for (size_t i = 0; i < size; i++)
|
||||
hash[i].I1() = invalid;
|
||||
}
|
||||
*/
|
||||
|
||||
public:
|
||||
int Size() const
|
||||
@ -1073,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;
|
||||
|
@ -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 ();
|
||||
|
@ -109,7 +109,7 @@ namespace netgen
|
||||
{
|
||||
void * p = new char [(line.maxsize+5) * elsize];
|
||||
|
||||
if (line.maxsize*elsize)
|
||||
if (line.maxsize && elsize)
|
||||
memcpy (p, line.col, line.maxsize * elsize);
|
||||
delete [] (char*)line.col;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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,9 +117,7 @@ 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;
|
||||
@ -413,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();
|
||||
@ -214,13 +229,18 @@ 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;
|
||||
@ -271,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:
|
||||
@ -327,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;
|
||||
}
|
||||
|
||||
@ -339,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() };
|
||||
@ -349,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();
|
||||
|
@ -60,7 +60,7 @@ static void WritePoints ( const Mesh & mesh, ostream & out )
|
||||
out << "*Node" << endl;
|
||||
for(auto pi : mesh.Points().Range() )
|
||||
{
|
||||
out << pi+1-PointIndex::BASE << ", ";
|
||||
out << pi+1-IndexBASE<PointIndex>() << ", ";
|
||||
auto p = mesh[pi];
|
||||
out << p[0] << ", " << p[1] << ", " << p[2] << '\n';
|
||||
}
|
||||
@ -73,7 +73,7 @@ static void WriteElement(ostream & out, const Mesh& mesh, ElIndex ei, const vect
|
||||
auto el = mesh[ei];
|
||||
out << el_counter;
|
||||
for(auto i : Range(el.PNums()))
|
||||
out << ", " << el[permutation[i]]+1-PointIndex::BASE;
|
||||
out << ", " << el[permutation[i]]+1-IndexBASE<PointIndex>();
|
||||
out << '\n';
|
||||
}
|
||||
|
||||
|
@ -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,7 @@ namespace netgen
|
||||
{
|
||||
data = NULL; height = width = 0;
|
||||
SetSize (m2.Height(), m2.Width());
|
||||
if (Height()*Width())
|
||||
if (Height() && Width())
|
||||
memcpy (data, m2.data, sizeof(double) * (Height() * Width()));
|
||||
}
|
||||
|
||||
@ -70,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,8 +801,8 @@ void AdFront3 :: SetStartFront (int /* baseelnp */)
|
||||
*/
|
||||
}
|
||||
|
||||
bool AdFront3 :: PointInsideGroup(const NgArray<PointIndex, PointIndex::BASE> &grouppindex,
|
||||
const NgArray<MiniElement2d> &groupfaces) const
|
||||
bool AdFront3 :: PointInsideGroup(const Array<PointIndex, PointIndex> &grouppindex,
|
||||
const Array<MiniElement2d> &groupfaces) const
|
||||
{
|
||||
for(auto pi : Range(points))
|
||||
{
|
||||
@ -797,7 +811,7 @@ bool AdFront3 :: PointInsideGroup(const NgArray<PointIndex, PointIndex::BASE> &g
|
||||
for(const auto& f : groupfaces)
|
||||
{
|
||||
for(auto i : Range(3))
|
||||
if(grouppindex.Get(f.PNum(i+1)) == pi)
|
||||
if(grouppindex[f.PNum(i+1)] == pi)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
@ -814,9 +828,9 @@ bool AdFront3 :: PointInsideGroup(const NgArray<PointIndex, PointIndex::BASE> &g
|
||||
int count = 0;
|
||||
for(const auto& f : groupfaces)
|
||||
{
|
||||
const auto& p1 = points[grouppindex.Get(f.PNum(1))].P();
|
||||
auto v1 = points[grouppindex.Get(f.PNum(2))].P() - p1;
|
||||
auto v2 = points[grouppindex.Get(f.PNum(3))].P() - p1;
|
||||
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];
|
||||
|
@ -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,18 +266,18 @@ public:
|
||||
void GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax,
|
||||
NgArray<int> & ifaces) const;
|
||||
|
||||
bool PointInsideGroup(const NgArray<PointIndex, PointIndex::BASE> &grouppindex,
|
||||
const NgArray<MiniElement2d>& groupfaces) 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,
|
||||
@ -281,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);
|
||||
@ -293,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);
|
||||
|
@ -214,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()
|
||||
{
|
||||
@ -472,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);
|
||||
}
|
||||
@ -582,16 +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);
|
||||
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);
|
||||
}
|
||||
|
||||
@ -1217,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)
|
||||
{
|
||||
@ -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);
|
||||
|
@ -271,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,85 +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
|
||||
|
||||
DLL_HEADER void GenerateBoundaryLayer (Mesh & mesh,
|
||||
const BoundaryLayerParameters & blp);
|
||||
struct SpecialBoundaryPoint
|
||||
{
|
||||
struct GrowthGroup
|
||||
{
|
||||
Array<int> faces;
|
||||
Vec<3> growth_vector;
|
||||
Array<PointIndex> new_points;
|
||||
|
||||
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>{});
|
||||
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 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 ProcessParameters();
|
||||
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;
|
||||
|
||||
// These parameters are derived from given BoundaryLayerParameters and the Mesh
|
||||
Array<double> par_heights;
|
||||
Array<int> par_surfid;
|
||||
map<string, string> par_new_mat;
|
||||
Array<size_t> par_project_boundaries;
|
||||
// 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;
|
||||
|
||||
bool have_single_segments;
|
||||
Array<Segment> segments, new_segments;
|
||||
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;
|
||||
|
||||
Array<double> surfacefacs;
|
||||
Array<int> si_map;
|
||||
Array<double, PointIndex> limits;
|
||||
Array<double> surfacefacs;
|
||||
Array<int> si_map;
|
||||
|
||||
// major steps called in Perform()
|
||||
void CreateNewFaceDescriptors();
|
||||
void CreateFaceDescriptorsSides();
|
||||
void CalculateGrowthVectors();
|
||||
Array<Array<pair<SegmentIndex, int>>, SegmentIndex> BuildSegMap();
|
||||
std::map<PointIndex, SpecialBoundaryPoint> special_boundary_points;
|
||||
std::map<PointIndex, std::tuple<Vec<3>*, double>> growth_vector_map;
|
||||
|
||||
BitArray ProjectGrowthVectorsOnSurface();
|
||||
void InterpolateSurfaceGrowthVectors();
|
||||
void InterpolateGrowthVectors();
|
||||
void LimitGrowthVectorLengths();
|
||||
// major steps called in Perform()
|
||||
void CreateNewFaceDescriptors ();
|
||||
void CreateFaceDescriptorsSides ();
|
||||
void CalculateGrowthVectors ();
|
||||
Array<Array<pair<SegmentIndex, int>>, SegmentIndex> BuildSegMap ();
|
||||
|
||||
void InsertNewElements(FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap, const BitArray & in_surface_direction);
|
||||
void SetDomInOut();
|
||||
void SetDomInOutSides();
|
||||
void AddSegments();
|
||||
void FixVolumeElements();
|
||||
BitArray ProjectGrowthVectorsOnSurface ();
|
||||
void InterpolateSurfaceGrowthVectors ();
|
||||
void InterpolateGrowthVectors ();
|
||||
void LimitGrowthVectorLengths ();
|
||||
void FixSurfaceElements ();
|
||||
|
||||
// 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 );
|
||||
void InsertNewElements (FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap, const BitArray& in_surface_direction);
|
||||
void SetDomInOut ();
|
||||
void SetDomInOutSides ();
|
||||
void AddSegments ();
|
||||
void AddSurfaceElements ();
|
||||
|
||||
Vec<3> getNormal(const Element2d & el)
|
||||
{
|
||||
auto v0 = mesh[el[0]];
|
||||
return Cross(mesh[el[1]]-v0, mesh[el[2]]-v0).Normalize();
|
||||
}
|
||||
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);
|
||||
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>();
|
||||
@ -40,7 +41,8 @@ namespace netgen
|
||||
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, int domainnr, 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,12 +610,15 @@ 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())
|
||||
@ -673,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 };
|
||||
@ -684,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;
|
||||
|
||||
@ -721,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');
|
||||
@ -747,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;
|
||||
@ -769,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;
|
||||
}
|
||||
@ -805,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++)
|
||||
@ -847,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();
|
||||
@ -867,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);
|
||||
@ -885,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) {
|
||||
@ -919,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);
|
||||
|
||||
@ -943,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;
|
||||
}
|
||||
@ -1012,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]);
|
||||
@ -1041,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))
|
||||
@ -1084,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);
|
||||
|
||||
@ -1108,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);
|
||||
}
|
||||
@ -1116,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);
|
||||
}
|
||||
@ -1129,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());
|
||||
@ -1149,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);
|
||||
|
||||
@ -1178,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))
|
||||
{
|
||||
@ -1193,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);
|
||||
}
|
||||
@ -1277,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;
|
||||
@ -1322,7 +1343,7 @@ namespace netgen
|
||||
|
||||
Point3d ci = Center (p1, p2, p3, p4);
|
||||
|
||||
inside = adfront->Inside (ci);
|
||||
inside = adfront.Inside (ci);
|
||||
|
||||
/*
|
||||
cout << "startel: " << i << endl;
|
||||
@ -1342,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++)
|
||||
@ -1404,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 !!!"
|
||||
@ -1432,10 +1453,10 @@ namespace netgen
|
||||
|
||||
}
|
||||
|
||||
if (adfront->Inside(ci))
|
||||
if (adfront.Inside(ci))
|
||||
outer.Clear(i);
|
||||
else
|
||||
outer.Set(i);
|
||||
outer.SetBit(i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1561,7 +1582,7 @@ namespace netgen
|
||||
|
||||
int np = mesh.GetNP();
|
||||
|
||||
Delaunay1 (mesh, domainnr, mp, adfront, tempels, oldnp, startel, pmin, pmax);
|
||||
Delaunay1 (mesh, domainnr, mp, *adfront, tempels, oldnp, startel, pmin, pmax);
|
||||
|
||||
{
|
||||
// improve delaunay - mesh by swapping !!!!
|
||||
@ -1664,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];
|
||||
|
@ -22,7 +22,7 @@ namespace netgen
|
||||
double r;
|
||||
double rad2;
|
||||
DelaunayTrig () = default;
|
||||
DelaunayTrig (int p1, int p2, int p3)
|
||||
DelaunayTrig (PointIndex p1, PointIndex p2, PointIndex p3)
|
||||
{
|
||||
pnums[0] = p1;
|
||||
pnums[1] = p2;
|
||||
@ -38,19 +38,19 @@ namespace netgen
|
||||
double Radius2() const { return rad2; }
|
||||
Box<2> BoundingBox() const { return Box<2> (c-Vec<2>(r,r), c+Vec<2>(r,r)); }
|
||||
|
||||
mutable PointIndex visited_pi = -1;
|
||||
mutable PointIndex visited_pi = PointIndex::INVALID; // -1;
|
||||
};
|
||||
|
||||
class DelaunayMesh
|
||||
{
|
||||
ngcore::ClosedHashTable<IVec<2>, IVec<2>> edge_to_trig;
|
||||
ngcore::ClosedHashTable<PointIndices<2>, IVec<2>> edge_to_trig;
|
||||
Array<DelaunayTrig> trigs;
|
||||
unique_ptr<DelaunayTree<2>> tree;
|
||||
Array<Point<2>, PointIndex> & points;
|
||||
|
||||
Array<int> closeels;
|
||||
Array<int> intersecting;
|
||||
Array<IVec<2>> edges;
|
||||
Array<PointIndices<2>> edges;
|
||||
|
||||
int GetNeighbour( int eli, int edge );
|
||||
|
||||
@ -58,7 +58,7 @@ namespace netgen
|
||||
|
||||
void UnsetNeighbours( int eli );
|
||||
|
||||
void AppendTrig( int pi0, int pi1, int pi2 );
|
||||
void AppendTrig( PointIndex pi0, PointIndex pi1, PointIndex pi2 );
|
||||
|
||||
public:
|
||||
DelaunayMesh( Array<Point<2>, PointIndex> & points_, Box<2> box );
|
||||
|
@ -9,6 +9,25 @@
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
inline int GetVolElement(const Mesh& mesh, const Point<3>& p,
|
||||
double* lami)
|
||||
{
|
||||
if(mesh.GetDimension() == 3)
|
||||
{
|
||||
auto ei = mesh.GetElementOfPoint(p, lami, true);
|
||||
if(!ei.IsValid())
|
||||
return -1;
|
||||
return ei;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto ei = mesh.GetSurfaceElementOfPoint(p, lami, true);
|
||||
if(!ei.IsValid())
|
||||
return -1;
|
||||
return ei;
|
||||
}
|
||||
}
|
||||
|
||||
RKStepper :: ~RKStepper()
|
||||
{
|
||||
delete a;
|
||||
@ -190,9 +209,9 @@ namespace netgen
|
||||
|
||||
for(int i=0; i<potential_startpoints.Size(); i++)
|
||||
{
|
||||
int elnr = mesh.GetElementOfPoint(potential_startpoints[i],lami,true) - 1;
|
||||
if(elnr == -1)
|
||||
continue;
|
||||
int elnr = GetVolElement(mesh, potential_startpoints[i], lami);
|
||||
if (elnr == -1)
|
||||
continue;
|
||||
|
||||
mesh.SetPointSearchStartElement(elnr);
|
||||
|
||||
@ -289,8 +308,7 @@ namespace netgen
|
||||
dirstart.SetSize(0);
|
||||
dirstart.Append(0);
|
||||
|
||||
|
||||
int startelnr = mesh.GetElementOfPoint(startpoint,startlami,true) - 1;
|
||||
int startelnr = GetVolElement(mesh, startpoint,startlami);
|
||||
(*testout) << "p = " << startpoint << "; elnr = " << startelnr << endl;
|
||||
if (startelnr == -1)
|
||||
return;
|
||||
@ -342,7 +360,7 @@ namespace netgen
|
||||
Point<3> newp;
|
||||
while(!stepper.GetNextData(newp,dummyt,h) && elnr != -1)
|
||||
{
|
||||
elnr = mesh.GetElementOfPoint(newp,lami,true) - 1;
|
||||
elnr = GetVolElement(mesh, newp, lami);
|
||||
if(elnr != -1)
|
||||
{
|
||||
mesh.SetPointSearchStartElement(elnr);
|
||||
|
@ -20,7 +20,7 @@ namespace netgen
|
||||
}
|
||||
}
|
||||
|
||||
void GeomSearch3d :: Init (NgArray <FrontPoint3,PointIndex::BASE, PointIndex> *pointsi, NgArray <FrontFace> *facesi)
|
||||
void GeomSearch3d :: Init (Array <FrontPoint3,PointIndex> *pointsi, NgArray <FrontFace> *facesi)
|
||||
{
|
||||
points = pointsi;
|
||||
faces = facesi;
|
||||
@ -106,6 +106,12 @@ namespace netgen
|
||||
size.i1 = int (boxext.X()/midext.X()/hashelemsizefactor+1);
|
||||
size.i2 = int (boxext.Y()/midext.Y()/hashelemsizefactor+1);
|
||||
size.i3 = int (boxext.Z()/midext.Z()/hashelemsizefactor+1);
|
||||
|
||||
int nfaces = faces->Size();
|
||||
size.i1 = min(size.i1, nfaces);
|
||||
size.i2 = min(size.i2, nfaces);
|
||||
size.i3 = min(size.i3, nfaces);
|
||||
|
||||
// PrintMessage (5, "hashsizes = ", size.i1, ", ", size.i2, ", ", size.i3);
|
||||
|
||||
elemsize.X()=boxext.X()/size.i1;
|
||||
@ -190,7 +196,7 @@ namespace netgen
|
||||
MinCoords(maxextreal,maxp);
|
||||
|
||||
|
||||
int cluster = faces->Get(fstind).Cluster();
|
||||
PointIndex cluster = faces->Get(fstind).Cluster();
|
||||
|
||||
int sx = int((minp.X()-minext.X())/elemsize.X()+1.);
|
||||
int ex = int((maxp.X()-minext.X())/elemsize.X()+1.);
|
||||
|
@ -27,7 +27,7 @@ public:
|
||||
virtual ~GeomSearch3d();
|
||||
|
||||
///
|
||||
void Init (NgArray <FrontPoint3,PointIndex::BASE, PointIndex> *pointsi, NgArray <FrontFace> *facesi);
|
||||
void Init (Array <FrontPoint3,PointIndex> *pointsi, NgArray <FrontFace> *facesi);
|
||||
|
||||
///get elements max extension
|
||||
void ElemMaxExt(Point3d& minp, Point3d& maxp, const MiniElement2d& elem);
|
||||
@ -52,7 +52,7 @@ public:
|
||||
private:
|
||||
|
||||
NgArray <FrontFace> *faces; // Pointers to Arrays in Adfront
|
||||
NgArray <FrontPoint3,PointIndex::BASE, PointIndex> *points;
|
||||
Array <FrontPoint3,PointIndex> *points;
|
||||
|
||||
NgArray <NgArray <int>*> hashtable;
|
||||
|
||||
|
@ -603,19 +603,21 @@ namespace netgen
|
||||
return hps;
|
||||
}
|
||||
|
||||
bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HASHTABLE<int> & edgepoiclt_dom,
|
||||
template <typename HT_EDGEPOINT_DOM>
|
||||
bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, HT_EDGEPOINT_DOM & edgepoiclt_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 & levels, int & act_ref);
|
||||
INDEX_2_HASHTABLE<int> & surf_edges, Array<int, PointIndex> & facepoint, int & levels, int & act_ref);
|
||||
|
||||
bool ClassifyHPElements (Mesh & mesh, NgArray<HPRefElement> & elements, SplittingType split, int & act_ref, int & levels);
|
||||
|
||||
|
||||
void InitHPElements(Mesh & mesh, NgArray<HPRefElement> & elements)
|
||||
{
|
||||
for(ElementIndex i = 0; i < mesh.GetNE(); i++)
|
||||
// for(ElementIndex i = 0; i < mesh.GetNE(); i++)
|
||||
for(ElementIndex i : mesh.VolumeElements().Range())
|
||||
{
|
||||
HPRefElement hpel(mesh[i]);
|
||||
hpel.coarse_elnr = i;
|
||||
hpel.coarse_elnr = int(i);
|
||||
|
||||
switch (mesh[i].GetType())
|
||||
{
|
||||
@ -1509,7 +1511,8 @@ namespace netgen
|
||||
|
||||
if(act_ref>=1)
|
||||
{
|
||||
for(ElementIndex i=0;i<mesh.GetNE(); i++)
|
||||
// for(ElementIndex i=0;i<mesh.GetNE(); i++)
|
||||
for (ElementIndex i : mesh.VolumeElements().Range())
|
||||
{
|
||||
// Element el = mesh[i] ;
|
||||
HPRefElement & hpel = hpelements[mesh[i].GetHpElnr()];
|
||||
@ -1632,9 +1635,10 @@ namespace netgen
|
||||
}
|
||||
}
|
||||
|
||||
bool CheckSingularities(Mesh & mesh, 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 & levels, int & act_ref)
|
||||
template <typename HT_EDGEPOINT_DOM>
|
||||
bool CheckSingularities(Mesh & mesh, 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 & levels, int & act_ref)
|
||||
{
|
||||
bool sing = 0;
|
||||
if (mesh.GetDimension() == 3)
|
||||
@ -1670,7 +1674,7 @@ bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HAS
|
||||
{
|
||||
if (mesh.Point(i).Singularity() * levels >= act_ref)
|
||||
{
|
||||
cornerpoint.Set(i);
|
||||
cornerpoint.SetBit(i);
|
||||
sing = 1;
|
||||
}
|
||||
}
|
||||
@ -1695,16 +1699,17 @@ bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HAS
|
||||
edges.Set (i2s, 1);
|
||||
|
||||
|
||||
edgepoint.Set (i2.I1());
|
||||
edgepoint.Set (i2.I2());
|
||||
edgepoint.SetBit (i2.I1());
|
||||
edgepoint.SetBit (i2.I2());
|
||||
sing = 1;
|
||||
}
|
||||
|
||||
// if 2 adjacent edges of an element are singular, the
|
||||
// common point must be a singular point
|
||||
for (int i = 1; i <= mesh.GetNE(); i++)
|
||||
// for (int i = 1; i <= mesh.GetNE(); i++)
|
||||
for (auto ei : mesh.VolumeElements().Range())
|
||||
{
|
||||
const Element & el = mesh.VolumeElement(i);
|
||||
const Element & el = mesh[ei];
|
||||
const ELEMENT_EDGE * eledges = MeshTopology::GetEdges1 (el.GetType());
|
||||
int nedges = MeshTopology::GetNEdges (el.GetType());
|
||||
for (int j = 0; j < nedges; j++)
|
||||
@ -1717,10 +1722,10 @@ bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HAS
|
||||
ek.Sort();
|
||||
if (edges.Used(ej) && edges.Used(ek))
|
||||
{
|
||||
if (ej.I1() == ek.I1()) cornerpoint.Set (ek.I1());
|
||||
if (ej.I1() == ek.I2()) cornerpoint.Set (ek.I2());
|
||||
if (ej.I2() == ek.I1()) cornerpoint.Set (ek.I1());
|
||||
if (ej.I2() == ek.I2()) cornerpoint.Set (ek.I2());
|
||||
if (ej.I1() == ek.I1()) cornerpoint.SetBit (ek.I1());
|
||||
if (ej.I1() == ek.I2()) cornerpoint.SetBit (ek.I2());
|
||||
if (ej.I2() == ek.I1()) cornerpoint.SetBit (ek.I1());
|
||||
if (ej.I2() == ek.I2()) cornerpoint.SetBit (ek.I2());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1800,33 +1805,33 @@ bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HAS
|
||||
if (seg.singedge_left * levels >= act_ref)
|
||||
{
|
||||
INDEX_2 i2 = INDEX_2::Sort(mesh.LineSegment(i)[0],
|
||||
mesh.LineSegment(i)[1]);
|
||||
mesh.LineSegment(i)[1]);
|
||||
edges.Set(i2,1);
|
||||
edgepoint.Set(i2.I1());
|
||||
edgepoint.Set(i2.I2());
|
||||
edgepoint.SetBit(i2.I1());
|
||||
edgepoint.SetBit(i2.I2());
|
||||
*testout << " singleft " << endl;
|
||||
*testout << " mesh.LineSegment(i).domout " << mesh.LineSegment(i).domout << endl;
|
||||
*testout << " mesh.LineSegment(i).domin " << mesh.LineSegment(i).domin << endl;
|
||||
edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domin, i2.I1()), 1);
|
||||
edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domin, i2.I2()), 1);
|
||||
edgepoint_dom.Set ( { mesh.LineSegment(i).domin, i2.I1() }, 1);
|
||||
edgepoint_dom.Set ( { mesh.LineSegment(i).domin, i2.I2() }, 1);
|
||||
sing = 1;
|
||||
|
||||
}
|
||||
|
||||
if (seg.singedge_right * levels >= act_ref)
|
||||
{
|
||||
INDEX_2 i2 = INDEX_2::Sort(mesh.LineSegment(i)[1],
|
||||
mesh.LineSegment(i)[0]);
|
||||
PointIndices<2> i2 = INDEX_2::Sort(mesh.LineSegment(i)[1],
|
||||
mesh.LineSegment(i)[0]);
|
||||
edges.Set (i2, 1);
|
||||
edgepoint.Set(i2.I1());
|
||||
edgepoint.Set(i2.I2());
|
||||
edgepoint.SetBit(i2.I1());
|
||||
edgepoint.SetBit(i2.I2());
|
||||
|
||||
*testout << " singright " << endl;
|
||||
*testout << " mesh.LineSegment(i).domout " << mesh.LineSegment(i).domout << endl;
|
||||
*testout << " mesh.LineSegment(i).domin " << mesh.LineSegment(i).domin << endl;
|
||||
|
||||
edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domout, i2.I1()), 1);
|
||||
edgepoint_dom.Set (INDEX_2(mesh.LineSegment(i).domout, i2.I2()), 1);
|
||||
edgepoint_dom.Set ( { mesh.LineSegment(i).domout, i2.I1() }, 1);
|
||||
edgepoint_dom.Set ( { mesh.LineSegment(i).domout, i2.I2() }, 1);
|
||||
sing = 1;
|
||||
}
|
||||
|
||||
@ -1857,14 +1862,14 @@ bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HAS
|
||||
if (surfonpoint.Get(i).I1())
|
||||
{
|
||||
// cornerpoint.Set(i); // disabled by JS, Aug 2009
|
||||
edgepoint.Set(i);
|
||||
edgepoint.SetBit(i);
|
||||
}
|
||||
|
||||
// mark points for refinement that are explicitly specified in input file
|
||||
if (mesh.Point(i).Singularity()*levels >= act_ref)
|
||||
{
|
||||
cornerpoint.Set(i);
|
||||
edgepoint.Set(i);
|
||||
cornerpoint.SetBit(i);
|
||||
edgepoint.SetBit(i);
|
||||
sing = 1;
|
||||
}
|
||||
}
|
||||
@ -1889,11 +1894,13 @@ bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HAS
|
||||
bool ClassifyHPElements (Mesh & mesh, NgArray<HPRefElement> & elements, SplittingType split, int & act_ref, int & levels)
|
||||
{
|
||||
INDEX_2_HASHTABLE<int> edges(mesh.GetNSeg()+1);
|
||||
NgBitArray edgepoint(mesh.GetNP());
|
||||
INDEX_2_HASHTABLE<int> edgepoint_dom(mesh.GetNSeg()+1);
|
||||
TBitArray<PointIndex> edgepoint(mesh.GetNP());
|
||||
// INDEX_2_HASHTABLE<int> edgepoint_dom(mesh.GetNSeg()+1);
|
||||
|
||||
HT_EDGEPOINT_DOM edgepoint_dom;
|
||||
|
||||
edgepoint.Clear();
|
||||
NgBitArray cornerpoint(mesh.GetNP());
|
||||
TBitArray<PointIndex> cornerpoint(mesh.GetNP());
|
||||
cornerpoint.Clear();
|
||||
|
||||
// value = nr > 0 ... refine elements in domain nr
|
||||
@ -1901,7 +1908,7 @@ bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HAS
|
||||
INDEX_3_HASHTABLE<int> faces(mesh.GetNSE()+1);
|
||||
INDEX_2_HASHTABLE<int> face_edges(mesh.GetNSE()+1);
|
||||
INDEX_2_HASHTABLE<int> surf_edges(mesh.GetNSE()+1);
|
||||
NgArray<int, PointIndex::BASE> facepoint(mesh.GetNP());
|
||||
Array<int, PointIndex> facepoint(mesh.GetNP());
|
||||
|
||||
bool sing = CheckSingularities(mesh, edges, edgepoint_dom,
|
||||
cornerpoint, edgepoint, faces, face_edges,
|
||||
@ -1917,7 +1924,7 @@ bool CheckSingularities(Mesh & mesh, INDEX_2_HASHTABLE<int> & edges, INDEX_2_HAS
|
||||
NgArray<int> misses(10000);
|
||||
misses = 0;
|
||||
|
||||
(*testout) << "edgepoint_dom = " << endl << edgepoint_dom << endl;
|
||||
// (*testout) << "edgepoint_dom = " << endl << edgepoint_dom << endl;
|
||||
|
||||
|
||||
for( int i = 0; i<elements.Size(); i++)
|
||||
|
@ -333,7 +333,7 @@ public:
|
||||
int levely;
|
||||
int levelz;
|
||||
int np;
|
||||
int coarse_elnr;
|
||||
int coarse_elnr; // issue (JS): same class is for ElementIndex, SurfaceElementIndex, SegmentIndex
|
||||
int domin, domout; // he: needed for segment!! in 3d there should be surf1, surf2!!
|
||||
// int coarse_hpelnr;
|
||||
PointIndex & operator[](int i) { return(pnums[i]);}
|
||||
|
@ -212,7 +212,7 @@ namespace netgen
|
||||
}
|
||||
|
||||
Array<Neighbour> neighbors(mesh.GetNSE());
|
||||
auto elements_on_node = mesh.CreatePoint2SurfaceElementTable(faceindex);
|
||||
auto elements_on_node = mesh.CreateCompressedPoint2SurfaceElementTable(faceindex);
|
||||
|
||||
Array<bool> swapped(mesh.GetNSE());
|
||||
Array<int,PointIndex> pdef(mesh.GetNP());
|
||||
@ -353,7 +353,7 @@ namespace netgen
|
||||
improvement_candidates[cnt++]= std::make_pair(t1,o1);
|
||||
});
|
||||
|
||||
auto elements_with_improvement = improvement_candidates.Range(cnt.load());
|
||||
auto elements_with_improvement = improvement_candidates.Range(0, cnt.load());
|
||||
QuickSort(elements_with_improvement);
|
||||
|
||||
for (auto [t1,o1] : elements_with_improvement)
|
||||
@ -366,9 +366,9 @@ namespace netgen
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T_PI2SEI>
|
||||
double CombineImproveEdge( Mesh & mesh,
|
||||
const Table<SurfaceElementIndex, PointIndex> & elementsonnode,
|
||||
const T_PI2SEI & elementsonnode,
|
||||
Array<Vec<3>, PointIndex> & normals,
|
||||
Array<bool, PointIndex> & fixed,
|
||||
PointIndex pi1, PointIndex pi2,
|
||||
@ -601,7 +601,7 @@ namespace netgen
|
||||
|
||||
int np = mesh.GetNP();
|
||||
|
||||
auto elementsonnode = mesh.CreatePoint2SurfaceElementTable(faceindex);
|
||||
auto elementsonnode = mesh.CreateCompressedPoint2SurfaceElementTable(faceindex);
|
||||
|
||||
// int ntasks = ngcore::TaskManager::GetMaxThreads();
|
||||
Array<std::tuple<PointIndex, PointIndex>> edges;
|
||||
@ -713,7 +713,7 @@ namespace netgen
|
||||
|
||||
if (mesh.IsSegment (pi1, pi2)) continue;
|
||||
|
||||
INDEX_2 ii2 (pi1, pi2);
|
||||
PointIndices<2> ii2 (pi1, pi2);
|
||||
ii2.Sort();
|
||||
if (els_on_edge.Used (ii2))
|
||||
{
|
||||
@ -739,7 +739,7 @@ namespace netgen
|
||||
if (mesh.LegalTrig(sel)) continue;
|
||||
|
||||
// find longest edge
|
||||
INDEX_2 edge;
|
||||
PointIndices<2> edge;
|
||||
double edge_len = 0;
|
||||
PointIndex pi1, pi2, pi3, pi4;
|
||||
PointGeomInfo gi1, gi2, gi3, gi4;
|
||||
|
@ -36,10 +36,10 @@ inline void AppendEdges( const Element & elem, PointIndex pi, Array<std::tuple<P
|
||||
}
|
||||
}
|
||||
|
||||
template<typename TINDEX>
|
||||
void BuildEdgeList( const Mesh & mesh, const Table<TINDEX, PointIndex> & elementsonnode, Array<std::tuple<PointIndex, PointIndex>> & edges )
|
||||
template<typename T_PI2SEI>
|
||||
void BuildEdgeList( const Mesh & mesh, const T_PI2SEI & elementsonnode, Array<std::tuple<PointIndex, PointIndex>> & edges )
|
||||
{
|
||||
static_assert(is_same_v<TINDEX, ElementIndex>||is_same_v<TINDEX,SurfaceElementIndex>, "Invalid type for TINDEX");
|
||||
// static_assert(is_same_v<TINDEX, ElementIndex>||is_same_v<TINDEX,SurfaceElementIndex>, "Invalid type for TINDEX");
|
||||
static Timer tbuild_edges("Build edges"); RegionTimer reg(tbuild_edges);
|
||||
|
||||
int ntasks = 4*ngcore::TaskManager::GetMaxThreads();
|
||||
@ -62,7 +62,7 @@ void BuildEdgeList( const Mesh & mesh, const Table<TINDEX, PointIndex> & element
|
||||
}
|
||||
QuickSort(local_edges);
|
||||
|
||||
auto edge_prev = std::make_tuple<PointIndex, PointIndex>(-1,-1);
|
||||
auto edge_prev = std::make_tuple<PointIndex, PointIndex>(PointIndex::INVALID, PointIndex::INVALID);
|
||||
|
||||
for(auto edge : local_edges)
|
||||
if(edge != edge_prev)
|
||||
|
@ -11,9 +11,9 @@ namespace netgen
|
||||
public:
|
||||
NgArray<Element2d> oldels;
|
||||
NgArray<Element2d> newels;
|
||||
NgArray<INDEX_2> deledges;
|
||||
NgArray<int> incelsonnode;
|
||||
NgArray<int> reused;
|
||||
NgArray<PointIndices<2>> deledges;
|
||||
Array<int,PointIndex> incelsonnode;
|
||||
Array<int,PointIndex> reused;
|
||||
int bonus;
|
||||
int onp;
|
||||
};
|
||||
@ -55,128 +55,137 @@ namespace netgen
|
||||
NgArray<ImprovementRule*> rules;
|
||||
NgArray<SurfaceElementIndex> elmap;
|
||||
NgArray<int> elrot;
|
||||
NgArray<PointIndex> pmap;
|
||||
NgArray<PointGeomInfo> pgi;
|
||||
Array<PointIndex,PointIndex> pmap;
|
||||
Array<PointGeomInfo,PointIndex> pgi;
|
||||
|
||||
int surfnr = mesh.GetFaceDescriptor (faceindex).SurfNr();
|
||||
|
||||
ImprovementRule * r1;
|
||||
|
||||
PointIndex p1 = IndexBASE<PointIndex>();
|
||||
PointIndex p2 = p1+1;
|
||||
PointIndex p3 = p2+1;
|
||||
PointIndex p4 = p3+1;
|
||||
PointIndex p5 = p4+1;
|
||||
PointIndex p6 = p5+1;
|
||||
PointIndex p7 = p6+1;
|
||||
|
||||
|
||||
// 2 triangles to quad
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3));
|
||||
r1->oldels.Append (Element2d (3, 2, 4));
|
||||
r1->newels.Append (Element2d (1, 2, 4, 3));
|
||||
r1->deledges.Append (INDEX_2 (2,3));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3));
|
||||
r1->oldels.Append (Element2d (p3, p2, p4));
|
||||
r1->newels.Append (Element2d (p1, p2, p4, p3));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->onp = 4;
|
||||
r1->bonus = 2;
|
||||
rules.Append (r1);
|
||||
|
||||
// 2 quad to 1 quad
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (4, 3, 2, 5));
|
||||
r1->newels.Append (Element2d (1, 2, 5, 4));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->deledges.Append (INDEX_2 (3, 4));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p4, p3, p2, p5));
|
||||
r1->newels.Append (Element2d (p1, p2, p5, p4));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->deledges.Append ( { p3, p4 } );
|
||||
r1->onp = 5;
|
||||
r1->bonus = 0;
|
||||
rules.Append (r1);
|
||||
|
||||
// swap quads
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (3, 2, 5, 6));
|
||||
r1->newels.Append (Element2d (1, 6, 3, 4));
|
||||
r1->newels.Append (Element2d (1, 2, 5, 6));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p3, p2, p5, p6));
|
||||
r1->newels.Append (Element2d (p1, p6, p3, p4));
|
||||
r1->newels.Append (Element2d (p1, p2, p5, p6));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->onp = 6;
|
||||
r1->bonus = 0;
|
||||
rules.Append (r1);
|
||||
|
||||
// three quads to 2
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (2, 5, 6, 3));
|
||||
r1->oldels.Append (Element2d (3, 6, 7, 4));
|
||||
r1->newels.Append (Element2d (1, 2, 5, 4));
|
||||
r1->newels.Append (Element2d (4, 5, 6, 7));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->deledges.Append (INDEX_2 (3, 4));
|
||||
r1->deledges.Append (INDEX_2 (3, 6));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p2, p5, p6, p3));
|
||||
r1->oldels.Append (Element2d (p3, p6, p7, p4));
|
||||
r1->newels.Append (Element2d (p1, p2, p5, p4));
|
||||
r1->newels.Append (Element2d (p4, p5, p6, p7));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->deledges.Append ( { p3, p4 } );
|
||||
r1->deledges.Append ( { p3, p6 } );
|
||||
r1->onp = 7;
|
||||
r1->bonus = -1;
|
||||
rules.Append (r1);
|
||||
|
||||
// quad + 2 connected trigs to quad
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (2, 5, 3));
|
||||
r1->oldels.Append (Element2d (3, 5, 4));
|
||||
r1->newels.Append (Element2d (1, 2, 5, 4));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->deledges.Append (INDEX_2 (3, 4));
|
||||
r1->deledges.Append (INDEX_2 (3, 5));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p2, p5, p3));
|
||||
r1->oldels.Append (Element2d (p3, p5, p4));
|
||||
r1->newels.Append (Element2d (p1, p2, p5, p4));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->deledges.Append ( { p3, p4 } );
|
||||
r1->deledges.Append ( { p3, p5 } );
|
||||
r1->onp = 5;
|
||||
r1->bonus = 0;
|
||||
rules.Append (r1);
|
||||
|
||||
// quad + 2 non-connected trigs to quad (a and b)
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (2, 6, 3));
|
||||
r1->oldels.Append (Element2d (1, 4, 5));
|
||||
r1->newels.Append (Element2d (1, 3, 4, 5));
|
||||
r1->newels.Append (Element2d (1, 2, 6, 3));
|
||||
r1->deledges.Append (INDEX_2 (1, 4));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p2, p6, p3));
|
||||
r1->oldels.Append (Element2d (p1, p4, p5));
|
||||
r1->newels.Append (Element2d (p1, p3, p4, p5));
|
||||
r1->newels.Append (Element2d (p1, p2, p6, p3));
|
||||
r1->deledges.Append ( { p1, p4 } );
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->onp = 6;
|
||||
r1->bonus = 0;
|
||||
rules.Append (r1);
|
||||
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (2, 6, 3));
|
||||
r1->oldels.Append (Element2d (1, 4, 5));
|
||||
r1->newels.Append (Element2d (1, 2, 4, 5));
|
||||
r1->newels.Append (Element2d (4, 2, 6, 3));
|
||||
r1->deledges.Append (INDEX_2 (1, 4));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p2, p6, p3));
|
||||
r1->oldels.Append (Element2d (p1, p4, p5));
|
||||
r1->newels.Append (Element2d (p1, p2, p4, p5));
|
||||
r1->newels.Append (Element2d (p4, p2, p6, p3));
|
||||
r1->deledges.Append ( { p1, p4 } );
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->onp = 6;
|
||||
r1->bonus = 0;
|
||||
rules.Append (r1);
|
||||
|
||||
// two quad + trig -> one quad + trig
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (2, 5, 6, 3));
|
||||
r1->oldels.Append (Element2d (4, 3, 6));
|
||||
r1->newels.Append (Element2d (1, 2, 6, 4));
|
||||
r1->newels.Append (Element2d (2, 5, 6));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->deledges.Append (INDEX_2 (3, 4));
|
||||
r1->deledges.Append (INDEX_2 (3, 6));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p2, p5, p6, p3));
|
||||
r1->oldels.Append (Element2d (p4, p3, p6));
|
||||
r1->newels.Append (Element2d (p1, p2, p6, p4));
|
||||
r1->newels.Append (Element2d (p2, p5, p6));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->deledges.Append ( { p3, p4 } );
|
||||
r1->deledges.Append ( { p3, p6 } );
|
||||
r1->onp = 6;
|
||||
r1->bonus = -1;
|
||||
rules.Append (r1);
|
||||
|
||||
// swap quad + trig (a and b)
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (2, 5, 3));
|
||||
r1->newels.Append (Element2d (2, 5, 3, 4));
|
||||
r1->newels.Append (Element2d (1, 2, 4));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p2, p5, p3));
|
||||
r1->newels.Append (Element2d (p2, p5, p3, p4));
|
||||
r1->newels.Append (Element2d (p1, p2, p4));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->onp = 5;
|
||||
r1->bonus = 0;
|
||||
rules.Append (r1);
|
||||
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (2, 5, 3));
|
||||
r1->newels.Append (Element2d (1, 2, 5, 3));
|
||||
r1->newels.Append (Element2d (1, 3, 4));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p2, p5, p3));
|
||||
r1->newels.Append (Element2d (p1, p2, p5, p3));
|
||||
r1->newels.Append (Element2d (p1, p3, p4));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->onp = 5;
|
||||
r1->bonus = 0;
|
||||
rules.Append (r1);
|
||||
@ -184,12 +193,12 @@ namespace netgen
|
||||
|
||||
// 2 quads to quad + 2 trigs
|
||||
r1 = new ImprovementRule;
|
||||
r1->oldels.Append (Element2d (1, 2, 3, 4));
|
||||
r1->oldels.Append (Element2d (3, 2, 5, 6));
|
||||
r1->newels.Append (Element2d (1, 5, 6, 4));
|
||||
r1->newels.Append (Element2d (1, 2, 5));
|
||||
r1->newels.Append (Element2d (4, 6, 3));
|
||||
r1->deledges.Append (INDEX_2 (2, 3));
|
||||
r1->oldels.Append (Element2d (p1, p2, p3, p4));
|
||||
r1->oldels.Append (Element2d (p3, p2, p5, p6));
|
||||
r1->newels.Append (Element2d (p1, p5, p6, p4));
|
||||
r1->newels.Append (Element2d (p1, p2, p5));
|
||||
r1->newels.Append (Element2d (p4, p6, p3));
|
||||
r1->deledges.Append ( { p2, p3 } );
|
||||
r1->onp = 6;
|
||||
r1->bonus = 0;
|
||||
// rules.Append (r1);
|
||||
@ -203,18 +212,21 @@ namespace netgen
|
||||
mapped = 0;
|
||||
|
||||
|
||||
|
||||
for (int ri = 0; ri < rules.Size(); ri++)
|
||||
{
|
||||
ImprovementRule & rule = *rules[ri];
|
||||
rule.incelsonnode.SetSize (rule.onp);
|
||||
rule.reused.SetSize (rule.onp);
|
||||
|
||||
/*
|
||||
for (int j = 0; j < rule.onp; j++)
|
||||
{
|
||||
rule.incelsonnode[j] = 0;
|
||||
rule.reused[j] = 0;
|
||||
}
|
||||
*/
|
||||
rule.incelsonnode = 0;
|
||||
rule.reused = 0;
|
||||
|
||||
/*
|
||||
for (int j = 1; j <= rule.oldels.Size(); j++)
|
||||
@ -226,15 +238,15 @@ namespace netgen
|
||||
*/
|
||||
for (const Element2d & el : rule.oldels)
|
||||
for (PointIndex pi : el.PNums())
|
||||
rule.incelsonnode[pi-PointIndex::BASE]--;
|
||||
rule.incelsonnode[pi]--;
|
||||
|
||||
for (int j = 1; j <= rule.newels.Size(); j++)
|
||||
{
|
||||
const Element2d & el = rule.newels.Elem(j);
|
||||
for (int k = 1; k <= el.GetNP(); k++)
|
||||
{
|
||||
rule.incelsonnode.Elem(el.PNum(k))++;
|
||||
rule.reused.Elem(el.PNum(k)) = 1;
|
||||
rule.incelsonnode[el.PNum(k)]++;
|
||||
rule.reused[el.PNum(k)] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -242,8 +254,8 @@ namespace netgen
|
||||
|
||||
|
||||
|
||||
TABLE<int,PointIndex::BASE> elonnode(np);
|
||||
NgArray<int,PointIndex::BASE> nelonnode(np);
|
||||
DynamicTable<int,PointIndex> elonnode(np);
|
||||
Array<int,PointIndex> nelonnode(np);
|
||||
TABLE<SurfaceElementIndex> nbels(ne);
|
||||
|
||||
nelonnode = -4;
|
||||
@ -314,13 +326,13 @@ namespace netgen
|
||||
if (el0.IsDeleted()) continue;
|
||||
if (el0.GetNP() != rel0.GetNP()) continue;
|
||||
|
||||
|
||||
pmap = PointIndex (-1);
|
||||
// pmap = PointIndex (-1);
|
||||
for (auto & p : pmap) p.Invalidate();
|
||||
|
||||
for (int k = 0; k < el0.GetNP(); k++)
|
||||
{
|
||||
pmap.Elem(rel0[k]) = el0.PNumMod(k+elrot[0]+1);
|
||||
pgi.Elem(rel0[k]) = el0.GeomInfoPiMod(k+elrot[0]+1);
|
||||
pmap[rel0[k]] = el0.PNumMod(k+elrot[0]+1);
|
||||
pgi[rel0[k]] = el0.GeomInfoPiMod(k+elrot[0]+1);
|
||||
}
|
||||
|
||||
ok = 1;
|
||||
@ -342,16 +354,16 @@ namespace netgen
|
||||
possible = 1;
|
||||
|
||||
for (int k = 0; k < rel.GetNP(); k++)
|
||||
if (pmap.Elem(rel[k]) != -1 &&
|
||||
pmap.Elem(rel[k]) != el.PNumMod (k+elrot[i]+1))
|
||||
if (pmap[rel[k]].IsValid() &&
|
||||
pmap[rel[k]] != el.PNumMod (k+elrot[i]+1))
|
||||
possible = 0;
|
||||
|
||||
if (possible)
|
||||
{
|
||||
for (int k = 0; k < el.GetNP(); k++)
|
||||
{
|
||||
pmap.Elem(rel[k]) = el.PNumMod(k+elrot[i]+1);
|
||||
pgi.Elem(rel[k]) = el.GeomInfoPiMod(k+elrot[i]+1);
|
||||
pmap[rel[k]] = el.PNumMod(k+elrot[i]+1);
|
||||
pgi[rel[k]] = el.GeomInfoPiMod(k+elrot[i]+1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -370,8 +382,8 @@ namespace netgen
|
||||
|
||||
for(int i=0; ok && i<rule.deledges.Size(); i++)
|
||||
{
|
||||
ok = !mesh.IsSegment(pmap.Elem(rule.deledges[i].I1()),
|
||||
pmap.Elem(rule.deledges[i].I2()));
|
||||
ok = !mesh.IsSegment(pmap[rule.deledges[i][0]],
|
||||
pmap[rule.deledges[i][1]]);
|
||||
}
|
||||
|
||||
|
||||
@ -382,15 +394,15 @@ namespace netgen
|
||||
mapped[ri]++;
|
||||
|
||||
olddef = 0;
|
||||
for (int j = 1; j <= pmap.Size(); j++)
|
||||
olddef += sqr (nelonnode[pmap.Get(j)]);
|
||||
for (auto j : pmap.Range())
|
||||
olddef += sqr (nelonnode[pmap[j]]);
|
||||
olddef += rule.bonus;
|
||||
|
||||
newdef = 0;
|
||||
for (int j = 1; j <= pmap.Size(); j++)
|
||||
if (rule.reused.Get(j))
|
||||
newdef += sqr (nelonnode[pmap.Get(j)] +
|
||||
rule.incelsonnode.Get(j));
|
||||
for (auto j : pmap.Range())
|
||||
if (rule.reused[j])
|
||||
newdef += sqr (nelonnode[pmap[j]] +
|
||||
rule.incelsonnode[j]);
|
||||
|
||||
if (newdef > olddef)
|
||||
continue;
|
||||
@ -398,7 +410,8 @@ namespace netgen
|
||||
// calc metric badness
|
||||
double bad1 = 0, bad2 = 0;
|
||||
// SelectSurfaceOfPoint (mesh.Point(pmap.Get(1)), pgi.Get(1));
|
||||
auto n = geo.GetNormal(surfnr, mesh.Point(pmap.Get(1)), &pgi.Elem(1));
|
||||
// auto n = geo.GetNormal(surfnr, mesh.Point(pmap.Get(1)), &pgi.Elem(1));
|
||||
auto n = geo.GetNormal(surfnr, mesh.Point(pmap.First()), pgi.Data());
|
||||
|
||||
for (int j = 0; j < rule.oldels.Size(); j++)
|
||||
bad1 += mesh[elmap[j]].CalcJacobianBadness (mesh.Points(), n);
|
||||
@ -409,7 +422,7 @@ namespace netgen
|
||||
const Element2d & rnel = rule.newels.Get(j);
|
||||
Element2d nel(rnel.GetNP());
|
||||
for (int k = 1; k <= rnel.GetNP(); k++)
|
||||
nel.PNum(k) = pmap.Get(rnel.PNum(k));
|
||||
nel.PNum(k) = pmap[rnel.PNum(k)];
|
||||
|
||||
bad2 += nel.CalcJacobianBadness (mesh.Points(), n);
|
||||
}
|
||||
@ -427,8 +440,8 @@ namespace netgen
|
||||
nel.SetIndex (faceindex);
|
||||
for (int k = 1; k <= rnel.GetNP(); k++)
|
||||
{
|
||||
nel.PNum(k) = pmap.Get(rnel.PNum(k));
|
||||
nel.GeomInfoPi(k) = pgi.Get(rnel.PNum(k));
|
||||
nel.PNum(k) = pmap[rnel.PNum(k)];
|
||||
nel.GeomInfoPi(k) = pgi[rnel.PNum(k)];
|
||||
}
|
||||
|
||||
mesh.AddSurfaceElement(nel);
|
||||
@ -437,8 +450,8 @@ namespace netgen
|
||||
for (int j = 0; j < rule.oldels.Size(); j++)
|
||||
mesh.Delete (elmap[j]);
|
||||
|
||||
for (int j = 1; j <= pmap.Size(); j++)
|
||||
nelonnode[pmap.Get(j)] += rule.incelsonnode.Get(j);
|
||||
for (PointIndex j : pmap.Range())
|
||||
nelonnode[pmap[j]] += rule.incelsonnode[j];
|
||||
|
||||
used[ri]++;
|
||||
}
|
||||
|
@ -14,6 +14,16 @@
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
bool WrongOrientation(Point<3> p1, Point<3> p2, Point<3> p3, Point<3> p4)
|
||||
{
|
||||
Vec<3> v1 = p2 - p1;
|
||||
Vec<3> v2 = p3 - p1;
|
||||
Vec<3> v3 = p4 - p1;
|
||||
|
||||
Vec<3> n = Cross(v1, v2);
|
||||
return n * v3 > 0;
|
||||
}
|
||||
|
||||
static constexpr int tetedges[6][2] =
|
||||
{ { 0, 1 }, { 0, 2 }, { 0, 3 },
|
||||
{ 1, 2 }, { 1, 3 }, { 2, 3 } };
|
||||
@ -100,7 +110,7 @@ static double SplitElementBadness (const Mesh::T_POINTS & points, const MeshingP
|
||||
{
|
||||
double badness = 0;
|
||||
auto np = old.GetNP();
|
||||
PointIndex dummy{-1};
|
||||
PointIndex dummy{PointIndex::INVALID};
|
||||
if(np == 4)
|
||||
{
|
||||
// Split tet into two tets
|
||||
@ -357,7 +367,7 @@ void MeshOptimize3d :: CombineImprove ()
|
||||
{
|
||||
static Timer t("MeshOptimize3d::CombineImprove"); RegionTimer reg(t);
|
||||
static Timer topt("Optimize");
|
||||
static Timer tsearch("Search");
|
||||
static Timer tsearch("Search-combine");
|
||||
static Timer tbuild_elements_table("Build elements table");
|
||||
|
||||
mesh.BuildBoundaryEdges(false);
|
||||
@ -439,7 +449,8 @@ void MeshOptimize3d :: CombineImprove ()
|
||||
(*testout) << "Total badness = " << totalbad << endl;
|
||||
|
||||
int cntill = 0;
|
||||
for (ElementIndex ei = 0; ei < ne; ei++)
|
||||
// for (ElementIndex ei = 0; ei < ne; ei++)
|
||||
for (ElementIndex ei : ngcore::T_Range<ElementIndex>(ne))
|
||||
if(!(mesh.GetDimension()==3 && mp.only3D_domain_nr && mp.only3D_domain_nr != mesh.VolumeElement(ei).GetIndex()))
|
||||
if (!mesh.LegalTet (mesh[ei]))
|
||||
cntill++;
|
||||
@ -451,7 +462,7 @@ void MeshOptimize3d :: CombineImprove ()
|
||||
|
||||
|
||||
|
||||
double MeshOptimize3d :: SplitImproveEdge (Table<ElementIndex,PointIndex> & elementsonnode, NgArray<INDEX_3> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only)
|
||||
double MeshOptimize3d :: SplitImproveEdge (Table<ElementIndex,PointIndex> & elementsonnode, NgArray<PointIndices<3>> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only)
|
||||
{
|
||||
double d_badness = 0.0;
|
||||
// int cnt = 0;
|
||||
@ -512,11 +523,11 @@ double MeshOptimize3d :: SplitImproveEdge (Table<ElementIndex,PointIndex> & elem
|
||||
for (int l = 0; l < 4; l++)
|
||||
if (el[l] == pi1 || el[l] == pi2)
|
||||
{
|
||||
INDEX_3 i3;
|
||||
PointIndices<3> i3;
|
||||
Element2d face(TRIG);
|
||||
el.GetFace (l+1, face);
|
||||
for (int kk = 1; kk <= 3; kk++)
|
||||
i3.I(kk) = face.PNum(kk);
|
||||
for (int kk = 0; kk < 3; kk++)
|
||||
i3[kk] = face[kk];
|
||||
locfaces.Append (i3);
|
||||
}
|
||||
}
|
||||
@ -536,7 +547,7 @@ double MeshOptimize3d :: SplitImproveEdge (Table<ElementIndex,PointIndex> & elem
|
||||
{
|
||||
int pok = pf.Func (px) < 1e10;
|
||||
if (!pok)
|
||||
pok = FindInnerPoint (mesh.Points(), locfaces, pnew);
|
||||
pok = FindInnerPoint (mesh.Points(), locfaces, pnew);
|
||||
|
||||
if(pok)
|
||||
{
|
||||
@ -561,15 +572,28 @@ double MeshOptimize3d :: SplitImproveEdge (Table<ElementIndex,PointIndex> & elem
|
||||
newel1.Touch();
|
||||
newel2.Touch();
|
||||
|
||||
Point<3> pel1[4];
|
||||
Point<3> pel2[4];
|
||||
for (int l = 0; l < 4; l++)
|
||||
{
|
||||
if (newel1[l] == pi2) newel1[l] = ptmp;
|
||||
if (newel2[l] == pi1) newel2[l] = ptmp;
|
||||
pel1[l] = pel2[l] = mesh[oldel[l]];
|
||||
if (newel1[l] == pi2) {
|
||||
newel1[l] = ptmp;
|
||||
pel1[l] = pnew;
|
||||
}
|
||||
if (newel2[l] == pi1) {
|
||||
newel2[l] = ptmp;
|
||||
pel2[l] = pnew;
|
||||
}
|
||||
}
|
||||
|
||||
if (!mesh.LegalTet (oldel)) return 0.0;
|
||||
if (!mesh.LegalTet (newel1)) return 0.0;
|
||||
if (!mesh.LegalTet (newel2)) return 0.0;
|
||||
|
||||
if( WrongOrientation(pel1[0], pel1[1], pel1[2], pel1[3]) ||
|
||||
WrongOrientation(pel2[0], pel2[1], pel2[2], pel2[3]) )
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if(bad2 >= 1e24) return 0.0;
|
||||
@ -612,7 +636,7 @@ void MeshOptimize3d :: SplitImprove ()
|
||||
{
|
||||
static Timer t("MeshOptimize3d::SplitImprove"); RegionTimer reg(t);
|
||||
static Timer topt("Optimize");
|
||||
static Timer tsearch("Search");
|
||||
static Timer tsearch("Search-split");
|
||||
|
||||
// int np = mesh.GetNP();
|
||||
int ne = mesh.GetNE();
|
||||
@ -647,7 +671,7 @@ void MeshOptimize3d :: SplitImprove ()
|
||||
tsearch.Start();
|
||||
ParallelForRange(Range(edges), [&] (auto myrange)
|
||||
{
|
||||
NgArray<INDEX_3> locfaces;
|
||||
NgArray<PointIndices<3>> locfaces;
|
||||
|
||||
for(auto i : myrange)
|
||||
{
|
||||
@ -671,7 +695,7 @@ void MeshOptimize3d :: SplitImprove ()
|
||||
// Apply actual optimizations
|
||||
topt.Start();
|
||||
int cnt = 0;
|
||||
NgArray<INDEX_3> locfaces;
|
||||
NgArray<PointIndices<3>> locfaces;
|
||||
for(auto [d_badness, ei] : edges_with_improvement)
|
||||
{
|
||||
auto [p0,p1] = edges[ei];
|
||||
@ -693,7 +717,8 @@ void MeshOptimize3d :: SplitImprove ()
|
||||
|
||||
[[maybe_unused]] int cntill = 0;
|
||||
ne = mesh.GetNE();
|
||||
for (ElementIndex ei = 0; ei < ne; ei++)
|
||||
// for (ElementIndex ei = 0; ei < ne; ei++)
|
||||
for (auto ei : ngcore::T_Range<ElementIndex>(ne))
|
||||
if (!mesh.LegalTet (mesh[ei]))
|
||||
cntill++;
|
||||
// cout << cntill << " illegal tets" << endl;
|
||||
@ -702,21 +727,12 @@ void MeshOptimize3d :: SplitImprove ()
|
||||
multithread.task = savetask;
|
||||
}
|
||||
|
||||
|
||||
double MeshOptimize3d :: SwapImproveEdge (
|
||||
const NgBitArray * working_elements,
|
||||
const TBitArray<ElementIndex> * working_elements,
|
||||
Table<ElementIndex, PointIndex> & elementsonnode,
|
||||
INDEX_3_HASHTABLE<int> & faces,
|
||||
PointIndex pi1, PointIndex pi2, bool check_only)
|
||||
{
|
||||
PointIndex pi3(PointIndex::INVALID), pi4(PointIndex::INVALID),
|
||||
pi5(PointIndex::INVALID), pi6(PointIndex::INVALID);
|
||||
|
||||
double bad1, bad2, bad3;
|
||||
|
||||
Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET);
|
||||
Element el1(TET), el2(TET), el3(TET), el4(TET);
|
||||
Element el1b(TET), el2b(TET), el3b(TET), el4b(TET);
|
||||
ArrayMem<ElementIndex, 20> hasbothpoints;
|
||||
|
||||
double d_badness = 0.0;
|
||||
@ -765,11 +781,14 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
|
||||
if(working_elements &&
|
||||
ei < working_elements->Size() &&
|
||||
!working_elements->Test(ei))
|
||||
!working_elements->Test(ei))
|
||||
return 0.0;
|
||||
|
||||
if (mesh[ei].IsDeleted())
|
||||
return 0.0;
|
||||
|
||||
if(WrongOrientation(mesh.Points(), mesh[ei]))
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
if(!NeedsOptimization(hasbothpoints))
|
||||
@ -778,8 +797,41 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
int nsuround = hasbothpoints.Size();
|
||||
int mattyp = mesh[hasbothpoints[0]].GetIndex();
|
||||
|
||||
auto fix_orientation = [&] (Element & el) {
|
||||
if (WrongOrientation (mesh.Points(), el))
|
||||
el.Invert();
|
||||
};
|
||||
|
||||
auto El = [&] ( PointIndex pi0, PointIndex pi1, PointIndex pi2, PointIndex pi3) -> Element {
|
||||
Element el(TET);
|
||||
el[0] = pi0;
|
||||
el[1] = pi1;
|
||||
el[2] = pi2;
|
||||
el[3] = pi3;
|
||||
el.SetIndex (mattyp);
|
||||
// fix_orientation(el);
|
||||
return el;
|
||||
};
|
||||
|
||||
auto combined_badness = [&] (std::initializer_list<Element> els, bool apply_illegal_penalty = true) {
|
||||
double bad = 0.0;
|
||||
bool have_illegal = false;
|
||||
for (auto el : els) {
|
||||
bad += CalcBad(mesh.Points(), el, 0);
|
||||
if(apply_illegal_penalty && !have_illegal) {
|
||||
el.Touch();
|
||||
have_illegal = !mesh.LegalTet(el);
|
||||
}
|
||||
}
|
||||
if(have_illegal && apply_illegal_penalty)
|
||||
bad += GetLegalPenalty();
|
||||
return bad;
|
||||
};
|
||||
|
||||
if ( nsuround == 3 )
|
||||
{
|
||||
PointIndex pi3(PointIndex::INVALID), pi4(PointIndex::INVALID), pi5(PointIndex::INVALID);
|
||||
|
||||
Element & elem = mesh[hasbothpoints[0]];
|
||||
for (int l = 0; l < 4; l++)
|
||||
if (elem[l] != pi1 && elem[l] != pi2)
|
||||
@ -788,12 +840,7 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
pi3 = elem[l];
|
||||
}
|
||||
|
||||
el31[0] = pi1;
|
||||
el31[1] = pi2;
|
||||
el31[2] = pi3;
|
||||
el31[3] = pi4;
|
||||
el31.SetIndex (mattyp);
|
||||
|
||||
auto el31 = El(pi1, pi2, pi3, pi4);
|
||||
if (WrongOrientation (mesh.Points(), el31))
|
||||
{
|
||||
Swap (pi3, pi4);
|
||||
@ -821,57 +868,18 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
throw NgException("Illegal state observed in SwapImprove");
|
||||
|
||||
|
||||
el32[0] = pi1;
|
||||
el32[1] = pi2;
|
||||
el32[2] = pi4;
|
||||
el32[3] = pi5;
|
||||
el32.SetIndex (mattyp);
|
||||
auto el32 = El(pi1, pi2, pi4, pi5);
|
||||
auto el33 = El(pi1, pi2, pi5, pi3);
|
||||
|
||||
el33[0] = pi1;
|
||||
el33[1] = pi2;
|
||||
el33[2] = pi5;
|
||||
el33[3] = pi3;
|
||||
el33.SetIndex (mattyp);
|
||||
|
||||
bad1 = CalcBad (mesh.Points(), el31, 0) +
|
||||
CalcBad (mesh.Points(), el32, 0) +
|
||||
CalcBad (mesh.Points(), el33, 0);
|
||||
|
||||
el31.Touch();
|
||||
el32.Touch();
|
||||
el33.Touch();
|
||||
|
||||
if (!mesh.LegalTet(el31) ||
|
||||
!mesh.LegalTet(el32) ||
|
||||
!mesh.LegalTet(el33))
|
||||
bad1 += GetLegalPenalty();
|
||||
|
||||
el21[0] = pi3;
|
||||
el21[1] = pi4;
|
||||
el21[2] = pi5;
|
||||
el21[3] = pi2;
|
||||
el21.SetIndex (mattyp);
|
||||
|
||||
el22[0] = pi5;
|
||||
el22[1] = pi4;
|
||||
el22[2] = pi3;
|
||||
el22[3] = pi1;
|
||||
el22.SetIndex (mattyp);
|
||||
|
||||
bad2 = CalcBad (mesh.Points(), el21, 0) +
|
||||
CalcBad (mesh.Points(), el22, 0);
|
||||
|
||||
el21.Touch();
|
||||
el22.Touch();
|
||||
|
||||
if (!mesh.LegalTet(el21) ||
|
||||
!mesh.LegalTet(el22))
|
||||
bad2 += GetLegalPenalty();
|
||||
auto el21 = El(pi3, pi4, pi5, pi2);
|
||||
auto el22 = El(pi5, pi4, pi3, pi1);
|
||||
|
||||
double bad1 = combined_badness({el31, el32, el33});
|
||||
double bad2 = combined_badness({el21, el22});
|
||||
|
||||
if ((goal == OPT_CONFORM) && NotTooBad(bad1, bad2))
|
||||
{
|
||||
INDEX_3 face(pi3, pi4, pi5);
|
||||
PointIndices<3> face(pi3, pi4, pi5);
|
||||
face.Sort();
|
||||
if (faces.Used(face))
|
||||
{
|
||||
@ -904,8 +912,6 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
mesh[hasbothpoints[1]].Delete();
|
||||
mesh[hasbothpoints[2]].Delete();
|
||||
|
||||
el21.Touch();
|
||||
el22.Touch();
|
||||
mesh.AddVolumeElement(el21);
|
||||
mesh.AddVolumeElement(el22);
|
||||
}
|
||||
@ -913,6 +919,9 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
|
||||
if (nsuround == 4)
|
||||
{
|
||||
PointIndex pi3(PointIndex::INVALID), pi4(PointIndex::INVALID);
|
||||
PointIndex pi5(PointIndex::INVALID), pi6(PointIndex::INVALID);
|
||||
|
||||
const Element & elem1 = mesh[hasbothpoints[0]];
|
||||
for (int l = 0; l < 4; l++)
|
||||
if (elem1[l] != pi1 && elem1[l] != pi2)
|
||||
@ -921,9 +930,7 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
pi3 = elem1[l];
|
||||
}
|
||||
|
||||
el1[0] = pi1; el1[1] = pi2;
|
||||
el1[2] = pi3; el1[3] = pi4;
|
||||
el1.SetIndex (mattyp);
|
||||
auto el1 = El(pi1, pi2, pi3, pi4);
|
||||
|
||||
if (WrongOrientation (mesh.Points(), el1))
|
||||
{
|
||||
@ -958,115 +965,26 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
}
|
||||
}
|
||||
|
||||
el1[0] = pi1; el1[1] = pi2;
|
||||
el1[2] = pi3; el1[3] = pi4;
|
||||
el1.SetIndex (mattyp);
|
||||
el1 = El(pi1, pi2, pi3, pi4);
|
||||
auto el2 = El(pi1, pi2, pi4, pi5);
|
||||
auto el3 = El(pi1, pi2, pi5, pi6);
|
||||
auto el4 = El(pi1, pi2, pi6, pi3);
|
||||
double bad1 = combined_badness({el1, el2, el3, el4}, goal != OPT_CONFORM);
|
||||
|
||||
el2[0] = pi1; el2[1] = pi2;
|
||||
el2[2] = pi4; el2[3] = pi5;
|
||||
el2.SetIndex (mattyp);
|
||||
el1 = El(pi3, pi5, pi2, pi4);
|
||||
el2 = El(pi3, pi5, pi4, pi1);
|
||||
el3 = El(pi3, pi5, pi1, pi6);
|
||||
el4 = El(pi3, pi5, pi6, pi2);
|
||||
double bad2 = combined_badness({el1, el2, el3, el4}, goal != OPT_CONFORM);
|
||||
|
||||
el3[0] = pi1; el3[1] = pi2;
|
||||
el3[2] = pi5; el3[3] = pi6;
|
||||
el3.SetIndex (mattyp);
|
||||
auto el1b = El(pi4, pi6, pi3, pi2);
|
||||
auto el2b = El(pi4, pi6, pi2, pi5);
|
||||
auto el3b = El(pi4, pi6, pi5, pi1);
|
||||
auto el4b = El(pi4, pi6, pi1, pi3);
|
||||
double bad3 = combined_badness({el1b, el2b, el3b, el4b}, goal != OPT_CONFORM);
|
||||
|
||||
el4[0] = pi1; el4[1] = pi2;
|
||||
el4[2] = pi6; el4[3] = pi3;
|
||||
el4.SetIndex (mattyp);
|
||||
|
||||
bad1 = CalcBad (mesh.Points(), el1, 0) +
|
||||
CalcBad (mesh.Points(), el2, 0) +
|
||||
CalcBad (mesh.Points(), el3, 0) +
|
||||
CalcBad (mesh.Points(), el4, 0);
|
||||
|
||||
|
||||
el1.Touch();
|
||||
el2.Touch();
|
||||
el3.Touch();
|
||||
el4.Touch();
|
||||
|
||||
|
||||
if (goal != OPT_CONFORM)
|
||||
{
|
||||
if (!mesh.LegalTet(el1) ||
|
||||
!mesh.LegalTet(el2) ||
|
||||
!mesh.LegalTet(el3) ||
|
||||
!mesh.LegalTet(el4))
|
||||
bad1 += GetLegalPenalty();
|
||||
}
|
||||
|
||||
el1[0] = pi3; el1[1] = pi5;
|
||||
el1[2] = pi2; el1[3] = pi4;
|
||||
el1.SetIndex (mattyp);
|
||||
|
||||
el2[0] = pi3; el2[1] = pi5;
|
||||
el2[2] = pi4; el2[3] = pi1;
|
||||
el2.SetIndex (mattyp);
|
||||
|
||||
el3[0] = pi3; el3[1] = pi5;
|
||||
el3[2] = pi1; el3[3] = pi6;
|
||||
el3.SetIndex (mattyp);
|
||||
|
||||
el4[0] = pi3; el4[1] = pi5;
|
||||
el4[2] = pi6; el4[3] = pi2;
|
||||
el4.SetIndex (mattyp);
|
||||
|
||||
bad2 = CalcBad (mesh.Points(), el1, 0) +
|
||||
CalcBad (mesh.Points(), el2, 0) +
|
||||
CalcBad (mesh.Points(), el3, 0) +
|
||||
CalcBad (mesh.Points(), el4, 0);
|
||||
|
||||
el1.Touch();
|
||||
el2.Touch();
|
||||
el3.Touch();
|
||||
el4.Touch();
|
||||
|
||||
if (goal != OPT_CONFORM)
|
||||
{
|
||||
if (!mesh.LegalTet(el1) ||
|
||||
!mesh.LegalTet(el2) ||
|
||||
!mesh.LegalTet(el3) ||
|
||||
!mesh.LegalTet(el4))
|
||||
bad2 += GetLegalPenalty();
|
||||
}
|
||||
|
||||
|
||||
el1b[0] = pi4; el1b[1] = pi6;
|
||||
el1b[2] = pi3; el1b[3] = pi2;
|
||||
el1b.SetIndex (mattyp);
|
||||
|
||||
el2b[0] = pi4; el2b[1] = pi6;
|
||||
el2b[2] = pi2; el2b[3] = pi5;
|
||||
el2b.SetIndex (mattyp);
|
||||
|
||||
el3b[0] = pi4; el3b[1] = pi6;
|
||||
el3b[2] = pi5; el3b[3] = pi1;
|
||||
el3b.SetIndex (mattyp);
|
||||
|
||||
el4b[0] = pi4; el4b[1] = pi6;
|
||||
el4b[2] = pi1; el4b[3] = pi3;
|
||||
el4b.SetIndex (mattyp);
|
||||
|
||||
bad3 = CalcBad (mesh.Points(), el1b, 0) +
|
||||
CalcBad (mesh.Points(), el2b, 0) +
|
||||
CalcBad (mesh.Points(), el3b, 0) +
|
||||
CalcBad (mesh.Points(), el4b, 0);
|
||||
|
||||
el1b.Touch();
|
||||
el2b.Touch();
|
||||
el3b.Touch();
|
||||
el4b.Touch();
|
||||
|
||||
if (goal != OPT_CONFORM)
|
||||
{
|
||||
if (!mesh.LegalTet(el1b) ||
|
||||
!mesh.LegalTet(el2b) ||
|
||||
!mesh.LegalTet(el3b) ||
|
||||
!mesh.LegalTet(el4b))
|
||||
bad3 += GetLegalPenalty();
|
||||
}
|
||||
|
||||
bool swap2, swap3;
|
||||
bool swap2=false;
|
||||
bool swap3=false;
|
||||
|
||||
if (goal == OPT_CONFORM)
|
||||
{
|
||||
@ -1092,10 +1010,6 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
for (auto i : IntRange(4))
|
||||
mesh[hasbothpoints[i]].Delete();
|
||||
|
||||
el1.Touch();
|
||||
el2.Touch();
|
||||
el3.Touch();
|
||||
el4.Touch();
|
||||
mesh.AddVolumeElement (el1);
|
||||
mesh.AddVolumeElement (el2);
|
||||
mesh.AddVolumeElement (el3);
|
||||
@ -1106,10 +1020,6 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
for (auto i : IntRange(4))
|
||||
mesh[hasbothpoints[i]].Delete();
|
||||
|
||||
el1b.Touch();
|
||||
el2b.Touch();
|
||||
el3b.Touch();
|
||||
el4b.Touch();
|
||||
mesh.AddVolumeElement (el1b);
|
||||
mesh.AddVolumeElement (el2b);
|
||||
mesh.AddVolumeElement (el3b);
|
||||
@ -1120,7 +1030,7 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
// if (goal == OPT_QUALITY)
|
||||
if (nsuround >= 5)
|
||||
{
|
||||
Element hel(TET);
|
||||
PointIndex pi3(PointIndex::INVALID), pi4(PointIndex::INVALID);
|
||||
|
||||
NgArrayMem<PointIndex, 50> suroundpts(nsuround);
|
||||
NgArrayMem<bool, 50> tetused(nsuround);
|
||||
@ -1134,19 +1044,8 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
pi3 = elem[l];
|
||||
}
|
||||
|
||||
hel[0] = pi1;
|
||||
hel[1] = pi2;
|
||||
hel[2] = pi3;
|
||||
hel[3] = pi4;
|
||||
hel.SetIndex (mattyp);
|
||||
|
||||
if (WrongOrientation (mesh.Points(), hel))
|
||||
{
|
||||
if (WrongOrientation (mesh.Points(), El(pi1, pi2, pi3, pi4)))
|
||||
Swap (pi3, pi4);
|
||||
hel[2] = pi3;
|
||||
hel[3] = pi4;
|
||||
}
|
||||
|
||||
|
||||
// suroundpts.SetSize (nsuround);
|
||||
suroundpts = PointIndex::INVALID;
|
||||
@ -1169,10 +1068,7 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
for (int k2 = 0; k2 < 4 && !newpi.IsValid(); k2++)
|
||||
if (nel[k2] == oldpi)
|
||||
{
|
||||
newpi =
|
||||
nel[0] + nel[1] + nel[2] + nel[3]
|
||||
- pi1 - pi2 - oldpi;
|
||||
|
||||
newpi = nel[0] - pi1 + nel[1] - pi2 + nel[2] - oldpi + nel[3];
|
||||
tetused[k] = true;
|
||||
suroundpts[l] = newpi;
|
||||
}
|
||||
@ -1180,17 +1076,9 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
}
|
||||
|
||||
|
||||
bad1 = 0;
|
||||
for (int k = 0; k < nsuround; k++)
|
||||
{
|
||||
hel[0] = pi1;
|
||||
hel[1] = pi2;
|
||||
hel[2] = suroundpts[k];
|
||||
hel[3] = suroundpts[(k+1) % nsuround];
|
||||
hel.SetIndex (mattyp);
|
||||
|
||||
bad1 += CalcBad (mesh.Points(), hel, 0);
|
||||
}
|
||||
double bad1 = 0;
|
||||
for (auto k : Range(nsuround))
|
||||
bad1 += CalcBad (mesh.Points(), El(pi1, pi2, suroundpts[k], suroundpts[(k+1) % nsuround]), 0);
|
||||
|
||||
// (*testout) << "nsuround = " << nsuround << " bad1 = " << bad1 << endl;
|
||||
|
||||
@ -1202,27 +1090,16 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
|
||||
for (int l = 0; l < nsuround; l++)
|
||||
{
|
||||
bad2 = 0;
|
||||
double bad2 = 0;
|
||||
|
||||
for (int k = l+1; k <= nsuround + l - 2; k++)
|
||||
{
|
||||
hel[0] = suroundpts[l];
|
||||
hel[1] = suroundpts[k % nsuround];
|
||||
hel[2] = suroundpts[(k+1) % nsuround];
|
||||
hel[3] = pi2;
|
||||
PointIndex pil = suroundpts[l];
|
||||
PointIndex pik0 = suroundpts[k % nsuround];
|
||||
PointIndex pik1 = suroundpts[(k+1) % nsuround];
|
||||
|
||||
bad2 += CalcBad (mesh.Points(), hel, 0);
|
||||
hel.Touch();
|
||||
if (!mesh.LegalTet(hel)) bad2 += GetLegalPenalty();
|
||||
|
||||
hel[2] = suroundpts[k % nsuround];
|
||||
hel[1] = suroundpts[(k+1) % nsuround];
|
||||
hel[3] = pi1;
|
||||
|
||||
bad2 += CalcBad (mesh.Points(), hel, 0);
|
||||
|
||||
hel.Touch();
|
||||
if (!mesh.LegalTet(hel)) bad2 += GetLegalPenalty();
|
||||
bad2 += combined_badness({El(pil, pik0, pik1, pi2)});
|
||||
bad2 += combined_badness({El(pil, pik1, pik0, pi1)});
|
||||
}
|
||||
// (*testout) << "bad2," << l << " = " << bad2 << endl;
|
||||
|
||||
@ -1239,9 +1116,9 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
|
||||
for (int k = l+1; k <= nsuround + l - 2; k++)
|
||||
{
|
||||
INDEX_3 hi3(suroundpts[l],
|
||||
suroundpts[k % nsuround],
|
||||
suroundpts[(k+1) % nsuround]);
|
||||
PointIndices<3> hi3(suroundpts[l],
|
||||
suroundpts[k % nsuround],
|
||||
suroundpts[(k+1) % nsuround]);
|
||||
hi3.Sort();
|
||||
if (faces.Used(hi3))
|
||||
{
|
||||
@ -1286,29 +1163,24 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
for (int k = bestl+1; k <= nsuround + bestl - 2; k++)
|
||||
{
|
||||
// int k1;
|
||||
PointIndex pi = suroundpts[bestl];
|
||||
PointIndex pik0 = suroundpts[k % nsuround];
|
||||
PointIndex pik1 = suroundpts[(k+1) % nsuround];
|
||||
|
||||
hel[0] = suroundpts[bestl];
|
||||
hel[1] = suroundpts[k % nsuround];
|
||||
hel[2] = suroundpts[(k+1) % nsuround];
|
||||
hel[3] = pi2;
|
||||
hel.Touch();
|
||||
|
||||
auto el = El(pi, pik0, pik1, pi2);
|
||||
/*
|
||||
(*testout) << nsuround << "-swap, new el,top = "
|
||||
<< hel << endl;
|
||||
<< el << endl;
|
||||
*/
|
||||
mesh.AddVolumeElement (hel);
|
||||
|
||||
hel[2] = suroundpts[k % nsuround];
|
||||
hel[1] = suroundpts[(k+1) % nsuround];
|
||||
hel[3] = pi1;
|
||||
mesh.AddVolumeElement (el);
|
||||
|
||||
el = El(pi, pik1, pik0, pi1);
|
||||
/*
|
||||
(*testout) << nsuround << "-swap, new el,bot = "
|
||||
<< hel << endl;
|
||||
<< el << endl;
|
||||
*/
|
||||
|
||||
mesh.AddVolumeElement (hel);
|
||||
mesh.AddVolumeElement (el);
|
||||
}
|
||||
|
||||
for (int k = 0; k < nsuround; k++)
|
||||
@ -1327,7 +1199,7 @@ double MeshOptimize3d :: SwapImproveEdge (
|
||||
return d_badness;
|
||||
}
|
||||
|
||||
void MeshOptimize3d :: SwapImprove (const NgBitArray * working_elements)
|
||||
void MeshOptimize3d :: SwapImprove (const TBitArray<ElementIndex> * working_elements)
|
||||
{
|
||||
static Timer t("MeshOptimize3d::SwapImprove"); RegionTimer reg(t);
|
||||
static Timer tloop("MeshOptimize3d::SwapImprove loop");
|
||||
@ -1338,7 +1210,7 @@ void MeshOptimize3d :: SwapImprove (const NgBitArray * working_elements)
|
||||
// int ne = mesh.GetNE();
|
||||
|
||||
mesh.BuildBoundaryEdges(false);
|
||||
BitArray free_points(mesh.GetNP()+PointIndex::BASE);
|
||||
TBitArray<PointIndex> free_points(mesh.GetNP());
|
||||
free_points.Clear();
|
||||
|
||||
ParallelForRange(mesh.VolumeElements().Range(), [&] (auto myrange)
|
||||
@ -1374,7 +1246,7 @@ void MeshOptimize3d :: SwapImprove (const NgBitArray * working_elements)
|
||||
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
|
||||
{
|
||||
const Element2d & hel = mesh.OpenElement(i);
|
||||
INDEX_3 face(hel[0], hel[1], hel[2]);
|
||||
PointIndices<3> face(hel[0], hel[1], hel[2]);
|
||||
face.Sort();
|
||||
faces.Set (face, i);
|
||||
}
|
||||
@ -1441,7 +1313,7 @@ void MeshOptimize3d :: SwapImprove (const NgBitArray * working_elements)
|
||||
{
|
||||
Element2d sel;
|
||||
el.GetFace(i, sel);
|
||||
INDEX_3 face(sel[0], sel[1], sel[2]);
|
||||
PointIndices<3> face(sel[0], sel[1], sel[2]);
|
||||
face.Sort();
|
||||
if(faces.Used(face))
|
||||
open_els[faces.Get(face)-1].Delete();
|
||||
@ -1465,11 +1337,11 @@ void MeshOptimize3d :: SwapImprove (const NgBitArray * working_elements)
|
||||
|
||||
|
||||
void MeshOptimize3d :: SwapImproveSurface (
|
||||
const NgBitArray * working_elements,
|
||||
const NgArray< NgArray<int,PointIndex::BASE>* > * idmaps)
|
||||
const TBitArray<ElementIndex> * working_elements,
|
||||
const NgArray< idmap_type* > * idmaps)
|
||||
{
|
||||
NgArray< NgArray<int,PointIndex::BASE>* > locidmaps;
|
||||
const NgArray< NgArray<int,PointIndex::BASE>* > * used_idmaps;
|
||||
NgArray< idmap_type* > locidmaps;
|
||||
const NgArray< idmap_type* > * used_idmaps;
|
||||
|
||||
if(idmaps)
|
||||
used_idmaps = idmaps;
|
||||
@ -1481,7 +1353,7 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
{
|
||||
if(mesh.GetIdentifications().GetType(i) == Identifications::PERIODIC)
|
||||
{
|
||||
locidmaps.Append(new NgArray<int,PointIndex::BASE>);
|
||||
locidmaps.Append(new idmap_type);
|
||||
mesh.GetIdentifications().GetMap(i,*locidmaps.Last(),true);
|
||||
}
|
||||
}
|
||||
@ -1504,9 +1376,9 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
|
||||
|
||||
// contains at least all elements at node
|
||||
TABLE<ElementIndex,PointIndex::BASE> elementsonnode(np);
|
||||
TABLE<SurfaceElementIndex,PointIndex::BASE> surfaceelementsonnode(np);
|
||||
TABLE<int,PointIndex::BASE> surfaceindicesonnode(np);
|
||||
DynamicTable<ElementIndex,PointIndex> elementsonnode(np);
|
||||
DynamicTable<SurfaceElementIndex,PointIndex> surfaceelementsonnode(np);
|
||||
DynamicTable<int,PointIndex> surfaceindicesonnode(np);
|
||||
|
||||
NgArray<ElementIndex> hasbothpoints;
|
||||
NgArray<ElementIndex> hasbothpointsother;
|
||||
@ -1584,11 +1456,11 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
bool found = false;
|
||||
for(int k=0; !found && k<used_idmaps->Size(); k++)
|
||||
{
|
||||
if(pi2 < (*used_idmaps)[k]->Size() + PointIndex::BASE)
|
||||
if(pi2 < (*used_idmaps)[k]->Size() + IndexBASE<PointIndex>())
|
||||
{
|
||||
pi1other = (*(*used_idmaps)[k])[pi1];
|
||||
pi2other = (*(*used_idmaps)[k])[pi2];
|
||||
found = (pi1other != 0 && pi2other != 0 && pi1other != pi1 && pi2other != pi2);
|
||||
found = (pi1other.IsValid() && pi2other.IsValid() && pi1other != pi1 && pi2other != pi2);
|
||||
if(found)
|
||||
idnum = k;
|
||||
}
|
||||
@ -1609,14 +1481,14 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
othermattype = -1;
|
||||
|
||||
|
||||
INDEX_2 i2 (pi1, pi2);
|
||||
PointIndices<2> i2 (pi1, pi2);
|
||||
i2.Sort();
|
||||
if (edgeused.Used(i2)) continue;
|
||||
edgeused.Set (i2, 1);
|
||||
if(periodic)
|
||||
{
|
||||
i2.I1() = pi1other;
|
||||
i2.I2() = pi2other;
|
||||
i2[0] = pi1other;
|
||||
i2[1] = pi2other;
|
||||
i2.Sort();
|
||||
edgeused.Set(i2,1);
|
||||
}
|
||||
@ -1772,7 +1644,7 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
|
||||
//(*testout) << "sel1 " << sel1 << " sel2 " << sel2 << " el " << mesh[sel1] << " resp. " << mesh[sel2] << endl;
|
||||
|
||||
PointIndex sp1(0), sp2(0);
|
||||
PointIndex sp1(PointIndex::INVALID), sp2(PointIndex::INVALID);
|
||||
PointIndex sp1other, sp2other;
|
||||
for(int l=0; l<mesh[sel1].GetNP(); l++)
|
||||
if(mesh[sel1][l] != pi1 && mesh[sel1][l] != pi2)
|
||||
@ -1829,7 +1701,7 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
int nsuround = hasbothpoints.Size();
|
||||
int nsuroundother = hasbothpointsother.Size();
|
||||
|
||||
NgArray < int > outerpoints(nsuround+1);
|
||||
NgArray < PointIndex > outerpoints(nsuround+1);
|
||||
outerpoints[0] = sp1;
|
||||
|
||||
for(int i=0; i<nsuround; i++)
|
||||
@ -1864,7 +1736,7 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
{
|
||||
(*testout) << mesh[hasbothpoints[ii]] << endl;
|
||||
for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++)
|
||||
if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0].IsValid())
|
||||
(*testout) << mesh[hasbothpoints[ii]][jj] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl;
|
||||
@ -1874,11 +1746,11 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
<< "sel2 " << mesh[sel2] << endl;
|
||||
for(int ii=0; ii<3; ii++)
|
||||
{
|
||||
if(mesh.mlbetweennodes[mesh[sel1][ii]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[sel1][ii]][0].IsValid())
|
||||
(*testout) << mesh[sel1][ii] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[sel1][ii]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl;
|
||||
if(mesh.mlbetweennodes[mesh[sel2][ii]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[sel2][ii]][0].IsValid())
|
||||
(*testout) << mesh[sel2][ii] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[sel2][ii]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl;
|
||||
@ -1886,7 +1758,7 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
}
|
||||
|
||||
|
||||
NgArray < int > outerpointsother;
|
||||
NgArray < PointIndex > outerpointsother;
|
||||
|
||||
if(nsuroundother > 0)
|
||||
{
|
||||
@ -1927,7 +1799,7 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
{
|
||||
(*testout) << mesh[hasbothpoints[ii]] << endl;
|
||||
for(int jj=0; jj<mesh[hasbothpoints[ii]].GetNP(); jj++)
|
||||
if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0].IsValid())
|
||||
(*testout) << mesh[hasbothpoints[ii]][jj] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[hasbothpoints[ii]][jj]][1] << endl;
|
||||
@ -1937,11 +1809,11 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
<< "sel2 " << mesh[sel2] << endl;
|
||||
for(int ii=0; ii<3; ii++)
|
||||
{
|
||||
if(mesh.mlbetweennodes[mesh[sel1][ii]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[sel1][ii]][0].IsValid())
|
||||
(*testout) << mesh[sel1][ii] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[sel1][ii]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[sel1][ii]][1] << endl;
|
||||
if(mesh.mlbetweennodes[mesh[sel2][ii]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[sel2][ii]][0].IsValid())
|
||||
(*testout) << mesh[sel2][ii] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[sel2][ii]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[sel2][ii]][1] << endl;
|
||||
@ -1953,7 +1825,7 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
{
|
||||
(*testout) << mesh[hasbothpointsother[ii]] << endl;
|
||||
for(int jj=0; jj<mesh[hasbothpointsother[ii]].GetNP(); jj++)
|
||||
if(mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0].IsValid())
|
||||
(*testout) << mesh[hasbothpointsother[ii]][jj] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[hasbothpointsother[ii]][jj]][1] << endl;
|
||||
@ -1963,11 +1835,11 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
<< "sel2other " << mesh[sel2other] << endl;
|
||||
for(int ii=0; ii<3; ii++)
|
||||
{
|
||||
if(mesh.mlbetweennodes[mesh[sel1other][ii]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[sel1other][ii]][0].IsValid())
|
||||
(*testout) << mesh[sel1other][ii] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[sel1other][ii]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[sel1other][ii]][1] << endl;
|
||||
if(mesh.mlbetweennodes[mesh[sel2other][ii]][0] > 0)
|
||||
if(mesh.mlbetweennodes[mesh[sel2other][ii]][0].IsValid())
|
||||
(*testout) << mesh[sel2other][ii] << " between "
|
||||
<< mesh.mlbetweennodes[mesh[sel2other][ii]][0] << " and "
|
||||
<< mesh.mlbetweennodes[mesh[sel2other][ii]][1] << endl;
|
||||
@ -2321,8 +2193,8 @@ void MeshOptimize3d :: SwapImproveSurface (
|
||||
*/
|
||||
|
||||
double MeshOptimize3d :: SwapImprove2 ( ElementIndex eli1, int face,
|
||||
Table<ElementIndex, PointIndex> & elementsonnode,
|
||||
TABLE<SurfaceElementIndex, PointIndex::BASE> & belementsonnode, bool check_only )
|
||||
Table<ElementIndex, PointIndex> & elementsonnode,
|
||||
DynamicTable<SurfaceElementIndex, PointIndex> & belementsonnode, bool conform_segments, bool check_only )
|
||||
{
|
||||
PointIndex pi1, pi2, pi3, pi4, pi5;
|
||||
Element el21(TET), el22(TET), el31(TET), el32(TET), el33(TET);
|
||||
@ -2356,28 +2228,31 @@ double MeshOptimize3d :: SwapImprove2 ( ElementIndex eli1, int face,
|
||||
}
|
||||
|
||||
|
||||
bool bface = 0;
|
||||
for (int k = 0; k < belementsonnode[pi1].Size(); k++)
|
||||
{
|
||||
const Element2d & bel =
|
||||
mesh[belementsonnode[pi1][k]];
|
||||
if(!conform_segments)
|
||||
{
|
||||
bool bface = 0;
|
||||
for (int k = 0; k < belementsonnode[pi1].Size(); k++)
|
||||
{
|
||||
const Element2d & bel =
|
||||
mesh[belementsonnode[pi1][k]];
|
||||
|
||||
bool bface1 = 1;
|
||||
for (int l = 0; l < 3; l++)
|
||||
if (bel[l] != pi1 && bel[l] != pi2 && bel[l] != pi3)
|
||||
bool bface1 = 1;
|
||||
for (int l = 0; l < 3; l++)
|
||||
if (bel[l] != pi1 && bel[l] != pi2 && bel[l] != pi3)
|
||||
{
|
||||
bface1 = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bface1)
|
||||
{
|
||||
bface1 = 0;
|
||||
bface = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (bface1)
|
||||
{
|
||||
bface = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bface) return 0.0;
|
||||
if (bface) return 0.0;
|
||||
}
|
||||
|
||||
|
||||
FlatArray<ElementIndex> row = elementsonnode[pi1];
|
||||
@ -2495,11 +2370,11 @@ double MeshOptimize3d :: SwapImprove2 ( ElementIndex eli1, int face,
|
||||
2 -> 3 conversion
|
||||
*/
|
||||
|
||||
void MeshOptimize3d :: SwapImprove2 ()
|
||||
void MeshOptimize3d :: SwapImprove2 (bool conform_segments)
|
||||
{
|
||||
static Timer t("MeshOptimize3d::SwapImprove2"); RegionTimer reg(t);
|
||||
|
||||
if (goal == OPT_CONFORM) return;
|
||||
if (!conform_segments && goal == OPT_CONFORM) return;
|
||||
|
||||
mesh.BuildBoundaryEdges(false);
|
||||
|
||||
@ -2511,7 +2386,7 @@ void MeshOptimize3d :: SwapImprove2 ()
|
||||
int nse = mesh.GetNSE();
|
||||
|
||||
// contains at least all elements at node
|
||||
TABLE<SurfaceElementIndex, PointIndex::BASE> belementsonnode(np);
|
||||
DynamicTable<SurfaceElementIndex, PointIndex> belementsonnode(np);
|
||||
|
||||
PrintMessage (3, "SwapImprove2 ");
|
||||
(*testout) << "\n" << "Start SwapImprove2" << "\n";
|
||||
@ -2561,7 +2436,7 @@ void MeshOptimize3d :: SwapImprove2 ()
|
||||
|
||||
for (int j = 0; j < 4; j++)
|
||||
{
|
||||
double d_badness = SwapImprove2( eli1, j, elementsonnode, belementsonnode, true);
|
||||
double d_badness = SwapImprove2( eli1, j, elementsonnode, belementsonnode, conform_segments, true);
|
||||
if(d_badness<0.0)
|
||||
my_faces_with_improvement.Append( std::make_tuple(d_badness, eli1, j) );
|
||||
}
|
||||
@ -2577,7 +2452,7 @@ void MeshOptimize3d :: SwapImprove2 ()
|
||||
{
|
||||
if(mesh[eli].IsDeleted())
|
||||
continue;
|
||||
if(SwapImprove2( eli, j, elementsonnode, belementsonnode, false) < 0.0)
|
||||
if(SwapImprove2( eli, j, elementsonnode, belementsonnode, conform_segments, false) < 0.0)
|
||||
cnt++;
|
||||
}
|
||||
|
||||
@ -2608,7 +2483,7 @@ double MeshOptimize3d :: SplitImprove2Element (
|
||||
// search for very flat tets, with two disjoint edges nearly crossing, like a rectangle with diagonals
|
||||
int minedge = -1;
|
||||
double mindist = 1e99;
|
||||
double minlam0, minlam1;
|
||||
double minlam0=0, minlam1=0;
|
||||
|
||||
for (int i : Range(3))
|
||||
{
|
||||
|
@ -35,18 +35,18 @@ public:
|
||||
void CombineImprove ();
|
||||
|
||||
void SplitImprove ();
|
||||
double SplitImproveEdge (Table<ElementIndex,PointIndex> & elementsonnode, NgArray<INDEX_3> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only=false);
|
||||
double SplitImproveEdge (Table<ElementIndex,PointIndex> & elementsonnode, NgArray<PointIndices<3>> &locfaces, double badmax, PointIndex pi1, PointIndex pi2, PointIndex ptmp, bool check_only=false);
|
||||
|
||||
void SplitImprove2 ();
|
||||
double SplitImprove2Element (ElementIndex ei, const Table<ElementIndex, PointIndex> & elements_of_point, bool check_only);
|
||||
|
||||
|
||||
double SwapImproveEdge (const NgBitArray * working_elements, Table<ElementIndex,PointIndex> & elementsonnode, INDEX_3_HASHTABLE<int> & faces, PointIndex pi1, PointIndex pi2, bool check_only=false);
|
||||
void SwapImprove (const NgBitArray * working_elements = NULL);
|
||||
void SwapImproveSurface (const NgBitArray * working_elements = NULL,
|
||||
const NgArray< NgArray<int,PointIndex::BASE>* > * idmaps = NULL);
|
||||
void SwapImprove2 ();
|
||||
double SwapImprove2 (ElementIndex eli1, int face, Table<ElementIndex, PointIndex> & elementsonnode, TABLE<SurfaceElementIndex, PointIndex::BASE> & belementsonnode, bool check_only=false );
|
||||
double SwapImproveEdge (const TBitArray<ElementIndex> * working_elements, Table<ElementIndex,PointIndex> & elementsonnode, INDEX_3_HASHTABLE<int> & faces, PointIndex pi1, PointIndex pi2, bool check_only=false);
|
||||
void SwapImprove (const TBitArray<ElementIndex> * working_elements = NULL);
|
||||
void SwapImproveSurface (const TBitArray<ElementIndex> * working_elements = NULL,
|
||||
const NgArray< idmap_type* > * idmaps = NULL);
|
||||
void SwapImprove2 (bool conform_segments = false);
|
||||
double SwapImprove2 (ElementIndex eli1, int face, Table<ElementIndex, PointIndex> & elementsonnode, DynamicTable<SurfaceElementIndex, PointIndex> & belementsonnode, bool conform_segments, bool check_only=false );
|
||||
|
||||
void ImproveMesh() { mesh.ImproveMesh(mp, goal); }
|
||||
|
||||
@ -108,12 +108,12 @@ public:
|
||||
class PointFunction1 : public MinFunction
|
||||
{
|
||||
Mesh::T_POINTS & points;
|
||||
const NgArray<INDEX_3> & faces;
|
||||
const NgArray<PointIndices<3>> & faces;
|
||||
const MeshingParameters & mp;
|
||||
double h;
|
||||
public:
|
||||
PointFunction1 (Mesh::T_POINTS & apoints,
|
||||
const NgArray<INDEX_3> & afaces,
|
||||
const NgArray<PointIndices<3>> & afaces,
|
||||
const MeshingParameters & amp,
|
||||
double ah);
|
||||
|
||||
|
@ -196,54 +196,41 @@ namespace netgen
|
||||
fabs (p(1) - root->xmid[1]) > root->h2)
|
||||
return;
|
||||
|
||||
if (GetH(p) <= 1.2 * h) return;
|
||||
|
||||
GradingBox * box = root;
|
||||
GradingBox * nbox = root;
|
||||
GradingBox * ngb;
|
||||
int childnr;
|
||||
double x1[3], x2[3];
|
||||
|
||||
while (nbox)
|
||||
{
|
||||
box = nbox;
|
||||
childnr = 0;
|
||||
if (p(0) > box->xmid[0]) childnr += 1;
|
||||
if (p(1) > box->xmid[1]) childnr += 2;
|
||||
nbox = box->childs[childnr];
|
||||
};
|
||||
GradingBox * box = Find(p);
|
||||
if (box->HOpt() <= 1.2 * h) return;
|
||||
|
||||
while (2 * box->h2 > h)
|
||||
{
|
||||
childnr = 0;
|
||||
if (p(0) > box->xmid[0]) childnr += 1;
|
||||
if (p(1) > box->xmid[1]) childnr += 2;
|
||||
|
||||
int childnr = 0;
|
||||
double x1[3], x2[3];
|
||||
|
||||
double h2 = box->h2;
|
||||
if (childnr & 1)
|
||||
if (p(0) > box->xmid[0])
|
||||
{
|
||||
childnr += 1;
|
||||
x1[0] = box->xmid[0];
|
||||
x2[0] = x1[0]+h2; // box->x2[0];
|
||||
x2[0] = x1[0]+h2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x2[0] = box->xmid[0];
|
||||
x1[0] = x2[0]-h2; // box->x1[0];
|
||||
x1[0] = x2[0]-h2;
|
||||
}
|
||||
|
||||
if (childnr & 2)
|
||||
if (p(1) > box->xmid[1])
|
||||
{
|
||||
childnr += 2;
|
||||
x1[1] = box->xmid[1];
|
||||
x2[1] = x1[1]+h2; // box->x2[1];
|
||||
x2[1] = x1[1]+h2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x2[1] = box->xmid[1];
|
||||
x1[1] = x2[1]-h2; // box->x1[1];
|
||||
x1[1] = x2[1]-h2;
|
||||
}
|
||||
x1[2] = x2[2] = 0;
|
||||
|
||||
ngb = new GradingBox (x1, x2);
|
||||
auto ngb = new GradingBox (x1, x2);
|
||||
box->childs[childnr] = ngb;
|
||||
ngb->father = box;
|
||||
|
||||
@ -276,67 +263,52 @@ namespace netgen
|
||||
fabs (p(2) - root->xmid[2]) > root->h2)
|
||||
return;
|
||||
|
||||
if (GetH(p) <= 1.2 * h) return;
|
||||
|
||||
GradingBox * box = root;
|
||||
GradingBox * nbox = root;
|
||||
GradingBox * ngb;
|
||||
int childnr;
|
||||
double x1[3], x2[3];
|
||||
|
||||
while (nbox)
|
||||
{
|
||||
box = nbox;
|
||||
childnr = 0;
|
||||
if (p(0) > box->xmid[0]) childnr += 1;
|
||||
if (p(1) > box->xmid[1]) childnr += 2;
|
||||
if (p(2) > box->xmid[2]) childnr += 4;
|
||||
nbox = box->childs[childnr];
|
||||
};
|
||||
|
||||
GradingBox * box = Find(p);
|
||||
if (box->HOpt() <= 1.2 * h) return;
|
||||
|
||||
while (2 * box->h2 > h)
|
||||
{
|
||||
childnr = 0;
|
||||
if (p(0) > box->xmid[0]) childnr += 1;
|
||||
if (p(1) > box->xmid[1]) childnr += 2;
|
||||
if (p(2) > box->xmid[2]) childnr += 4;
|
||||
|
||||
double x1[3], x2[3];
|
||||
int childnr = 0;
|
||||
double h2 = box->h2;
|
||||
if (childnr & 1)
|
||||
|
||||
if (p(0) > box->xmid[0])
|
||||
{
|
||||
childnr += 1;
|
||||
x1[0] = box->xmid[0];
|
||||
x2[0] = x1[0]+h2; // box->x2[0];
|
||||
x2[0] = x1[0]+h2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x2[0] = box->xmid[0];
|
||||
x1[0] = x2[0]-h2; // box->x1[0];
|
||||
x1[0] = x2[0]-h2;
|
||||
}
|
||||
|
||||
if (childnr & 2)
|
||||
if (p(1) > box->xmid[1])
|
||||
{
|
||||
childnr += 2;
|
||||
x1[1] = box->xmid[1];
|
||||
x2[1] = x1[1]+h2; // box->x2[1];
|
||||
x2[1] = x1[1]+h2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x2[1] = box->xmid[1];
|
||||
x1[1] = x2[1]-h2; // box->x1[1];
|
||||
x1[1] = x2[1]-h2;
|
||||
}
|
||||
|
||||
if (childnr & 4)
|
||||
if (p(2) > box->xmid[2])
|
||||
{
|
||||
childnr += 4;
|
||||
x1[2] = box->xmid[2];
|
||||
x2[2] = x1[2]+h2; // box->x2[2];
|
||||
x2[2] = x1[2]+h2;
|
||||
}
|
||||
else
|
||||
{
|
||||
x2[2] = box->xmid[2];
|
||||
x1[2] = x2[2]-h2; // box->x1[2];
|
||||
x1[2] = x2[2]-h2;
|
||||
}
|
||||
|
||||
ngb = new GradingBox (x1, x2);
|
||||
auto ngb = new GradingBox (x1, x2);
|
||||
box->childs[childnr] = ngb;
|
||||
ngb->father = box;
|
||||
|
||||
@ -366,37 +338,7 @@ namespace netgen
|
||||
|
||||
double LocalH :: GetH (Point<3> x) const
|
||||
{
|
||||
const GradingBox * box = root;
|
||||
if (dimension == 2)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int childnr = 0;
|
||||
if (x(0) > box->xmid[0]) childnr += 1;
|
||||
if (x(1) > box->xmid[1]) childnr += 2;
|
||||
|
||||
if (box->childs[childnr])
|
||||
box = box->childs[childnr];
|
||||
else
|
||||
return box->hopt;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int childnr = 0;
|
||||
if (x(0) > box->xmid[0]) childnr += 1;
|
||||
if (x(1) > box->xmid[1]) childnr += 2;
|
||||
if (x(2) > box->xmid[2]) childnr += 4;
|
||||
|
||||
if (box->childs[childnr])
|
||||
box = box->childs[childnr];
|
||||
else
|
||||
return box->hopt;
|
||||
}
|
||||
}
|
||||
|
||||
return Find(x)->HOpt();
|
||||
}
|
||||
|
||||
|
||||
@ -488,15 +430,50 @@ namespace netgen
|
||||
}
|
||||
|
||||
|
||||
GradingBox * LocalH :: Find (Point<3> p) const
|
||||
{
|
||||
GradingBox * box = root;
|
||||
if (dimension == 2)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int childnr = 0;
|
||||
if (p(0) > box->xmid[0]) childnr += 1;
|
||||
if (p(1) > box->xmid[1]) childnr += 2;
|
||||
|
||||
void LocalH :: FindInnerBoxes (AdFront3 * adfront,
|
||||
if (box->childs[childnr])
|
||||
box = box->childs[childnr];
|
||||
else
|
||||
return box;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
int childnr = 0;
|
||||
if (p(0) > box->xmid[0]) childnr += 1;
|
||||
if (p(1) > box->xmid[1]) childnr += 2;
|
||||
if (p(2) > box->xmid[2]) childnr += 4;
|
||||
|
||||
if (box->childs[childnr])
|
||||
box = box->childs[childnr];
|
||||
else
|
||||
return box;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void LocalH :: FindInnerBoxes (const AdFront3 & adfront,
|
||||
int (*testinner)(const Point3d & p1))
|
||||
{
|
||||
static Timer timer("LocalH::FindInnerBoxes");
|
||||
RegionTimer reg (timer);
|
||||
|
||||
|
||||
int nf = adfront->GetNF();
|
||||
int nf = adfront.GetNF();
|
||||
|
||||
for (int i = 0; i < boxes.Size(); i++)
|
||||
boxes[i] -> flags.isinner = 0;
|
||||
@ -509,7 +486,7 @@ namespace netgen
|
||||
// Point3d rx1 = rpmid - rv;
|
||||
|
||||
|
||||
root->flags.pinner = !adfront->SameSide (rpmid, rx2);
|
||||
root->flags.pinner = !adfront.SameSide (rpmid, rx2);
|
||||
|
||||
if (testinner)
|
||||
(*testout) << "inner = " << root->flags.pinner << " =?= "
|
||||
@ -521,7 +498,7 @@ namespace netgen
|
||||
for (int i = 1; i <= nf; i++)
|
||||
{
|
||||
faceinds.Elem(i) = i;
|
||||
adfront->GetFaceBoundingBox(i, faceboxes.Elem(i));
|
||||
adfront.GetFaceBoundingBox(i, faceboxes.Elem(i));
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
@ -531,7 +508,7 @@ namespace netgen
|
||||
|
||||
void LocalH ::
|
||||
FindInnerBoxesRec2 (GradingBox * box,
|
||||
class AdFront3 * adfront,
|
||||
const AdFront3 & adfront,
|
||||
NgArray<Box3d> & faceboxes,
|
||||
NgArray<int> & faceinds, int nfinbox)
|
||||
{
|
||||
@ -592,7 +569,7 @@ namespace netgen
|
||||
box->flags.pinner = 1;
|
||||
else
|
||||
{
|
||||
if (adfront->SameSide (c, cf, &faceused2))
|
||||
if (adfront.SameSide (c, cf, &faceused2))
|
||||
box->flags.pinner = father->flags.pinner;
|
||||
else
|
||||
box->flags.pinner = 1 - father->flags.pinner;
|
||||
@ -644,7 +621,7 @@ namespace netgen
|
||||
|
||||
|
||||
|
||||
void LocalH :: FindInnerBoxes (AdFront2 * adfront,
|
||||
void LocalH :: FindInnerBoxes (const AdFront2 & adfront,
|
||||
int (*testinner)(const Point<2> & p1))
|
||||
{
|
||||
static Timer t("LocalH::FindInnerBoxes 2d"); RegionTimer reg (t);
|
||||
@ -667,23 +644,23 @@ namespace netgen
|
||||
// Point<2> rx1 = rpmid - rv;
|
||||
|
||||
|
||||
root->flags.pinner = !adfront->SameSide (rpmid, rx2);
|
||||
root->flags.pinner = !adfront.SameSide (rpmid, rx2);
|
||||
|
||||
if (testinner)
|
||||
(*testout) << "inner = " << root->flags.pinner << " =?= "
|
||||
<< testinner(rpmid) << endl;
|
||||
|
||||
|
||||
int nf = adfront->GetNFL();
|
||||
int nf = adfront.GetNFL();
|
||||
Array<int> faceinds(nf);
|
||||
Array<Box<2>> faceboxes(nf);
|
||||
|
||||
for (int i = 0; i < nf; i++)
|
||||
{
|
||||
faceinds[i] = i;
|
||||
const FrontLine & line = adfront->GetLine(i);
|
||||
Point<3> p1 = adfront->GetPoint (line.L().I1());
|
||||
Point<3> p2 = adfront->GetPoint (line.L().I2());
|
||||
const FrontLine & line = adfront.GetLine(i);
|
||||
Point<3> p1 = adfront.GetPoint (line.L().I1());
|
||||
Point<3> p2 = adfront.GetPoint (line.L().I2());
|
||||
|
||||
faceboxes[i].Set (Point<2> (p1(0), p1(1)));
|
||||
faceboxes[i].Add (Point<2> (p2(0), p2(1)));
|
||||
@ -697,7 +674,7 @@ namespace netgen
|
||||
|
||||
void LocalH ::
|
||||
FindInnerBoxesRec2 (GradingBox * box,
|
||||
class AdFront2 * adfront,
|
||||
const class AdFront2 & adfront,
|
||||
FlatArray<Box<2>> faceboxes,
|
||||
FlatArray<int> faceinds) // , int nfinbox)
|
||||
{
|
||||
@ -743,7 +720,7 @@ namespace netgen
|
||||
|
||||
// bool sameside = adfront->SameSide (c2d, cf2d, &faceused2);
|
||||
auto sub = faceinds.Range(0, iused);
|
||||
bool sameside = adfront->SameSide (c, fc, &sub);
|
||||
bool sameside = adfront.SameSide (c, fc, &sub);
|
||||
if (sameside)
|
||||
box->flags.pinner = father->flags.pinner;
|
||||
else
|
||||
|
@ -54,6 +54,7 @@ namespace netgen
|
||||
|
||||
Point<3> PMid() const { return Point<3> (xmid[0], xmid[1], xmid[2]); }
|
||||
double H2() const { return h2; }
|
||||
double HOpt() const { return hopt; }
|
||||
|
||||
bool HasChilds() const
|
||||
{
|
||||
@ -119,12 +120,14 @@ namespace netgen
|
||||
|
||||
void CutBoundary (const Box<3> & box)
|
||||
{ CutBoundaryRec (box.PMin(), box.PMax(), root); }
|
||||
|
||||
GradingBox * Find(Point<3> p) const;
|
||||
|
||||
/// find inner boxes
|
||||
void FindInnerBoxes (class AdFront3 * adfront,
|
||||
void FindInnerBoxes (const class AdFront3 & adfront,
|
||||
int (*testinner)(const Point3d & p1));
|
||||
|
||||
void FindInnerBoxes (class AdFront2 * adfront,
|
||||
void FindInnerBoxes (const class AdFront2 & adfront,
|
||||
int (*testinner)(const Point<2> & p1));
|
||||
|
||||
|
||||
@ -166,7 +169,7 @@ namespace netgen
|
||||
|
||||
///
|
||||
void FindInnerBoxesRec2 (GradingBox * box,
|
||||
class AdFront3 * adfront,
|
||||
const class AdFront3 & adfront,
|
||||
NgArray<Box3d> & faceboxes,
|
||||
NgArray<int> & finds, int nfinbox);
|
||||
|
||||
@ -177,7 +180,7 @@ namespace netgen
|
||||
|
||||
///
|
||||
void FindInnerBoxesRec2 (GradingBox * box,
|
||||
class AdFront2 * adfront,
|
||||
const class AdFront2 & adfront,
|
||||
FlatArray<Box<2>> faceboxes,
|
||||
FlatArray<int> finds); // , int nfinbox);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,7 @@
|
||||
#include "meshtype.hpp"
|
||||
#include "localh.hpp"
|
||||
#include "topology.hpp"
|
||||
#include "paralleltop.hpp"
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
@ -42,7 +43,7 @@ namespace netgen
|
||||
class MarkedTri;
|
||||
class MarkedQuad;
|
||||
|
||||
typedef Array<MarkedTet> T_MTETS;
|
||||
typedef Array<MarkedTet,ElementIndex> T_MTETS;
|
||||
typedef NgArray<MarkedPrism> T_MPRISMS;
|
||||
typedef NgArray<MarkedIdentification> T_MIDS;
|
||||
typedef NgArray<MarkedTri> T_MTRIS;
|
||||
@ -127,18 +128,26 @@ namespace netgen
|
||||
*/
|
||||
NgArray<EdgeDescriptor> edgedecoding;
|
||||
|
||||
Array<string*> region_name_cd[4];
|
||||
Array<string*> & materials = region_name_cd[0];
|
||||
Array<string*> & bcnames = region_name_cd[1];
|
||||
Array<string*> & cd2names = region_name_cd[2];
|
||||
Array<string*> & cd3names = region_name_cd[3];
|
||||
|
||||
/*
|
||||
/// sub-domain materials
|
||||
NgArray<string*> materials;
|
||||
Array<string*> materials;
|
||||
|
||||
/// labels for boundary conditions
|
||||
NgArray<string*> bcnames;
|
||||
Array<string*> bcnames;
|
||||
|
||||
/// labels for co dim 2 bboundary conditions
|
||||
NgArray<string*> cd2names;
|
||||
Array<string*> cd2names;
|
||||
|
||||
/// labels for co dim 3 bbboundary conditions
|
||||
NgArray<string*> cd3names;
|
||||
|
||||
Array<string*> cd3names;
|
||||
*/
|
||||
|
||||
/// Periodic surface, close surface, etc. identifications
|
||||
unique_ptr<Identifications> ident;
|
||||
|
||||
@ -147,9 +156,10 @@ namespace netgen
|
||||
int numvertices;
|
||||
|
||||
/// geometric search tree for interval intersection search
|
||||
unique_ptr<BoxTree<3>> elementsearchtree;
|
||||
unique_ptr<BoxTree<3, ElementIndex>> elementsearchtree_vol;
|
||||
unique_ptr<BoxTree<3, SurfaceElementIndex>> elementsearchtree_surf;
|
||||
/// time stamp for tree
|
||||
mutable int elementsearchtreets;
|
||||
mutable size_t elementsearchtreets[4];
|
||||
|
||||
/// element -> face, element -> edge etc ...
|
||||
MeshTopology topology;
|
||||
@ -199,11 +209,11 @@ namespace netgen
|
||||
|
||||
DLL_HEADER bool PointContainedIn2DElement(const Point3d & p,
|
||||
double lami[3],
|
||||
const int element,
|
||||
SurfaceElementIndex element,
|
||||
bool consider3D = false) const;
|
||||
DLL_HEADER bool PointContainedIn3DElement(const Point3d & p,
|
||||
double lami[3],
|
||||
const int element) const;
|
||||
ElementIndex element) const;
|
||||
DLL_HEADER bool PointContainedIn3DElementOld(const Point3d & p,
|
||||
double lami[3],
|
||||
const int element) const;
|
||||
@ -222,11 +232,11 @@ namespace netgen
|
||||
// number of vertices on each refinement level:
|
||||
NgArray<size_t> level_nv;
|
||||
/// refinement hierarchy
|
||||
NgArray<PointIndices<2>,PointIndex::BASE> mlbetweennodes;
|
||||
Array<PointIndices<2>,PointIndex> mlbetweennodes;
|
||||
/// parent element of volume element
|
||||
NgArray<int> mlparentelement;
|
||||
Array<ElementIndex, ElementIndex> mlparentelement;
|
||||
/// parent element of surface element
|
||||
NgArray<int> mlparentsurfaceelement;
|
||||
Array<SurfaceElementIndex, SurfaceElementIndex> mlparentsurfaceelement;
|
||||
|
||||
|
||||
|
||||
@ -269,17 +279,19 @@ namespace netgen
|
||||
auto GetNP () const { return points.Size(); }
|
||||
|
||||
// [[deprecated("Use Point(PointIndex) instead of int !")]]
|
||||
MeshPoint & Point(int i)
|
||||
MeshPoint & Point(int i) // 1-based
|
||||
{
|
||||
// return points.Elem(i);
|
||||
return Point (PointIndex(i+PointIndex::BASE-1));
|
||||
}
|
||||
// return Point (PointIndex(i+PointIndex::BASE-1));
|
||||
return Point (PointIndex(IndexBASE<PointIndex>()+i-1));
|
||||
}
|
||||
MeshPoint & Point(PointIndex pi) { return points[pi]; }
|
||||
// [[deprecated("Use Point(PointIndex) instead of int !")]]
|
||||
const MeshPoint & Point(int i) const
|
||||
{
|
||||
// return points.Get(i);
|
||||
return Point (PointIndex(i+PointIndex::BASE-1));
|
||||
// return Point (PointIndex(i+PointIndex::BASE-1));
|
||||
return Point (PointIndex(IndexBASE<PointIndex>()+i-1));
|
||||
}
|
||||
const MeshPoint & Point(PointIndex pi) const { return points[pi]; }
|
||||
|
||||
@ -375,7 +387,7 @@ namespace netgen
|
||||
const auto & SurfaceElements() const { return surfelements; }
|
||||
auto & SurfaceElements() { return surfelements; }
|
||||
|
||||
|
||||
|
||||
DLL_HEADER void RebuildSurfaceElementLists ();
|
||||
DLL_HEADER void GetSurfaceElementsOfFace (int facenr, Array<SurfaceElementIndex> & sei) const;
|
||||
|
||||
@ -386,9 +398,9 @@ namespace netgen
|
||||
auto GetNE () const { return volelements.Size(); }
|
||||
|
||||
// [[deprecated("Use VolumeElement(ElementIndex) instead of int !")]]
|
||||
Element & VolumeElement(int i) { return volelements[i-1]; }
|
||||
Element & VolumeElement(int i) { return volelements[IndexBASE<ElementIndex>()+(i-1)]; }
|
||||
// [[deprecated("Use VolumeElement(ElementIndex) instead of int !")]]
|
||||
const Element & VolumeElement(int i) const { return volelements[i-1]; }
|
||||
const Element & VolumeElement(int i) const { return volelements[IndexBASE<ElementIndex>()+(i-1)]; }
|
||||
// [[deprecated("Use mesh[](VolumeElementIndex) instead !")]]
|
||||
Element & VolumeElement(ElementIndex i) { return volelements[i]; }
|
||||
// [[deprecated("Use mesh[](VolumeElementIndex) instead !")]]
|
||||
@ -423,7 +435,7 @@ namespace netgen
|
||||
DLL_HEADER void CalcSurfacesOfNode ();
|
||||
|
||||
/// additional (temporarily) fix points
|
||||
void FixPoints (const NgBitArray & fixpoints);
|
||||
void FixPoints (const TBitArray<PointIndex> & fixpoints);
|
||||
|
||||
/**
|
||||
finds elements without neighbour and
|
||||
@ -505,7 +517,7 @@ namespace netgen
|
||||
///
|
||||
LocalH & LocalHFunction (int layer=1) { return * lochfunc[layer-1]; }
|
||||
|
||||
shared_ptr<LocalH> GetLocalH(int layer=1) const
|
||||
shared_ptr<LocalH> & GetLocalH(int layer=1) const
|
||||
{
|
||||
if(lochfunc.Size() == 1)
|
||||
return lochfunc[0];
|
||||
@ -551,8 +563,8 @@ namespace netgen
|
||||
{
|
||||
if(!boundaryedges)
|
||||
const_cast<Mesh *>(this)->BuildBoundaryEdges();
|
||||
|
||||
INDEX_2 i2 (pi1, pi2);
|
||||
|
||||
PointIndices<2> i2(pi1, pi2);
|
||||
i2.Sort();
|
||||
return boundaryedges->Used (i2);
|
||||
}
|
||||
@ -564,14 +576,14 @@ namespace netgen
|
||||
|
||||
bool IsSegment (PointIndex pi1, PointIndex pi2) const
|
||||
{
|
||||
INDEX_2 i2 (pi1, pi2);
|
||||
PointIndices<2> i2 (pi1, pi2);
|
||||
i2.Sort();
|
||||
return segmentht->Used (i2);
|
||||
}
|
||||
|
||||
SegmentIndex SegmentNr (PointIndex pi1, PointIndex pi2) const
|
||||
{
|
||||
INDEX_2 i2 (pi1, pi2);
|
||||
PointIndices<2> i2(pi1, pi2);
|
||||
i2.Sort();
|
||||
return segmentht->Get (i2);
|
||||
}
|
||||
@ -604,13 +616,14 @@ namespace netgen
|
||||
DLL_HEADER void ImproveMesh (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY);
|
||||
|
||||
///
|
||||
void ImproveMeshJacobian (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY, const NgBitArray * usepoint = NULL);
|
||||
void ImproveMeshJacobian (const MeshingParameters & mp, OPTIMIZEGOAL goal = OPT_QUALITY,
|
||||
const TBitArray<PointIndex> * usepoint = NULL);
|
||||
///
|
||||
void ImproveMeshJacobianOnSurface (const MeshingParameters & mp,
|
||||
const NgBitArray & usepoint,
|
||||
const TBitArray<PointIndex> & usepoint,
|
||||
const NgArray< Vec<3>* > & nv,
|
||||
OPTIMIZEGOAL goal = OPT_QUALITY,
|
||||
const NgArray< NgArray<int,PointIndex::BASE>* > * idmaps = NULL);
|
||||
const NgArray< idmap_type* > * idmaps = NULL);
|
||||
/**
|
||||
free nodes in environment of openelements
|
||||
for optimiztion
|
||||
@ -659,35 +672,48 @@ namespace netgen
|
||||
|
||||
|
||||
/// build box-search tree
|
||||
DLL_HEADER void BuildElementSearchTree ();
|
||||
DLL_HEADER void BuildElementSearchTree (int dim);
|
||||
BoxTree<3, ElementIndex>* GetElementSearchTree () const
|
||||
{
|
||||
return elementsearchtree_vol.get();
|
||||
}
|
||||
|
||||
BoxTree<3, SurfaceElementIndex>* GetSurfaceElementSearchTree () const
|
||||
{
|
||||
return elementsearchtree_surf.get();
|
||||
}
|
||||
|
||||
void SetPointSearchStartElement(const int el) const {ps_startelement = el;}
|
||||
|
||||
/// gives element of point, barycentric coordinates
|
||||
DLL_HEADER int GetElementOfPoint (const netgen::Point<3> & p,
|
||||
double * lami,
|
||||
bool build_searchtree = 0,
|
||||
const int index = -1,
|
||||
const bool allowindex = true) const;
|
||||
DLL_HEADER int GetElementOfPoint (const netgen::Point<3> & p,
|
||||
double * lami,
|
||||
const NgArray<int> * const indices,
|
||||
bool build_searchtree = 0,
|
||||
const bool allowindex = true) const;
|
||||
DLL_HEADER int GetSurfaceElementOfPoint (const netgen::Point<3> & p,
|
||||
double * lami,
|
||||
bool build_searchtree = 0,
|
||||
const int index = -1,
|
||||
const bool allowindex = true) const;
|
||||
DLL_HEADER int GetSurfaceElementOfPoint (const netgen::Point<3> & p,
|
||||
double * lami,
|
||||
const NgArray<int> * const indices,
|
||||
bool build_searchtree = 0,
|
||||
const bool allowindex = true) const;
|
||||
DLL_HEADER ElementIndex
|
||||
GetElementOfPoint (const netgen::Point<3> & p,
|
||||
double * lami,
|
||||
bool build_searchtree = false,
|
||||
int index = -1,
|
||||
bool allowindex = true) const;
|
||||
DLL_HEADER ElementIndex
|
||||
GetElementOfPoint (const netgen::Point<3> & p,
|
||||
double * lami,
|
||||
std::optional<FlatArray<int>> indices,
|
||||
bool build_searchtree = 0,
|
||||
bool allowindex = true) const;
|
||||
DLL_HEADER SurfaceElementIndex
|
||||
GetSurfaceElementOfPoint (const netgen::Point<3> & p,
|
||||
double * lami,
|
||||
bool build_searchtree = false,
|
||||
int index = -1,
|
||||
bool allowindex = true) const;
|
||||
DLL_HEADER SurfaceElementIndex
|
||||
GetSurfaceElementOfPoint (const netgen::Point<3> & p,
|
||||
double * lami,
|
||||
std::optional<FlatArray<int>> indices,
|
||||
bool build_searchtree = false,
|
||||
bool allowindex = true) const;
|
||||
|
||||
/// give list of vol elements which are int the box(p1,p2)
|
||||
void GetIntersectingVolEls(const Point3d& p1, const Point3d& p2,
|
||||
NgArray<int> & locels) const;
|
||||
Array<ElementIndex> & locels) const;
|
||||
|
||||
///
|
||||
int AddFaceDescriptor(const FaceDescriptor& fd)
|
||||
@ -709,7 +735,7 @@ namespace netgen
|
||||
DLL_HEADER static string defaultmat;
|
||||
const string * GetMaterialPtr (int domnr) const // 1-based
|
||||
{
|
||||
return domnr <= materials.Size() ? materials.Get(domnr) : &defaultmat;
|
||||
return domnr <= materials.Size() ? materials[domnr-1] : &defaultmat;
|
||||
}
|
||||
|
||||
DLL_HEADER void SetNBCNames ( int nbcn );
|
||||
@ -748,7 +774,7 @@ namespace netgen
|
||||
{ return (bcnr < bcnames.Size() && bcnames[bcnr]) ? bcnames[bcnr] : &default_bc; }
|
||||
|
||||
|
||||
DLL_HEADER NgArray<string*> & GetRegionNamesCD (int codim);
|
||||
DLL_HEADER Array<string*> & GetRegionNamesCD (int codim);
|
||||
|
||||
DLL_HEADER std::string_view GetRegionName(const Segment & el) const;
|
||||
DLL_HEADER std::string_view GetRegionName(const Element2d & el) const;
|
||||
@ -757,6 +783,15 @@ namespace netgen
|
||||
std::string_view GetRegionName(SegmentIndex ei) const { return GetRegionName((*this)[ei]); }
|
||||
std::string_view GetRegionName(SurfaceElementIndex ei) const { return GetRegionName((*this)[ei]); }
|
||||
std::string_view GetRegionName(ElementIndex ei) const { return GetRegionName((*this)[ei]); }
|
||||
|
||||
DLL_HEADER static string_view defaultmat_sv;
|
||||
std::string_view GetRegionName (int dim, int domnr) // 1-based domnr
|
||||
{
|
||||
domnr--;
|
||||
auto & names = region_name_cd[dimension-dim];
|
||||
if (domnr < names.Size() && names[domnr]) return *names[domnr];
|
||||
return defaultmat_sv;
|
||||
}
|
||||
|
||||
///
|
||||
void ClearFaceDescriptors()
|
||||
@ -841,8 +876,10 @@ namespace netgen
|
||||
|
||||
|
||||
|
||||
DLL_HEADER Table<ElementIndex, PointIndex> CreatePoint2ElementTable(std::optional<BitArray> points = std::nullopt, int domain = 0) const;
|
||||
DLL_HEADER Table<ElementIndex, PointIndex> CreatePoint2ElementTable(std::optional<TBitArray<PointIndex>> points = std::nullopt, int domain = 0) const;
|
||||
// DLL_HEADER Table<SurfaceElementIndex, PointIndex> CreatePoint2SurfaceElementTable( int faceindex=0 ) const;
|
||||
DLL_HEADER Table<SurfaceElementIndex, PointIndex> CreatePoint2SurfaceElementTable( int faceindex=0 ) const;
|
||||
DLL_HEADER CompressedTable<SurfaceElementIndex, PointIndex> CreateCompressedPoint2SurfaceElementTable( int faceindex=0 ) const;
|
||||
|
||||
DLL_HEADER bool PureTrigMesh (int faceindex = 0) const;
|
||||
DLL_HEADER bool PureTetMesh () const;
|
||||
@ -953,7 +990,7 @@ namespace netgen
|
||||
/// distributes the master-mesh to local meshes
|
||||
DLL_HEADER void Distribute ();
|
||||
DLL_HEADER void Distribute (NgArray<int> & volume_weights, NgArray<int> & surface_weights,
|
||||
NgArray<int> & segment_weights);
|
||||
NgArray<int> & segment_weights);
|
||||
|
||||
|
||||
/// find connection to parallel meshes
|
||||
@ -963,20 +1000,19 @@ namespace netgen
|
||||
// void FindExchangeFaces ();
|
||||
|
||||
/// use metis to decompose master mesh
|
||||
DLL_HEADER void ParallelMetis (int nproc); // NgArray<int> & neloc );
|
||||
DLL_HEADER void ParallelMetis (int nproc);
|
||||
DLL_HEADER void ParallelMetis (NgArray<int> & volume_weights, NgArray<int> & surface_weights,
|
||||
NgArray<int> & segment_weights);
|
||||
|
||||
void PartHybridMesh (); // NgArray<int> & neloc );
|
||||
void PartDualHybridMesh (); // NgArray<int> & neloc );
|
||||
void PartDualHybridMesh2D (); // ( NgArray<int> & neloc );
|
||||
NgArray<int> & segment_weights);
|
||||
|
||||
void PartHybridMesh ();
|
||||
void PartDualHybridMesh ();
|
||||
void PartDualHybridMesh2D ();
|
||||
|
||||
/// send mesh from master to local procs
|
||||
void SendRecvMesh ();
|
||||
|
||||
/// send mesh to parallel machine, keep global mesh at master
|
||||
void SendMesh ( ) const; // Mesh * mastermesh, NgArray<int> & neloc) const;
|
||||
void SendMesh ( ) const;
|
||||
/// loads a mesh sent from master processor
|
||||
void ReceiveParallelMesh ();
|
||||
|
||||
@ -989,7 +1025,7 @@ namespace netgen
|
||||
NgArray<int> & segment_weights){ }
|
||||
#endif
|
||||
|
||||
NgArray<int> vol_partition;
|
||||
Array<int, ElementIndex> vol_partition;
|
||||
NgArray<int> surf_partition;
|
||||
NgArray<int> seg_partition;
|
||||
|
||||
@ -1030,7 +1066,7 @@ namespace netgen
|
||||
return FlatArray<T_FACE>(GetNFaces ( (*mesh)[elnr].GetType()), &faces[elnr][0]);
|
||||
}
|
||||
|
||||
|
||||
DLL_HEADER void AddFacesBetweenDomains(Mesh & mesh);
|
||||
}
|
||||
|
||||
#endif // NETGEN_MESHCLASS_HPP
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <mystdlib.h>
|
||||
#include "meshing.hpp"
|
||||
#include "debugging.hpp"
|
||||
#include "boundarylayer.hpp"
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
@ -58,6 +59,11 @@ namespace netgen
|
||||
auto num_points = mesh.GetNP();
|
||||
auto num_facedescriptors = mesh.GetNFD();
|
||||
|
||||
|
||||
constexpr PointIndex state0 = IndexBASE<PointIndex>()-1;
|
||||
constexpr PointIndex state1 = state0+1;
|
||||
constexpr PointIndex state2 = state0+2;
|
||||
|
||||
for(auto i : Range(ret))
|
||||
{
|
||||
auto & md = ret[i];
|
||||
@ -72,7 +78,7 @@ namespace netgen
|
||||
m.SetLocalH(mesh.GetLocalH());
|
||||
|
||||
ipmap[i].SetSize(num_points);
|
||||
ipmap[i] = PointIndex::INVALID;
|
||||
ipmap[i] = state0; // 0; // PointIndex::INVALID;
|
||||
m.SetDimension( mesh.GetDimension() );
|
||||
m.SetGeometry( mesh.GetGeometry() );
|
||||
|
||||
@ -85,8 +91,8 @@ namespace netgen
|
||||
{
|
||||
if(seg.domin > 0 && seg.domin == seg.domout)
|
||||
{
|
||||
ipmap[seg.domin-1][seg[0]] = 1;
|
||||
ipmap[seg.domin-1][seg[1]] = 1;
|
||||
ipmap[seg.domin-1][seg[0]] = state1; // 1;
|
||||
ipmap[seg.domin-1][seg[1]] = state1; // 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,12 +105,12 @@ namespace netgen
|
||||
|
||||
for( auto dom : {dom_in, dom_out} )
|
||||
{
|
||||
if(dom==0)
|
||||
if(dom<=0)
|
||||
continue;
|
||||
|
||||
auto & sels = ret[dom-1].mesh->SurfaceElements();
|
||||
for(auto pi : sel.PNums())
|
||||
ipmap[dom-1][pi] = 1;
|
||||
ipmap[dom-1][pi] = state1; // 1;
|
||||
sels.Append(sel);
|
||||
}
|
||||
}
|
||||
@ -113,17 +119,17 @@ namespace netgen
|
||||
for(const auto & el : mesh.VolumeElements())
|
||||
{
|
||||
auto dom = el.GetIndex();
|
||||
|
||||
|
||||
auto & els = ret[dom-1].mesh->VolumeElements();
|
||||
for(auto pi : el.PNums())
|
||||
ipmap[dom-1][pi] = 1;
|
||||
ipmap[dom-1][pi] = state1; // 1;
|
||||
els.Append(el);
|
||||
}
|
||||
|
||||
// mark locked/fixed points for each domain TODO: domain bounding box to add only relevant points?
|
||||
for(auto pi : mesh.LockedPoints())
|
||||
for(auto i : Range(ret))
|
||||
ipmap[i][pi] = 2;
|
||||
ipmap[i][pi] = state2; // 2;
|
||||
|
||||
// add used points to domain mesh, build point mapping
|
||||
for(auto i : Range(ret))
|
||||
@ -132,11 +138,11 @@ namespace netgen
|
||||
auto & pmap = ret[i].pmap;
|
||||
|
||||
for(auto pi : Range(ipmap[i]))
|
||||
if(ipmap[i][pi])
|
||||
if(ipmap[i][pi] != state0)
|
||||
{
|
||||
const auto& mp = mesh[pi];
|
||||
auto pi_new = m.AddPoint( mp, mp.GetLayer(), mp.Type() );
|
||||
if(ipmap[i][pi] == 2)
|
||||
if(ipmap[i][pi] == state2) // 2)
|
||||
mesh.AddLockedPoint(pi_new);
|
||||
ipmap[i][pi] = pi_new;
|
||||
pmap.Append( pi );
|
||||
@ -210,8 +216,8 @@ namespace netgen
|
||||
if(!have_closesurfaces)
|
||||
return;
|
||||
|
||||
NgArray<int, PointIndex::BASE> map;
|
||||
std::set<std::tuple<int,int,int>> hex_faces;
|
||||
idmap_type map;
|
||||
std::set<std::tuple<PointIndex,PointIndex,PointIndex>> hex_faces;
|
||||
for(auto identnr : Range(1,nmax+1))
|
||||
{
|
||||
if(identifications.GetType(identnr) != Identifications::CLOSESURFACES)
|
||||
@ -242,7 +248,7 @@ namespace netgen
|
||||
// insert prism/hex
|
||||
auto np = sel.GetNP();
|
||||
Element el(2*np);
|
||||
std::set<int> pis;
|
||||
std::set<PointIndex> pis;
|
||||
for(auto i : Range(np))
|
||||
{
|
||||
el[i] = sel[i];
|
||||
@ -356,7 +362,8 @@ namespace netgen
|
||||
|
||||
meshing.GenerateMesh (mesh, mpquad);
|
||||
|
||||
for (int i = oldne + 1; i <= mesh.GetNE(); i++)
|
||||
// for (int i = oldne + 1; i <= mesh.GetNE(); i++)
|
||||
for (ElementIndex i : mesh.VolumeElements().Range().Modify(oldne, 0))
|
||||
mesh.VolumeElement(i).SetIndex (domain);
|
||||
|
||||
(*testout)
|
||||
@ -372,6 +379,7 @@ namespace netgen
|
||||
if(debugparam.write_mesh_on_error) {
|
||||
md.mesh->Save("open_quads_starting_mesh_"+ToString(md.domain)+".vol.gz");
|
||||
GetOpenElements(*md.mesh, md.domain)->Save("open_quads_rest_" + ToString(md.domain)+".vol.gz");
|
||||
GetOpenElements(*md.mesh, md.domain, true)->Save("open_quads_rest_" + ToString(md.domain)+"_only_quads.vol.gz");
|
||||
}
|
||||
PrintSysError ("mesh has still open quads");
|
||||
throw NgException ("Stop meshing since too many attempts");
|
||||
@ -396,34 +404,35 @@ namespace netgen
|
||||
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
|
||||
md.meshing->AddBoundaryElement (mesh.OpenElement(i));
|
||||
|
||||
if (mp.delaunay && mesh.GetNOpenElements())
|
||||
{
|
||||
if (mp.delaunay && mesh.GetNOpenElements())
|
||||
{
|
||||
int oldne = mesh.GetNE();
|
||||
|
||||
md.meshing->Delaunay (mesh, domain, mp);
|
||||
|
||||
for (int i = oldne + 1; i <= mesh.GetNE(); i++)
|
||||
// for (int i = oldne + 1; i <= mesh.GetNE(); i++)
|
||||
for (ElementIndex i : mesh.VolumeElements().Range().Modify(oldne, 0))
|
||||
mesh.VolumeElement(i).SetIndex (domain);
|
||||
|
||||
PrintMessage (3, mesh.GetNP(), " points, ",
|
||||
mesh.GetNE(), " elements");
|
||||
mesh.FindOpenElements(domain);
|
||||
}
|
||||
}
|
||||
|
||||
Box<3> domain_bbox( Box<3>::EMPTY_BOX );
|
||||
Box<3> domain_bbox( Box<3>::EMPTY_BOX );
|
||||
|
||||
for (auto & sel : mesh.SurfaceElements())
|
||||
for (auto & sel : mesh.SurfaceElements())
|
||||
{
|
||||
if (sel.IsDeleted() ) continue;
|
||||
|
||||
for (auto pi : sel.PNums())
|
||||
domain_bbox.Add (mesh[pi]);
|
||||
}
|
||||
domain_bbox.Increase (0.01 * domain_bbox.Diam());
|
||||
domain_bbox.Increase (0.01 * domain_bbox.Diam());
|
||||
|
||||
int cntsteps = 0;
|
||||
int meshed;
|
||||
if (mesh.GetNOpenElements())
|
||||
int cntsteps = 0;
|
||||
int meshed;
|
||||
if (mesh.GetNOpenElements())
|
||||
do
|
||||
{
|
||||
if (multithread.terminate)
|
||||
@ -431,7 +440,7 @@ namespace netgen
|
||||
|
||||
mesh.FindOpenElements(domain);
|
||||
PrintMessage (5, mesh.GetNOpenElements(), " open faces");
|
||||
// GetOpenElements( mesh, domain )->Save("open_"+ToString(cntsteps)+".vol");
|
||||
// GetOpenElements( mesh, domain )->Save("open_"+ToString(domain)+"_"+ToString(cntsteps)+".vol");
|
||||
cntsteps++;
|
||||
|
||||
|
||||
@ -455,14 +464,14 @@ namespace netgen
|
||||
|
||||
for (PointIndex pi : mesh.Points().Range())
|
||||
if (domain_bbox.IsIn (mesh[pi]))
|
||||
glob2loc[pi] = meshing.AddPoint (mesh[pi], pi);
|
||||
glob2loc[pi] = meshing.AddPoint (mesh[pi], pi);
|
||||
|
||||
for (auto sel : mesh.OpenElements() )
|
||||
{
|
||||
for(auto & pi : sel.PNums())
|
||||
for (auto sel : mesh.OpenElements())
|
||||
{
|
||||
for(auto & pi : sel.PNums())
|
||||
pi = glob2loc[pi];
|
||||
meshing.AddBoundaryElement (sel);
|
||||
}
|
||||
meshing.AddBoundaryElement (sel);
|
||||
}
|
||||
|
||||
int oldne = mesh.GetNE();
|
||||
|
||||
@ -470,8 +479,8 @@ namespace netgen
|
||||
mp.sloppy = 5;
|
||||
meshing.GenerateMesh (mesh, mp);
|
||||
|
||||
for (ElementIndex ei = oldne; ei < mesh.GetNE(); ei++)
|
||||
mesh[ei].SetIndex (domain);
|
||||
for (auto & el : mesh.VolumeElements().Range(oldne, END))
|
||||
el.SetIndex (domain);
|
||||
|
||||
|
||||
mesh.CalcSurfacesOfNode();
|
||||
@ -515,24 +524,22 @@ namespace netgen
|
||||
PrintMessage (1, "Success !");
|
||||
}
|
||||
}
|
||||
while (!meshed);
|
||||
|
||||
{
|
||||
PrintMessage (3, "Check subdomain ", domain, " / ", mesh.GetNDomains());
|
||||
while (!meshed);
|
||||
|
||||
mesh.FindOpenElements(domain);
|
||||
PrintMessage (3, "Check subdomain ", domain, " / ", mesh.GetNDomains());
|
||||
|
||||
bool res = (mesh.CheckConsistentBoundary() != 0);
|
||||
if (res)
|
||||
{
|
||||
if(debugparam.write_mesh_on_error)
|
||||
md.mesh->Save("inconsistent_surface_domain_"+ToString(md.domain)+".vol.gz");
|
||||
PrintError ("Surface mesh not consistent");
|
||||
throw NgException ("Stop meshing since surface mesh not consistent");
|
||||
}
|
||||
}
|
||||
RemoveIllegalElements (mesh, domain);
|
||||
ConformToFreeSegments (mesh, domain);
|
||||
mesh.FindOpenElements(domain);
|
||||
|
||||
bool res = (mesh.CheckConsistentBoundary() != 0);
|
||||
if (res)
|
||||
{
|
||||
if(debugparam.write_mesh_on_error)
|
||||
md.mesh->Save("inconsistent_surface_domain_"+ToString(md.domain)+".vol.gz");
|
||||
PrintError ("Surface mesh not consistent");
|
||||
throw NgException ("Stop meshing since surface mesh not consistent");
|
||||
}
|
||||
RemoveIllegalElements (mesh, domain);
|
||||
ConformToFreeSegments (mesh, domain);
|
||||
}
|
||||
|
||||
void MergeMeshes( Mesh & mesh, Array<MeshingData> & md )
|
||||
@ -557,7 +564,7 @@ namespace netgen
|
||||
auto first_new_pi = m_.pmap.Range().Next();
|
||||
auto & m = *m_.mesh;
|
||||
Array<PointIndex, PointIndex> pmap(m.Points().Size());
|
||||
for(auto pi : Range(PointIndex(PointIndex::BASE), first_new_pi))
|
||||
for(auto pi : Range(IndexBASE<PointIndex>(), first_new_pi))
|
||||
pmap[pi] = m_.pmap[pi];
|
||||
|
||||
for (auto pi : Range(first_new_pi, m.Points().Range().Next()))
|
||||
@ -571,8 +578,10 @@ namespace netgen
|
||||
el.SetIndex(m_.domain);
|
||||
mesh.AddVolumeElement(el);
|
||||
}
|
||||
for(const auto& [p1p2, dummy] : m.GetIdentifications().GetIdentifiedPoints())
|
||||
mesh.GetIdentifications().Add(pmap[p1p2[0]], pmap[p1p2[1]], p1p2[2]);
|
||||
// for(const auto& [p1p2, dummy] : m.GetIdentifications().GetIdentifiedPoints())
|
||||
// mesh.GetIdentifications().Add(pmap[p1p2[0]], pmap[p1p2[1]], p1p2[2]);
|
||||
for(const auto& [p1p2, dummy] : m.GetIdentifications().GetIdentifiedPoints())
|
||||
mesh.GetIdentifications().Add( pmap[ get<0>(p1p2)[0] ], pmap[ get<0>(p1p2)[1]] , get<1>(p1p2) );
|
||||
for(auto i : Range(m.GetIdentifications().GetMaxNr()))
|
||||
{
|
||||
mesh.GetIdentifications().SetType(i+1, m.GetIdentifications().GetType(i+1));
|
||||
@ -589,7 +598,7 @@ namespace netgen
|
||||
for(auto & m : meshes)
|
||||
{
|
||||
Array<PointIndex, PointIndex> pmap(m.Points().Size());
|
||||
for(auto pi : Range(PointIndex(PointIndex::BASE), first_new_pi))
|
||||
for(auto pi : Range(IndexBASE<PointIndex>(), first_new_pi))
|
||||
pmap[pi] = pi;
|
||||
|
||||
for (auto pi : Range(first_new_pi, m.Points().Range().Next()))
|
||||
@ -611,12 +620,18 @@ namespace netgen
|
||||
static Timer t("MeshVolume"); RegionTimer reg(t);
|
||||
|
||||
mesh3d.Compress();
|
||||
for (auto bl : mp.boundary_layers)
|
||||
GenerateBoundaryLayer(mesh3d, bl);
|
||||
|
||||
if(mesh3d.GetNDomains()==0)
|
||||
return MESHING3_OK;
|
||||
|
||||
auto geo = mesh3d.GetGeometry();
|
||||
for (auto i : Range(std::min(geo->GetNSolids(), (size_t)mesh3d.GetNDomains())))
|
||||
if (auto name = geo->GetSolid(i).properties.name)
|
||||
mesh3d.SetMaterial (i+1, *name);
|
||||
|
||||
for (auto bl : mp.boundary_layers)
|
||||
GenerateBoundaryLayer(mesh3d, bl);
|
||||
|
||||
if (!mesh3d.HasLocalHFunction())
|
||||
mesh3d.CalcLocalH(mp.grading);
|
||||
|
||||
@ -641,6 +656,8 @@ namespace netgen
|
||||
MeshDomain(md[i]);
|
||||
}
|
||||
catch (const Exception & e) {
|
||||
if(debugparam.write_mesh_on_error)
|
||||
md[i].mesh->Save("meshing_error_domain_"+ToString(md[i].domain)+".vol.gz");
|
||||
cerr << "Meshing of domain " << i+1 << " failed with error: " << e.what() << endl;
|
||||
throw e;
|
||||
}
|
||||
@ -756,22 +773,20 @@ namespace netgen
|
||||
auto geo = mesh.GetGeometry();
|
||||
if(!geo) return;
|
||||
auto n_solids = geo->GetNSolids();
|
||||
if(!n_solids) return;
|
||||
if(n_solids < domain) return;
|
||||
if(geo->GetSolid(domain-1).free_edges.Size() == 0)
|
||||
return;
|
||||
|
||||
Segment bad_seg;
|
||||
Array<Segment> free_segs;
|
||||
for (auto seg : mesh.LineSegments())
|
||||
if(seg.domin == domain && seg.domout == domain)
|
||||
free_segs.Append(seg);
|
||||
Array<SegmentIndex> free_segs;
|
||||
for (auto segi : Range(mesh.LineSegments()))
|
||||
if(mesh[segi].domin == domain && mesh[segi].domout == domain)
|
||||
free_segs.Append(segi);
|
||||
|
||||
auto num_nonconforming = [&] () {
|
||||
size_t count = 0;
|
||||
auto get_nonconforming = [&] (const auto & p2el) {
|
||||
Array<SegmentIndex> nonconforming;
|
||||
|
||||
auto p2el = mesh.CreatePoint2ElementTable();
|
||||
|
||||
for (auto seg : free_segs) {
|
||||
for (auto segi : free_segs) {
|
||||
auto seg = mesh[segi];
|
||||
|
||||
auto has_p0 = p2el[seg[0]];
|
||||
bool has_both = false;
|
||||
@ -781,34 +796,136 @@ namespace netgen
|
||||
has_both = true;
|
||||
}
|
||||
|
||||
if(!has_both) {
|
||||
bad_seg = seg;
|
||||
count++;
|
||||
}
|
||||
if(!has_both)
|
||||
nonconforming.Append(segi);
|
||||
}
|
||||
return count;
|
||||
return nonconforming;
|
||||
};
|
||||
|
||||
for (auto i : Range(5)) {
|
||||
auto num_bad_segs = num_nonconforming();
|
||||
PrintMessage(1, "Non-conforming free segments in domain ", domain, ": ", num_bad_segs);
|
||||
auto split_segment = [&] (SegmentIndex segi, const auto & p2el) {
|
||||
auto seg = mesh[segi];
|
||||
auto p_new = Center(mesh[seg[0]], mesh[seg[1]]);
|
||||
double lam[3];
|
||||
ElementIndex ei_start = mesh.GetElementOfPoint(p_new, lam, false, domain);
|
||||
|
||||
if(!ei_start.IsValid()) {
|
||||
PrintMessage(1, "Could not find volume element with new point");
|
||||
return;
|
||||
}
|
||||
|
||||
if(mesh[ei_start].IsDeleted())
|
||||
return;
|
||||
|
||||
double max_inside = -1.;
|
||||
ElementIndex ei_max_inside = ElementIndex::INVALID;
|
||||
|
||||
// search for adjacent volume element, where the new point is "most inside",
|
||||
// i.e. the minimal barycentric coordinate is maximal
|
||||
for(auto pi : mesh[ei_start].PNums()) {
|
||||
for(auto ei1 : p2el[pi]) {
|
||||
double lam[3];
|
||||
|
||||
if(mesh[ei1].IsDeleted())
|
||||
return;
|
||||
if(!mesh.PointContainedIn3DElement(p_new, lam, ei1))
|
||||
continue;
|
||||
|
||||
double inside = min(min(lam[0], lam[1]), min(lam[2], 1.0-lam[0]-lam[1]));
|
||||
if(inside > max_inside) {
|
||||
max_inside = inside;
|
||||
ei_max_inside = ei1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(max_inside < 1e-4) {
|
||||
PrintMessage(3, "Could not find volume element with new point inside");
|
||||
return;
|
||||
}
|
||||
|
||||
// split tet into 4 new tests, with new point inside
|
||||
auto el = mesh[ei_max_inside];
|
||||
if(el.GetNP() != 4) {
|
||||
PrintMessage(3, "Only tet elements are supported to split around free segments");
|
||||
return;
|
||||
}
|
||||
|
||||
if(el.IsDeleted()) {
|
||||
PrintMessage(3,"Element to split is already deleted");
|
||||
return;
|
||||
}
|
||||
|
||||
auto pi_new = mesh.AddPoint(p_new);
|
||||
auto seg_new0 = seg;
|
||||
auto seg_new1 = seg;
|
||||
seg_new0[1] = pi_new;
|
||||
seg_new1[0] = pi_new;
|
||||
|
||||
mesh[segi][0] = PointIndex::INVALID;
|
||||
mesh.AddSegment(seg_new0);
|
||||
mesh.AddSegment(seg_new1);
|
||||
|
||||
|
||||
int pmap[4][4] = {
|
||||
{0,1,2,4},
|
||||
{1,3,2,4},
|
||||
{0,2,3,4},
|
||||
{0,3,1,4}
|
||||
};
|
||||
|
||||
PointIndex pis[5] = {el[0], el[1], el[2], el[3], pi_new};
|
||||
|
||||
for (auto i : Range(4)) {
|
||||
Element el_new;
|
||||
el_new = el;
|
||||
for (auto j : Range(4))
|
||||
el_new[j] = pis[pmap[i][j]];
|
||||
mesh.AddVolumeElement(el_new);
|
||||
}
|
||||
mesh[ei_max_inside].Delete();
|
||||
};
|
||||
|
||||
size_t last_num_bad_segs = -1;
|
||||
for ([[maybe_unused]] auto i : Range(10)) {
|
||||
auto p2el = mesh.CreatePoint2ElementTable();
|
||||
|
||||
auto bad_segs = get_nonconforming(p2el);
|
||||
auto num_bad_segs = bad_segs.Size();
|
||||
|
||||
if(num_bad_segs == 0)
|
||||
return;
|
||||
|
||||
PrintMessage(3, "Non-conforming free segments in domain ", domain, ": ", num_bad_segs);
|
||||
|
||||
if(i>=5 || num_bad_segs != last_num_bad_segs) {
|
||||
for(auto i : bad_segs)
|
||||
split_segment(i, p2el);
|
||||
mesh.Compress();
|
||||
}
|
||||
|
||||
MeshingParameters dummymp;
|
||||
MeshOptimize3d optmesh(mesh, dummymp, OPT_CONFORM);
|
||||
|
||||
for (auto i : Range(3)) {
|
||||
optmesh.SwapImprove2 ();
|
||||
for ([[maybe_unused]] auto i : Range(3)) {
|
||||
optmesh.ImproveMesh();
|
||||
optmesh.SwapImprove2(true);
|
||||
optmesh.ImproveMesh();
|
||||
optmesh.SwapImprove();
|
||||
optmesh.ImproveMesh();
|
||||
optmesh.CombineImprove();
|
||||
}
|
||||
last_num_bad_segs = num_bad_segs;
|
||||
}
|
||||
|
||||
if(debugparam.write_mesh_on_error)
|
||||
mesh.Save("free_segment_not_conformed_dom_"+ToString(domain)+"_seg_"+ToString(bad_seg[0])+"_"+ToString(bad_seg[1])+".vol.gz");
|
||||
throw Exception("Segment not resolved in volume mesh in domain " + ToString(domain)+ ", seg: " + ToString(bad_seg));
|
||||
auto p2el = mesh.CreatePoint2ElementTable();
|
||||
auto bad_segs = get_nonconforming(p2el);
|
||||
|
||||
if(bad_segs.Size() > 0) {
|
||||
auto bad_seg = mesh[bad_segs[0]];
|
||||
if(debugparam.write_mesh_on_error)
|
||||
mesh.Save("free_segment_not_conformed_dom_"+ToString(domain)+"_seg_"+ToString(bad_seg[0])+"_"+ToString(bad_seg[1])+".vol.gz");
|
||||
throw Exception("Segment not resolved in volume mesh in domain " + ToString(domain)+ ", seg: " + ToString(bad_seg));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,8 +1,6 @@
|
||||
#ifndef FILE_MESHING
|
||||
#define FILE_MESHING
|
||||
|
||||
|
||||
|
||||
#include "../include/myadt.hpp"
|
||||
#include "../include/gprim.hpp"
|
||||
#include "../include/linalg.hpp"
|
||||
@ -19,12 +17,12 @@ namespace netgen
|
||||
}
|
||||
|
||||
|
||||
#include "msghandler.hpp"
|
||||
#include "meshtype.hpp"
|
||||
#include "localh.hpp"
|
||||
#include "topology.hpp"
|
||||
#include "meshclass.hpp"
|
||||
#include "global.hpp"
|
||||
// #include "msghandler.hpp"
|
||||
// #include "meshtype.hpp"
|
||||
// #include "localh.hpp"
|
||||
// #include "topology.hpp"
|
||||
// #include "meshclass.hpp"
|
||||
// #include "global.hpp"
|
||||
|
||||
#include "meshtool.hpp"
|
||||
|
||||
@ -53,7 +51,6 @@ namespace netgen
|
||||
#include "bisect.hpp"
|
||||
#include "hprefinement.hpp"
|
||||
|
||||
#include "boundarylayer.hpp"
|
||||
#include "specials.hpp"
|
||||
#include "validate.hpp"
|
||||
#include "basegeom.hpp"
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include <mystdlib.h>
|
||||
#include "meshing.hpp"
|
||||
|
||||
#include "meshing2.hpp"
|
||||
|
||||
#include "visual_interface.hpp"
|
||||
|
||||
namespace netgen
|
||||
@ -246,8 +248,8 @@ namespace netgen
|
||||
{
|
||||
static Timer timer("surface meshing"); RegionTimer reg(timer);
|
||||
|
||||
static int timer1 = NgProfiler::CreateTimer ("surface meshing1");
|
||||
static int timer2 = NgProfiler::CreateTimer ("surface meshing2");
|
||||
static Timer timer1("surface meshing1");
|
||||
static Timer timer2("surface meshing2");
|
||||
static int timer3 = NgProfiler::CreateTimer ("surface meshing3");
|
||||
|
||||
static int ts1 = NgProfiler::CreateTimer ("surface meshing start 1");
|
||||
@ -408,7 +410,7 @@ namespace netgen
|
||||
RegionTimer rloop(tloop);
|
||||
while (!adfront.Empty() && !multithread.terminate)
|
||||
{
|
||||
NgProfiler::RegionTimer reg1 (timer1);
|
||||
// RegionTimer reg1 (timer1);
|
||||
|
||||
if (multithread.terminate)
|
||||
throw NgException ("Meshing stopped");
|
||||
@ -487,8 +489,7 @@ namespace netgen
|
||||
pindex, lindex, 2*hinner);
|
||||
// tgetlocals.Stop();
|
||||
|
||||
NgProfiler::RegionTimer reg2 (timer2);
|
||||
|
||||
// RegionTimer reg2 (timer2);
|
||||
//(*testout) << "h for locals: " << 2*hinner << endl;
|
||||
|
||||
|
||||
@ -541,8 +542,8 @@ namespace netgen
|
||||
|
||||
// problem recognition !
|
||||
if (found &&
|
||||
(gpi1 < illegalpoint.Size()+PointIndex::BASE) &&
|
||||
(gpi2 < illegalpoint.Size()+PointIndex::BASE) )
|
||||
(gpi1 < illegalpoint.Size()+IndexBASE<PointIndex>()) &&
|
||||
(gpi2 < illegalpoint.Size()+IndexBASE<PointIndex>()) )
|
||||
{
|
||||
if (illegalpoint[gpi1] || illegalpoint[gpi2])
|
||||
found = 0;
|
||||
@ -557,7 +558,7 @@ namespace netgen
|
||||
oldnl = loclines.Size();
|
||||
|
||||
UpdateVisSurfaceMeshData(oldnl);
|
||||
|
||||
|
||||
if (debugflag)
|
||||
(*testout) << "define new transformation" << endl;
|
||||
|
||||
@ -574,15 +575,16 @@ namespace netgen
|
||||
*testout << "3d points: " << endl << locpoints << endl;
|
||||
}
|
||||
|
||||
|
||||
for (size_t i = 0; i < locpoints.Size(); i++)
|
||||
{
|
||||
Point<2> pp;
|
||||
TransformToPlain (locpoints[i], mpgeominfo[i],
|
||||
pp, h, plainzones[i]);
|
||||
plainpoints[i] = pp;
|
||||
}
|
||||
|
||||
{
|
||||
// RegionTimer reg2 (timer2);
|
||||
for (size_t i = 0; i < locpoints.Size(); i++)
|
||||
{
|
||||
Point<2> pp;
|
||||
TransformToPlain (locpoints[i], mpgeominfo[i],
|
||||
pp, h, plainzones[i]);
|
||||
plainpoints[i] = pp;
|
||||
}
|
||||
}
|
||||
/*
|
||||
for (int i = 1; i <= locpoints.Size(); i++)
|
||||
{
|
||||
@ -633,7 +635,6 @@ namespace netgen
|
||||
// plainpoints.Elem(i) = Point2d (1e4, 1e4);
|
||||
*/
|
||||
|
||||
|
||||
|
||||
for (int i = 2; i <= loclines.Size(); i++) // don't remove first line
|
||||
{
|
||||
@ -858,7 +859,8 @@ namespace netgen
|
||||
const Element2d & el = locelements.Get(i);
|
||||
|
||||
for (int j = 1; j <= el.GetNP(); j++)
|
||||
if (el.PNum(j) <= oldnp && pindex.Get(el.PNum(j)) == -1)
|
||||
// if (el.PNum(j) <= oldnp && pindex.Get(el.PNum(j)) == -1)
|
||||
if (el.PNum(j) < IndexBASE<PointIndex>()+oldnp && pindex.Get(el.PNum(j)) == -1)
|
||||
{
|
||||
found = 0;
|
||||
PrintSysError ("meshing2, index missing");
|
||||
|
@ -7,6 +7,11 @@
|
||||
/* Date: 01. Okt. 95 */
|
||||
/**************************************************************************/
|
||||
|
||||
|
||||
#include "adfront2.hpp"
|
||||
#include "ruler2.hpp"
|
||||
#include "basegeom.hpp"
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include <mystdlib.h>
|
||||
#include "meshing.hpp"
|
||||
|
||||
#include "meshing3.hpp"
|
||||
#include "findip.hpp"
|
||||
#include "findip2.hpp"
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
@ -9,8 +12,6 @@ double minwithoutother;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
MeshingStat3d :: MeshingStat3d ()
|
||||
{
|
||||
cntsucc = cnttrials = cntelem = qualclass = 0;
|
||||
@ -24,13 +25,14 @@ Meshing3 :: Meshing3 (const string & rulefilename)
|
||||
tolfak = 1;
|
||||
|
||||
LoadRules (rulefilename.c_str(), NULL);
|
||||
adfront = new AdFront3;
|
||||
adfront = make_unique<AdFront3>();
|
||||
|
||||
problems.SetSize (rules.Size());
|
||||
foundmap.SetSize (rules.Size());
|
||||
canuse.SetSize (rules.Size());
|
||||
ruleused.SetSize (rules.Size());
|
||||
|
||||
/*
|
||||
for (int i = 1; i <= rules.Size(); i++)
|
||||
{
|
||||
problems.Elem(i) = new char[255];
|
||||
@ -38,6 +40,11 @@ Meshing3 :: Meshing3 (const string & rulefilename)
|
||||
canuse.Elem(i) = 0;
|
||||
ruleused.Elem(i) = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
foundmap = 0;
|
||||
canuse = 0;
|
||||
ruleused = 0;
|
||||
}
|
||||
|
||||
|
||||
@ -46,13 +53,14 @@ Meshing3 :: Meshing3 (const char ** rulep)
|
||||
tolfak = 1;
|
||||
|
||||
LoadRules (NULL, rulep);
|
||||
adfront = new AdFront3;
|
||||
adfront = make_unique<AdFront3>();
|
||||
|
||||
problems.SetSize (rules.Size());
|
||||
foundmap.SetSize (rules.Size());
|
||||
canuse.SetSize (rules.Size());
|
||||
ruleused.SetSize (rules.Size());
|
||||
|
||||
/*
|
||||
for (int i = 0; i < rules.Size(); i++)
|
||||
{
|
||||
problems[i] = new char[255];
|
||||
@ -60,16 +68,22 @@ Meshing3 :: Meshing3 (const char ** rulep)
|
||||
canuse[i] = 0;
|
||||
ruleused[i] = 0;
|
||||
}
|
||||
*/
|
||||
foundmap = 0;
|
||||
canuse = 0;
|
||||
ruleused = 0;
|
||||
}
|
||||
|
||||
Meshing3 :: ~Meshing3 ()
|
||||
{
|
||||
delete adfront;
|
||||
// delete adfront;
|
||||
/*
|
||||
for (int i = 0; i < rules.Size(); i++)
|
||||
{
|
||||
delete [] problems[i];
|
||||
delete rules[i];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@ -181,21 +195,21 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
// NgProfiler::RegionTimer reg (meshing3_timer);
|
||||
|
||||
|
||||
NgArray<Point3d, PointIndex::BASE> locpoints; // local points
|
||||
NgArray<MiniElement2d> locfaces; // local faces
|
||||
NgArray<PointIndex, PointIndex::BASE> pindex; // mapping from local to front point numbering
|
||||
NgArray<int, PointIndex::BASE> allowpoint; // point is allowed ?
|
||||
NgArray<INDEX> findex; // mapping from local to front face numbering
|
||||
Array<Point3d, PointIndex> locpoints; // local points
|
||||
Array<MiniElement2d> locfaces; // local faces
|
||||
Array<PointIndex, PointIndex> pindex; // mapping from local to front point numbering
|
||||
Array<int, PointIndex> allowpoint; // point is allowed (0/1/2) ?
|
||||
Array<INDEX> findex; // mapping from local to front face numbering
|
||||
//INDEX_2_HASHTABLE<int> connectedpairs(100); // connecgted pairs for prism meshing
|
||||
|
||||
NgArray<Point3d, PointIndex::BASE> plainpoints; // points in reference coordinates
|
||||
NgArray<int> delpoints, delfaces; // points and lines to be deleted
|
||||
Array<Point3d, PointIndex> plainpoints; // points in reference coordinates
|
||||
// NgArray<int> delpoints; // points to be deleted
|
||||
NgArray<int> delfaces; // lines to be deleted
|
||||
NgArray<Element> locelements; // new generated elements
|
||||
|
||||
int j, oldnp, oldnf;
|
||||
int found;
|
||||
referencetransform trans;
|
||||
int rotind;
|
||||
Point3d inp;
|
||||
float err;
|
||||
|
||||
@ -211,10 +225,10 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
|
||||
|
||||
// for star-shaped domain meshing
|
||||
NgArray<MeshPoint, PointIndex::BASE> grouppoints;
|
||||
NgArray<MiniElement2d> groupfaces;
|
||||
NgArray<PointIndex, PointIndex::BASE> grouppindex;
|
||||
NgArray<INDEX> groupfindex;
|
||||
Array<MeshPoint, PointIndex> grouppoints;
|
||||
Array<MiniElement2d> groupfaces;
|
||||
Array<PointIndex, PointIndex> grouppindex;
|
||||
Array<INDEX> groupfindex;
|
||||
|
||||
|
||||
float minerr;
|
||||
@ -313,7 +327,7 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
|
||||
if (loktestmode)
|
||||
{
|
||||
(*testout) << "baseel = " << baseelem << ", ind = " << findex.Get(1) << endl;
|
||||
(*testout) << "baseel = " << baseelem << ", ind = " << findex[0] << endl;
|
||||
int pi1 = pindex[locfaces[0].PNum(1)];
|
||||
int pi2 = pindex[locfaces[0].PNum(2)];
|
||||
int pi3 = pindex[locfaces[0].PNum(3)];
|
||||
@ -342,10 +356,11 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
|
||||
allowpoint.SetSize(locpoints.Size());
|
||||
if (uselocalh && stat.qualclass <= 3)
|
||||
for(int i = 1; i <= allowpoint.Size(); i++)
|
||||
//for(int i = 1; i <= allowpoint.Size(); i++)
|
||||
for(auto i : allowpoint.Range())
|
||||
{
|
||||
allowpoint.Elem(i) =
|
||||
(mesh.GetH (locpoints.Get(i)) > 0.4 * hshould / mp.sloppy) ? 2 : 1;
|
||||
allowpoint[i] =
|
||||
(mesh.GetH (locpoints[i]) > 0.4 * hshould / mp.sloppy) ? 2 : 1;
|
||||
}
|
||||
else
|
||||
allowpoint = 2;
|
||||
@ -367,41 +382,41 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
grouppindex, groupfindex);
|
||||
|
||||
bool onlytri = 1;
|
||||
for (auto i : groupfaces.Range())
|
||||
if (groupfaces[i].GetNP() != 3)
|
||||
onlytri = 0;
|
||||
|
||||
for (auto & f : groupfaces)
|
||||
if (f.GetNP() != 3)
|
||||
onlytri = 0;
|
||||
|
||||
|
||||
if (onlytri && groupfaces.Size() <= 20 + 2*stat.qualclass &&
|
||||
FindInnerPoint (grouppoints, groupfaces, inp) &&
|
||||
!adfront->PointInsideGroup(grouppindex, groupfaces))
|
||||
{
|
||||
(*testout) << "inner point found" << endl;
|
||||
|
||||
for(int i = 1; i <= groupfaces.Size(); i++)
|
||||
adfront -> DeleteFace (groupfindex.Get(i));
|
||||
|
||||
for(int i = 0; i < groupfaces.Size(); i++)
|
||||
adfront -> DeleteFace (groupfindex[i]);
|
||||
|
||||
for(int i = 1; i <= groupfaces.Size(); i++)
|
||||
for (j = 1; j <= locfaces.Size(); j++)
|
||||
if (findex.Get(j) == groupfindex.Get(i))
|
||||
if (findex[j-1] == groupfindex[i-1])
|
||||
delfaces.Append (j);
|
||||
|
||||
|
||||
delfaces.SetSize (0);
|
||||
|
||||
INDEX npi;
|
||||
Element newel(TET);
|
||||
|
||||
npi = mesh.AddPoint (inp);
|
||||
PointIndex npi = mesh.AddPoint (inp);
|
||||
newel.SetNP(4);
|
||||
newel.PNum(4) = npi;
|
||||
|
||||
for(int i = 1; i <= groupfaces.Size(); i++)
|
||||
for(int i = 0; i < groupfaces.Size(); i++)
|
||||
{
|
||||
for (j = 1; j <= 3; j++)
|
||||
{
|
||||
newel.PNum(j) =
|
||||
adfront->GetGlobalIndex
|
||||
(grouppindex.Get(groupfaces.Get(i).PNum(j)));
|
||||
(grouppindex[groupfaces[i].PNum(j)]);
|
||||
}
|
||||
mesh.AddVolumeElement (newel);
|
||||
}
|
||||
@ -436,7 +451,7 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
|
||||
bool impossible = 1;
|
||||
|
||||
for (rotind = 1; rotind <= locfaces[0].GetNP(); rotind++)
|
||||
for (int rotind = 1; rotind <= locfaces[0].GetNP(); rotind++)
|
||||
{
|
||||
// set transformatino to reference coordinates
|
||||
|
||||
@ -469,12 +484,12 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
if (stat.cnttrials % 100 == 0)
|
||||
{
|
||||
(*testout) << "\n";
|
||||
for(int i = 1; i <= canuse.Size(); i++)
|
||||
{
|
||||
(*testout) << foundmap.Get(i) << "/"
|
||||
<< canuse.Get(i) << "/"
|
||||
<< ruleused.Get(i) << " map/can/use rule " << rules.Get(i)->Name() << "\n";
|
||||
}
|
||||
for(int i : canuse.Range())
|
||||
{
|
||||
(*testout) << foundmap[i] << "/"
|
||||
<< canuse[i] << "/"
|
||||
<< ruleused[i] << " map/can/use rule " << rules[i]->Name() << "\n";
|
||||
}
|
||||
(*testout) << endl;
|
||||
}
|
||||
|
||||
@ -505,9 +520,13 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
if (found) stat.cntsucc++;
|
||||
|
||||
locpoints.SetSize (plainpoints.Size());
|
||||
/*
|
||||
for (int i = oldnp+1; i <= plainpoints.Size(); i++)
|
||||
trans.FromPlain (plainpoints.Elem(i), locpoints.Elem(i));
|
||||
|
||||
*/
|
||||
for (auto i : plainpoints.Range().Modify(oldnp,0))
|
||||
trans.FromPlain (plainpoints[i], locpoints[i]);
|
||||
|
||||
|
||||
|
||||
// avoid meshing from large to small mesh-size
|
||||
@ -541,8 +560,8 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
|
||||
|
||||
if (found)
|
||||
ruleused.Elem(found)++;
|
||||
|
||||
ruleused[found-1]++;
|
||||
|
||||
|
||||
// plotstat->Plot(stat);
|
||||
|
||||
@ -565,14 +584,15 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
if (testmode)
|
||||
{
|
||||
(*testout) << "found is active, 3" << endl;
|
||||
for(int i = 1; i <= plainpoints.Size(); i++)
|
||||
//for(int i = 1; i <= plainpoints.Size(); i++)
|
||||
for(auto i : plainpoints.Range())
|
||||
{
|
||||
(*testout) << "p";
|
||||
if (i <= pindex.Size())
|
||||
(*testout) << pindex.Get(i) << ": ";
|
||||
if (i < pindex.Range().Next())
|
||||
(*testout) << pindex[i] << ": ";
|
||||
else
|
||||
(*testout) << "new: ";
|
||||
(*testout) << plainpoints.Get(i) << endl;
|
||||
(*testout) << plainpoints[i] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -582,20 +602,24 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
minerr = err;
|
||||
|
||||
tempnewpoints.SetSize (0);
|
||||
for(int i = oldnp+1; i <= locpoints.Size(); i++)
|
||||
tempnewpoints.Append (locpoints.Get(i));
|
||||
// for(int i = oldnp+1; i <= locpoints.Size(); i++)
|
||||
for (auto i : locpoints.Range().Modify(oldnp,0))
|
||||
tempnewpoints.Append (locpoints[i]);
|
||||
|
||||
tempnewfaces.SetSize (0);
|
||||
for(int i = oldnf+1; i <= locfaces.Size(); i++)
|
||||
tempnewfaces.Append (locfaces.Get(i));
|
||||
// for(int i = oldnf+1; i <= locfaces.Size(); i++)
|
||||
for (auto i : locfaces.Range().Modify(oldnf,0))
|
||||
tempnewfaces.Append (locfaces[i]);
|
||||
|
||||
tempdelfaces.SetSize (0);
|
||||
for(int i = 1; i <= delfaces.Size(); i++)
|
||||
tempdelfaces.Append (delfaces.Get(i));
|
||||
// for(int i = 1; i <= delfaces.Size(); i++)
|
||||
for (auto i : delfaces.Range())
|
||||
tempdelfaces.Append (delfaces[i]);
|
||||
|
||||
templocelements.SetSize (0);
|
||||
for(int i = 1; i <= locelements.Size(); i++)
|
||||
templocelements.Append (locelements.Get(i));
|
||||
// for(int i = 1; i <= locelements.Size(); i++)
|
||||
for (auto i : locelements.Range())
|
||||
templocelements.Append (locelements[i]);
|
||||
|
||||
/*
|
||||
optother =
|
||||
@ -637,14 +661,14 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
if (loktestmode)
|
||||
{
|
||||
(*testout) << "apply rule" << endl;
|
||||
for(int i = 1; i <= locpoints.Size(); i++)
|
||||
for (auto i : locpoints.Range())
|
||||
{
|
||||
(*testout) << "p";
|
||||
if (i <= pindex.Size())
|
||||
(*testout) << pindex.Get(i) << ": ";
|
||||
if (pindex.Range().Contains(i))
|
||||
(*testout) << pindex[i] << ": ";
|
||||
else
|
||||
(*testout) << "new: ";
|
||||
(*testout) << locpoints.Get(i) << endl;
|
||||
(*testout) << locpoints[i] << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -652,10 +676,11 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
|
||||
pindex.SetSize(locpoints.Size());
|
||||
|
||||
for (int i = oldnp+1; i <= locpoints.Size(); i++)
|
||||
// for (int i = oldnp+1; i <= locpoints.Size(); i++)
|
||||
for (auto i : locpoints.Range().Modify(oldnp,0))
|
||||
{
|
||||
PointIndex globind = mesh.AddPoint (locpoints.Get(i));
|
||||
pindex.Elem(i) = adfront -> AddPoint (locpoints.Get(i), globind);
|
||||
PointIndex globind = mesh.AddPoint (locpoints[i]);
|
||||
pindex[i] = adfront -> AddPoint (locpoints[i], globind);
|
||||
}
|
||||
|
||||
for (int i = 1; i <= locelements.Size(); i++)
|
||||
@ -676,31 +701,31 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
stat.cntelem++;
|
||||
}
|
||||
|
||||
for(int i = oldnf+1; i <= locfaces.Size(); i++)
|
||||
for(int i = oldnf; i < locfaces.Size(); i++)
|
||||
{
|
||||
for (j = 1; j <= locfaces.Get(i).GetNP(); j++)
|
||||
locfaces.Elem(i).PNum(j) =
|
||||
pindex[locfaces.Get(i).PNum(j)];
|
||||
for (j = 1; j <= locfaces[i].GetNP(); j++)
|
||||
locfaces[i].PNum(j) =
|
||||
pindex[locfaces[i].PNum(j)];
|
||||
// (*testout) << "add face " << locfaces.Get(i) << endl;
|
||||
adfront->AddFace (locfaces.Get(i));
|
||||
adfront->AddFace (locfaces[i]);
|
||||
}
|
||||
|
||||
for(int i = 1; i <= delfaces.Size(); i++)
|
||||
adfront->DeleteFace (findex.Get(delfaces.Get(i)));
|
||||
adfront->DeleteFace (findex[delfaces.Get(i)-1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
adfront->IncrementClass (findex.Get(1));
|
||||
adfront->IncrementClass (findex[0]);
|
||||
if (impossible && mp.check_impossible)
|
||||
{
|
||||
(*testout) << "skip face since it is impossible" << endl;
|
||||
for (j = 0; j < 100; j++)
|
||||
adfront->IncrementClass (findex.Get(1));
|
||||
adfront->IncrementClass (findex[0]);
|
||||
}
|
||||
}
|
||||
|
||||
locelements.SetSize (0);
|
||||
delpoints.SetSize(0);
|
||||
// delpoints.SetSize(0);
|
||||
delfaces.SetSize(0);
|
||||
|
||||
if (stat.qualclass >= mp.giveuptol)
|
||||
@ -709,9 +734,9 @@ GenerateMesh (Mesh & mesh, const MeshingParameters & mp)
|
||||
|
||||
PrintMessage (5, ""); // line feed after statistics
|
||||
|
||||
for(int i = 1; i <= ruleused.Size(); i++)
|
||||
(*testout) << setw(4) << ruleused.Get(i)
|
||||
<< " times used rule " << rules.Get(i) -> Name() << endl;
|
||||
for(int i : ruleused.Range())
|
||||
(*testout) << setw(4) << ruleused[i]
|
||||
<< " times used rule " << rules[i] -> Name() << endl;
|
||||
|
||||
|
||||
if (!mp.baseelnp && adfront->Empty())
|
||||
@ -927,7 +952,7 @@ void Meshing3 :: BlockFill (Mesh & mesh, double gh)
|
||||
|
||||
for(int i = 1; i <= n; i++)
|
||||
{
|
||||
pointnr.Elem(i) = 0;
|
||||
pointnr.Elem(i) = PointIndex::INVALID;
|
||||
frontpointnr.Elem(i) = 0;
|
||||
}
|
||||
|
||||
@ -943,7 +968,7 @@ void Meshing3 :: BlockFill (Mesh & mesh, double gh)
|
||||
for (j3 = i3; j3 <= i3+1; j3++)
|
||||
{
|
||||
j = j3 + (j2-1) * n3 + (j1-1) * n2 * n3;
|
||||
if (pointnr.Get(j) == 0)
|
||||
if (!pointnr.Get(j).IsValid())
|
||||
{
|
||||
Point3d hp(xmin + (j1-1) * gh,
|
||||
ymin + (j2-1) * gh,
|
||||
@ -1174,7 +1199,7 @@ void Meshing3 :: BlockFillLocalH (Mesh & mesh,
|
||||
tbox.Stop();
|
||||
|
||||
// locadfront = adfront;
|
||||
loch.FindInnerBoxes (adfront, NULL);
|
||||
loch.FindInnerBoxes (*adfront, NULL);
|
||||
|
||||
npoints.SetSize(0);
|
||||
loch.GetInnerPoints (npoints);
|
||||
@ -1260,7 +1285,7 @@ void Meshing3 :: BlockFillLocalH (Mesh & mesh,
|
||||
tloch2.Stop();
|
||||
|
||||
// locadfront = adfront;
|
||||
loch2.FindInnerBoxes (adfront, NULL);
|
||||
loch2.FindInnerBoxes (*adfront, NULL);
|
||||
|
||||
npoints.SetSize(0);
|
||||
loch2.GetOuterPoints (npoints);
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef FILE_MESHING3
|
||||
#define FILE_MESHING3
|
||||
|
||||
#include "meshclass.hpp"
|
||||
#include "adfront3.hpp"
|
||||
#include "ruler3.hpp"
|
||||
|
||||
@ -22,13 +23,13 @@ enum MESHING3_RESULT
|
||||
class Meshing3
|
||||
{
|
||||
/// current state of front
|
||||
AdFront3 * adfront;
|
||||
unique_ptr<AdFront3> adfront;
|
||||
/// 3d generation rules
|
||||
NgArray<vnetrule*> rules;
|
||||
Array<unique_ptr<vnetrule>> rules;
|
||||
/// counts how often a rule is used
|
||||
NgArray<int> ruleused, canuse, foundmap;
|
||||
Array<int> ruleused, canuse, foundmap;
|
||||
/// describes, why a rule is not applied
|
||||
NgArray<char*> problems;
|
||||
Array<string> problems;
|
||||
/// tolerance criterion
|
||||
double tolfak;
|
||||
public:
|
||||
@ -45,9 +46,9 @@ public:
|
||||
MESHING3_RESULT GenerateMesh (Mesh & mesh, const MeshingParameters & mp);
|
||||
|
||||
///
|
||||
int ApplyRules (NgArray<Point3d, PointIndex::BASE> & lpoints,
|
||||
NgArray<int, PointIndex::BASE> & allowpoint,
|
||||
NgArray<MiniElement2d> & lfaces, INDEX lfacesplit,
|
||||
int ApplyRules (Array<Point3d, PointIndex> & lpoints,
|
||||
Array<int, PointIndex> & allowpoint,
|
||||
Array<MiniElement2d> & lfaces, INDEX lfacesplit,
|
||||
INDEX_2_HASHTABLE<int> & connectedpairs,
|
||||
NgArray<Element> & elements,
|
||||
NgArray<INDEX> & delfaces, int tolerance,
|
||||
|
@ -4,8 +4,9 @@
|
||||
// #include "../general/ngarray.hpp"
|
||||
// #include "../gprim/geom3d.hpp"
|
||||
// #include "../gprim/geomobjects.hpp"
|
||||
// #include "meshtype.hpp"
|
||||
// #include "meshclass.hpp"
|
||||
|
||||
#include "meshtype.hpp"
|
||||
#include "meshclass.hpp"
|
||||
|
||||
namespace netgen {
|
||||
///
|
||||
|
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