Compare commits

...

188 Commits

Author SHA1 Message Date
Christopher Lackner
a9e8f2a1c9 return invalid surfaceindex (index is 0 based) 2025-04-28 20:29:51 +02:00
Matthias Hochsteger
b84975586c Boundarylayer thickness limitation fix
Don't check for intersecting mapped trigs if only volume elements are
added (and no mapped surface elements).

In case of only inserted volume elements, we don't care about the limit
at special points.
2025-04-28 16:36:00 +02:00
Matthias Hochsteger
aa66cd11c4 Export Mesh.GetCurveOrder() to Python 2025-04-28 15:31:50 +02:00
Matthias Hochsteger
494b0ae37c code formatting in blayer files 2025-04-28 15:31:30 +02:00
Matthias Hochsteger
f42d0c0be4 Fix missing identifications in boundarylayer generation, some code refactoring 2025-04-28 15:30:29 +02:00
Matthias Hochsteger
b43eb033d2 Pass -DCMAKE_POLICY_VERSION_MINIMUM=3.5 to subprojects for cmake 4 compatibility 2025-04-23 08:39:58 +02:00
Matthias Hochsteger
1fc382867d Fix segfault in occ (use Handle when creating new Geom_Plane) 2025-04-15 18:39:20 +02:00
Schöberl, Joachim
6ea09e1151 Merge branch 'occ_wp_ellipse' into 'master'
add ellipse to occ workplane

See merge request ngsolve/netgen!705
2025-04-14 22:00:36 +02:00
Christopher Lackner
36cbd5fc00 add ellipse to occ workplane 2025-04-14 17:48:18 +02:00
Christopher Lackner
3a9060fc2f fix occ Ellipse function 2025-04-14 17:04:33 +02:00
Joachim Schoeberl
109e7ffcf7 fix for 1D meshing (without region names) 2025-04-14 10:40:41 +02:00
Christopher Lackner
1db8ea3500 also different BRepTools::Write on occ lower than 7.6 2025-04-14 09:12:08 +02:00
Christopher Lackner
b05c32675b check for binary output for older occ versions 2025-04-14 08:34:59 +02:00
Joachim Schoeberl
cb3eb0d355 common arrays of region names 2025-04-13 16:14:01 +02:00
Christopher Lackner
42294117bd 0 dim elements are not curved 2025-04-11 10:44:56 +02:00
Matthias Hochsteger
60c1151205 Utility function to draw lines (used for contact boundary in NGSolve) 2025-04-09 11:39:57 +02:00
Matthias Hochsteger
3f28651e63 Boundary layers - don't ignore edges on cylinder sides when smoothing growth vectors 2025-04-09 11:39:57 +02:00
Christopher Lackner
5a66cbee72 allow writing brep in different versions and binary 2025-04-04 08:54:32 +02:00
Christopher Lackner
788c782455 OCCGeometry properties to query subshapes in netgen-order 2025-03-31 09:16:44 +02:00
Matthias Hochsteger
12ef984e93 OCC - Set metricweight in 2d mesh optimization (like in CSG) 2025-03-26 16:29:32 +01:00
Matthias Hochsteger
f15ba64a90 LocalH::Find() utility function to find GradingBox
Simplifies code and avoids searching for same grading box twice in SetH().
2025-03-26 15:37:06 +01:00
Matthias Hochsteger
3b79dbc8ff Layer parameter for RestrictH 2025-03-26 15:19:11 +01:00
Christopher Lackner
7b13db740d fix bisect with periodic boundaries 2025-03-25 11:00:24 +01:00
Christopher Lackner
78994da199 1d occ meshes 2025-03-19 17:38:51 +01:00
Hochsteger, Matthias
42c1818784 Merge branch 'fix_colors_occ' into 'master'
fix colors from step read if they are set on solid for subshapes

See merge request ngsolve/netgen!704
2025-03-19 09:49:34 +01:00
Christopher Lackner
97f869207e fix colors from step read if they are set on solid for subshapes 2025-03-19 08:58:49 +01:00
Schöberl, Joachim
951e20a7e4 Merge branch 'from_pyocc' into 'master'
add From_PyOCC function to convert swig pyocc shape to netgen.occ

See merge request ngsolve/netgen!703
2025-03-17 15:21:44 +01:00
Christopher Lackner
8cde49627b remove debug cout 2025-03-17 11:23:40 +01:00
Christopher Lackner
36c9201ffc add From_PyOCC function to convert swig pyocc shape to netgen.occ 2025-03-17 11:20:19 +01:00
Christopher Lackner
8478ff5078 add edges to occ visualization data 2025-03-16 09:31:06 +01:00
Christopher Lackner
714158e928 fix and improve occ visualizationdata function 2025-03-15 04:34:16 +01:00
Christopher Lackner
9399f753c4 allow list of profiles in PipeShell 2025-03-14 11:36:00 +01:00
Lackner, Christopher
8944322e60 Merge branch 'cleanup_searchtree_elementindex' into 'master'
move all searchtrees to use elementindex

See merge request ngsolve/netgen!702
2025-03-13 19:55:29 +01:00
Christopher Lackner
15bd6cbed0 take autoscale value on drawn regions only 2025-03-13 18:49:28 +01:00
Christopher Lackner
b8d722d6a8 remove debug output 2025-03-13 18:41:38 +01:00
Christopher Lackner
7aae5369c4 move all searchtrees to use elementindex 2025-03-13 18:39:21 +01:00
Christopher Lackner
787c6043fa set timestamp in element search tree 2025-03-13 10:10:04 +01:00
Christopher Lackner
d240203932 fix 1d FindPointInElement 2025-03-07 18:01:00 +01:00
Schöberl, Joachim
0c789fb04f Merge branch 'findpointinelement' into 'master'
Improvements to FindPointInElement interface code

See merge request ngsolve/netgen!701
2025-03-07 17:42:24 +01:00
Christopher Lackner
9204b079f6 Improvements to FindPointInElement interface code 2025-03-07 17:14:31 +01:00
Hochsteger, Matthias
2778b934e6 Merge branch 'fix_conform_segments' into 'master'
Fixes to conform to free segments

See merge request ngsolve/netgen!700
2025-03-06 19:11:34 +01:00
Matthias Hochsteger
627e89d579 Fixes to conform to free segments 2025-03-06 18:53:16 +01:00
Christopher Lackner
bc194027a2 fix edges and new domains in BoundaryLayer2d with make_new_domain=True 2025-03-04 09:59:56 +01:00
Christopher Lackner
d1a9f7ee3d raise Exception on BoundaryLayer call (should be given as meshing parameters now) 2025-02-28 09:04:20 +01:00
Matthias Hochsteger
82befccada Fix excessive hashtable size if meshpoints are close together (happens with boundary layers) 2025-02-27 19:44:36 +01:00
Matthias Hochsteger
9601f70c17 Keep free segments when generating boundary layers, also revert seg.si back to seg.edgenr+1 2025-02-27 17:27:54 +01:00
Matthias Hochsteger
5ab7a4995c Some fixes for boundary layers when adjacent faces are mapped to different new materials 2025-02-25 18:04:18 +01:00
Matthias Hochsteger
8b0b9e507f More robust tet splitting for free segment conformity 2025-02-25 12:46:39 +01:00
Matthias Hochsteger
f236648847 Skip SplitImprove if it would insert tets with negative volume 2025-02-24 19:56:43 +01:00
Christopher Lackner
2220fc093f export restrictlocalh of netgen mesh 2025-02-21 11:43:37 +01:00
Joachim Schoeberl
5e742f017c GetFaceEdges index fix 2025-02-17 23:31:29 +01:00
Matthias Hochsteger
fb399595fa Skip SwapImproveEdge if one adjacent element has wrong orientation 2025-02-14 19:16:13 +01:00
Matthias Hochsteger
d2f7c24a5e Utility function for debugging 2025-02-14 18:12:28 +01:00
Matthias Hochsteger
d7ae61e00a Clean up SwapImproveEdge 2025-02-14 18:11:47 +01:00
Matthias Hochsteger
058cdce84d Free edges - split Segments if other optimizations are not enough, also apply ImproveMesh 2025-02-14 10:04:56 +01:00
Joachim Schoeberl
15ffcbae8e Segment numpy-descriptor 'index' changed to si 2025-02-13 23:04:21 +01:00
Matthias Hochsteger
913ede1cae Boundarylayers - disable curving on edges with moved points 2025-02-12 09:59:07 +01:00
Matthias Hochsteger
44fe189bf0 Fix undefined behavior in 2d boundarylayer code 2025-02-11 18:32:39 +01:00
Matthias Hochsteger
b811162086 Don't apply lighting to identification lines 2025-02-10 17:16:49 +01:00
Matthias Hochsteger
12ff6d6f51 Fix identification propagation in boundary layer generation 2025-02-10 17:15:59 +01:00
Matthias Hochsteger
b14a9e6d2b Also shrink identifications in visualization 2025-02-10 17:15:36 +01:00
Matthias Hochsteger
d1228b6ce9 Less tolerance for smoothing of boundarylayer vectors 2025-02-06 19:15:59 +01:00
Matthias Hochsteger
7aff94046f Also smooth boundary layers at corners if adjacent surface elements have similar normal vectors 2025-02-06 18:50:04 +01:00
Matthias Hochsteger
a8a75614c0 More tolerance for boundary layer smoothing along inner edges 2025-02-06 18:49:36 +01:00
Matthias Hochsteger
6f574ec191 Fix range exception in boundarylayer limiter 2025-02-03 17:06:28 +01:00
Matthias Hochsteger
20196cd8e9 Pyodide fixes 2025-01-31 13:06:44 +01:00
Christopher Lackner
cf6c702d2c fix archive of identifications that point to shapes that are not in geometrz 2025-01-29 16:19:19 +01:00
Matthias Hochsteger
5856001819 Fix range exception in boundary limiter, rename npi to first_new_pi 2025-01-29 11:33:12 +01:00
Matthias Hochsteger
49ecbd55ee OCC - use relative tolerances when building OCC incremental mesh 2025-01-28 15:15:11 +01:00
Matthias Hochsteger
311ae9e89b Use fabi-version=17 by default with gcc 2025-01-24 13:38:40 +01:00
Christopher Lackner
5292a09c94 add TopoDS_Shape.WriteBrep 2025-01-22 12:24:30 +01:00
Christopher Lackner
b79128fabf fix bug in mesh read/write when identification name is empty 2025-01-21 09:58:16 +01:00
Matthias Hochsteger
886bb14299 avx512 - const operator[] for SIMD<8, double> 2025-01-20 10:00:15 +01:00
Joachim Schoeberl
892271fd08 proper initialize face2surfedl 2025-01-10 16:59:43 +01:00
Schöberl, Joachim
c4985c49e1 Merge branch 'cherry-pick-b99b8eec' into 'master'
use SortedPointIndex-HT

See merge request ngsolve/netgen!697
2025-01-08 18:57:22 +01:00
Schöberl, Joachim
06e8764d01 use SortedPointIndex-HT
(cherry picked from commit b99b8eec349f0e39edd67341254e3181d4cd86ad)

Co-authored-by: Joachim Schoeberl <joachim.schoeberl@tuwien.ac.at>
2025-01-08 18:57:01 +01:00
Joachim Schoeberl
dcd6f6d60d TablePrefixSum 32/64 bit decision 2025-01-08 08:25:12 +01:00
Joachim Schoeberl
0a1fd5a2e2 EdgeIndex and FaceIndex 2025-01-07 16:41:37 +01:00
Joachim Schoeberl
5642d435e1 missing constexpr 2025-01-06 18:33:44 +01:00
Joachim Schoeberl
6af9b48bda fix range index, Index-operators 2025-01-06 18:05:13 +01:00
Joachim Schoeberl
c0b33db5c0 Index operators 2025-01-06 11:26:50 +01:00
Joachim Schoeberl
59e5974a28 NgArray -> Array bcnames etc 2025-01-05 18:19:21 +01:00
Joachim Schoeberl
1f70e62fc7 int - PointIndex conversion 2025-01-05 15:42:58 +01:00
Joachim Schoeberl
b1e840f7d8 some more 0-based arrays 2025-01-05 15:33:48 +01:00
Joachim Schoeberl
1ebc6a0e81 more ngcore::Array in topology, include headers 2025-01-05 12:14:08 +01:00
Joachim Schoeberl
63cb566b8d mesh.parentelement with correct types 2025-01-04 12:41:04 +01:00
Joachim Schoeberl
9bc0273784 different enditerator experiment 2025-01-04 12:37:38 +01:00
Joachim Schoeberl
c99f26ec12 use HashTable<SortedPointIndices> for bisect 2025-01-04 12:10:25 +01:00
Joachim Schoeberl
0b480f1eab little polish of hashtable 2025-01-04 12:09:38 +01:00
Joachim Schoeberl
eefeca571b polish in meshtype 2025-01-03 11:37:09 +01:00
Christopher Lackner
58db55c2ff fix gui crash in 2d when selecting face numbers 2025-01-03 10:14:58 +01:00
Joachim Schoeberl
0497dc25fd fix archive hashtable 2025-01-03 00:11:29 +01:00
Joachim Schoeberl
2838327ba1 trigger rebuild 2025-01-02 22:27:28 +01:00
Schöberl, Joachim
566182f977 Merge branch 'constexpr_experiments' into 'master'
Constexpr experiments

See merge request ngsolve/netgen!694
2025-01-02 22:01:47 +01:00
Schöberl, Joachim
dd508bf675 Merge branch 'master' into 'constexpr_experiments'
# Conflicts:
#   libsrc/meshing/meshtype.hpp
2025-01-02 21:55:44 +01:00
Joachim Schoeberl
643898c5e2 avoid shared ptr copy 2025-01-02 20:51:11 +01:00
Joachim Schoeberl
3b3491a597 some little steps 2025-01-02 10:17:24 +01:00
Joachim Schoeberl
e926071bb2 archiving ngscore::CloseHashTable 2025-01-01 16:42:11 +01:00
Joachim Schoeberl
ce5f6d695c all tests passing for PointIndex::BASE=0 2025-01-01 15:53:23 +01:00
Joachim Schoeberl
aca27f6421 some more int->PointIndex 2025-01-01 13:53:01 +01:00
Joachim Schoeberl
3185256ad3 PointIndex for csg lockedpnts 2025-01-01 12:27:44 +01:00
Joachim Schoeberl
6d6e297a1f PointInd for edge on closed surf 2025-01-01 12:09:03 +01:00
Joachim Schoeberl
bcbd390f7d PointIndex in Identifications 2024-12-31 21:26:04 +01:00
Schöberl, Joachim
f117281ea4 Merge branch 'constexpr_experiments' into 'master'
Constexpr experiments

See merge request ngsolve/netgen!692
2024-12-31 14:26:09 +01:00
Schöberl, Joachim
3362d91a37 Constexpr experiments 2024-12-31 14:26:09 +01:00
Joachim Schoeberl
fe21b0bb8b cleanup 2024-12-31 14:07:27 +01:00
Joachim Schoeberl
104c576caa ctor 2024-12-31 13:54:11 +01:00
Joachim Schoeberl
2fdc293b9a ctor 2024-12-31 13:38:04 +01:00
Joachim Schoeberl
2b75d091e9 inheriated ctor 2024-12-31 13:31:31 +01:00
Joachim Schoeberl
9bc9ee8e7d remove convert operator 2024-12-31 13:18:03 +01:00
Joachim Schoeberl
3c273bf537 calling ctor 2024-12-31 13:13:57 +01:00
Joachim Schoeberl
990fb0657c calling ctor 2024-12-31 13:09:33 +01:00
Joachim Schoeberl
7fac77d28e calling ctor 2024-12-31 13:04:57 +01:00
Joachim Schoeberl
626507f8fb missing constexpr 2024-12-31 13:03:46 +01:00
Joachim Schoeberl
9ab086f819 unified Index class 2024-12-31 12:54:25 +01:00
Joachim Schoeberl
b7b168e265 base Index template 2024-12-31 12:16:53 +01:00
Joachim Schoeberl
9efaac072e metis graph with PointIndex::BASE 2024-12-30 15:14:26 +01:00
Joachim Schoeberl
4ed519e819 facet-base 2024-12-30 14:31:07 +01:00
Joachim Schoeberl
0e1bebaa1d fix PointIndex 2024-12-30 14:31:07 +01:00
Joachim Schoeberl
e57cc13047 more ElementIndex 2024-12-30 14:31:07 +01:00
Lackner, Christopher
16962aea69 Merge branch 'fix_empty_string_distribute' into 'master'
fix empty names in mesh distribute

See merge request ngsolve/netgen!691
2024-12-30 13:14:43 +01:00
Christopher Lackner
e0abf93ce1 fix empty names in mesh distribute 2024-12-30 12:54:45 +01:00
Joachim Schoeberl
95e9408db0 use of ElementIndex 2024-12-29 22:20:46 +01:00
Joachim Schoeberl
4a9188da61 more use of ElementIndex, T_Range<T>(size_t) is now explicit 2024-12-29 21:36:37 +01:00
Joachim Schoeberl
bb37ae1987 convert NgArrays 2024-12-29 18:57:47 +01:00
Joachim Schoeberl
100279be6c try again with constexpr 2024-12-29 17:32:10 +01:00
Joachim Schoeberl
fd0421d573 more ngcore arrays 2024-12-29 17:23:35 +01:00
Joachim Schoeberl
7afcaf3406 use of ElementIndex in toplogy 2024-12-29 16:34:16 +01:00
Joachim Schoeberl
a2ea0c407a more general ClosedHashTable, e.g. hash for tuples 2024-12-29 15:42:21 +01:00
Joachim Schoeberl
55474772cd fix debug build 2024-12-28 23:46:27 +01:00
Joachim Schoeberl
fa6f8c53ec fix rangecheck-error 2024-12-28 23:09:49 +01:00
Joachim Schoeberl
a5ce9915d1 compare PointIndex only with PointIndex 2024-12-28 22:58:44 +01:00
Joachim Schoeberl
75032f9905 operators +/- for PointIndex 2024-12-28 21:26:05 +01:00
Joachim Schoeberl
00e3a3490b some index fixes 2024-12-28 19:46:29 +01:00
Joachim Schoeberl
00edc92c00 improve3 with consistent PointIndex 2024-12-28 13:01:20 +01:00
Joachim Schoeberl
10a56a9e86 PointIndex in improve2gen 2024-12-28 10:35:18 +01:00
Joachim Schoeberl
2291221719 fixes for PointIndex::BASE=0 2024-12-28 00:11:26 +01:00
Joachim Schoeberl
ceddf31f87 PointIndex 2024-12-27 18:05:04 +01:00
Joachim Schoeberl
0a7a206223 ElementIndex 2024-12-27 13:12:59 +01:00
Joachim Schoeberl
c466fe8d07 more PointIndex 2024-12-27 10:51:58 +01:00
Joachim Schoeberl
386edbf75e t_size(-1) 2024-12-26 20:56:49 +01:00
Joachim Schoeberl
f87aefbcc9 GetTable 2024-12-26 20:41:49 +01:00
Joachim Schoeberl
c0080ae62e too much constexpr 2024-12-26 20:36:57 +01:00
Joachim Schoeberl
1a610b060f CompressedTable(Creator) 2024-12-26 20:29:38 +01:00
Joachim Schoeberl
a675c42d89 more PointIndex 2024-12-26 16:32:50 +01:00
Joachim Schoeberl
9c9b4ea880 switch to ngcore::ClosedHashTable 2024-12-26 15:06:50 +01:00
Joachim Schoeberl
abe18a9b74 little polish 2024-12-24 00:52:38 +01:00
Joachim Schoeberl
209863d79e replace (most) NgBitArrays 2024-12-24 00:10:20 +01:00
Joachim Schoeberl
b5fe5a4fb2 trigger rebuild 2024-12-23 22:27:17 +01:00
Joachim Schoeberl
0a8db69aa7 PointIndex in delaunay 2024-12-23 21:42:22 +01:00
Joachim Schoeberl
73bcb1bd29 PointIndex in bisect 2024-12-23 19:24:48 +01:00
Lackner, Christopher
31ed810144 Merge branch 'boundarylayer_fixes' into 'master'
Boundary Layers - Automatic thickness limiation and fixes

See merge request ngsolve/netgen!690
2024-12-23 12:30:28 +01:00
Hochsteger, Matthias
1aa34da6af Boundary Layers - Automatic thickness limiation and fixes 2024-12-23 12:30:28 +01:00
Joachim Schoeberl
0e2eee3618 keep ifdef parallel 2024-12-22 21:45:33 +01:00
Joachim Schoeberl
bcc9f43f76 idmap using PointIndex 2024-12-22 21:38:50 +01:00
Joachim Schoeberl
34c3d971b0 more ElementIndex 2024-12-22 19:58:00 +01:00
Joachim Schoeberl
386c290dc0 rectangle with edge-names 2024-12-21 00:37:50 +01:00
Joachim Schoeberl
975414c2fe auto difference type 2024-12-18 08:18:40 +01:00
Joachim Schoeberl
8f73a00d2d code cleanup 2024-12-15 18:00:50 +01:00
Joachim Schoeberl
b560719a47 more PointIndex 2024-12-14 21:59:49 +01:00
Joachim Schoeberl
07191d6e1b more PointIndex, fix range-check 2024-12-14 20:21:18 +01:00
Joachim Schoeberl
b08a1a5db5 more ngcore::Arrays and PointIndex 2024-12-14 18:57:12 +01:00
Joachim Schoeberl
868ee9643f more to nginterface2 2024-12-13 16:48:37 +01:00
Joachim Schoeberl
0bb738b29e remove commented code 2024-12-13 13:06:41 +01:00
Schöberl, Joachim
aa9f93a487 Merge branch 'occ_archive_vertex_properties' into 'master'
archive vertex properties (in backwards compatible way)

See merge request ngsolve/netgen!689
2024-12-13 12:48:57 +01:00
Christopher Lackner
7d0bbdab07 archive vertex properties (in backwards compatible way) 2024-12-12 17:45:39 +01:00
Matthias Hochsteger
ecc3db6760 Fix point selection on clipping plane 2024-12-12 16:42:57 +01:00
Matthias Hochsteger
b808d84957 Remove (unused) Togl 1.7 source files 2024-12-06 11:17:09 +01:00
Matthias Hochsteger
36cdde4889 Use unnamed namespace for struct Line in basegeom.cpp
See https://github.com/NGSolve/netgen/issues/198
2024-12-06 11:15:40 +01:00
Joachim Schoeberl
c7adfee5d8 include 'ranges.hpp' to ngcore 2024-12-04 23:03:53 +01:00
Joachim Schoeberl
6f8e4e9f5f more constexpr 2024-12-04 16:05:50 +01:00
Joachim Schoeberl
c3e27a1792 fix warning 2024-12-04 08:11:43 +01:00
Schöberl, Joachim
27197f146c Merge branch 'fix_warnings' into 'master'
Some memory tracer fixes/features, fix build warnings

See merge request ngsolve/netgen!688
2024-12-03 20:33:27 +01:00
Matthias Hochsteger
519490ecee Workaround to use webgui interface from command line 2024-12-03 18:58:12 +01:00
Matthias Hochsteger
3bfa6c19fa Fix build warnings (found with gcc -Wall) 2024-12-03 18:58:12 +01:00
Matthias Hochsteger
0c1943c77b Fix bug in nginterface (discovered by gcc -Wall) 2024-12-03 18:58:12 +01:00
Matthias Hochsteger
32e0026128 Some memory tracer fixes/features
If range checks are enabled:
- Trace all objects
- Check if memory usage never gets negative
- Check if memory usage is 0 in destructor
- Track total memory usage (use pyngcore.GetTotalMemory())
2024-12-03 18:58:07 +01:00
Joachim Schoeberl
9935d877cc mpi cleanup 2024-12-01 18:55:01 +01:00
Joachim Schoeberl
8c1882226c missed waits 2024-12-01 17:19:45 +01:00
Joachim Schoeberl
75504c3a6d mpi-dummies 2024-12-01 16:06:09 +01:00
Joachim Schoeberl
eead94dfc1 mpirequests::Reset 2024-12-01 13:31:07 +01:00
Joachim Schoeberl
ad5c50eef5 fix size_t-1 problem (got warning in ngsxfem) 2024-12-01 09:34:52 +01:00
Joachim Schoeberl
a4c6655fa7 tolerance in CrossPointBarycentric 2024-11-29 13:01:34 +01:00
Matthias Hochsteger
516c089c42 Fix build error 2024-11-27 21:55:11 +01:00
Joachim Schoeberl
ebf4d4d1b8 fix non-mpi 2024-11-27 21:29:43 +01:00
Joachim Schoeberl
14c39f8283 introduce NgMPI_Request(s) 2024-11-27 21:16:48 +01:00
Matthias Hochsteger
1c6d53f387 Manage global JacobiPols array inside struct
Works around emscripten issue, where the global array was not
constructed properly
2024-11-27 18:54:32 +01:00
Joachim Schoeberl
7570468686 bcast material etc names using ibcast 2024-11-26 13:29:14 +01:00
181 changed files with 7897 additions and 18208 deletions

64
.clang-format Normal file
View 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -22,5 +22,6 @@
#include "xbool.hpp"
#include "ngstream.hpp"
#include "utils.hpp"
#include "ranges.hpp"
#endif // NETGEN_CORE_NGCORE_HPP

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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()
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 ();

View File

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

View File

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

View File

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

View File

@ -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] );

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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();

View File

@ -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';
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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; }
///

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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

View 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

View File

@ -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] << " ";

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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++)
{

View File

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

View File

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

View File

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

View File

@ -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.);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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]++;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -7,6 +7,11 @@
/* Date: 01. Okt. 95 */
/**************************************************************************/
#include "adfront2.hpp"
#include "ruler2.hpp"
#include "basegeom.hpp"
namespace netgen
{

View File

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

View File

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

View File

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