Compare commits

...

334 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
Joachim Schoeberl
a86d231714 check for num=0 before memcpy 2024-11-25 17:25:40 +01:00
Matthias Hochsteger
22797971f6 Cleanup Abaqus export, implement 1d and 2d elements 2024-11-25 16:27:34 +01:00
Matthias Hochsteger
dd6638b1ab Mesh::GetRegionName(element_or_elindex) 2024-11-25 16:27:34 +01:00
Lackner, Christopher
7d483dcade Merge branch 'free_edges' into 'master'
OCC - support free-floating edges in solids

See merge request ngsolve/netgen!687
2024-11-25 14:14:47 +01:00
Hochsteger, Matthias
3e30ad9b75 OCC - support free-floating edges in solids 2024-11-25 14:14:47 +01:00
Matthias Hochsteger
44611e668c Fix Segfault in MPI ReceiveMesh
See https://github.com/NGSolve/netgen/issues/196
2024-11-25 13:56:39 +01:00
Matthias Hochsteger
9e80e5f195 Fix MPICH compatibility
When building without MPI wrapper: Use preprocessor macros instead of global variables for MPI symbols

See https://github.com/NGSolve/netgen/issues/196
2024-11-25 11:20:32 +01:00
Matthias Hochsteger
e2a20a44bc Put IsSafe to ngcore namespace, separate functions for range check macros for readability 2024-11-20 20:53:35 +01:00
Matthias Hochsteger
69f5e8e572 Use nest_asyncio for playwright/screenshots in docu 2024-11-11 12:41:36 +01:00
Matthias Hochsteger
47ea05dc24 Use playwright for screenshots in docu 2024-11-11 10:33:55 +01:00
Schöberl, Joachim
fb41dddf3d Merge branch 'wp_close_name' into 'master'
optional name in wp.Close for last edge

See merge request ngsolve/netgen!686
2024-11-05 17:35:30 +01:00
Christopher Lackner
22a251e4fd optional name in wp.Close for last edge 2024-11-05 14:58:30 +01:00
Schöberl, Joachim
ddf64c8250 Merge branch 'std_exception_inv_arg' into 'master'
use std invalid argument instead of Exception in py constructor

See merge request ngsolve/netgen!685
2024-11-05 11:00:48 +01:00
Matthias Hochsteger
629cca9413 Use std::tuple<double,double> instead of py::tuple with length and type checks 2024-11-05 10:46:08 +01:00
Christopher Lackner
45acbbf6ef use std invalid argument instead of Exception in py constructor 2024-11-05 07:55:23 +01:00
Joachim Schoeberl
9a7a9fa445 remove unused variable 2024-10-19 14:38:48 +02:00
Lackner, Christopher
6debf03402 Merge branch 'periodic_and_cs' into 'master'
enable periodic + closesurface identification on same boundaries

See merge request ngsolve/netgen!684
2024-10-16 20:02:23 +02:00
Christopher Lackner
b981d45069 enable periodic + closesurface identification on same boundaries 2024-10-16 19:42:57 +02:00
Matthias Hochsteger
db9aaef220 Don't build for Python 3.8 anymore 2024-10-16 10:26:53 +02:00
Schöberl, Joachim
141af42887 Merge branch 'idnrs_in_merge_mesh' into 'master'
propagate idnrs in merge mesh (for ZRefine)

See merge request ngsolve/netgen!682
2024-10-13 13:34:49 +02:00
Christopher Lackner
75823e8244 propagate idnrs in merge mesh (for ZRefine) 2024-10-13 10:57:29 +02:00
Schöberl, Joachim
5b245d4de3 Merge branch 'build_with_older_pybind11' into 'master'
also allow building with older pybind11 without py::set_error

See merge request ngsolve/netgen!681
2024-10-10 09:17:12 +02:00
Lackner, Christopher
587b766418 also allow building with older pybind11 without py::set_error 2024-10-10 09:17:11 +02:00
Hochsteger, Matthias
e30677169b Merge branch 'misc_fixes' into 'master'
Misc fixes

See merge request ngsolve/netgen!680
2024-10-08 14:31:40 +02:00
Matthias Hochsteger
ab985ba044 Fix optimizations in domains with non-tet elements 2024-10-08 14:01:22 +02:00
Matthias Hochsteger
8a049799e2 Fix debugging function GetOpenElements() 2024-10-08 14:00:12 +02:00
Matthias Hochsteger
a8309fae1c Update d3, fix styles in timing html chart 2024-10-08 13:59:30 +02:00
Matthias Hochsteger
267830387f PajeTrace - option to write only (small) html charts and no trace file 2024-10-08 13:58:23 +02:00
Matthias Hochsteger
96bad51dd3 Pyodide fixes 2024-10-07 18:04:20 +02:00
Matthias Hochsteger
12f42b30cd New test results 2024-10-01 14:16:15 +02:00
Matthias Hochsteger
1e20c1860b Fix RemoveIllegalElements
- Only search in relevant domain
- Break if number of illegal elements increases (avoids infinite loop)
  -> This shouldn't actually happen and is just a workaround until the
  optimization routines are fixed
2024-10-01 13:34:19 +02:00
Joachim Schoeberl
c4dbe60f78 create edge from two vertices 2024-09-28 20:29:22 +02:00
Schöberl, Joachim
ce3f627e36 Merge branch 'occ_vec_from_dir' into 'master'
convert gp_Dir to gp_Vec

See merge request ngsolve/netgen!679
2024-09-28 20:17:25 +02:00
Christopher Lackner
10986ffbab convert gp_Dir to gp_Vec 2024-09-28 16:39:19 +02:00
Schöberl, Joachim
3e279da9bf Merge branch 'occ_make_polygon' into 'master'
export occ MakePolygon

See merge request ngsolve/netgen!678
2024-09-28 15:34:40 +02:00
Christopher Lackner
6b662a9634 export occ MakePolygon 2024-09-28 15:15:44 +02:00
Matthias Hochsteger
7f8172aaf6 Allow vector<int> as domain, project_boundaries in BoundaryLayerParameters 2024-09-27 17:29:05 +02:00
Schöberl, Joachim
2ff62bc283 Merge branch 'blayer_as_meshing_parameter' into 'master'
Add BoundarylayerParameters to MeshingParameters

See merge request ngsolve/netgen!677
2024-09-27 16:30:50 +02:00
Hochsteger, Matthias
833a177e34 Add BoundarylayerParameters to MeshingParameters 2024-09-27 16:30:50 +02:00
Schöberl, Joachim
592221ee19 Merge branch 'fix_identified_point_handling' into 'master'
Fix handling identified points in Compress and MeshVolume

See merge request ngsolve/netgen!676
2024-09-27 16:30:29 +02:00
Hochsteger, Matthias
27b8b5e7c8 Fix handling identified points in Compress and MeshVolume 2024-09-27 16:30:29 +02:00
Schöberl, Joachim
fb39692f9c Merge branch 'skip_non_tet_points_in_smoothing' into 'master'
Don't do mesh smoothing at non-tet elements

See merge request ngsolve/netgen!675
2024-09-27 16:29:47 +02:00
Hochsteger, Matthias
61bed581ec Don't do mesh smoothing at non-tet elements 2024-09-27 16:29:47 +02:00
Schöberl, Joachim
f3a2cee15b Merge branch 'range_check_in_ngarray' into 'master'
Use new range check macro in NgArray

See merge request ngsolve/netgen!632
2024-09-27 16:29:29 +02:00
Matthias Hochsteger
13d962acdd Write more debug output meshes on failure 2024-09-27 11:48:42 +02:00
Matthias Hochsteger
5e3743df31 Code cleanup 2024-09-27 11:43:54 +02:00
Matthias Hochsteger
156a429898 Remove empty file ngarray.cpp 2024-09-27 11:27:41 +02:00
Matthias Hochsteger
5c38bef3cf Fix initializing empty tables 2024-09-27 11:27:41 +02:00
Matthias Hochsteger
451e59afa2 Use new range check macro in NgArray 2024-09-27 11:27:41 +02:00
Schöberl, Joachim
5b6a659356 Merge branch 'fix_splitimprove_edge' into 'master'
Fix splitimprove edge

See merge request ngsolve/netgen!674
2024-09-27 01:00:51 +02:00
Hochsteger, Matthias
9f6c64a4f9 Fix splitimprove edge 2024-09-27 01:00:50 +02:00
Matthias Hochsteger
e51918df35 Fix pip on Linux 2024-09-23 16:31:47 +02:00
Hochsteger, Matthias
c96eeee117 Merge branch 'occ_fix_maxh' into 'master'
Propagate OCC maxh settings correctly

See merge request ngsolve/netgen!673
2024-09-23 13:36:45 +02:00
Hochsteger, Matthias
0ddcfdd0c7 Propagate OCC maxh settings correctly 2024-09-23 13:36:44 +02:00
Matthias Hochsteger
ee6ba53d91 Fix finding Tcl/Tk on MacOS with Python 3.13 2024-09-19 17:40:39 +02:00
Matthias Hochsteger
7167b4cff9 Set .dev1 postfix correctly on non-master branches, some formatting 2024-09-19 17:04:05 +02:00
Matthias Hochsteger
99b7533251 Fix installing ccache and dpkg on almalinux 8 2024-09-19 16:37:47 +02:00
Matthias Hochsteger
449179bcec Install requests before building pip package 2024-09-19 16:19:33 +02:00
Matthias Hochsteger
e279140a4d Use manylinux2_28 docker image build pip packages for Linux 2024-09-19 16:17:39 +02:00
Matthias Hochsteger
c20dfbbc39 Build .dev1 packages on non-master branches 2024-09-19 16:05:45 +02:00
Matthias Hochsteger
eaec560618 Remove unused autitwheel code 2024-09-19 15:58:21 +02:00
Matthias Hochsteger
d79b259ece Build pip packages for Python 3.13 2024-09-19 15:58:21 +02:00
Lackner, Christopher
e94096e008 Merge branch 'textinarchive_windows_unix_compatibility' into 'master'
Fix TextOutArchive (Win) -> TextInArchive (Unix) incompatibility

See merge request ngsolve/netgen!671
2024-09-18 17:48:37 +02:00
Hochsteger, Matthias
d73cffd0c7 Fix TextOutArchive (Win) -> TextInArchive (Unix) incompatibility 2024-09-18 17:48:36 +02:00
Hochsteger, Matthias
876331afaf Merge branch 'update_pybind11' into 'master'
Update pybind11 to 2.13.6 (including a patch for binary compatibility accross MSVC versions)

See merge request ngsolve/netgen!670
2024-09-18 13:17:33 +02:00
Matthias Hochsteger
1fb2501b7e Update pybind11 to 2.13.6 (including a patch for binary compatibility accross MSVC versions) 2024-09-18 12:09:25 +02:00
Schöberl, Joachim
7656211b3e Merge branch 'property_propagate_geo_glue' into 'master'
propagate properties correctly in occgeom.Glue

See merge request ngsolve/netgen!669
2024-09-16 10:14:33 +02:00
Christopher Lackner
827b02d94c propagate properties correctly in occgeom.Glue 2024-09-16 09:59:42 +02:00
Hochsteger, Matthias
fe5a3acc8b Merge branch 'fix_splitimprove' into 'master'
Skip SplitImproveEdge if it would insert tets with negative volume

See merge request ngsolve/netgen!668
2024-09-13 10:22:50 +02:00
Hochsteger, Matthias
73c75240f8 Skip SplitImproveEdge if it would insert tets with negative volume 2024-09-13 10:22:50 +02:00
Matthias Hochsteger
67a67a453d Fix copying BitArray in immediate operators in python bindings 2024-09-12 11:11:15 +02:00
Matthias Hochsteger
cef04cfd2a Utility tool to wait until package is available on pypi 2024-09-11 12:08:47 +02:00
Lackner, Christopher
b955c377f1 Merge branch 'project_added_edge' into 'master'
Project added Element1D/Element2D

See merge request ngsolve/netgen!655
2024-09-09 17:18:04 +02:00
Lackner, Christopher
f807be50c2 Project added Element1D/Element2D 2024-09-09 17:18:04 +02:00
Matthias Hochsteger
a504372f82 Fix Mesh::GetSubMesh for 2d meshes 2024-09-05 14:46:57 +02:00
Joachim Schoeberl
bb3c3ff565 fix warning 2024-09-03 11:11:51 +02:00
Lackner, Christopher
c096536e32 Merge branch 'pickle_ident_names' into 'master'
pickle identification names

See merge request ngsolve/netgen!667
2024-09-02 16:46:57 +02:00
Christopher Lackner
d014119b19 pickle identification names 2024-09-02 16:35:57 +02:00
Matthias Hochsteger
508136b533 Fix memory leak in TaskManager (thx @roystgnr) 2024-09-02 10:15:28 +02:00
Matthias Hochsteger
00664898c3 Fix building with USE_NUMA 2024-09-02 10:14:04 +02:00
Schöberl, Joachim
16c49d41eb Merge branch 'write_identificationnames_mesh' into 'master'
write identification names into mesh

See merge request ngsolve/netgen!666
2024-08-30 11:19:08 +02:00
Christopher Lackner
bda192ba90 write identification names into mesh 2024-08-30 11:01:03 +02:00
Matthias Hochsteger
7f5df05bb7 Force cmake to use/find static zlibs for pip builds 2024-08-29 16:35:40 +02:00
Matthias Hochsteger
725576fc42 Fix pip dev version numbering 2024-08-29 14:28:05 +02:00
Matthias Hochsteger
18ea280388 Check if pip package already available before building 2024-08-29 14:13:16 +02:00
Matthias Hochsteger
a009825d83 Fix linking zlib in MacOS pip builds 2024-08-28 18:14:27 +02:00
Matthias Hochsteger
fd7e5867b4 Use static zlib everywhere if it is built during superbuild 2024-08-28 18:01:08 +02:00
Schöberl, Joachim
79d385dc0b Merge branch 'fix_identification_on_layered_mesh' into 'master'
fix periodic identifications for meshes where edges touch

See merge request ngsolve/netgen!665
2024-08-28 11:48:08 +02:00
Christopher Lackner
1497bf36cc fix periodic identifications for meshes where edges touch 2024-08-28 11:07:11 +02:00
Schöberl, Joachim
69f2ea5635 Merge branch 'fix_mt_swap_in_array_move' into 'master'
fix size of me in mt swap in array move constructor

See merge request ngsolve/netgen!664
2024-08-27 19:03:43 +02:00
Lackner, Christopher
4964691fd9 Merge branch 'add_inner_point_check' into 'master'
add check if any inner points are in polygon when adding inner point

See merge request ngsolve/netgen!663
2024-08-27 18:53:50 +02:00
Christopher Lackner
334c3fe702 fix size of me in mt swap in array move constructor 2024-08-27 18:33:36 +02:00
Christopher Lackner
72e861be80 add check if any inner points are in polygon when adding inner point 2024-08-27 17:41:20 +02:00
Schöberl, Joachim
2e3264ec69 Merge branch 'segment_set_index_edgenr' into 'master'
add property setter for index and edgenr for segment

See merge request ngsolve/netgen!662
2024-08-26 17:39:10 +02:00
Christopher Lackner
c032ad58ca add property setter for index and edgenr for segment 2024-08-26 16:37:50 +02:00
Christopher Lackner
1772e01edb update IdentifyPeriodicBoundaries to also support 2d meshes (and more stable) 2024-08-26 16:37:08 +02:00
Schöberl, Joachim
0fb5b416ba Merge branch 'raise_len_error_not_ngs' into 'master'
Raise len error not ngs

See merge request ngsolve/netgen!659
2024-08-26 12:35:09 +02:00
Schöberl, Joachim
5103dac8d4 Merge branch 'fix_pybind11_warning' into 'master'
fix pybind11 exception binding warning

See merge request ngsolve/netgen!661
2024-08-26 12:34:19 +02:00
Christopher Lackner
c7800704b0 fix pybind11 exception binding warning 2024-08-26 12:21:56 +02:00
Christopher Lackner
d9247d094b netgen trafo.mat returns Mat<3,3> and takes Mat<3,3> 2024-08-26 11:49:35 +02:00
Lackner, Christopher
4f399675ce Merge branch 'fix_identify_periodic_2d' into 'master'
fix IdentifyPeriodic points in mesh in 2d mesh

See merge request ngsolve/netgen!660
2024-08-26 11:34:54 +02:00
Christopher Lackner
945bf2b3a3 raise length_error not netgen::Exception on wrong tuple size 2024-08-26 11:14:29 +02:00
Christopher Lackner
d72801d19a fix IdentifyPeriodic points in mesh in 2d mesh 2024-08-26 11:13:56 +02:00
Matthias Hochsteger
7f666547c9 Fix file extension check in snapshot function 2024-08-07 10:49:50 +02:00
Joachim Schoeberl
325175c88f comment deprecated function 2024-07-20 10:53:59 +02:00
Joachim Schoeberl
53b08efc6a remove commented code 2024-07-20 10:38:01 +02:00
Joachim Schoeberl
cb8c7850ba fix (false) warnings 2024-07-20 10:25:45 +02:00
Joachim Schoeberl
487942bc22 ThrowRangeException with [[noreturn]] 2024-07-19 22:30:34 +02:00
Joachim Schoeberl
3c9f98b38d save index bypasses range-check 2024-07-19 12:33:56 +02:00
Joachim Schoeberl
8f762bc33d std::move in register_archive 2024-07-18 18:57:06 +02:00
Matthias Hochsteger
62d2e4fba5 Copy ctor for IVec 2024-07-18 15:07:41 +02:00
Joachim Schoeberl
4fd89120b8 sqr is constexpr 2024-07-18 09:44:45 +02:00
Joachim Schoeberl
ad99e5fdea Exception::Throw 2024-07-17 18:01:59 +02:00
Joachim Schoeberl
ba472f7a11 Exception::Throw 2024-07-17 17:58:38 +02:00
Joachim Schoeberl
357ff7badf exception with stringview 2024-07-17 12:01:59 +02:00
Joachim Schoeberl
b6b20be30b IVec with HTArray 2024-07-16 19:20:07 +02:00
Joachim Schoeberl
e075d32f14 fix unused warning 2024-07-16 16:50:28 +02:00
Joachim Schoeberl
bac10cf1fb go back to C-array (since tests fail) 2024-07-16 16:11:20 +02:00
Joachim Schoeberl
7968ae4588 use std::array in IVec (for 0-size handling) 2024-07-16 13:48:17 +02:00
Joachim Schoeberl
54d59cff1e fix warnings 2024-07-16 13:03:49 +02:00
Joachim Schoeberl
20e0b3efa5 replace const string& by string_view in Flags and SymbolTable 2024-07-16 12:44:04 +02:00
Joachim Schoeberl
63986a4e5f throw range exception via function call -> reduces code size 2024-07-16 10:18:16 +02:00
Joachim Schoeberl
304ce7364a mpi-send of 0D-elements 2024-07-14 20:38:36 +02:00
Joachim Schoeberl
f1e06f0a6d pickling 0D-elements 2024-07-12 18:21:46 +02:00
Hochsteger, Matthias
5e9d22e496 Merge branch 'fix_face_colors_in_blayers' into 'master'
Fix reading face_colors and face_transparencies for faces without attached geometry surface

See merge request ngsolve/netgen!658
2024-07-10 19:02:10 +02:00
Matthias Hochsteger
da743467fb Fix reading face_colors and face_transparencies for faces without attached geometry surface 2024-07-10 10:36:03 +02:00
Matthias Hochsteger
78832cb7c5 Fix building with mpi wrapper but without python support 2024-07-08 11:48:27 +02:00
Hochsteger, Matthias
151c8da887 Merge branch 'fix_no_python_build' into 'master'
Fix building without Python

See merge request ngsolve/netgen!657
2024-07-04 17:36:34 +02:00
Matthias Hochsteger
d987051f2b Fix building without Python 2024-07-04 17:26:47 +02:00
Matthias Hochsteger
000a312dc2 Use same color for shifted faces in boundary layer generation 2024-07-04 15:00:50 +02:00
Matthias Hochsteger
6091669e28 Build pip Post Releases from release branch 2024-07-02 12:53:03 +02:00
Christopher Lackner
3974191ffa correctly check for degenerated edges 2024-06-27 21:00:52 +02:00
Matthias Hochsteger
a2d9455627 Fix compiling with cuda and active mem-tracer 2024-06-27 11:29:26 +02:00
Matthias Hochsteger
73822401f1 Make sure the GIL is held on cleanup 2024-06-25 17:13:32 +02:00
Lackner, Christopher
32f291c66e Merge branch 'binary_brep' into 'master'
allow reading of binary brep files

See merge request ngsolve/netgen!654
2024-06-24 18:28:10 +02:00
Matthias Hochsteger
e7e945a84c Use netgen-occt to build netgen 2024-06-24 16:18:41 +02:00
Joachim Schoeberl
f9d7d3a4fd store newest vertex from bisection 2024-06-24 15:30:08 +02:00
Christopher Lackner
3709ea8f94 allow reading of binary brep files 2024-06-21 15:16:47 +02:00
Matthias Hochsteger
af5e003790 Fix GIL issue (see previous commit for details) 2024-06-21 11:51:12 +02:00
Matthias Hochsteger
163135981e Fix GIL issues in GenerateMesh() functions
Functions with a python typed argument (kwargs in this case) cannot use
  py::call_guard<py::gil_scoped_release>()
because it means, the GIL is not held when the function returns (and
cleans up arguments/temporary variables).

Thus, remove the global call guard and create a local variable
  py::gil_scoped_release gil_release;
after arguments are processed and before meshing starts.

This local variable is destroyed before the function returns
(acquiring the GIL again).
2024-06-21 11:36:37 +02:00
Matthias Hochsteger
c2f42f2f16 Backward compatibility for occ geometry loading (from mesh file) 2024-06-20 18:05:43 +02:00
Christopher Lackner
eff5e946f7 fix export of submesh faces 2024-06-20 11:12:01 +02:00
Matthias Hochsteger
690eb2093a Update pybind11 for Numpy 2 compatibility
Use pybind11 v2.12 with an additional commit to allow
compatibility across MSVC versions
2024-06-18 09:46:37 +02:00
Matthias Hochsteger
15ee1c9fae Pip - build recent py versions first, upload them immediately on linux 2024-06-15 23:46:45 +02:00
Matthias Hochsteger
3329834560 Set dev or release build for pip by env variable 2024-06-15 23:41:11 +02:00
Matthias Hochsteger
919000a5ef Add optional arguments "center" and "radius" to webgui.Draw() 2024-06-15 16:35:23 +02:00
220 changed files with 9902 additions and 19271 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

@ -32,13 +32,23 @@ push_github:
- "echo off"
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64"
- set CI_DIR=C:\ci\%CI_PIPELINE_ID%
- set CLCACHE_BASEDIR=C:\ci\%CI_PIPELINE_ID%
- set CCACHE_BASEDIR=C:\ci\%CI_PIPELINE_ID%
- set NETGEN_BUILD_DIR=%CI_DIR%\build
- set INSTALL_DIR=%CI_DIR%\install
- set SRC_DIR=%CI_DIR%\src
- set NETGENDIR=%INSTALL_DIR%\bin
- set PYTHONPATH=%INSTALL_DIR%\lib\site-packages
- set PATH=%NETGENDIR%;%PATH%
- echo %PATH%
- set PATH=%INSTALL_DIR%\bin;C:\python312;C:\python312\bin;C:\python312\Scripts;C:\tools\;%PATH%
- echo %PATH%
- set CCACHE_HARDLINK=1
- set CCACHE_NOHASHDIR=1
- C:\tools\ccache -s
- C:\tools\ccache -M 20G
- dir C:\python312
- python.exe --version
- python.exe -m pip install -U netgen-occt netgen-occt-devel
- cmake --version
build_win:
<<: *win
@ -54,12 +64,14 @@ build_win:
- >-
cmake %SRC_DIR%
-G Ninja
-DCMAKE_PREFIX=C:/python312
-DPython3_ROOT_DIR=C:/python312
-DCMAKE_INSTALL_PREFIX=%INSTALL_DIR%
-DCHECK_RANGE=ON
-DUSE_CGNS=ON
-DUSE_OCC=ON
-DUSE_CCACHE=ON
-DENABLE_UNIT_TESTS=ON
-DENABLE_UNIT_TESTS=OFF
-DCMAKE_BUILD_TYPE=Release
- cmake --build . --target install --config Release
@ -69,11 +81,20 @@ test_win:
script:
- pip install pytest-check
- cd tests\pytest
- python test_tutorials.py new_results.json
- cd %NETGEN_BUILD_DIR%\netgen
- ctest -C Release -V --output-on-failure
- cd ..
needs: ["build_win"]
generate_results:
<<: *win
stage: test
script:
- pip install pytest-check
- cd tests\pytest
- python test_tutorials.py new_results.json
needs: ["build_win"]
when: manual
artifacts:
paths:
- tests/pytest/new_results.json
@ -260,7 +281,7 @@ cleanup_mac:
needs: ["test_mac"]
pip_linux:
image: quay.io/pypa/manylinux2014_x86_64
image: quay.io/pypa/manylinux_2_28_x86_64
stage: build
tags:
- pip
@ -276,11 +297,11 @@ pip_windows:
- pip
- windows
script:
- .\tests\build_pip.ps1 C:\Python38
- .\tests\build_pip.ps1 C:\Python39
- .\tests\build_pip.ps1 C:\Python310
- .\tests\build_pip.ps1 C:\Python311
- .\tests\build_pip.ps1 C:\Python313
- .\tests\build_pip.ps1 C:\Python312
- .\tests\build_pip.ps1 C:\Python311
- .\tests\build_pip.ps1 C:\Python310
- .\tests\build_pip.ps1 C:\Python39
when: manual
pip_macos:
@ -290,9 +311,9 @@ pip_macos:
- macosx
- m1
script:
- ./tests/build_pip_mac.sh 3.8
- ./tests/build_pip_mac.sh 3.9
- ./tests/build_pip_mac.sh 3.10
- ./tests/build_pip_mac.sh 3.11
- ./tests/build_pip_mac.sh 3.13
- ./tests/build_pip_mac.sh 3.12
- ./tests/build_pip_mac.sh 3.11
- ./tests/build_pip_mac.sh 3.10
- ./tests/build_pip_mac.sh 3.9
when: manual

View File

@ -164,6 +164,7 @@ if(USE_CCACHE)
find_program(CCACHE_FOUND NAMES ccache ccache.bat)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_FOUND})
message(STATUS "Using ccache ${CCACHE_FOUND}")
endif(CCACHE_FOUND)
endif(USE_CCACHE)
@ -398,7 +399,12 @@ if (USE_OCC)
endif()
target_link_libraries(occ_libs INTERFACE ${OCC_LIBRARIES})
include_directories(${OpenCASCADE_INCLUDE_DIR})
get_target_property(occ_include_dir TKernel INTERFACE_INCLUDE_DIRECTORIES)
if(NOT occ_include_dir)
set(occ_include_dir ${OpenCASCADE_INCLUDE_DIR})
endif()
target_include_directories(occ_libs INTERFACE ${occ_include_dir})
message(STATUS "OpenCasCade include dirs: ${occ_include_dir}")
if(NOT OpenCASCADE_BUILD_SHARED_LIBS)
if(OpenCASCADE_WITH_FREETYPE)
find_library( FREETYPE NAMES freetype HINTS ${OpenCASCADE_LIBRARY_DIR})
@ -413,10 +419,12 @@ if (USE_OCC)
find_package(Threads REQUIRED)
target_link_libraries(occ_libs INTERFACE Threads::Threads)
endif()
message(STATUS "OCC DIRS ${OpenCASCADE_INCLUDE_DIR}")
if(WIN32 AND USE_GUI)
target_link_libraries(nggui PRIVATE occ_libs Ws2_32.lib)
target_link_libraries(nggui PRIVATE Ws2_32.lib)
endif(WIN32 AND USE_GUI)
if(USE_GUI)
target_link_libraries(nggui PRIVATE occ_libs)
endif(USE_GUI)
endif (USE_OCC)
#######################################################################

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)
@ -120,27 +120,14 @@ if(BUILD_OCC)
list(APPEND NETGEN_DEPENDENCIES project_occ)
set(OpenCascade_ROOT ${OCC_DIR})
else(BUILD_OCC)
if(WIN32 AND NOT OCC_INCLUDE_DIR AND NOT OpenCASCADE_DIR)
# we can download prebuilt occ binaries for windows
ExternalProject_Add(win_download_occ
${SUBPROJECT_ARGS}
URL ${OCC_DOWNLOAD_URL_WIN}
UPDATE_COMMAND "" # Disable update
BUILD_IN_SOURCE 1
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}
)
list(APPEND NETGEN_DEPENDENCIES win_download_occ)
else()
find_package(OpenCascade NAMES OpenCasCade OpenCASCADE opencascade)
if(NOT OpenCascade_FOUND)
message(FATAL_ERROR "Opencascade not found, either\n\
- set OpenCascade_DIR to a directory containting opencascadeConfig.cmake\n\
- build OpenCascade automatically by passing -DBUILD_OCC=ON\n\
- disable OpenCascade by passing -DUSE_OCC=OFF\n\
")
endif()
find_package(OpenCascade NAMES OpenCasCade OpenCASCADE opencascade)
if(NOT OpenCascade_FOUND)
message(FATAL_ERROR "Opencascade not found, either\n\
- install pip packages netgen-occt-devel netgen-occ\n\
- set OpenCascade_DIR to a directory containting opencascadeConfig.cmake\n\
- build OpenCascade automatically by passing -DBUILD_OCC=ON\n\
- disable OpenCascade by passing -DUSE_OCC=OFF\n\
")
endif()
endif(BUILD_OCC)
endif(USE_OCC)
@ -164,9 +151,11 @@ if(BUILD_ZLIB)
# force linking the static library
set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)
set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/zlibstatic.lib)
elseif(EMSCRIPTEN)
set(ZLIB_LIBRARY_RELEASE ${ZLIB_ROOT}/lib/zlibstatic.lib)
else(WIN32)
set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)
set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/libz.a)
set(ZLIB_LIBRARY_RELEASE ${ZLIB_ROOT}/lib/libz.a)
endif(WIN32)
else()
include(cmake/external_projects/zlib.cmake)
@ -270,6 +259,7 @@ set_vars( NETGEN_CMAKE_ARGS
OpenCascade_ROOT
ZLIB_INCLUDE_DIRS
ZLIB_LIBRARIES
ZLIB_LIBRARY_RELEASE
ZLIB_ROOT
NGLIB_LIBRARY_TYPE

View File

@ -51,12 +51,17 @@ if(APPLE OR WIN32)
NO_SYSTEM_ENVIRONMENT_PATH
NO_CMAKE_SYSTEM_PATH
NO_CMAKE_FIND_ROOT_PATH
HINTS ${PYTHON_PREFIX}/lib ${PYTHON_PREFIX}/tcl
HINTS
${PYTHON_PREFIX}/lib
${PYTHON_PREFIX}/tcl
${PYTHON_PREFIX}/Frameworks
${PYTHON_PREFIX}/Frameworks/Tcl.framework
${PYTHON_PREFIX}/Frameworks/Tk.framework
)
find_library(TCL_STUB_LIBRARY NAMES tclstub85 tclstub8.5 tclstub86 tclstub8.6 ${tcl_find_args})
find_library(TK_STUB_LIBRARY NAMES tkstub85 tkstub8.5 tkstub86 tkstub8.6 ${tcl_find_args})
find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t ${tcl_find_args})
find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t ${tcl_find_args})
find_library(TCL_LIBRARY NAMES tcl85 tcl8.5 tcl86 tcl8.6 tcl86t Tcl ${tcl_find_args})
find_library(TK_LIBRARY NAMES tk85 tk8.5 tk86 tk8.6 tk86t Tk ${tcl_find_args})
else()
# use system tcl/tk on linux
find_package(TclStub REQUIRED)
@ -104,6 +109,7 @@ if(APPLE)
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}/Contents/MacOS
-DTCL_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework/Headers
-DTK_INCLUDE_PATH=${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/Headers
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
${SUBPROJECT_ARGS}
)

@ -1 +1 @@
Subproject commit 80dc998efced8ceb2be59756668a7e90e8bef917
Subproject commit 38bf7b174875c27c1ba98bdf5a9bf13d967f14d4

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

@ -1,6 +1,7 @@
#ifndef NETGEN_CORE_ARCHIVE_HPP
#define NETGEN_CORE_ARCHIVE_HPP
#include <algorithm>
#include <any>
#include <array> // for array
#include <complex> // for complex
@ -77,7 +78,8 @@ namespace ngcore
{
template <class T, class Tuple, size_t... Is>
T* construct_from_tuple(Tuple&& tuple, std::index_sequence<Is...> ) {
return new T{std::get<Is>(std::forward<Tuple>(tuple))...};
// return new T{std::get<Is>(std::forward<Tuple>(tuple))...};
return new T{std::get<Is>(std::move(tuple))...};
}
template <class T, class Tuple>
@ -1135,15 +1137,32 @@ namespace ngcore
{ char c; *stream >> c; b = (c=='t'); return *this; }
Archive & operator & (std::string & str) override
{
// Ignore \r (carriage return) characters when reading strings
// this is necessary for instance when a file was written on Windows and is read on Unix
int len;
*stream >> len;
char ch;
stream->get(ch); // '\n'
stream->get(ch); // read newline character
if(ch == '\r') // windows line endings -> read \n as well
stream->get(ch);
str.resize(len);
if(len)
stream->get(&str[0], len+1, '\0');
// remove all \r characters from the string, check if size changed
// if so, read the remaining characters
str.erase(std::remove(str.begin(), str.end(), '\r'), str.cend());
size_t chars_to_read = len-str.size();
while (chars_to_read>0)
{
auto old_size = str.size();
str.resize(len);
stream->get(&str[old_size], chars_to_read+1, '\0');
str.erase(std::remove(str.begin()+old_size, str.end(), '\r'), str.cend());
chars_to_read = len - str.size();
}
return *this;
}
Archive & operator & (char *& str) override

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(sizeof(T) * allocsize, a2.mt, sizeof(T) * a2.allocsize);
mt = std::move(a2.mt);
size = a2.size;
data = a2.data;
allocsize = a2.allocsize;
@ -753,6 +769,7 @@ namespace ngcore
{
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*size);
for (size_t i = 0; i < size; i++)
data[i] = a2.data[i];
}
@ -772,6 +789,7 @@ namespace ngcore
{
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*size);
/*
for (size_t i = 0; i < size; i++)
data[i] = a2[i];
@ -788,6 +806,7 @@ namespace ngcore
{
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*size);
size_t cnt = 0;
for (auto val : list)
data[cnt++] = val;
@ -800,6 +819,7 @@ namespace ngcore
{
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*size);
for(size_t i = 0; i < a2.Size(); i++)
data[i] = a2[i];
for (size_t i = a2.Size(), j=0; i < size; i++,j++)
@ -834,6 +854,9 @@ namespace ngcore
NETGEN_INLINE void NothingToDelete ()
{
mem_to_delete = nullptr;
// this memory is not managed by the Array anymore, so set the memory usage to 0
mt.Free(sizeof(T)*allocsize);
}
/// Change logical size. If necessary, do reallocation. Keeps contents.
@ -947,7 +970,7 @@ namespace ngcore
/// Delete element i. Move last element to position i.
NETGEN_INLINE void DeleteElement (size_t i)
NETGEN_INLINE void DeleteElement (IndexType i)
{
NETGEN_CHECK_RANGE(i,BASE,BASE+size);
data[i-BASE] = std::move(data[size-1]);
@ -956,10 +979,10 @@ namespace ngcore
/// Delete element i. Move all remaining elements forward
NETGEN_INLINE void RemoveElement (size_t i)
NETGEN_INLINE void RemoveElement (IndexType i)
{
NETGEN_CHECK_RANGE(i, BASE, BASE+size);
for(size_t j = i; j < this->size-1; j++)
for(size_t j = i-BASE; j+1 < this->size; j++)
this->data[j] = this->data[j+1];
this->size--;
}
@ -1011,8 +1034,7 @@ namespace ngcore
/// steal array
NETGEN_INLINE Array & operator= (Array && a2)
{
mt.Swap(sizeof(T)*allocsize, a2.mt, sizeof(T)*a2.allocsize);
mt = std::move(a2.mt);
ngcore::Swap (size, a2.size);
ngcore::Swap (data, a2.data);
ngcore::Swap (allocsize, a2.allocsize);
@ -1086,8 +1108,7 @@ namespace ngcore
NETGEN_INLINE void Swap (Array & b)
{
mt.Swap(sizeof(T) * allocsize, b.mt, sizeof(T) * b.allocsize);
mt = std::move(b.mt);
ngcore::Swap (size, b.size);
ngcore::Swap (data, b.data);
ngcore::Swap (allocsize, b.allocsize);
@ -1096,7 +1117,8 @@ namespace ngcore
NETGEN_INLINE void StartMemoryTracing () const
{
mt.Alloc(sizeof(T) * allocsize);
if(mem_to_delete)
mt.Alloc(sizeof(T) * allocsize);
}
const MemoryTracer& GetMemoryTracer() const { return mt; }
@ -1105,7 +1127,6 @@ namespace ngcore
/// resize array, at least to size minsize. copy contents
NETGEN_INLINE void ReSize (size_t minsize);
MemoryTracer mt;
};
@ -1158,6 +1179,7 @@ namespace ngcore
using Array<T>::allocsize;
using Array<T>::data;
using Array<T>::mem_to_delete;
using Array<T>::mt;
// using Array<T>::ownmem;
public:
@ -1171,6 +1193,7 @@ namespace ngcore
data = new T[asize];
allocsize = size;
mem_to_delete = data;
mt.Alloc(sizeof(T)*asize);
}
}
@ -1191,6 +1214,7 @@ namespace ngcore
ArrayMem(ArrayMem && a2)
: Array<T> (a2.Size(), (T*)mem)
{
mt = std::move(a2.mt);
if (a2.mem_to_delete)
{
mem_to_delete = a2.mem_to_delete;
@ -1233,6 +1257,7 @@ namespace ngcore
ArrayMem & operator= (ArrayMem && a2)
{
mt = std::move(a2.mt);
ngcore::Swap (mem_to_delete, a2.mem_to_delete);
ngcore::Swap (allocsize, a2.allocsize);
ngcore::Swap (size, a2.size);
@ -1528,6 +1553,8 @@ namespace ngcore
}
struct HTAHelp { };
// head-tail array
template <size_t S, typename T>
class HTArray
@ -1535,10 +1562,22 @@ namespace ngcore
HTArray<S-1,T> tail;
T head;
public:
HTArray () = default;
HTArray (const HTArray &) = default;
constexpr HTArray () = default;
constexpr HTArray (const HTArray &) = default;
template <typename T2>
HTArray (const HTArray<S,T2> & a2) : tail(a2.Tail()), head(a2.Head()) { ; }
constexpr HTArray (const HTArray<S,T2> & a2) : tail(a2.Tail()), head(a2.Head()) { ; }
constexpr HTArray (T v) : tail(v), head(v) { } // all the same
template <class... T2,
std::enable_if_t<S==1+sizeof...(T2),bool> = true>
constexpr HTArray (const T &v, T2... rest)
: tail{HTAHelp(), v,rest...}, head(std::get<S-2>(std::tuple(rest...))) { }
template <class... T2>
constexpr HTArray (HTAHelp h, const T &v, T2... rest)
: tail{h, v,rest...}, head(std::get<S-2>(std::tuple(rest...))) { }
HTArray & operator= (const HTArray &) = default;
@ -1559,10 +1598,15 @@ namespace ngcore
{
T head;
public:
HTArray () = default;
HTArray (const HTArray &) = default;
constexpr HTArray () = default;
constexpr HTArray (const HTArray &) = default;
template <typename T2>
HTArray (const HTArray<1,T2> & a2) : head(a2.Head()) { ; }
constexpr HTArray (const HTArray<1,T2> & a2) : head(a2.Head()) { ; }
constexpr HTArray (T v) : head(v) { } // all the same
template <class... T2>
constexpr HTArray (HTAHelp h, const T &v, T2... rest)
: head(v) { }
HTArray & operator= (const HTArray &) = default;
@ -1590,7 +1634,7 @@ namespace ngcore
HTArray (const HTArray &) = default;
template <typename T2>
HTArray (const HTArray<0,T2> & a2) { ; }
constexpr HTArray (T v) { } // all the same
HTArray & operator= (const HTArray &) = default;
/*

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

@ -23,6 +23,47 @@ namespace ngcore
}
Exception :: Exception(std::string_view s1, std::string_view s2)
: Exception(std::string(s1)+std::string(s2))
{ }
Exception :: Exception(std::string_view s1, std::string_view s2, std::string_view s3)
: Exception(std::string(s1)+std::string(s2)+std::string(s3))
{ }
void Exception :: Throw (std::string_view s1)
{
throw Exception(std::string(s1));
}
void Exception :: Throw (std::string_view s1, std::string_view s2)
{
throw Exception(std::string(s1)+std::string(s2));
}
void Exception :: Throw (std::string_view s1, std::string_view s2, std::string_view s3)
{
throw Exception(std::string(s1)+std::string(s2)+std::string(s3));
}
RangeException :: RangeException (// const std::string & where,
const char * where,
ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax) : Exception("")
{
std::stringstream str;
str << where << ": index " << ind << " out of range [" << imin << "," << imax << ")\n";
Append (str.str());
Append (GetBackTrace());
}
void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax)
{
throw RangeException(s, ind, imin, imax);
}
void ThrowException(const std::string & s)
{
throw Exception (s);
@ -32,6 +73,13 @@ namespace ngcore
{
throw Exception (s);
}
void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b)
{
throw ngcore::Exception(std::string(s) + ", a="+ToString(a) + ", b="+ToString(b) + GetBackTrace());
}
} // namespace ngcore

View File

@ -1,11 +1,13 @@
#ifndef NETGEN_CORE_EXCEPTION_HPP
#define NETGEN_CORE_EXCEPTION_HPP
#include <cstddef>
#include <sstream> // for stringstream
#include <stdexcept> // for exception
#include <string> // for string
#include "ngcore_api.hpp" // for NGCORE_API
#include "utils.hpp" // for ToString
namespace ngcore
@ -32,8 +34,14 @@ namespace ngcore
Exception(Exception&&) = default;
Exception(const std::string& s); // : m_what(s) {}
Exception(const char* s); // : m_what(s) {}
Exception(std::string_view s1, std::string_view s2);
Exception(std::string_view s1, std::string_view s2, std::string_view s3);
~Exception() override = default;
[[noreturn]] static void Throw (std::string_view s1);
[[noreturn]] static void Throw (std::string_view s1, std::string_view s2);
[[noreturn]] static void Throw (std::string_view s1, std::string_view s2, std::string_view s3);
Exception& operator =(const Exception&) = default;
Exception& operator =(Exception&&) noexcept = default;
@ -49,23 +57,26 @@ namespace ngcore
const char* what() const noexcept override { return m_what.c_str(); }
};
NGCORE_API void ThrowException(const std::string & s);
NGCORE_API void ThrowException(const char * s);
[[noreturn]] NGCORE_API void ThrowException(const std::string & s);
[[noreturn]] NGCORE_API void ThrowException(const char * s);
// Out of Range exception
class NGCORE_API RangeException : public Exception
{
public:
/// where it occurs, index, minimal and maximal indices
RangeException (const std::string & where,
int ind, int imin, int imax) : Exception("")
RangeException (// const std::string & where,
const char * where,
ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);
/*
: Exception("")
{
std::stringstream str;
str << where << ": index " << ind << " out of range [" << imin << "," << imax << ")\n";
Append (str.str());
Append (GetBackTrace());
}
*/
template<typename T>
RangeException(const std::string& where, const T& value)
{
@ -75,9 +86,40 @@ namespace ngcore
}
};
[[noreturn]] NGCORE_API void ThrowRangeException(const char * s, ptrdiff_t ind, ptrdiff_t imin, ptrdiff_t imax);
[[noreturn]] NGCORE_API void ThrowNotTheSameException(const char * s, ptrdiff_t a, ptrdiff_t b);
// Exception used if no simd implementation is available to fall back to standard evaluation
class NGCORE_API ExceptionNOSIMD : public Exception
{ public: using Exception::Exception; };
template <typename T>
struct IsSafe {
constexpr operator bool() const { return false; } };
namespace detail {
template <typename T, typename Tmin, typename Tmax>
inline static constexpr void CheckRange(const char * s, const T& n, Tmin first, Tmax next)
{
if constexpr (!IsSafe<decltype(n)>())
if (n<first || n>=next)
ThrowRangeException(s, ptrdiff_t(n), ptrdiff_t(first), ptrdiff_t(next));
}
template <typename Ta, typename Tb>
inline static constexpr void CheckSame(const char * s, const Ta& a, const Tb& b)
{
if constexpr (!IsSafe<decltype(a)>() || !IsSafe<decltype(b)>())
if(a != b)
{
if constexpr(std::is_integral_v<decltype(a)> && std::is_same_v<decltype(a),decltype(b)>)
ThrowNotTheSameException(s, long(a), long(b)); \
else
throw Exception(std::string(s) + "\t: not the same, a="+ToString(a) + ", b="+ngcore::ToString(b) + GetBackTrace());
}
}
} // namespace detail
} // namespace ngcore
#define NETGEN_CORE_NGEXEPTION_STR_HELPER(x) #x
@ -87,20 +129,14 @@ namespace ngcore
#define NG_EXCEPTION(s) ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t"+std::string(s))
#if defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
#define NETGEN_CHECK_RANGE(value, min, max_plus_one) \
{ if ((value)<(min) || (value)>=(max_plus_one)) \
throw ngcore::RangeException(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", int(value), int(min), int(max_plus_one)); }
#define NETGEN_CHECK_SHAPE(a,b) \
{ if(a.Shape() != b.Shape()) \
throw ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t: shape don't match"); }
#define NETGEN_CHECK_SAME(a,b) \
{ if(a != b) \
throw ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t: not the same, a="+ToString(a) + ", b="+ToString(b) + GetBackTrace()); }
#define NETGEN_CHECK_RANGE(value, min, max_plus_one) ngcore::detail::CheckRange(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", value, min, max_plus_one);
#define NETGEN_CHECK_SAME(a,b) ngcore::detail::CheckSame(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", a, b);
#define NETGEN_NOEXCEPT
#else // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
#define NETGEN_CHECK_RANGE(value, min, max)
#define NETGEN_CHECK_SAME(a,b)
#define NETGEN_CHECK_SHAPE(a,b)
// #define NETGEN_CHECK_SHAPE(a,b)
#define NETGEN_NOEXCEPT noexcept
#endif // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)

View File

@ -16,6 +16,7 @@
namespace ngcore
{
using std::string;
using std::string_view;
using std::endl;
Flags :: Flags () { ; }
@ -209,18 +210,18 @@ namespace ngcore
}
double Flags :: GetNumFlag (const string & name, double def) const
double Flags :: GetNumFlag (string_view name, double def) const
{
if (numflags.Used (name))
return numflags[name];
return numflags[string(name)];
else
return def;
}
const double * Flags :: GetNumFlagPtr (const string & name) const
const double * Flags :: GetNumFlagPtr (string_view name) const
{
if (numflags.Used (name))
return & ((SymbolTable<double>&)numflags)[name];
return & ((SymbolTable<double>&)numflags)[string(name)];
else
return NULL;
}
@ -239,16 +240,16 @@ namespace ngcore
return defflags.Used (name);
}
*/
bool Flags :: GetDefineFlag (const string & name) const throw()
bool Flags :: GetDefineFlag (string_view name) const throw()
{
if (!defflags.Used (name)) return false;
return defflags[name];
if (!defflags.Used (string(name))) return false;
return defflags[string(name)];
}
xbool Flags :: GetDefineFlagX (const string & name) const throw()
xbool Flags :: GetDefineFlagX (string_view name) const throw()
{
if (!defflags.Used (name)) return maybe;
return bool(defflags[name]);
if (!defflags.Used (string(name))) return maybe;
return bool(defflags[string(name)]);
}
@ -296,32 +297,32 @@ namespace ngcore
return empty;
}
bool Flags :: StringFlagDefined (const string & name) const
bool Flags :: StringFlagDefined (string_view name) const noexcept
{
return strflags.Used (name);
}
bool Flags :: NumFlagDefined (const string &name) const
bool Flags :: NumFlagDefined (string_view name) const noexcept
{
return numflags.Used (name);
}
bool Flags :: FlagsFlagDefined (const string &name) const
bool Flags :: FlagsFlagDefined (string_view name) const noexcept
{
return flaglistflags.Used (name);
}
bool Flags :: StringListFlagDefined (const string & name) const
bool Flags :: StringListFlagDefined (string_view name) const noexcept
{
return strlistflags.Used (name);
}
bool Flags :: NumListFlagDefined (const string & name) const
bool Flags :: NumListFlagDefined (string_view name) const noexcept
{
return numlistflags.Used (name);
}
bool Flags :: AnyFlagDefined (const string& name) const
bool Flags :: AnyFlagDefined (string_view name) const noexcept
{
return anyflags.Used(name);
}

View File

@ -125,15 +125,15 @@ namespace ngcore
/// Returns std::string flag, default value if not exists
std::string GetStringFlag (const std::string & name, std::string def = "") const;
/// Returns numerical flag, default value if not exists
double GetNumFlag (const std::string & name, double def) const;
double GetNumFlag (std::string_view name, double def) const;
/// Returns address of numerical flag, null if not exists
const double * GetNumFlagPtr (const std::string & name) const;
const double * GetNumFlagPtr (std::string_view name) const;
/// Returns address of numerical flag, null if not exists
double * GetNumFlagPtr (const std::string & name);
/// Returns boolean flag
// int GetDefineFlag (const char * name) const;
bool GetDefineFlag (const std::string & name) const throw();
xbool GetDefineFlagX (const std::string & name) const throw();
bool GetDefineFlag (std::string_view name) const noexcept;
xbool GetDefineFlagX (std::string_view name) const noexcept;
/// Returns string list flag, empty array if not exist
const Array<std::string> & GetStringListFlag (const std::string & name) const;
/// Returns num list flag, empty array if not exist
@ -144,16 +144,16 @@ namespace ngcore
/// Test, if string flag is defined
bool StringFlagDefined (const std::string & name) const;
bool StringFlagDefined (std::string_view name) const noexcept;
/// Test, if num flag is defined
bool NumFlagDefined (const std::string & name) const;
bool NumFlagDefined (std::string_view name) const noexcept;
/// Test, if num flag is defined
bool FlagsFlagDefined (const std::string & name) const;
bool FlagsFlagDefined (std::string_view name) const noexcept;
/// Test, if string list flag is defined
bool StringListFlagDefined (const std::string & name) const;
bool StringListFlagDefined (std::string_view name) const noexcept;
/// Test, if num list flag is defined
bool NumListFlagDefined (const std::string & name) const;
bool AnyFlagDefined (const std::string& name) const;
bool NumListFlagDefined (std::string_view name) const noexcept;
bool AnyFlagDefined (std::string_view name) const noexcept;
/// number of string flags
int GetNStringFlags () const { return strflags.Size(); }

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*"),
@ -105,13 +106,13 @@ def generate_declarations():
name = f[1]
args = ", ".join(get_args(f))
code += f"NGCORE_API extern {ret} (*NG_{name})({args});\n"
nowrapper_code += f"static const auto NG_{name} = {name};\n"
nowrapper_code += f"#define NG_{name} {name}\n"
for typ, name in constants:
if typ.startswith("MPI_"):
typ = "NG_" + typ
code += f"NGCORE_API extern {typ} NG_{name};\n"
nowrapper_code += f"static const decltype({name}) NG_{name} = {name};\n"
nowrapper_code += f"#define NG_{name} {name}\n"
with open("ng_mpi_generated_declarations.hpp", "w") as f:
f.write("#ifdef NG_MPI_WRAPPER\n")

View File

@ -9,6 +9,7 @@
#include <string>
#include <tuple>
#include <optional>
// #include "mpi_wrapper.hpp"
#include "ngcore_api.hpp"
@ -46,16 +47,27 @@ namespace ngcore
class IVec
{
/// data
T i[(N>0)?N:1];
// T i[(N>0)?N:1];
HTArray<N,T> i;
public:
///
NETGEN_INLINE IVec () { }
constexpr NETGEN_INLINE IVec () = default;
constexpr NETGEN_INLINE IVec (const IVec & i1) : i(i1.i) { }
constexpr NETGEN_INLINE IVec (T ai1) : i(ai1) { }
template <class... T2,
std::enable_if_t<N==1+sizeof...(T2),bool> = true>
constexpr IVec (const T &v, T2... rest)
: i{v,rest...} { }
/*
/// init all
NETGEN_INLINE IVec (T ai1)
{
for (int j = 0; j < N; j++) { i[j] = ai1; }
for (int j = 0; j < N; j++) { i[j] = ai1; }
}
/// init i[0], i[1]
@ -77,11 +89,13 @@ namespace ngcore
/// init i[0], i[1], i[2]
NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4, T ai5, T ai6, T ai7, T ai8, T ai9)
: i{ai1, ai2, ai3, ai4, ai5, ai6, ai7, ai8, ai9 } { ; }
*/
template <typename ARCHIVE>
void DoArchive(ARCHIVE& ar)
{
ar.Do(i, N);
// ar.Do(i.begin(), N);
ar.Do(i.Ptr(), N);
}
template <int N2, typename T2>
@ -286,7 +300,7 @@ namespace ngcore
template <int N, typename TI>
NETGEN_INLINE size_t HashValue2 (const IVec<N,TI> & ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<N,TI> & ind, size_t mask)
{
IVec<N,size_t> lind = ind;
size_t sum = 0;
@ -297,14 +311,14 @@ namespace ngcore
/// hash value of 1 int
template <typename TI>
NETGEN_INLINE size_t HashValue2 (const IVec<1,TI> & ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<1,TI> & ind, size_t mask)
{
return ind[0] & mask;
}
/// hash value of 2 int
template <typename TI>
NETGEN_INLINE size_t HashValue2 (const IVec<2,TI> & ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<2,TI> & ind, size_t mask)
{
IVec<2,size_t> lind = ind;
return (113*lind[0]+lind[1]) & mask;
@ -312,17 +326,17 @@ namespace ngcore
/// hash value of 3 int
template <typename TI>
NETGEN_INLINE size_t HashValue2 (const IVec<3,TI> & ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<3,TI> & ind, size_t mask)
{
IVec<3,size_t> lind = ind;
return (113*lind[0]+59*lind[1]+lind[2]) & mask;
}
NETGEN_INLINE size_t HashValue2 (size_t ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (size_t ind, size_t mask)
{
return ind & mask;
}
NETGEN_INLINE size_t HashValue2 (int ind, size_t mask)
NETGEN_INLINE constexpr size_t HashValue2 (int ind, size_t mask)
{
return size_t(ind) & mask;
}
@ -577,7 +591,27 @@ namespace ngcore
return res;
}
template <typename T>
constexpr inline T InvalidHash() { return T(-1); }
template <typename T_HASH>
struct CHT_trait
{
constexpr static inline T_HASH Invalid() { return InvalidHash<T_HASH>(); }
constexpr static inline size_t HashValue (const T_HASH & hash, size_t mask) { return HashValue2(hash, mask); }
};
template <typename T1, typename T2>
struct CHT_trait<std::tuple<T1,T2>>
{
constexpr static inline std::tuple<T1,T2> Invalid() { return { CHT_trait<T1>::Invalid(), CHT_trait<T2>::Invalid() } ; }
constexpr static inline size_t HashValue (const std::tuple<T1,T2> & hash, size_t mask)
{
return (CHT_trait<T1>::HashValue(std::get<0>(hash), mask) + CHT_trait<T2>::HashValue(std::get<1>(hash),mask)) & mask;
}
};
/**
A closed hash-table.
@ -598,14 +632,18 @@ namespace ngcore
///
Array<T> cont;
///
T_HASH invalid = -1;
// T_HASH invalid = -1;
// static constexpr T_HASH invalid = InvalidHash<T_HASH>();
static constexpr T_HASH invalid = CHT_trait<T_HASH>::Invalid();
public:
///
ClosedHashTable (size_t asize = 128)
: size(RoundUp2(asize)), hash(size), cont(size)
{
mask = size-1;
hash = T_HASH(invalid);
// hash = T_HASH(invalid);
// hash = InvalidHash<T_HASH>();
hash = CHT_trait<T_HASH>::Invalid();
}
ClosedHashTable (ClosedHashTable && ht2) = default;
@ -614,7 +652,8 @@ namespace ngcore
ClosedHashTable (size_t asize, LocalHeap & lh)
: size(RoundUp2(asize)), mask(size-1), hash(size, lh), cont(size, lh)
{
hash = T_HASH(invalid);
// hash = T_HASH(invalid);
hash = InvalidHash<T_HASH>();
}
ClosedHashTable & operator= (ClosedHashTable && ht2) = default;
@ -639,7 +678,8 @@ namespace ngcore
size_t Position (const T_HASH ind) const
{
size_t i = HashValue2(ind, mask);
// size_t i = HashValue2(ind, mask);
size_t i = CHT_trait<T_HASH>::HashValue(ind, mask);
while (true)
{
if (hash[i] == ind) return i;
@ -661,7 +701,8 @@ namespace ngcore
{
if (UsedElements()*2 > Size()) DoubleSize();
size_t i = HashValue2 (ind, mask);
// size_t i = HashValue2 (ind, mask);
size_t i = CHT_trait<T_HASH>::HashValue (ind, mask);
while (true)
{
@ -706,6 +747,16 @@ namespace ngcore
return (Position (ahash) != size_t(-1));
}
inline std::optional<T> GetIfUsed (const T_HASH & ahash) const
{
size_t pos = Position (ahash);
if (pos != size_t(-1))
return cont[pos];
else
return std::nullopt;
}
void SetData (size_t pos, const T_HASH & ahash, const T & acont)
{
hash[pos] = ahash;
@ -783,6 +834,15 @@ namespace ngcore
hash = T_HASH(invalid);
used = 0;
}
template <typename ARCHIVE>
void DoArchive (ARCHIVE& ar)
{
ar & hash & cont;
ar & size & mask & used;
}
struct EndIterator { };
class Iterator
{
@ -800,24 +860,21 @@ namespace ngcore
while (nr < tab.Size() && !tab.UsedPos(nr)) nr++;
return *this;
}
bool operator!= (const Iterator & it2) { return nr != it2.nr; }
auto operator* () const
{
T_HASH hash;
T val;
tab.GetData(nr, hash,val);
return std::make_pair(hash,val);
}
bool operator!= (EndIterator it2) { return nr != tab.Size(); }
auto operator* () const { return tab.GetBoth(nr); }
};
Iterator begin() const { return Iterator(*this, 0); }
Iterator end() const { return Iterator(*this, Size()); }
EndIterator end() const { return EndIterator(); }
};
template <class T_HASH, class T>
ostream & operator<< (ostream & ost,
const ClosedHashTable<T_HASH,T> & tab)
{
/*
for (size_t i = 0; i < tab.Size(); i++)
if (tab.UsedPos(i))
{
@ -826,6 +883,9 @@ namespace ngcore
tab.GetData (i, key, val);
ost << key << ": " << val << ", ";
}
*/
for (auto [key,val] : tab)
ost << key << ": " << val << ", ";
return ost;
}
@ -1070,6 +1130,106 @@ namespace ngcore
return ost;
}
template <class T, class IndexType>
class CompressedTable
{
Table<T, size_t> table;
ClosedHashTable<IndexType, size_t> idmap;
public:
CompressedTable (Table<T, size_t> && atable, ClosedHashTable<IndexType, size_t> && aidmap)
: table(std::move(atable)), idmap(std::move(aidmap)) { }
FlatArray<T> operator[](IndexType id) const
{
if (auto nr = idmap.GetIfUsed(id))
return table[*nr];
else
return { 0, nullptr };
}
auto & GetTable() { return table; }
};
template <class T, typename IndexType>
class CompressedTableCreator
{
protected:
int mode; // 1 .. cnt, 2 .. cnt entries, 3 .. fill table
size_t nd; // number of entries;
ClosedHashTable<IndexType, size_t> idmap;
Array<int,size_t> cnt;
Table<T,size_t> table;
public:
CompressedTableCreator()
{ nd = 0; mode = 1; }
CompressedTable<T,IndexType> MoveTable()
{
return { std::move(table), std::move(idmap) };
}
bool Done () { return mode > 3; }
void operator++(int) { SetMode (mode+1); }
int GetMode () const { return mode; }
void SetMode (int amode)
{
mode = amode;
if (mode == 2)
{
cnt.SetSize(nd);
cnt = 0;
}
if (mode == 3)
{
table = Table<T,size_t> (cnt);
cnt = 0;
}
}
void Add (IndexType blocknr, const T & data)
{
switch (mode)
{
case 1:
{
if (!idmap.Used (blocknr))
idmap[blocknr] = nd++;
break;
}
case 2:
cnt[idmap.Get(blocknr)]++;
break;
case 3:
size_t cblock = idmap.Get(blocknr);
int ci = cnt[cblock]++;
table[cblock][ci] = data;
break;
}
}
};
} // namespace ngcore

View File

@ -35,11 +35,16 @@ namespace ngcore
class MemoryTracer
{
#ifdef NETGEN_TRACE_MEMORY
#if defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)
NGCORE_API static std::vector<std::string> names;
NGCORE_API static std::vector<int> parents;
static int CreateId(const std::string& name)
#if defined(NETGEN_CHECK_RANGE)
NGCORE_API static std::atomic<size_t> total_memory;
mutable size_t allocated_memory = 0;
#endif // NETGEN_CHECK_RANGE
static int CreateId(const std::string& name = "")
{
int id = names.size();
names.push_back(name);
@ -48,7 +53,7 @@ namespace ngcore
std::cerr << "Allocated " << id << " MemoryTracer objects" << std::endl;
return id;
}
int id;
mutable int id = 0;
public:
@ -57,8 +62,33 @@ namespace ngcore
id = CreateId(name);
}
// not tracing
MemoryTracer() : id(0) {}
MemoryTracer() { }
MemoryTracer(const MemoryTracer & tracer)
{
(*this) = tracer;
}
MemoryTracer(MemoryTracer && tracer)
{
(*this) = std::move(tracer);
}
MemoryTracer & operator=(const MemoryTracer & tracer) {
if(tracer.id)
id = CreateId(names[tracer.id]);
return *this;
}
MemoryTracer & operator=(MemoryTracer && tracer) {
ngcore::Swap(id, tracer.id);
#if defined(NETGEN_CHECK_RANGE)
ngcore::Swap(allocated_memory, tracer.allocated_memory);
#endif // NETGEN_CHECK_RANGE
return *this;
}
template <typename... TRest>
MemoryTracer( std::string name, TRest & ... rest )
@ -67,38 +97,48 @@ namespace ngcore
Track(rest...);
}
#if defined(NETGEN_CHECK_RANGE)
// check if all memory was freed when object is destroyed
~MemoryTracer()
{
NETGEN_CHECK_SAME(allocated_memory, 0);
}
#endif // NETGEN_CHECK_RANGE
NETGEN_INLINE void Alloc(size_t size) const
{
#if defined(NETGEN_CHECK_RANGE)
// Trace also nameless Memtracer objects if range checks are active
if(!id && size)
id = CreateId();
#endif // NETGEN_CHECK_RANGE
if(id && trace)
trace->AllocMemory(id, size);
#if defined(NETGEN_CHECK_RANGE)
if(id)
{
allocated_memory += size;
total_memory += size;
}
#endif // NETGEN_CHECK_RANGE
}
void Free(size_t size) const
{
if(id && trace)
trace->FreeMemory(id, size);
}
void Swap(size_t mysize, MemoryTracer& other, size_t other_size) const
{
if(!trace || (id == 0 && other.id == 0))
return;
if(id == 0)
return trace->ChangeMemory(other.id, mysize - other_size);
if(other.id == 0)
return trace->ChangeMemory(id, other_size - mysize);
// first decrease memory, otherwise have artificial/wrong high peak memory usage
if(mysize<other_size)
{
trace->ChangeMemory(other.id, mysize-other_size);
trace->ChangeMemory(id, other_size-mysize);
}
else
{
trace->ChangeMemory(id, other_size-mysize);
trace->ChangeMemory(other.id, mysize-other_size);
}
#if defined(NETGEN_CHECK_RANGE)
if(id)
{
// check if we have at least size bytes of memory currently allocated (such that allocated_memory doesn't get negative)
NETGEN_CHECK_RANGE(allocated_memory, static_cast<ptrdiff_t>(size), std::numeric_limits<ptrdiff_t>::max());
allocated_memory -= size;
total_memory -= size;
#endif // NETGEN_CHECK_RANGE
}
}
int GetId() const { return id; }
@ -148,7 +188,15 @@ namespace ngcore
static const std::vector<std::string> & GetNames() { return names; }
static const std::vector<int> & GetParents() { return parents; }
#else // NETGEN_TRACE_MEMORY
static size_t GetTotalMemory()
{
#if defined(NETGEN_CHECK_RANGE)
return total_memory;
#else
return 0;
#endif // NETGEN_CHECK_RANGE
}
#else // defined(NETGEN_TRACE_MEMORY) && !defined(__CUDA_ARCH__)
public:
MemoryTracer() {}
MemoryTracer( std::string /* name */ ) {}
@ -157,7 +205,6 @@ namespace ngcore
void Alloc(size_t /* size */) const {}
void Free(size_t /* size */) const {}
void Swap(...) const {}
int GetId() const { return 0; }
template <typename... TRest>
@ -166,6 +213,7 @@ namespace ngcore
static std::string GetName(int /* id */) { return ""; }
std::string GetName() const { return ""; }
void SetName(std::string /* name */) const {}
static size_t GetTotalMemory() { return 0; }
#endif // NETGEN_TRACE_MEMORY
};
} // namespace ngcore

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

@ -7,16 +7,16 @@
#include "array.hpp"
#include "ngcore_api.hpp"
#include "pybind11/pytypes.h"
#ifdef NG_PYTHON
#include "pybind11/pytypes.h"
#include "python_ngcore.hpp"
#endif
#define MPI4PY_LIMITED_API 1
#define MPI4PY_LIMITED_API_SKIP_MESSAGE 1
#define MPI4PY_LIMITED_API_SKIP_SESSION 1
#include "mpi4py_pycapi.h" // mpi4py < 4.0.0
#endif
#ifdef MSMPI_VER
int MPI_Comm_create_group(MPI_Comm arg0, MPI_Group arg1, int arg2,
@ -164,7 +164,7 @@ void ng_init_mpi() {
imported_mpi4py = true;
}
PyObject* py_src = src.ptr();
auto type = Py_TYPE(py_src);
[[maybe_unused]] auto type = Py_TYPE(py_src);
if (PyObject_TypeCheck(py_src, &PyMPIComm_Type)) {
dst = mpi2ng(*PyMPIComm_Get(py_src));
return !PyErr_Occurred();

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*);
@ -75,79 +76,80 @@ NGCORE_API extern int NG_MPI_THREAD_SINGLE;
NGCORE_API extern int NG_MPI_VERSION;
NGCORE_API extern void* NG_MPI_IN_PLACE;
#else // NG_MPI_WRAPPER
static const auto NG_MPI_Wtime = MPI_Wtime;
static const auto NG_MPI_Allgather = MPI_Allgather;
static const auto NG_MPI_Allreduce = MPI_Allreduce;
static const auto NG_MPI_Alltoall = MPI_Alltoall;
static const auto NG_MPI_Barrier = MPI_Barrier;
static const auto NG_MPI_Bcast = MPI_Bcast;
static const auto NG_MPI_Comm_c2f = MPI_Comm_c2f;
static const auto NG_MPI_Comm_create = MPI_Comm_create;
static const auto NG_MPI_Comm_create_group = MPI_Comm_create_group;
static const auto NG_MPI_Comm_free = MPI_Comm_free;
static const auto NG_MPI_Comm_group = MPI_Comm_group;
static const auto NG_MPI_Comm_rank = MPI_Comm_rank;
static const auto NG_MPI_Comm_size = MPI_Comm_size;
static const auto NG_MPI_Finalize = MPI_Finalize;
static const auto NG_MPI_Gather = MPI_Gather;
static const auto NG_MPI_Gatherv = MPI_Gatherv;
static const auto NG_MPI_Get_count = MPI_Get_count;
static const auto NG_MPI_Get_processor_name = MPI_Get_processor_name;
static const auto NG_MPI_Group_incl = MPI_Group_incl;
static const auto NG_MPI_Init = MPI_Init;
static const auto NG_MPI_Init_thread = MPI_Init_thread;
static const auto NG_MPI_Initialized = MPI_Initialized;
static const auto NG_MPI_Iprobe = MPI_Iprobe;
static const auto NG_MPI_Irecv = MPI_Irecv;
static const auto NG_MPI_Isend = MPI_Isend;
static const auto NG_MPI_Probe = MPI_Probe;
static const auto NG_MPI_Query_thread = MPI_Query_thread;
static const auto NG_MPI_Recv = MPI_Recv;
static const auto NG_MPI_Recv_init = MPI_Recv_init;
static const auto NG_MPI_Reduce = MPI_Reduce;
static const auto NG_MPI_Reduce_local = MPI_Reduce_local;
static const auto NG_MPI_Request_free = MPI_Request_free;
static const auto NG_MPI_Scatter = MPI_Scatter;
static const auto NG_MPI_Send = MPI_Send;
static const auto NG_MPI_Send_init = MPI_Send_init;
static const auto NG_MPI_Startall = MPI_Startall;
static const auto NG_MPI_Type_commit = MPI_Type_commit;
static const auto NG_MPI_Type_contiguous = MPI_Type_contiguous;
static const auto NG_MPI_Type_create_resized = MPI_Type_create_resized;
static const auto NG_MPI_Type_create_struct = MPI_Type_create_struct;
static const auto NG_MPI_Type_free = MPI_Type_free;
static const auto NG_MPI_Type_get_extent = MPI_Type_get_extent;
static const auto NG_MPI_Type_indexed = MPI_Type_indexed;
static const auto NG_MPI_Type_size = MPI_Type_size;
static const auto NG_MPI_Wait = MPI_Wait;
static const auto NG_MPI_Waitall = MPI_Waitall;
static const auto NG_MPI_Waitany = MPI_Waitany;
static const decltype(MPI_COMM_NULL) NG_MPI_COMM_NULL = MPI_COMM_NULL;
static const decltype(MPI_COMM_WORLD) NG_MPI_COMM_WORLD = MPI_COMM_WORLD;
static const decltype(MPI_CHAR) NG_MPI_CHAR = MPI_CHAR;
static const decltype(MPI_CXX_DOUBLE_COMPLEX) NG_MPI_CXX_DOUBLE_COMPLEX = MPI_CXX_DOUBLE_COMPLEX;
static const decltype(MPI_C_BOOL) NG_MPI_C_BOOL = MPI_C_BOOL;
static const decltype(MPI_DATATYPE_NULL) NG_MPI_DATATYPE_NULL = MPI_DATATYPE_NULL;
static const decltype(MPI_DOUBLE) NG_MPI_DOUBLE = MPI_DOUBLE;
static const decltype(MPI_FLOAT) NG_MPI_FLOAT = MPI_FLOAT;
static const decltype(MPI_INT) NG_MPI_INT = MPI_INT;
static const decltype(MPI_SHORT) NG_MPI_SHORT = MPI_SHORT;
static const decltype(MPI_UINT64_T) NG_MPI_UINT64_T = MPI_UINT64_T;
static const decltype(MPI_LOR) NG_MPI_LOR = MPI_LOR;
static const decltype(MPI_MAX) NG_MPI_MAX = MPI_MAX;
static const decltype(MPI_MIN) NG_MPI_MIN = MPI_MIN;
static const decltype(MPI_SUM) NG_MPI_SUM = MPI_SUM;
static const decltype(MPI_REQUEST_NULL) NG_MPI_REQUEST_NULL = MPI_REQUEST_NULL;
static const decltype(MPI_STATUSES_IGNORE) NG_MPI_STATUSES_IGNORE = MPI_STATUSES_IGNORE;
static const decltype(MPI_STATUS_IGNORE) NG_MPI_STATUS_IGNORE = MPI_STATUS_IGNORE;
static const decltype(MPI_ANY_SOURCE) NG_MPI_ANY_SOURCE = MPI_ANY_SOURCE;
static const decltype(MPI_ANY_TAG) NG_MPI_ANY_TAG = MPI_ANY_TAG;
static const decltype(MPI_MAX_PROCESSOR_NAME) NG_MPI_MAX_PROCESSOR_NAME = MPI_MAX_PROCESSOR_NAME;
static const decltype(MPI_PROC_NULL) NG_MPI_PROC_NULL = MPI_PROC_NULL;
static const decltype(MPI_ROOT) NG_MPI_ROOT = MPI_ROOT;
static const decltype(MPI_SUBVERSION) NG_MPI_SUBVERSION = MPI_SUBVERSION;
static const decltype(MPI_THREAD_MULTIPLE) NG_MPI_THREAD_MULTIPLE = MPI_THREAD_MULTIPLE;
static const decltype(MPI_THREAD_SINGLE) NG_MPI_THREAD_SINGLE = MPI_THREAD_SINGLE;
static const decltype(MPI_VERSION) NG_MPI_VERSION = MPI_VERSION;
static const decltype(MPI_IN_PLACE) NG_MPI_IN_PLACE = MPI_IN_PLACE;
#define NG_MPI_Wtime MPI_Wtime
#define NG_MPI_Allgather MPI_Allgather
#define NG_MPI_Allreduce MPI_Allreduce
#define NG_MPI_Alltoall MPI_Alltoall
#define NG_MPI_Barrier MPI_Barrier
#define NG_MPI_Bcast MPI_Bcast
#define NG_MPI_Ibcast MPI_Ibcast
#define NG_MPI_Comm_c2f MPI_Comm_c2f
#define NG_MPI_Comm_create MPI_Comm_create
#define NG_MPI_Comm_create_group MPI_Comm_create_group
#define NG_MPI_Comm_free MPI_Comm_free
#define NG_MPI_Comm_group MPI_Comm_group
#define NG_MPI_Comm_rank MPI_Comm_rank
#define NG_MPI_Comm_size MPI_Comm_size
#define NG_MPI_Finalize MPI_Finalize
#define NG_MPI_Gather MPI_Gather
#define NG_MPI_Gatherv MPI_Gatherv
#define NG_MPI_Get_count MPI_Get_count
#define NG_MPI_Get_processor_name MPI_Get_processor_name
#define NG_MPI_Group_incl MPI_Group_incl
#define NG_MPI_Init MPI_Init
#define NG_MPI_Init_thread MPI_Init_thread
#define NG_MPI_Initialized MPI_Initialized
#define NG_MPI_Iprobe MPI_Iprobe
#define NG_MPI_Irecv MPI_Irecv
#define NG_MPI_Isend MPI_Isend
#define NG_MPI_Probe MPI_Probe
#define NG_MPI_Query_thread MPI_Query_thread
#define NG_MPI_Recv MPI_Recv
#define NG_MPI_Recv_init MPI_Recv_init
#define NG_MPI_Reduce MPI_Reduce
#define NG_MPI_Reduce_local MPI_Reduce_local
#define NG_MPI_Request_free MPI_Request_free
#define NG_MPI_Scatter MPI_Scatter
#define NG_MPI_Send MPI_Send
#define NG_MPI_Send_init MPI_Send_init
#define NG_MPI_Startall MPI_Startall
#define NG_MPI_Type_commit MPI_Type_commit
#define NG_MPI_Type_contiguous MPI_Type_contiguous
#define NG_MPI_Type_create_resized MPI_Type_create_resized
#define NG_MPI_Type_create_struct MPI_Type_create_struct
#define NG_MPI_Type_free MPI_Type_free
#define NG_MPI_Type_get_extent MPI_Type_get_extent
#define NG_MPI_Type_indexed MPI_Type_indexed
#define NG_MPI_Type_size MPI_Type_size
#define NG_MPI_Wait MPI_Wait
#define NG_MPI_Waitall MPI_Waitall
#define NG_MPI_Waitany MPI_Waitany
#define NG_MPI_COMM_NULL MPI_COMM_NULL
#define NG_MPI_COMM_WORLD MPI_COMM_WORLD
#define NG_MPI_CHAR MPI_CHAR
#define NG_MPI_CXX_DOUBLE_COMPLEX MPI_CXX_DOUBLE_COMPLEX
#define NG_MPI_C_BOOL MPI_C_BOOL
#define NG_MPI_DATATYPE_NULL MPI_DATATYPE_NULL
#define NG_MPI_DOUBLE MPI_DOUBLE
#define NG_MPI_FLOAT MPI_FLOAT
#define NG_MPI_INT MPI_INT
#define NG_MPI_SHORT MPI_SHORT
#define NG_MPI_UINT64_T MPI_UINT64_T
#define NG_MPI_LOR MPI_LOR
#define NG_MPI_MAX MPI_MAX
#define NG_MPI_MIN MPI_MIN
#define NG_MPI_SUM MPI_SUM
#define NG_MPI_REQUEST_NULL MPI_REQUEST_NULL
#define NG_MPI_STATUSES_IGNORE MPI_STATUSES_IGNORE
#define NG_MPI_STATUS_IGNORE MPI_STATUS_IGNORE
#define NG_MPI_ANY_SOURCE MPI_ANY_SOURCE
#define NG_MPI_ANY_TAG MPI_ANY_TAG
#define NG_MPI_MAX_PROCESSOR_NAME MPI_MAX_PROCESSOR_NAME
#define NG_MPI_PROC_NULL MPI_PROC_NULL
#define NG_MPI_ROOT MPI_ROOT
#define NG_MPI_SUBVERSION MPI_SUBVERSION
#define NG_MPI_THREAD_MULTIPLE MPI_THREAD_MULTIPLE
#define NG_MPI_THREAD_SINGLE MPI_THREAD_SINGLE
#define NG_MPI_VERSION MPI_VERSION
#define NG_MPI_IN_PLACE MPI_IN_PLACE
#endif // NG_MPI_WRAPPER

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

@ -6,7 +6,9 @@
#include "ng_mpi.hpp"
#include "ngstream.hpp"
#ifdef NG_PYTHON
#include "python_ngcore.hpp"
#endif // NG_PYTHON
#include "utils.hpp"
using std::cerr;
@ -14,10 +16,12 @@ using std::cout;
using std::endl;
#ifndef NG_MPI_WRAPPER
#ifdef NG_PYTHON
#define MPI4PY_LIMITED_API 1
#define MPI4PY_LIMITED_API_SKIP_MESSAGE 1
#define MPI4PY_LIMITED_API_SKIP_SESSION 1
#include "mpi4py_pycapi.h" // mpi4py < 4.0.0
#endif // NG_PYTHON
#endif // NG_MPI_WRAPPER
namespace ngcore {
@ -94,6 +98,7 @@ void InitMPI(std::optional<std::filesystem::path> mpi_lib_path) {
throw e;
}
} else {
#ifdef NG_PYTHON
// Use mpi4py to init MPI library and get the vendor name
auto mpi4py = py::module::import("mpi4py.MPI");
vendor = mpi4py.attr("get_vendor")()[py::int_(0)].cast<std::string>();
@ -106,6 +111,7 @@ void InitMPI(std::optional<std::filesystem::path> mpi_lib_path) {
mpi_lib =
std::make_unique<SharedLibrary>(mpi4py_lib_file, std::nullopt, true);
#endif // WIN32
#endif // NG_PYTHON
}
std::string ng_lib_name = "";

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

@ -41,6 +41,7 @@ namespace ngcore
bool PajeTrace::trace_thread_counter = false;
bool PajeTrace::trace_threads = true;
bool PajeTrace::mem_tracing_enabled = true;
bool PajeTrace::write_paje_file = true;
PajeTrace :: PajeTrace(int anthreads, std::string aname)
{
@ -124,7 +125,7 @@ namespace ngcore
#endif
if(comm.Size()==1)
{
Write(tracefile_name);
Write();
}
else
{
@ -136,7 +137,7 @@ namespace ngcore
event.timer_id += NgProfiler::SIZE*comm.Rank();
if(comm.Rank() == MPI_PAJE_WRITER)
Write(tracefile_name);
Write();
else
SendData();
}
@ -443,7 +444,16 @@ namespace ngcore
NGCORE_API PajeTrace *trace;
void PajeTrace::Write( const std::string & filename )
void PajeTrace::Write( )
{
if(write_paje_file) WritePajeFile( tracefile_name );
WriteTimingChart();
#ifdef NETGEN_TRACE_MEMORY
WriteMemoryChart("");
#endif // NETGEN_TRACE_MEMORY
}
void PajeTrace::WritePajeFile( const std::string & filename )
{
auto n_events = jobs.size() + timer_events.size();
for(auto & vtasks : tasks)
@ -849,10 +859,6 @@ namespace ngcore
}
}
}
WriteTimingChart();
#ifdef NETGEN_TRACE_MEMORY
WriteMemoryChart("");
#endif // NETGEN_TRACE_MEMORY
paje.WriteEvents();
}
@ -961,10 +967,18 @@ namespace ngcore
f.precision(4);
f << R"CODE_(
<head>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/d3@7"></script>
<script src="https://unpkg.com/sunburst-chart"></script>
<style>body { margin: 0 }</style>
<style>
body { margin: 0 }
.tooltip {
white-space: pre-line !important;
max-width: 800px !important;
word-wrap: break-word !important;
padding: 10px !important;
}
</style>
)CODE_";
if(!time_or_memory)
f << "<title>Maximum Memory Consumption</title>\n";

View File

@ -25,6 +25,7 @@ namespace ngcore
NGCORE_API static bool trace_thread_counter;
NGCORE_API static bool trace_threads;
NGCORE_API static bool mem_tracing_enabled;
NGCORE_API static bool write_paje_file;
bool tracing_enabled;
TTimePoint start_time;
@ -32,6 +33,8 @@ namespace ngcore
size_t n_memory_events_at_start;
public:
NGCORE_API void Write();
NGCORE_API void WritePajeFile( const std::string & filename );
NGCORE_API void WriteTimingChart();
#ifdef NETGEN_TRACE_MEMORY
NGCORE_API void WriteMemoryChart( std::string fname );
@ -61,6 +64,11 @@ namespace ngcore
max_tracefile_size = max_size;
}
static void SetWritePajeFile( bool write )
{
write_paje_file = write;
}
std::string tracefile_name;
struct Job
@ -262,8 +270,6 @@ namespace ngcore
links[thread_id].push_back( ThreadLink{thread_id, key, GetTimeCounter(), false} );
}
void Write( const std::string & filename );
void SendData(); // MPI parallel data reduction
};

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

@ -141,8 +141,16 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
.def(py::self | py::self)
.def(py::self & py::self)
#ifdef __clang__
// see https://github.com/pybind/pybind11/issues/1893
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wself-assign-overloaded"
#endif
.def(py::self |= py::self)
.def(py::self &= py::self)
#ifdef __clang__
#pragma GCC diagnostic pop
#endif
.def(~py::self)
;
@ -316,6 +324,8 @@ threads : int
#endif // NETGEN_TRACE_MEMORY
;
m.def("GetTotalMemory", MemoryTracer::GetTotalMemory);
py::class_<Timer<>> (m, "Timer")
.def(py::init<const string&>())
.def("Start", static_cast<void (Timer<>::*)()const>(&Timer<>::Start), "start timer")

View File

@ -34,6 +34,8 @@ namespace ngcore {
return *this;
}
/*
// now using has_shared_from_this2 in archive.hpp
template <typename T>
struct has_shared_from_this
{
@ -42,6 +44,7 @@ namespace ngcore {
typedef decltype( check<T>(sizeof(char)) ) type;
static constexpr type value = type();
};
*/
#endif // NETGEN_PYTHON
@ -59,7 +62,7 @@ namespace ngcore {
{
detail::TCargs<T> args;
ar &args;
auto nT = detail::constructIfPossible<T>(args);
auto nT = detail::constructIfPossible<T>(std::move(args));
return typeid(T) == ti ? nT
: Archive::Caster<T, Bases>::tryUpcast(ti, nT);
};

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

@ -45,7 +45,7 @@ namespace ngcore
}
/// INDEX of symbol name, throws exception if unused
size_t Index (const std::string & name) const
size_t Index (std::string_view name) const
{
for (size_t i = 0; i < names.size(); i++)
if (names[i] == name) return i;
@ -53,7 +53,7 @@ namespace ngcore
}
/// Index of symbol name, returns -1 if unused
int CheckIndex (const std::string & name) const
int CheckIndex (std::string_view name) const
{
for (int i = 0; i < names.size(); i++)
if (names[i] == name) return i;
@ -67,12 +67,12 @@ namespace ngcore
}
/// Returns reference to element. exception for unused identifier
reference operator[] (const std::string & name)
reference operator[] (std::string_view name)
{
return data[Index (name)];
}
const_reference operator[] (const std::string & name) const
const_reference operator[] (std::string_view name) const
{
return data[Index (name)];
}
@ -99,7 +99,7 @@ namespace ngcore
}
/// Associates el to the string name, overrides if name is used
void Set (const std::string & name, const T & el)
void Set (std::string_view name, const T & el)
{
int i = CheckIndex (name);
if (i >= 0)
@ -107,15 +107,24 @@ namespace ngcore
else
{
data.push_back(el);
names.push_back(name);
names.push_back(std::string(name));
}
}
/*
bool Used (const std::string & name) const
{
return CheckIndex(name) >= 0;
}
*/
bool Used (std::string_view name) const
{
return CheckIndex(name) >= 0;
}
/// Deletes symboltable
inline void DeleteAll ()
{

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

@ -168,6 +168,12 @@ namespace ngcore
trace = nullptr;
}
num_threads = 1;
#ifdef USE_NUMA
for (int j = 0; j < num_nodes; j++)
numa_free (nodedata[j], sizeof(NodeData));
#else
delete nodedata[0];
#endif
}
#ifdef WIN32

View File

@ -10,6 +10,7 @@
#include <atomic>
#include <functional>
#include <list>
#include <cmath>
#include <ostream>
#include <thread>
@ -316,6 +317,7 @@ namespace ngcore
public:
SharedLoop (IntRange ar) : r(ar) { cnt = r.begin(); }
SharedLoop (size_t s) : SharedLoop (IntRange{s}) { ; }
SharedIterator begin() { return SharedIterator (cnt, r.end(), true); }
SharedIterator end() { return SharedIterator (cnt, r.end(), false); }
};
@ -622,6 +624,8 @@ public:
Reset (r);
}
SharedLoop2 (size_t s) : SharedLoop2 (IntRange{s}) { }
void Reset (IntRange r)
{
for (size_t i = 0; i < ranges.Size(); i++)
@ -631,6 +635,9 @@ public:
participants.store(0, std::memory_order_relaxed);
processed.store(0, std::memory_order_release);
}
void Reset (size_t s) { Reset(IntRange{s}); }
SharedIterator begin()
{
@ -1010,7 +1017,7 @@ public:
int num_nodes = numa_num_configured_nodes();
size_t pagesize = numa_pagesize();
int npages = ceil ( double(s)*sizeof(T) / pagesize );
int npages = std::ceil ( double(s)*sizeof(T) / pagesize );
// cout << "size = " << numa_size << endl;
// cout << "npages = " << npages << endl;

View File

@ -182,7 +182,7 @@ namespace ngcore
/// square element
template <class T>
NETGEN_INLINE T sqr (const T a)
NETGEN_INLINE constexpr T sqr (const T a)
{
return a * a;
}

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);
}
@ -396,15 +408,15 @@ void PeriodicIdentification :: IdentifyFaces (class Mesh & mesh)
if (side == 1)
{
if (mesh.GetIdentifications().Get (seg1[0], seg2[0]) &&
mesh.GetIdentifications().Get (seg1[1], seg2[1]))
if (mesh.GetIdentifications().Used (seg1[0], seg2[0]) &&
mesh.GetIdentifications().Used (seg1[1], seg2[1]))
{
foundother = 1;
break;
}
if (mesh.GetIdentifications().Get (seg1[0], seg2[1]) &&
mesh.GetIdentifications().Get (seg1[1], seg2[0]))
if (mesh.GetIdentifications().Used (seg1[0], seg2[1]) &&
mesh.GetIdentifications().Used (seg1[1], seg2[0]))
{
foundother = 1;
break;
@ -412,15 +424,15 @@ void PeriodicIdentification :: IdentifyFaces (class Mesh & mesh)
}
else
{
if (mesh.GetIdentifications().Get (seg2[0], seg1[0]) &&
mesh.GetIdentifications().Get (seg2[1], seg1[1]))
if (mesh.GetIdentifications().Used (seg2[0], seg1[0]) &&
mesh.GetIdentifications().Used (seg2[1], seg1[1]))
{
foundother = 1;
break;
}
if (mesh.GetIdentifications().Get (seg2[0], seg1[1]) &&
mesh.GetIdentifications().Get (seg2[1], seg1[0]))
if (mesh.GetIdentifications().Used (seg2[0], seg1[1]) &&
mesh.GetIdentifications().Used (seg2[1], seg1[0]))
{
foundother = 1;
break;
@ -885,17 +897,21 @@ ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const
int CloseSurfaceIdentification ::
GetIdentifiedPoint (class Mesh & mesh, int pi)
PointIndex CloseSurfaceIdentification ::
GetIdentifiedPoint (class Mesh & mesh, PointIndex pi)
{
const Surface *snew;
const Point<3> & p = mesh.Point (pi);
NgArray<int,PointIndex::BASE> identmap(mesh.GetNP());
idmap_type identmap(mesh.GetNP());
mesh.GetIdentifications().GetMap (nr, identmap);
/*
if (identmap.Get(pi))
return identmap.Get(pi);
*/
if (identmap[pi].IsValid())
return identmap[pi];
if (s1->PointOnSurface (p))
snew = s2;
@ -1168,15 +1184,15 @@ void CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh)
if (side == 1)
{
if (mesh.GetIdentifications().Get (seg1[0], seg2[0]) &&
mesh.GetIdentifications().Get (seg1[1], seg2[1]))
if (mesh.GetIdentifications().Used (seg1[0], seg2[0]) &&
mesh.GetIdentifications().Used (seg1[1], seg2[1]))
{
foundother = 1;
break;
}
if (mesh.GetIdentifications().Get (seg1[0], seg2[1]) &&
mesh.GetIdentifications().Get (seg1[1], seg2[0]))
if (mesh.GetIdentifications().Used (seg1[0], seg2[1]) &&
mesh.GetIdentifications().Used (seg1[1], seg2[0]))
{
foundother = 1;
break;
@ -1184,15 +1200,15 @@ void CloseSurfaceIdentification :: IdentifyFaces (class Mesh & mesh)
}
else
{
if (mesh.GetIdentifications().Get (seg2[0], seg1[0]) &&
mesh.GetIdentifications().Get (seg2[1], seg1[1]))
if (mesh.GetIdentifications().Used (seg2[0], seg1[0]) &&
mesh.GetIdentifications().Used (seg2[1], seg1[1]))
{
foundother = 1;
break;
}
if (mesh.GetIdentifications().Get (seg2[0], seg1[1]) &&
mesh.GetIdentifications().Get (seg2[1], seg1[0]))
if (mesh.GetIdentifications().Used (seg2[0], seg1[1]) &&
mesh.GetIdentifications().Used (seg2[1], seg1[0]))
{
foundother = 1;
break;
@ -1229,7 +1245,7 @@ BuildSurfaceElements (NgArray<Segment> & segs,
bool found = 0;
int cntquads = 0;
NgArray<int,PointIndex::BASE> identmap;
idmap_type identmap;
identmap = 0;
mesh.GetIdentifications().GetMap (nr, identmap);
@ -1650,8 +1666,8 @@ BuildSurfaceElements (NgArray<Segment> & segs,
{
const Segment & s1 = segs.Get(i1);
const Segment & s2 = segs.Get(i2);
if (mesh.GetIdentifications().Get (s1[0], s2[1]) &&
mesh.GetIdentifications().Get (s1[1], s2[0]))
if (mesh.GetIdentifications().Used (s1[0], s2[1]) &&
mesh.GetIdentifications().Used (s1[1], s2[0]))
{
Element2d el(QUAD);
el.PNum(1) = s1[0];

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

@ -756,10 +756,8 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
{
MeshingParameters mp;
if(pars) mp = *pars;
{
py::gil_scoped_acquire aq;
CreateMPfromKwargs(mp, kwargs);
}
CreateMPfromKwargs(mp, kwargs);
py::gil_scoped_release gil_rel;
auto mesh = make_shared<Mesh>();
SetGlobalMesh (mesh);
mesh->SetGeometry(geo);
@ -770,8 +768,7 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
throw Exception("Meshing failed!");
return mesh;
}, py::arg("mp") = nullptr,
meshingparameter_description.c_str(),
py::call_guard<py::gil_scoped_release>())
meshingparameter_description.c_str())
;
m.def("Save", FunctionPointer

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,18 +111,18 @@ namespace netgen
*/
void MakePrismsClosePoints (Mesh & mesh)
{
int i, j, k;
for (i = 1; i <= mesh.GetNE(); i++)
// int i, j, k;
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element & el = mesh.VolumeElement(i);
Element & el = mesh.VolumeElement(ei);
if (el.GetType() == TET)
{
for (j = 1; j <= 3; j++)
for (k = j+1; k <= 4; k++)
for (int j = 1; j <= 3; j++)
for (int k = j+1; k <= 4; k++)
{
INDEX_2 edge(el.PNum(j), el.PNum(k));
edge.Sort();
if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k)))
if (mesh.GetIdentifications().UsedSymmetric (el.PNum(j), el.PNum(k)))
{
int pi3 = 1, pi4 = 1;
while (pi3 == j || pi3 == k) pi3++;
@ -145,7 +146,7 @@ namespace netgen
{
// pyramid, base face = 1,2,3,4
for (j = 0; j <= 1; j++)
for (int j = 0; j <= 1; j++)
{
PointIndex pi1 = el.PNum( (j+0) % 4 + 1);
PointIndex pi2 = el.PNum( (j+1) % 4 + 1);
@ -157,8 +158,8 @@ namespace netgen
INDEX_2 edge2(pi2, pi3);
edge1.Sort();
edge2.Sort();
if (mesh.GetIdentifications().GetSymmetric (pi1, pi4) &&
mesh.GetIdentifications().GetSymmetric (pi2, pi3))
if (mesh.GetIdentifications().UsedSymmetric (pi1, pi4) &&
mesh.GetIdentifications().UsedSymmetric (pi2, pi3))
{
//int p3 = el.PNum(pi3);
//int p4 = el.PNum(pi4);
@ -175,18 +176,18 @@ namespace netgen
}
}
for (i = 1; i <= mesh.GetNSE(); i++)
for (SurfaceElementIndex sei = 0; sei < mesh.GetNSE(); sei++)
{
Element2d & el = mesh.SurfaceElement(i);
Element2d & el = mesh.SurfaceElement(sei);
if (el.GetType() != TRIG) continue;
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
k = (j % 3) + 1;
int k = (j % 3) + 1;
INDEX_2 edge(el.PNum(j), el.PNum(k));
edge.Sort();
if (mesh.GetIdentifications().GetSymmetric (el.PNum(j), el.PNum(k)))
if (mesh.GetIdentifications().UsedSymmetric (el.PNum(j), el.PNum(k)))
{
int pi3 = 6-j-k;
int p3 = el.PNum(pi3);
@ -244,7 +245,7 @@ namespace netgen
void RefinePrisms (Mesh & mesh, const CSGeometry * geom,
ZRefinementOptions & opt)
{
int i, j;
// int i, j;
bool found, change;
int cnt = 0;
@ -261,15 +262,23 @@ namespace netgen
// if (mesh.GetIdentifications().HasIdentifiedPoints())
{
INDEX_2_HASHTABLE<int> & identpts =
auto & identpts =
mesh.GetIdentifications().GetIdentifiedPoints ();
for (i = 1; i <= identpts.GetNBags(); i++)
for (j = 1; j <= identpts.GetBagSize(i); j++)
/*
for (int i = 1; i <= identpts.GetNBags(); i++)
for (int j = 1; j <= identpts.GetBagSize(i); j++)
{
INDEX_2 pair;
int idnr;
identpts.GetData(i, j, pair, idnr);
INDEX_3 pair;
int dummy;
identpts.GetData(i, j, pair, dummy);
*/
for (auto [hash, val] : identpts)\
{
auto [hash_pts, idnr] = hash;
auto [pi1, pi2] = hash_pts;
// auto idnr = pair[2];
const CloseSurfaceIdentification * csid =
dynamic_cast<const CloseSurfaceIdentification*>
(geom->identifications.Get(idnr));
@ -280,17 +289,25 @@ namespace netgen
if (first_id.Test (idnr))
{
first_id.Clear(idnr);
/*
ref_uniform.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels()));
ref_singular.Append (INDEX_3 (pair.I1(), pair.I2(), csid->RefLevels1()));
ref_singular.Append (INDEX_3 (pair.I2(), pair.I1(), csid->RefLevels2()));
*/
ref_uniform.Append (INDEX_3 (pi1, pi2, csid->RefLevels()));
ref_singular.Append (INDEX_3 (pi1, pi2, csid->RefLevels1()));
ref_singular.Append (INDEX_3 (pi2, pi1, csid->RefLevels2()));
}
}
else
{
//const NgArray<double> & slices = csid->GetSlices();
INDEX_4 i4;
i4[0] = pair.I1();
i4[1] = pair.I2();
// i4[0] = pair.I1();
// i4[1] = pair.I2();
i4[0] = pi1;
i4[1] = pi2;
i4[2] = idnr;
i4[3] = csid->GetSlices().Size();
ref_slices.Append (i4);
@ -313,7 +330,7 @@ namespace netgen
found = 0;
// mark prisms due to close surface flags:
int oldsize = ref_uniform.Size();
for (i = 1; i <= oldsize; i++)
for (int i = 1; i <= oldsize; i++)
{
int pi1 = ref_uniform.Get(i).I1();
int pi2 = ref_uniform.Get(i).I2();
@ -339,7 +356,7 @@ namespace netgen
ref_uniform.Append (INDEX_3(pi2, npi, levels-1));
}
}
for (i = 1; i <= ref_singular.Size(); i++)
for (int i = 1; i <= ref_singular.Size(); i++)
{
int pi1 = ref_singular.Get(i).I1();
int pi2 = ref_singular.Get(i).I2();
@ -367,7 +384,7 @@ namespace netgen
}
}
for (i = 1; i <= ref_slices.Size(); i++)
for (int i = 1; i <= ref_slices.Size(); i++)
{
int pi1 = ref_slices.Get(i)[0];
int pi2 = ref_slices.Get(i)[1];
@ -413,13 +430,13 @@ namespace netgen
for (i = 1; i <= mesh.GetNE(); i++)
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element & el = mesh.VolumeElement (i);
Element & el = mesh.VolumeElement (ei);
if (el.GetType() != PRISM)
continue;
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
int pi1 = el.PNum(j);
int pi2 = el.PNum(j+3);
@ -465,14 +482,14 @@ namespace netgen
{
PrintMessage (5, "start loop");
change = 0;
for (i = 1; i <= mesh.GetNE(); i++)
for (ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element & el = mesh.VolumeElement (i);
Element & el = mesh.VolumeElement (ei);
if (el.GetType() != PRISM)
continue;
bool hasref = 0, hasnonref = 0;
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
int pi1 = el.PNum(j);
int pi2 = el.PNum(j+3);
@ -491,7 +508,7 @@ namespace netgen
{
// cout << "el " << i << " in closure" << endl;
change = 1;
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
int pi1 = el.PNum(j);
int pi2 = el.PNum(j+3);
@ -518,7 +535,7 @@ namespace netgen
int oldns = mesh.GetNSeg();
for (i = 1; i <= oldns; i++)
for (int i = 1; i <= oldns; i++)
{
const Segment & el = mesh.LineSegment(i);
@ -572,14 +589,14 @@ namespace netgen
// do refinement
int oldne = mesh.GetNE();
for (i = 1; i <= oldne; i++)
for (ElementIndex ei = 0; ei < oldne; ei++)
{
Element & el = mesh.VolumeElement (i);
Element & el = mesh.VolumeElement (ei);
if (el.GetNP() != 6)
continue;
int npi[3];
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
int pi1 = el.PNum(j);
int pi2 = el.PNum(j+3);
@ -607,7 +624,7 @@ namespace netgen
if (npi[0])
{
Element nel1(6), nel2(6);
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
nel1.PNum(j) = el.PNum(j);
nel1.PNum(j+3) = npi[j-1];
@ -616,7 +633,7 @@ namespace netgen
}
nel1.SetIndex (el.GetIndex());
nel2.SetIndex (el.GetIndex());
mesh.VolumeElement (i) = nel1;
mesh.VolumeElement (ei) = nel1;
mesh.AddVolumeElement (nel2);
}
}
@ -628,15 +645,15 @@ namespace netgen
// do surface elements
int oldnse = mesh.GetNSE();
// cout << "oldnse = " << oldnse << endl;
for (i = 1; i <= oldnse; i++)
for (SurfaceElementIndex sei = 0; sei < oldnse; sei++)
{
Element2d & el = mesh.SurfaceElement (i);
Element2d & el = mesh.SurfaceElement (sei);
if (el.GetType() != QUAD)
continue;
int index = el.GetIndex();
int npi[2];
for (j = 1; j <= 2; j++)
for (int j = 1; j <= 2; j++)
{
int pi1, pi2;
@ -669,7 +686,7 @@ namespace netgen
if (npi[0])
{
Element2d nel1(QUAD), nel2(QUAD);
for (j = 1; j <= 4; j++)
for (int j = 1; j <= 4; j++)
{
nel1.PNum(j) = el.PNum(j);
nel2.PNum(j) = el.PNum(j);
@ -690,7 +707,7 @@ namespace netgen
nel1.SetIndex (el.GetIndex());
nel2.SetIndex (el.GetIndex());
mesh.SurfaceElement (i) = nel1;
mesh.SurfaceElement (sei) = nel1;
mesh.AddSurfaceElement (nel2);
int si = mesh.GetFaceDescriptor (index).SurfNr();
@ -716,9 +733,9 @@ namespace netgen
void CombineSingularPrisms(Mesh& mesh)
{
for(int i = 1; i<=mesh.GetNE(); i++)
for(ElementIndex ei = 0; ei < mesh.GetNE(); ei++)
{
Element& el = mesh.VolumeElement(i);
Element& el = mesh.VolumeElement(ei);
if(el.GetType() != PRISM)
continue;
if(el.PNum(3) == el.PNum(6))

View File

@ -2,7 +2,6 @@ target_sources(nglib PRIVATE
gzstream.cpp
hashtabl.cpp
mystring.cpp
ngarray.cpp
ngbitarray.cpp
optmem.cpp
parthreads.cpp

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

@ -414,9 +414,14 @@ public:
int BagNr() const { return bagnr; }
int Pos() const { return pos; }
void operator++ (int)
Iterator operator++ (int)
{
Iterator it(ht, bagnr, pos);
++(*this);
return it;
}
Iterator& operator++()
{
// cout << "begin Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl;
pos++;
while (bagnr < ht.GetNBags() &&
pos == ht.GetBagSize(bagnr+1))
@ -424,7 +429,12 @@ public:
pos = 0;
bagnr++;
}
// cout << "end Operator ++: bagnr = " << bagnr << " - pos = " << pos << endl;
return *this;
}
std::pair<INDEX_3, T> operator*()
{
return std::make_pair(ht.hash[bagnr][pos], ht.cont[bagnr][pos]);
}
bool operator != (int i) const
@ -446,6 +456,18 @@ public:
return GetNBags();
}
Iterator begin () const
{
Iterator it(*this, 0, -1);
it++;
return it;
}
int end() const
{
return GetNBags();
}
void GetData (const Iterator & it,
INDEX_3 & ahash, T & acont) const
{
@ -839,9 +861,10 @@ inline ostream & operator<< (ostream & ost, const INDEX_2_CLOSED_HASHTABLE<T> &
for (int i = 0; i < ht.Size(); i++)
if (ht.UsedPos(i))
{
INDEX_2 hash;
T data;
ht.GetData0 (i, hash, data);
// INDEX_2 hash;
// T data;
// ht.GetData0 (i, hash, data);
auto [hash,data] = ht.GetBoth(i);
ost << "hash = " << hash << ", data = " << data << endl;
}
return ost;
@ -858,7 +881,8 @@ protected:
size_t mask;
protected:
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size)
BASE_INDEX_3_CLOSED_HASHTABLE (size_t size);
/*
: hash(RoundUp2(size))
{
// cout << "orig size = " << size
@ -870,6 +894,7 @@ protected:
for (size_t i = 0; i < size; i++)
hash[i].I1() = invalid;
}
*/
public:
int Size() const
@ -1051,9 +1076,12 @@ inline ostream & operator<< (ostream & ost, const INDEX_3_CLOSED_HASHTABLE<T> &
for (int i = 0; i < ht.Size(); i++)
if (ht.UsedPos(i))
{
/*
INDEX_3 hash;
T data;
ht.GetData (i, hash, data);
ht.GetData (i, hash, data);
*/
auto [hash, data] = ht.GetBoth();
ost << "hash = " << hash << ", data = " << data << endl;
}
return ost;

View File

@ -223,6 +223,16 @@ MyStr::MyStr(const string & st)
strcpy (str, st.c_str());
}
MyStr::MyStr(string_view sv)
{
length = unsigned(sv.length());
if (length > SHORTLEN)
str = new char[length + 1];
else
str = shortstr;
strcpy (str, sv.data());
}
MyStr::MyStr(const filesystem::path & path)
: MyStr(path.string())
{ }

View File

@ -60,6 +60,7 @@ public:
MyStr(const Point3d& p);
MyStr(const Vec3d& p);
MyStr(const string & st);
MyStr(string_view sv);
MyStr(const filesystem::path & st);
~MyStr();

View File

@ -1,75 +0,0 @@
#ifndef FILE_NGSTD_NgArrayCPP
#define FILE_NGSTD_NgArrayCPP
// necessary for SGI ????
/**************************************************************************/
/* File: array.cpp */
/* Author: Joachim Schoeberl */
/* Date: 01. Jun. 95 */
/**************************************************************************/
/*
Abstract data type NgArray
*/
#include <mystdlib.h>
#include <myadt.hpp>
#include <assert.h>
namespace netgen
{
//using namespace netgen;
#ifdef NONE
void BASE_Array :: ReSize (int minsize, int elementsize)
{
cout << "resize, minsize = " << minsize << endl;
if (inc == -1)
throw Exception ("Try to resize fixed size array");
void * p;
int nsize = (inc) ? allocsize + inc : 2 * allocsize;
if (nsize < minsize) nsize = minsize;
if (data)
{
p = new char [nsize * elementsize];
int mins = (nsize < actsize) ? nsize : actsize;
memcpy (p, data, mins * elementsize);
delete [] static_cast<char*> (data);
data = p;
}
else
{
data = new char[nsize * elementsize];
}
allocsize = nsize;
cout << "resize done" << endl;
}
void BASE_Array :: RangeCheck (int i) const
{
if (i < 0 || i >= actsize)
throw ArrayRangeException ();
}
void BASE_Array :: CheckNonEmpty () const
{
if (!actsize)
{
throw Exception ("NgArray should not be empty");
// cerr << "NgArray shouldn't be empty";
}
}
#endif
}
#endif // FILE_NGSTD_NgArrayCPP

View File

@ -11,6 +11,7 @@
namespace netgen
{
using namespace ngcore;
// template <class T, int B1, int B2> class IndirectArray;
template <class TA1, class TA2> class NgIndirectArray;
@ -111,11 +112,7 @@ namespace netgen
/// Access array. BASE-based
T & operator[] (TIND i) const
{
#ifdef DEBUG
if (i-BASE < 0 || i-BASE >= size)
cout << "array<" << typeid(T).name() << "> out of range, i = " << i << ", s = " << size << endl;
#endif
NETGEN_CHECK_RANGE(i,BASE,size+BASE);
return data[i-BASE];
}
@ -130,13 +127,7 @@ namespace netgen
/// Access array, one-based (old fashioned)
T & Elem (int i)
{
#ifdef DEBUG
if (i < 1 || i > size)
cout << "NgArray<" << typeid(T).name()
<< ">::Elem out of range, i = " << i
<< ", s = " << size << endl;
#endif
NETGEN_CHECK_RANGE(i,1,size+1);
return ((T*)data)[i-1];
}
@ -144,30 +135,21 @@ namespace netgen
// [[deprecated("Use operator[] instead")]]
const T & Get (int i) const
{
#ifdef DEBUG
if (i < 1 || i > size)
cout << "NgArray<" << typeid(T).name() << ">::Get out of range, i = " << i
<< ", s = " << size << endl;
#endif
NETGEN_CHECK_RANGE(i,1,size+1);
return ((const T*)data)[i-1];
}
/// Access array, one-based (old fashioned)
void Set (int i, const T & el)
{
#ifdef DEBUG
if (i < 1 || i > size)
cout << "NgArray<" << typeid(T).name() << ">::Set out of range, i = " << i
<< ", s = " << size << endl;
#endif
NETGEN_CHECK_RANGE(i,1,size+1);
((T*)data)[i-1] = el;
}
/// access first element
T & First () const
{
NETGEN_CHECK_RANGE(0,0,size);
return data[0];
}
@ -175,6 +157,7 @@ namespace netgen
/// access last element. check by macro CHECK_RANGE
T & Last () const
{
NETGEN_CHECK_RANGE(size-1,0,size);
return data[size-1];
}
@ -345,10 +328,7 @@ namespace netgen
/// Delete element i (0-based). Move last element to position i.
void Delete (TIND i)
{
#ifdef CHECK_Array_RANGE
RangeCheck (i+1);
#endif
NETGEN_CHECK_RANGE(i,0,size);
data[i] = std::move(data[size-1]);
size--;
// DeleteElement (i+1);
@ -358,10 +338,7 @@ namespace netgen
/// Delete element i (1-based). Move last element to position i.
void DeleteElement (TIND i)
{
#ifdef CHECK_Array_RANGE
RangeCheck (i);
#endif
NETGEN_CHECK_RANGE(i,1,size+1);
data[i-1] = std::move(data[size-1]);
size--;
}

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

@ -108,8 +108,9 @@ namespace netgen
if (line.size == line.maxsize)
{
void * p = new char [(line.maxsize+5) * elsize];
memcpy (p, line.col, line.maxsize * elsize);
if (line.maxsize && elsize)
memcpy (p, line.col, line.maxsize * elsize);
delete [] (char*)line.col;
line.col = p;

View File

@ -120,7 +120,7 @@ public:
/// Creates fixed maximal element size table
inline TABLE (const NgFlatArray<int,BASE> & entrysizes)
: BASE_TABLE (NgFlatArray<int> (entrysizes.Size(), const_cast<int*>(&entrysizes[BASE])),
: BASE_TABLE (NgFlatArray<int> (entrysizes.Size(), entrysizes.Size() ? const_cast<int*>(&entrysizes[BASE]) : nullptr),
sizeof(T))
{ ; }

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

@ -401,10 +401,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
{
MeshingParameters mp;
if(pars) mp = *pars;
{
py::gil_scoped_acquire aq;
CreateMPfromKwargs(mp, kwargs);
}
CreateMPfromKwargs(mp, kwargs);
py::gil_scoped_release gil_release;
auto mesh = make_shared<Mesh>();
mesh->SetGeometry(self);
SetGlobalMesh (mesh);
@ -414,7 +412,6 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
throw Exception("Meshing failed!");
return mesh;
}, py::arg("mp") = nullopt,
py::call_guard<py::gil_scoped_release>(),
meshingparameter_description.c_str())
.def("_SetDomainTensorMeshing", &SplineGeometry2d::SetDomainTensorMeshing)
;
@ -427,7 +424,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
.def(py::self-py::self)
.def(py::self*py::self)
.def(py::self+=py::self)
.def(py::self-=py::self)
// .def(py::self-=py::self) // false clange warning, see https://github.com/pybind/pybind11/issues/1893
.def("__isub__", [](Solid2d& lhs, const Solid2d& rhs) { return lhs -= rhs; }, py::is_operator())
.def(py::self*=py::self)
.def("Mat", &Solid2d::Mat)
@ -466,10 +464,8 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
{
MeshingParameters mp;
if(pars) mp = *pars;
{
py::gil_scoped_acquire aq;
CreateMPfromKwargs(mp, kwargs);
}
py::gil_scoped_release gil_release;
auto mesh = make_shared<Mesh>();
auto geo = self.GenerateSplineGeometry();
mesh->SetGeometry(geo);
@ -480,7 +476,6 @@ NGCORE_API_EXPORT void ExportGeom2d(py::module &m)
throw Exception("Meshing failed!");
return mesh;
}, py::arg("mp") = nullopt,
py::call_guard<py::gil_scoped_release>(),
meshingparameter_description.c_str())
;

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,12 +117,11 @@ namespace netgen
int GetIndex() const { return index-1; }
Ng_Points points; // all points
Ng_Vertices vertices;
// Ng_Edges edges;
FlatArray<T_EDGE2> edges;
// Ng_Faces faces;
FlatArray<T_FACE2> faces;
Ng_Facets facets;
bool is_curved;
int8_t newest_vertex;
};
@ -412,6 +374,10 @@ namespace netgen
int GetClusterRepEdge (int edi) const;
int GetClusterRepFace (int fai) const;
int GetClusterRepElement (int eli) const;
// just copied from nginterface, now 0-based
int GetElement_Faces (int elnr, int * faces, int * orient = 0) const;
int GetSurfaceElement_Face (int selnr, int * orient = 0) const;
};

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();
@ -191,6 +206,7 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<2> (size_t nr) const
ret.facets.ptr = ret.edges.Data();
}
ret.is_curved = el.IsCurved();
ret.newest_vertex = el.NewestVertex();
return ret;
}
@ -213,19 +229,25 @@ NGX_INLINE DLL_HEADER Ng_Element Ngx_Mesh :: GetElement<3> (size_t nr) const
ret.edges.num = MeshTopology::GetNEdges (el.GetType());
ret.edges.ptr = mesh->GetTopology().GetElementEdgesPtr (nr);
*/
ret.edges.Assign (mesh->GetTopology().GetEdges (ElementIndex(nr)));
// ret.edges.Assign (mesh->GetTopology().GetEdges (ElementIndex(nr)));
auto hedges = mesh->GetTopology().GetEdges (ElementIndex(nr));
ret.edges.Assign ( { hedges.Size(), (int*)hedges.Data() } );
/*
ret.faces.num = MeshTopology::GetNFaces (el.GetType());
ret.faces.ptr = mesh->GetTopology().GetElementFacesPtr (nr);
*/
ret.faces.Assign (mesh->GetTopology().GetFaces (ElementIndex(nr)));
// ret.faces.Assign (mesh->GetTopology().GetFaces (ElementIndex(nr)));
auto hfaces = mesh->GetTopology().GetFaces (ElementIndex(nr));
ret.faces.Assign ( { hfaces.Size(), (int*)hfaces.Data() } );
ret.facets.num = ret.faces.Size();
ret.facets.base = 0;
ret.facets.ptr = ret.faces.Data();
ret.is_curved = el.IsCurved();
ret.newest_vertex = el.NewestVertex();
return ret;
}
@ -269,10 +291,10 @@ template <> NGX_INLINE DLL_HEADER int Ngx_Mesh :: GetNNodes<2> ()
return mesh->GetTopology().GetNFaces();
}
template <> NGX_INLINE DLL_HEADER const Ng_Node<0> Ngx_Mesh :: GetNode<0> (int vnr) const
template <> NGX_INLINE DLL_HEADER const Ng_Node<0> Ngx_Mesh :: GetNode<0> (int vnr_) const
{
Ng_Node<0> node;
vnr++;
PointIndex vnr = IndexBASE<PointIndex>() + vnr_;
switch (mesh->GetDimension())
{
case 3:
@ -325,8 +347,8 @@ template <> NGX_INLINE DLL_HEADER const Ng_Node<2> Ngx_Mesh :: GetNode<2> (int n
{
Ng_Node<2> node;
node.vertices.ptr = (const int*)mesh->GetTopology().GetFaceVerticesPtr(nr);
node.vertices.nv = (node.vertices.ptr[3] == 0) ? 3 : 4;
node.surface_el = mesh->GetTopology().GetFace2SurfaceElement (nr+1)-1;
node.vertices.nv = (node.vertices.ptr[3]+1 == PointIndex::BASE) ? 3 : 4;
node.surface_el = mesh->GetTopology().GetFace2SurfaceElement (nr);
return node;
}
@ -337,8 +359,8 @@ NGX_INLINE DLL_HEADER Ng_Buffer<int[2]> Ngx_Mesh :: GetPeriodicVertices(int idnr
mesh->GetIdentifications().GetPairs (idnr+1, apairs);
for(auto& ind : apairs)
{
ind.I1()--;
ind.I2()--;
ind.I1() -= IndexBASE<PointIndex>();
ind.I2() -= IndexBASE<PointIndex>();
}
typedef int ti2[2];
return { apairs.Size(), (ti2*)(void*)apairs.Release() };
@ -347,12 +369,9 @@ NGX_INLINE DLL_HEADER Ng_Buffer<int[2]> Ngx_Mesh :: GetPeriodicVertices(int idnr
NGX_INLINE void Ngx_Mesh :: GetParentNodes (int ni, int * parents) const
{
ni++;
if (ni <= mesh->mlbetweennodes.Size())
{
parents[0] = mesh->mlbetweennodes.Get(ni).I1()-1;
parents[1] = mesh->mlbetweennodes.Get(ni).I2()-1;
}
if (ni < mesh->mlbetweennodes.Size())
for (int j = 0; j < 2; j++)
parents[j] = mesh->mlbetweennodes[IndexBASE<PointIndex>()+ni][j] - IndexBASE<PointIndex>();
else
parents[0] = parents[1] = -1;
}

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

@ -15,15 +15,103 @@
namespace netgen
{
using std::vector;
struct AbaqusElementType
{
const char * name;
const vector<int> permutation;
AbaqusElementType(const char * name, const vector<int> & permutation)
: name(name), permutation(permutation)
{}
};
static inline const AbaqusElementType & GetAbaqusType(int dim, int num_nodes)
{
// maps num_nodes to AbaqusElementType for each dimension
typedef std::map<int, AbaqusElementType> AbaqusElementTypes;
static const std::map<int, AbaqusElementType> abaqus_eltypes[3] =
{
// 1D
AbaqusElementTypes{
{2, AbaqusElementType{"T2D2", vector{0,1}}},
},
// 2D
AbaqusElementTypes{
{3, AbaqusElementType{"CPS3", vector{0,1,2}}},
},
// 3D
AbaqusElementTypes{
{4, AbaqusElementType{"C3D4", vector{0,1,3,2}}},
{10, AbaqusElementType{"C3D10", vector{0,1,3,2,4,8,6,5,7,9}}},
}
};
const auto & eltypes = abaqus_eltypes[dim-1];
if (eltypes.count(num_nodes) > 0)
return eltypes.at(num_nodes);
else
throw Exception("unsupported " + ToString(dim)+"d Element type with " + ToString(num_nodes) + " nodes");
}
static void WritePoints ( const Mesh & mesh, ostream & out )
{
out << "*Node" << endl;
for(auto pi : mesh.Points().Range() )
{
out << pi+1-IndexBASE<PointIndex>() << ", ";
auto p = mesh[pi];
out << p[0] << ", " << p[1] << ", " << p[2] << '\n';
}
}
template <typename ElIndex>
static void WriteElement(ostream & out, const Mesh& mesh, ElIndex ei, const vector<int> & permutation, int & el_counter)
{
el_counter++;
auto el = mesh[ei];
out << el_counter;
for(auto i : Range(el.PNums()))
out << ", " << el[permutation[i]]+1-IndexBASE<PointIndex>();
out << '\n';
}
template <typename ElIndex, typename Elements>
static void WriteElements ( ostream & out, const Mesh & mesh, int dim, const Elements & el_range, int & el_counter)
{
// map index, num_nodes to elements
std::map<std::tuple<int, int>, Array<ElIndex>> elset_map;
for(auto ei : el_range)
{
const auto & el = mesh[ei];
int index = 0;
if constexpr(std::is_same_v<ElIndex,SegmentIndex>)
index = el.edgenr;
else
index = el.GetIndex();
elset_map[{index, el.GetNP()}].Append(ei);
}
for(auto & [key, elems] : elset_map)
{
auto [index, num_nodes] = key;
auto name = mesh.GetRegionName(elems[0]);
if (name == "") name = "default";
PrintMessage (5, index, ": ", name);
const auto & eltype = GetAbaqusType(dim, num_nodes) ;
out << "*Element, type=" << eltype.name << ", ELSET=" << name << endl;
for(auto ei : elems)
WriteElement(out, mesh, ei, eltype.permutation, el_counter);
}
}
void WriteAbaqusFormat (const Mesh & mesh,
const filesystem::path & filename)
{
cout << "\nWrite Abaqus Volume Mesh" << endl;
PrintMessage (1, "Write Abaqus Mesh");
ofstream outfile (filename);
@ -32,96 +120,17 @@ void WriteAbaqusFormat (const Mesh & mesh,
outfile.precision(8);
outfile << "*Node" << endl;
int np = mesh.GetNP();
int ne = mesh.GetNE();
int i, j, k;
for (i = 1; i <= np; i++)
{
outfile << i << ", ";
outfile << mesh.Point(i)(0) << ", ";
outfile << mesh.Point(i)(1) << ", ";
outfile << mesh.Point(i)(2) << "\n";
}
int elemcnt = 0; //element counter
int finished = 0;
int indcnt = 1; //index counter
while (!finished)
{
int actcnt = 0;
const Element & el1 = mesh.VolumeElement(1);
int non = el1.GetNP();
if (non == 4)
{
outfile << "*Element, type=C3D4, ELSET=PART" << indcnt << endl;
}
else if (non == 10)
{
outfile << "*Element, type=C3D10, ELSET=PART" << indcnt << endl;
}
else
{
cout << "unsupported Element type!!!" << endl;
}
for (i = 1; i <= ne; i++)
{
const Element & el = mesh.VolumeElement(i);
if (el.GetIndex() == indcnt)
{
actcnt++;
if (el.GetNP() != non)
{
cout << "different element-types in a subdomain are not possible!!!" << endl;
continue;
}
elemcnt++;
outfile << elemcnt << ", ";
if (non == 4)
{
outfile << el.PNum(1) << ", ";
outfile << el.PNum(2) << ", ";
outfile << el.PNum(4) << ", ";
outfile << el.PNum(3) << "\n";
}
else if (non == 10)
{
outfile << el.PNum(1) << ", ";
outfile << el.PNum(2) << ", ";
outfile << el.PNum(4) << ", ";
outfile << el.PNum(3) << ", ";
outfile << el.PNum(5) << ", ";
outfile << el.PNum(9) << ", ";
outfile << el.PNum(7) << ", " << "\n";
outfile << el.PNum(6) << ", ";
outfile << el.PNum(8) << ", ";
outfile << el.PNum(10) << "\n";
}
else
{
cout << "unsupported Element type!!!" << endl;
for (j = 1; j <= el.GetNP(); j++)
{
outfile << el.PNum(j);
if (j != el.GetNP()) outfile << ", ";
}
outfile << "\n";
}
}
}
indcnt++;
if (elemcnt == ne) {finished = 1; cout << "all elements found by Index!" << endl;}
if (actcnt == 0) {finished = 1;}
}
int element_counter = 0;
WritePoints(mesh, outfile);
if(mesh.GetDimension() < 3)
WriteElements<SegmentIndex>(outfile, mesh, 1, mesh.LineSegments().Range(), element_counter);
WriteElements<SurfaceElementIndex>(outfile, mesh, 2, mesh.SurfaceElements().Range(), element_counter);
WriteElements<ElementIndex>(outfile, mesh, 3, mesh.VolumeElements().Range(), element_counter);
// Write identifications (untested!)
if (mesh.GetIdentifications().GetMaxNr())
{
const auto np = mesh.GetNP();
// periodic identification, implementation for
// Helmut J. Boehm, TU Vienna
@ -138,27 +147,27 @@ void WriteAbaqusFormat (const Mesh & mesh,
NgArray<INDEX_2> pairs;
NgBitArray master(np), help(np);
master.Set();
for (i = 1; i <= 3; i++)
for (int i = 1; i <= 3; i++)
{
mesh.GetIdentifications().GetPairs (i, pairs);
help.Clear();
for (j = 1; j <= pairs.Size(); j++)
for (int j = 1; j <= pairs.Size(); j++)
{
help.Set (pairs.Get(j).I1());
}
master.And (help);
}
for (i = 1; i <= np; i++)
for (int i = 1; i <= np; i++)
if (master.Test(i))
masternode = i;
cout << "masternode = " << masternode << " = "
<< mesh.Point(masternode) << endl;
NgArray<int> minions(3);
for (i = 1; i <= 3; i++)
for (int i = 1; i <= 3; i++)
{
mesh.GetIdentifications().GetPairs (i, pairs);
for (j = 1; j <= pairs.Size(); j++)
for (int j = 1; j <= pairs.Size(); j++)
{
if (pairs.Get(j).I1() == masternode)
minions.Elem(i) = pairs.Get(j).I2();
@ -179,12 +188,12 @@ void WriteAbaqusFormat (const Mesh & mesh,
<< "**POINT_fixed\n"
<< "**\n"
<< "*BOUNDARY, OP=NEW\n";
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
outfile << masternode << ", " << j << ",, 0.\n";
outfile << "**\n"
<< "*BOUNDARY, OP=NEW\n";
for (j = 1; j <= 3; j++)
for (int j = 1; j <= 3; j++)
{
Vec3d v(mesh.Point(masternode), mesh.Point(minions.Get(j)));
double vlen = v.Length();
@ -203,18 +212,18 @@ void WriteAbaqusFormat (const Mesh & mesh,
NgBitArray eliminated(np);
eliminated.Clear();
for (i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)
for (int i = 1; i <= mesh.GetIdentifications().GetMaxNr(); i++)
{
mesh.GetIdentifications().GetPairs (i, pairs);
if (!pairs.Size())
continue;
for (j = 1; j <= pairs.Size(); j++)
for (int j = 1; j <= pairs.Size(); j++)
if (pairs.Get(j).I1() != masternode &&
!eliminated.Test(pairs.Get(j).I2()))
{
eliminated.Set (pairs.Get(j).I2());
for (k = 1; k <= 3; k++)
for (int k = 1; k <= 3; k++)
{
mpc << "4" << "\n";
mpc << pairs.Get(j).I2() << "," << k << ", -1.0, ";
@ -227,7 +236,7 @@ void WriteAbaqusFormat (const Mesh & mesh,
}
cout << "done" << endl;
PrintMessage(1, "done");
}
static RegisterUserFormat reg_abaqus ("Abaqus Format", {".mesh"}, nullopt, WriteAbaqusFormat);

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,8 @@ namespace netgen
{
data = NULL; height = width = 0;
SetSize (m2.Height(), m2.Width());
memcpy (data, m2.data, sizeof(double) * Height() * Width());
if (Height() && Width())
memcpy (data, m2.data, sizeof(double) * (Height() * Width()));
}
DenseMatrix :: ~DenseMatrix ()
@ -69,7 +70,7 @@ namespace netgen
delete[] data;
if (h*w)
if (h && w)
data = new double[h*w];
else
data = NULL;

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,6 +801,54 @@ void AdFront3 :: SetStartFront (int /* baseelnp */)
*/
}
bool AdFront3 :: PointInsideGroup(const Array<PointIndex, PointIndex> &grouppindex,
const Array<MiniElement2d> &groupfaces) const
{
for(auto pi : Range(points))
{
const auto& p = points[pi].P();
bool found = false;
for(const auto& f : groupfaces)
{
for(auto i : Range(3))
if(grouppindex[f.PNum(i+1)] == pi)
{
found = true;
break;
}
}
if(found)
continue;
// "random" direction
Vec<3> dir = { 0.123871, 0.15432,-0.43989 };
DenseMatrix a(3), ainv(3);
Vector b(3), u(3);
int count = 0;
for(const auto& f : groupfaces)
{
const auto& p1 = points[grouppindex[f.PNum(1)]].P();
auto v1 = points[grouppindex[f.PNum(2)]].P() - p1;
auto v2 = points[grouppindex[f.PNum(3)]].P() - p1;
for(auto i : Range(3))
{
a(i,0) = v1[i];
a(i,1) = v2[i];
a(i,2) = -dir[i];
b(i) = p[i] - p1[i];
}
CalcInverse (a, ainv);
ainv.Mult (b, u);
if (u(0) >= 0 && u(1) >= 0 && u(0)+u(1) <= 1 &&
u(2) > 0)
count++;
}
if (count % 2 == 1)
return true;
}
return false;
}
bool AdFront3 :: Inside (const Point<3> & p) const
{

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,15 +266,18 @@ public:
void GetIntersectingFaces (const Point<3> & pmin, const Point<3> & pmax,
NgArray<int> & ifaces) const;
bool PointInsideGroup(const Array<PointIndex, PointIndex> &grouppindex,
const Array<MiniElement2d>& groupfaces) const;
///
void GetFaceBoundingBox (int i, Box3d & box) const;
///
int GetLocals (int baseelement,
NgArray<Point3d, PointIndex::BASE> & locpoints,
NgArray<MiniElement2d> & locfaces, // local index
NgArray<PointIndex, PointIndex::BASE> & pindex,
NgArray<INDEX> & findex,
Array<Point3d, PointIndex> & locpoints,
Array<MiniElement2d> & locfaces, // local index
Array<PointIndex, PointIndex> & pindex,
Array<INDEX> & findex,
INDEX_2_HASHTABLE<int> & connectedpairs,
float xh,
float relh,
@ -278,10 +285,10 @@ public:
///
void GetGroup (int fi,
NgArray<MeshPoint, PointIndex::BASE> & grouppoints,
NgArray<MiniElement2d> & groupelements,
NgArray<PointIndex, PointIndex::BASE> & pindex,
NgArray<INDEX> & findex);
Array<MeshPoint, PointIndex> & grouppoints,
Array<MiniElement2d> & groupelements,
Array<PointIndex, PointIndex> & pindex,
Array<INDEX> & findex);
///
void DeleteFace (INDEX fi);
@ -290,14 +297,14 @@ public:
///
INDEX AddFace (const MiniElement2d & e);
///
INDEX AddConnectedPair (const INDEX_2 & pair);
INDEX AddConnectedPair (PointIndices<2> pair);
///
void IncrementClass (INDEX fi)
{ faces.Elem(fi).IncrementQualClass(); }
{ faces[fi-1].IncrementQualClass(); }
///
void ResetClass (INDEX fi)
{ faces.Elem(fi).ResetQualClass(); }
{ faces[fi-1].ResetQualClass(); }
///
void SetStartFront (int baseelnp = 0);

View File

@ -8,25 +8,26 @@ namespace netgen
{
struct PointTree
{
BoxTree<3> tree;
std::map<int, BoxTree<3>> tree;
Box<3> bounding_box;
PointTree( Box<3> bb ) : tree(bb) {}
PointTree( Box<3> bb ) : bounding_box(bb) {}
void Insert(Point<3> p, PointIndex n)
void Insert(Point<3> p, PointIndex n, int index)
{
tree.Insert(p, p, n);
if(tree.count(index) == 0)
tree.emplace(index, bounding_box);
tree.at(index).Insert(p, p, n);
}
PointIndex Find(Point<3> p) const
PointIndex Find(Point<3> p, int index) const
{
ArrayMem<int, 1> points;
tree.GetIntersecting(p, p, points);
tree.at(index).GetIntersecting(p, p, points);
if(points.Size()==0)
throw Exception("cannot find mapped point " + ToString(p));
return points[0];
}
double GetTolerance() { return tree.GetTolerance(); }
};
DLL_HEADER GeometryRegisterArray geometryregister;
@ -213,22 +214,24 @@ namespace netgen
}
}
struct Line
{
Point<3> p0, p1;
inline double Length() const { return (p1-p0).Length(); }
inline double Dist(const Line& other) const
namespace {
struct Line
{
Vec<3> n = p1-p0;
Vec<3> q = other.p1-other.p0;
double nq = n*q;
Point<3> p = p0 + 0.5*n;
double lambda = (p-other.p0)*n / (nq + 1e-10);
if (lambda >= 0 && lambda <= 1)
return (p-other.p0-lambda*q).Length();
return 1e99;
}
};
Point<3> p0, p1;
inline double Length() const { return (p1-p0).Length(); }
inline double Dist(const Line& other) const
{
Vec<3> n = p1-p0;
Vec<3> q = other.p1-other.p0;
double nq = n*q;
Point<3> p = p0 + 0.5*n;
double lambda = (p-other.p0)*n / (nq + 1e-10);
if (lambda >= 0 && lambda <= 1)
return (p-other.p0-lambda*q).Length();
return 1e99;
}
};
}
void NetgenGeometry :: Clear()
{
@ -471,7 +474,7 @@ namespace netgen
}
for(const auto& mspnt : mparam.meshsize_points)
mesh.RestrictLocalH(mspnt.pnt, mspnt.h);
mesh.RestrictLocalH(mspnt.pnt, mspnt.h, mspnt.layer);
mesh.LoadLocalMeshSize(mparam.meshsizefilename);
}
@ -581,17 +584,17 @@ namespace netgen
Array<PointIndex> vert2meshpt(vertices.Size());
vert2meshpt = PointIndex::INVALID;
for(auto & vert : vertices)
{
auto pi = mesh.AddPoint(vert->GetPoint(), vert->properties.layer);
tree.Insert(mesh[pi], pi);
vert2meshpt[vert->nr] = pi;
mesh[pi].Singularity(vert->properties.hpref);
mesh[pi].SetType(FIXEDPOINT);
Element0d el(pi, pi);
Element0d el(pi, pi-IndexBASE<PointIndex>()+1);
el.name = vert->properties.GetName();
mesh.SetCD3Name(pi, el.name);
mesh.SetCD3Name(pi-IndexBASE<PointIndex>()+1, el.name);
mesh.pointelements.Append (el);
}
@ -616,8 +619,8 @@ namespace netgen
endp = vert2meshpt[edge->GetEndVertex().nr];
// ignore collapsed edges
if(startp == endp && edge->GetLength() < 1e-10 * bounding_box.Diam())
continue;
if(edge->IsDegenerated())
continue;
// ----------- Add Points to mesh and create segments -----
auto & pnums = all_pnums[edgenr];
@ -716,7 +719,8 @@ namespace netgen
for(auto i : Range(edge_points))
{
auto pi = mesh.AddPoint(edge_points[i], edge->properties.layer);
tree.Insert(mesh[pi], pi);
if(edge->identifications.Size())
tree.Insert(mesh[pi], pi, edge->nr);
pnums[i+1] = pi;
}
@ -757,7 +761,7 @@ namespace netgen
p_other = (*ident.trafo)(mesh[pi]);
else
static_cast<GeometryEdge*>(ident.to)->ProjectPoint(p_other, nullptr);
auto pi_other = tree.Find(p_other);
auto pi_other = tree.Find(p_other, ident.to->nr);
identifications.Add(pi, pi_other, ident.name, ident.type);
}
}
@ -866,7 +870,7 @@ namespace netgen
for(auto pi : s.PNums())
if(!is_point_in_tree[pi])
{
tree.Insert(mesh[pi], pi);
tree.Insert(mesh[pi], pi, -1);
is_point_in_tree[pi] = true;
}
@ -936,8 +940,8 @@ namespace netgen
edges[mapped_edges[edgenr]]->ProjectPoint(p2, nullptr);
edges[mapped_edges[edgenr]]->ProjectPoint(p3, nullptr);
}
sel[2] = tree.Find(p2);
sel[3] = tree.Find(p3);
sel[2] = tree.Find(p2, -1);
sel[3] = tree.Find(p3, -1);
// find mapped segment to set PointGeomInfo correctly
Segment s_other;
@ -1017,7 +1021,7 @@ namespace netgen
if(mesh[pi].Type() == SURFACEPOINT && pi_to_face[pi]==-1)
{
pi_to_face[pi] = face->nr;
tree.Insert(mesh[pi], pi);
tree.Insert(mesh[pi], pi, -1);
pi_of_face[face->nr].Append(pi);
}
}
@ -1085,7 +1089,7 @@ namespace netgen
else
edge->ProjectPoint(p, nullptr);
}
tree.Insert(p, pi);
tree.Insert(p, pi, -1);
is_point_in_tree[pi] = true;
}
}
@ -1097,7 +1101,7 @@ namespace netgen
{
auto pi = seg[i];
if(!pmap[pi].IsValid())
pmap[tree.Find(mesh[pi])] = pi;
pmap[tree.Find(mesh[pi], -1)] = pi;
// store uv values (might be different values for same point in case of internal edges)
double u = seg.epgeominfo[i].u;
@ -1216,6 +1220,7 @@ namespace netgen
{
PrintMessage(3, "Optimization step ", i);
meshopt.SetFaceIndex(k+1);
meshopt.SetMetricWeight (mparam.elsizeweight);
int innerstep = 0;
for(auto optstep : mparam.optimize2d)
{
@ -1244,8 +1249,7 @@ namespace netgen
void NetgenGeometry :: FinalizeMesh(Mesh& mesh) const
{
if(solids.Size())
for (int i = 0; i < mesh.GetNDomains(); i++)
for (int i = 0; i < std::min(solids.Size(), (size_t)mesh.GetNDomains()); i++)
if (auto name = solids[i]->properties.name)
mesh.SetMaterial (i+1, *name);
@ -1311,6 +1315,13 @@ namespace netgen
if(multithread.terminate || mparam.perfstepsend <= MESHCONST_MESHEDGES)
return 0;
if(dimension == 1)
{
FinalizeMesh(*mesh);
mesh->SetDimension(1);
return 0;
}
if (mparam.perfstepsstart <= MESHCONST_MESHSURFACE)
{
MeshSurface(*mesh, mparam);

View File

@ -86,6 +86,9 @@ namespace netgen
protected:
GeometryVertex *start, *end;
public:
// Neighboring domains in 2d
// In 3d unused, EXCEPT for free floating edges in a domain,
// then both are pointing to the containing domain
int domin=-1, domout=-1;
GeometryEdge( GeometryVertex &start_, GeometryVertex &end_ )
@ -187,7 +190,10 @@ namespace netgen
};
class DLL_HEADER GeometrySolid : public GeometryShape
{ };
{
public:
Array<GeometryEdge*> free_edges; // edges with no adjacent face
};
class DLL_HEADER NetgenGeometry
{
@ -212,11 +218,18 @@ namespace netgen
size_t GetNVertices() const { return vertices.Size(); }
size_t GetNEdges() const { return edges.Size(); }
size_t GetNFaces() const { return faces.Size(); }
size_t GetNSolids() const { return solids.Size(); }
const GeometrySolid & GetSolid(int i) const { return *solids[i]; }
const GeometryFace & GetFace(int i) const { return *faces[i]; }
const GeometryEdge & GetEdge(int i) const { return *edges[i]; }
const GeometryVertex & GetVertex(int i) const { return *vertices[i]; }
auto Solids() const { return FlatArray{solids}; }
auto Faces() const { return FlatArray{faces}; }
auto Edges() const { return FlatArray{edges}; }
auto Vertices() const { return FlatArray{vertices}; }
virtual Array<const GeometryVertex*> GetFaceVertices(const GeometryFace& face) const { return Array<const GeometryVertex*>{}; }
void Clear();
@ -258,7 +271,7 @@ namespace netgen
virtual void ProjectPointEdge (int surfind, int surfind2, Point<3> & p, EdgePointGeomInfo* gi = nullptr) const
{
if(gi && gi->edgenr < edges.Size())
if(gi && gi->edgenr < edges.Size() && gi->edgenr >= 0)
edges[gi->edgenr]->ProjectPoint(p, gi);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +1,112 @@
#ifndef NETGEN_BOUNDARYLAYER_HPP
#define NETGEN_BOUNDARYLAYER_HPP
#include <core/array.hpp>
#include <mystdlib.h>
#include <meshing.hpp>
namespace netgen
{
///
DLL_HEADER extern void InsertVirtualBoundaryLayer (Mesh & mesh);
DLL_HEADER extern void InsertVirtualBoundaryLayer (Mesh& mesh);
/// Create a typical prismatic boundary layer on the given
/// Create a typical prismatic boundary layer on the given
/// surfaces
class BoundaryLayerParameters
struct SpecialBoundaryPoint
{
public:
// parameters by Philippose ..
Array<int> surfid;
Array<double> heights;
map<string, string> new_mat;
BitArray domains;
bool outside = false; // set the boundary layer on the outside
bool grow_edges = false;
bool limit_growth_vectors = true;
double limit_safety = 0.3; // alloow only 30% of the growth vector length
bool sides_keep_surfaceindex = false;
bool keep_surfaceindex = false;
Array<size_t> project_boundaries;
struct GrowthGroup
{
Array<int> faces;
Vec<3> growth_vector;
Array<PointIndex> new_points;
GrowthGroup (FlatArray<int> faces_, FlatArray<Vec<3>> normals);
GrowthGroup (const GrowthGroup&) = default;
GrowthGroup () = default;
};
Array<GrowthGroup> growth_groups;
Vec<3> separating_direction;
SpecialBoundaryPoint (const std::map<int, Vec<3>>& normals);
SpecialBoundaryPoint () = default;
};
DLL_HEADER void GenerateBoundaryLayer (Mesh & mesh,
const BoundaryLayerParameters & blp);
DLL_HEADER void GenerateBoundaryLayer (Mesh& mesh,
const BoundaryLayerParameters& blp);
DLL_HEADER int /* new_domain_number */ GenerateBoundaryLayer2 (Mesh & mesh, int domain, const Array<double> & thicknesses, bool should_make_new_domain=true, const Array<int> & boundaries=Array<int>{});
DLL_HEADER int /* new_domain_number */ GenerateBoundaryLayer2 (Mesh& mesh, int domain, const Array<double>& thicknesses, bool should_make_new_domain = true, const Array<int>& boundaries = Array<int>{});
class BoundaryLayerTool
{
public:
BoundaryLayerTool(Mesh & mesh_, const BoundaryLayerParameters & params_);
void Perform();
public:
BoundaryLayerTool (Mesh& mesh_, const BoundaryLayerParameters& params_);
void ProcessParameters ();
void Perform ();
protected:
Mesh & mesh;
MeshTopology & topo;
BoundaryLayerParameters params;
Array<Vec<3>, PointIndex> growthvectors;
Table<SurfaceElementIndex, PointIndex> p2sel;
Mesh& mesh;
MeshTopology& topo;
BoundaryLayerParameters params;
Array<Vec<3>, PointIndex> growthvectors;
std::map<PointIndex, Vec<3>> non_bl_growth_vectors;
Table<SurfaceElementIndex, PointIndex> p2sel;
BitArray domains, is_edge_moved, is_boundary_projected, is_boundary_moved;
Array<SegmentIndex> moved_segs;
int max_edge_nr, nfd_old, ndom_old;
Array<int> new_mat_nrs;
BitArray moved_surfaces;
int np, nseg, nse, ne;
double height;
BitArray domains, is_edge_moved, is_boundary_projected, is_boundary_moved;
Array<SegmentIndex> moved_segs;
int max_edge_nr, nfd_old, ndom_old;
Array<int> new_mat_nrs;
BitArray moved_surfaces;
int np, nseg, nse, ne;
PointIndex first_new_pi;
double total_height;
Array<POINTTYPE, PointIndex> point_types;
bool have_single_segments;
Array<Segment> segments, new_segments;
// These parameters are derived from given BoundaryLayerParameters and the Mesh
Array<double> par_heights;
Array<int> par_surfid;
bool insert_only_volume_elements;
map<string, string> par_new_mat;
bool have_material_map = false;
Array<size_t> par_project_boundaries;
Array<double> surfacefacs;
Array<int> si_map;
Array<double, PointIndex> limits;
bool have_single_segments;
Array<Segment> old_segments, free_segments, segments, new_segments, new_segments_on_moved_bnd;
Array<Element2d, SurfaceElementIndex> new_sels, new_sels_on_moved_bnd;
Array<Array<PointIndex>, PointIndex> mapto;
Array<PointIndex, PointIndex> mapfrom;
// major steps called in Perform()
void CreateNewFaceDescriptors();
void CreateFaceDescriptorsSides();
void CalculateGrowthVectors();
Array<Array<pair<SegmentIndex, int>>, SegmentIndex> BuildSegMap();
Array<double> surfacefacs;
Array<int> si_map;
BitArray ProjectGrowthVectorsOnSurface();
void InterpolateSurfaceGrowthVectors();
void InterpolateGrowthVectors();
void LimitGrowthVectorLengths();
std::map<PointIndex, SpecialBoundaryPoint> special_boundary_points;
std::map<PointIndex, std::tuple<Vec<3>*, double>> growth_vector_map;
void InsertNewElements(FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap, const BitArray & in_surface_direction);
void SetDomInOut();
void SetDomInOutSides();
void AddSegments();
void FixVolumeElements();
// major steps called in Perform()
void CreateNewFaceDescriptors ();
void CreateFaceDescriptorsSides ();
void CalculateGrowthVectors ();
Array<Array<pair<SegmentIndex, int>>, SegmentIndex> BuildSegMap ();
// utility functions
array<Point<3>, 2> GetMappedSeg( PointIndex pi );
ArrayMem<Point<3>, 4> GetFace( SurfaceElementIndex sei );
ArrayMem<Point<3>, 4> GetMappedFace( SurfaceElementIndex sei );
ArrayMem<Point<3>, 4> GetMappedFace( SurfaceElementIndex sei, int face );
BitArray ProjectGrowthVectorsOnSurface ();
void InterpolateSurfaceGrowthVectors ();
void InterpolateGrowthVectors ();
void LimitGrowthVectorLengths ();
void FixSurfaceElements ();
Vec<3> getNormal(const Element2d & el)
{
auto v0 = mesh[el[0]];
return Cross(mesh[el[1]]-v0, mesh[el[2]]-v0).Normalize();
}
void InsertNewElements (FlatArray<Array<pair<SegmentIndex, int>>, SegmentIndex> segmap, const BitArray& in_surface_direction);
void SetDomInOut ();
void SetDomInOutSides ();
void AddSegments ();
void AddSurfaceElements ();
Vec<3> getEdgeTangent(PointIndex pi, int edgenr);
Vec<3> getNormal (const Element2d& el)
{
auto v0 = mesh[el[0]];
return Cross(mesh[el[1]] - v0, mesh[el[2]] - v0).Normalize();
}
Vec<3> getEdgeTangent (PointIndex pi, int edgenr, FlatArray<Segment*> segs);
};
} // namespace netgen

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>();
@ -36,13 +37,14 @@ namespace netgen
mesh->SetMaterial(2, "2_points");
mesh->SetMaterial(3, "3_points");
mesh->SetMaterial(4, "4_points");
mesh->Compress();
mesh->ClearSurfaceElements();
for (auto & el : openelements)
mesh->AddSurfaceElement( el );
if(!only_quads || el.GetNP() == 4)
mesh->AddSurfaceElement( el );
mesh->Compress();
return mesh;
}
@ -95,6 +97,127 @@ namespace netgen
return mesh_ptr;
}
void CheckMesh (const Mesh& mesh, MESHING_STEP step)
{
if (step == MESHCONST_OPTVOLUME)
{
bool have_error = false;
for (auto el : mesh.VolumeElements())
{
double volume = el.Volume(mesh.Points());
if (volume < 0)
{
have_error = true;
cout << "volume of element " << el << " is negative: " << volume << endl;
}
}
if (have_error)
throw Exception("Negative volume");
CheckElementsAroundEdges(mesh);
}
}
}
void CheckElementsAroundEdges (const Mesh& mesh)
{
static Mesh last_good_mesh;
Array<std::tuple<PointIndex, PointIndex>> edges;
auto elementsonnode = mesh.CreatePoint2ElementTable();
BuildEdgeList(mesh, elementsonnode, edges);
mesh.BoundaryEdge(1, 2); // trigger build of boundary edges
ArrayMem<ElementIndex, 20> hasbothpoints;
for (auto [pi0, pi1] : edges)
{
if (mesh.BoundaryEdge(pi0, pi1))
continue;
hasbothpoints.SetSize(0);
for (ElementIndex ei : elementsonnode[pi0])
if (mesh[ei].PNums().Contains(pi1))
hasbothpoints.Append(ei);
bool skip = false;
for (ElementIndex ei : hasbothpoints)
{
if (mesh[ei].GetType() != TET)
{
skip = true;
break;
}
}
if (skip)
continue;
int nsuround = hasbothpoints.Size();
ArrayMem<PointIndex, 50> suroundpts(nsuround + 1);
suroundpts = PointIndex::INVALID;
ArrayMem<bool, 50> tetused(nsuround);
tetused = false;
tetused[0] = true;
auto el = mesh[hasbothpoints[0]];
PointIndex pi2 = PointIndex::INVALID;
PointIndex pi3 = PointIndex::INVALID;
for (auto pi : el.PNums())
if (pi != pi0 && pi != pi1)
{
pi3 = pi2;
pi2 = pi;
}
suroundpts[0] = pi2;
suroundpts[1] = pi3;
for (auto i : Range(2, nsuround + 1))
{
PointIndex oldpi = suroundpts[i - 1];
PointIndex newpi = PointIndex::INVALID;
for (int k = 0; k < nsuround && !newpi.IsValid(); k++)
if (!tetused[k])
{
const Element& nel = mesh[hasbothpoints[k]];
for (int k2 = 0; k2 < 4 && !newpi.IsValid(); k2++)
if (nel[k2] == oldpi)
{
newpi = nel[0] - pi0 + nel[1] - pi1 + nel[2] - oldpi + nel[3];
tetused[k] = true;
suroundpts[i] = newpi;
ArrayMem<PointIndex, 4> nelpts{nel[0], nel[1], nel[2], nel[3]};
ArrayMem<PointIndex, 4> check_points{pi0, pi1, oldpi, newpi};
QuickSort(check_points);
QuickSort(nelpts);
if (check_points != nelpts)
{
cout << __FILE__ << ":" << __LINE__ << "\tFound error" << endl;
cout << "i = " << i << endl;
cout << "oldpi = " << oldpi << endl;
cout << "newpi = " << newpi << endl;
cout << "Elements: " << endl;
cout << "nel " << nel << endl;
for (auto ei : hasbothpoints)
cout << mesh[ei] << endl;
cout << endl;
cout << "check_points: " << check_points << endl;
cout << "nelpts: " << nelpts << endl;
cout << "hasbothpoints: " << hasbothpoints << endl;
cout << "suroundpts: " << suroundpts << endl;
throw Exception("Found error");
}
}
}
}
if (suroundpts.Last() != suroundpts[0])
{
cout << __FILE__ << ":" << __LINE__ << "\tFound error" << endl;
cout << "hasbothpoints: " << hasbothpoints << endl;
cout << "suroundpts: " << suroundpts << endl;
for (auto ei : hasbothpoints)
cout << mesh[ei] << endl;
throw Exception("Found error");
}
}
}
} // namespace netgen

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, const MeshingParameters & mp, AdFront3 * adfront,
void Delaunay1 (Mesh & mesh, int domainnr, const MeshingParameters & mp, const AdFront3 & adfront,
NgArray<DelaunayTet> & tempels,
int oldnp, DelaunayTet & startel, Point3d & pmin, Point3d & pmax)
{
@ -575,7 +573,7 @@ namespace netgen
Box<3> bbox(Box<3>::EMPTY_BOX);
for (auto & face : adfront->Faces())
for (auto & face : adfront.Faces())
for (PointIndex pi : face.Face().PNums())
bbox.Add (mesh.Point(pi));
@ -612,17 +610,27 @@ namespace netgen
Array<bool, PointIndex> usep(np);
usep = false;
for (auto & face : adfront->Faces())
for (auto & face : adfront.Faces())
for (PointIndex pi : face.Face().PNums())
usep[pi] = true;
/*
for (size_t i = oldnp + PointIndex::BASE;
i < np + PointIndex::BASE; i++)
*/
for (auto i : mesh.Points().Range().Modify(oldnp, -4))
usep[i] = true;
for (PointIndex pi : mesh.LockedPoints())
usep[pi] = true;
// mark points of free edge segments (no adjacent face)
for (auto & seg : mesh.LineSegments())
if(seg.domin == domainnr && seg.domout == domainnr)
{
usep[seg[0]] = true;
usep[seg[1]] = true;
}
NgArray<int> freelist;
@ -666,7 +674,7 @@ namespace netgen
IndexSet closesphere(mesh.GetNP());
// "random" reordering of points (speeds a factor 3 - 5 !!!)
NgArray<PointIndex, PointIndex::BASE, PointIndex> mixed(np);
Array<PointIndex, PointIndex> mixed(np);
// int prims[] = { 11, 13, 17, 19, 23, 29, 31, 37 };
// int prims[] = { 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
int prims[] = { 211, 223, 227, 229, 233, 239, 241, 251, 257, 263 };
@ -677,24 +685,25 @@ namespace netgen
while (np % prims[i] == 0) i++;
prim = prims[i];
}
// for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++)
for (PointIndex pi : mesh.Points().Range().Modify(0, -4))
mixed[pi] = PointIndex ( (prim * pi) % np + PointIndex::BASE );
// mixed[pi] = PointIndex ( (prim * pi) % np + PointIndex::BASE );
mixed[pi] = (prim * (pi-IndexBASE<PointIndex>()+1)) % np + IndexBASE<PointIndex>() ;
Array<DelaunayTet> newels;
// for (PointIndex pi = mesh.Points().Begin(); pi < mesh.Points().End()-4; pi++)
for (PointIndex pi : mesh.Points().Range().Modify(0, -4))
{
if (pi % 1000 == 0)
if ((pi-IndexBASE<PointIndex>()) % 1000 == 0)
{
if (pi % 10000 == 0)
if ((pi-IndexBASE<PointIndex>()) % 10000 == 0)
PrintDot ('+');
else
PrintDot ('.');
}
multithread.percent = 100.0 * pi / np;
multithread.percent = 100.0 * (pi-IndexBASE<PointIndex>()) / np;
if (multithread.terminate)
break;
@ -714,7 +723,7 @@ namespace netgen
}
for (int i = tempels.Size(); i >= 1; i--)
if (tempels.Get(i)[0] <= 0)
if (!tempels.Get(i)[0].IsValid())
tempels.DeleteElement (i);
PrintDot ('\n');
@ -740,7 +749,7 @@ namespace netgen
{
static Timer tdegenerated("Delaunay - remove degenerated"); RegionTimer rt(tdegenerated);
NgBitArray badnode(points.Size());
TBitArray<PointIndex> badnode(points.Size());
badnode.Clear();
int ndeg = 0;
@ -762,13 +771,15 @@ namespace netgen
double h = v1.Length() + v2.Length() + v3.Length();
if (fabs (vol) < 1e-8 * (h * h * h) &&
(el[0] <= np && el[1] <= np &&
el[2] <= np && el[3] <= np) ) // old: 1e-12
(el[0] < IndexBASE<PointIndex>()+np &&
el[1] < IndexBASE<PointIndex>()+np &&
el[2] < IndexBASE<PointIndex>()+np &&
el[3] < IndexBASE<PointIndex>()+np) ) // old: 1e-12
{
badnode.Set(el[0]);
badnode.Set(el[1]);
badnode.Set(el[2]);
badnode.Set(el[3]);
badnode.SetBitAtomic(el[0]);
badnode.SetBitAtomic(el[1]);
badnode.SetBitAtomic(el[2]);
badnode.SetBitAtomic(el[3]);
ndeg++;
(*testout) << "vol = " << vol << " h = " << h << endl;
}
@ -798,7 +809,7 @@ namespace netgen
static Timer topenel("Delaunay - find openel"); RegionTimer rt(topenel);
// find surface triangles which are no face of any tet
BitArray bnd_points( mesh.GetNP() + PointIndex::BASE );
TBitArray<PointIndex> bnd_points( mesh.GetNP() );
bnd_points.Clear();
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
@ -840,16 +851,17 @@ namespace netgen
tets_with_3_bnd_points.SetSize(cnt);
static Timer t1("Build face table"); t1.Start();
ngcore::ClosedHashTable< ngcore::IVec<3>, int > face_table( 4*cnt + 3 );
for(auto ei : tets_with_3_bnd_points)
for(auto j : Range(4))
// ngcore::ClosedHashTable< ngcore::IVec<3>, int > face_table( 4*cnt + 3 );
ngcore::ClosedHashTable< PointIndices<3>, int > face_table( 4*cnt + 3 );
for (auto ei : tets_with_3_bnd_points)
for (auto j : Range(4))
{
auto i3_ = tempels[ei].GetFace (j);
ngcore::IVec<3> i3 = {i3_[0], i3_[1], i3_[2]};
if(bnd_points[i3[0]] && bnd_points[i3[1]] && bnd_points[i3[2]])
PointIndices<3> i3 = tempels[ei].GetFace (j);
// ngcore::IVec<3> i3 = {i3_[0], i3_[1], i3_[2]};
if(bnd_points[i3[0]] && bnd_points[i3[1]] && bnd_points[i3[2]])
{
i3.Sort();
face_table.Set( i3, true );
i3.Sort();
face_table.Set( i3, true );
}
}
t1.Stop();
@ -860,7 +872,8 @@ namespace netgen
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
{
const Element2d & tri = mesh.OpenElement(i);
ngcore::IVec<3> i3(tri[0], tri[1], tri[2]);
// ngcore::IVec<3,PointIndex> i3(tri[0], tri[1], tri[2]);
PointIndices<3> i3(tri[0], tri[1], tri[2]);
i3.Sort();
if(!face_table.Used(i3))
openels.Append(i);
@ -878,7 +891,7 @@ namespace netgen
table.Add(tri[2], openel_i);
}, mesh.GetNP());
ngcore::BitArray badnode(mesh.GetNP()+PointIndex::BASE);
TBitArray<PointIndex> badnode(mesh.GetNP());
badnode.Clear();
ngcore::ParallelForRange(openels.Size(), [&] (auto myrange) {
@ -912,7 +925,7 @@ namespace netgen
{
auto & tri_other = mesh.OpenElement(i_other);
PointIndex pi2 = tri[(edge+2)%3];
PointIndex pi3 = tri_other[0]+tri_other[1]+tri_other[2] - pi0 - pi1;
PointIndex pi3 = tri_other[0]-pi0+tri_other[1]-pi1+tri_other[2];
if(pi2>pi3)
Swap(pi2, pi3);
@ -936,8 +949,8 @@ namespace netgen
double h = v1.Length() + v2.Length() + v3.Length();
if (fabs (vol) < 1e-4 * (h * h * h)) // old: 1e-12
{
badnode.SetBitAtomic(pi2);
badnode.SetBitAtomic(pi3);
badnode.SetBitAtomic(pi2);
badnode.SetBitAtomic(pi3);
}
break;
}
@ -1005,7 +1018,7 @@ namespace netgen
for (int j = 0; j < 4; j++)
{
pp[j] = &mesh.Point(el[j]);
tetpi[j] = el[j];
tetpi[j] = el[j]-IndexBASE<PointIndex>()+1;
}
Point3d tetpmin(*pp[0]);
@ -1034,7 +1047,7 @@ namespace netgen
for (int k = 1; k <= 3; k++)
{
tripp[k-1] = &mesh.Point (tri.PNum(k));
tripi[k-1] = tri.PNum(k);
tripi[k-1] = tri.PNum(k)-IndexBASE<PointIndex>()+1;
}
if (IntersectTetTriangle (&pp[0], &tripp[0], tetpi, tripi))
@ -1077,7 +1090,7 @@ namespace netgen
}
}
void DelaunayRemoveOuter( const Mesh & mesh, NgArray<DelaunayTet> & tempels, AdFront3 * adfront )
void DelaunayRemoveOuter( const Mesh & mesh, NgArray<DelaunayTet> & tempels, const AdFront3 & adfront )
{
static Timer trem_outer("Delaunay - remove outer"); RegionTimer rt(trem_outer);
@ -1101,7 +1114,7 @@ namespace netgen
*/
for (const Element2d & tri : mesh.OpenElements())
{
INDEX_3 i3 (tri[0], tri[1], tri[2]);
PointIndices<3> i3 (tri[0], tri[1], tri[2]);
i3.Sort();
boundaryfaces.PrepareSet (i3);
}
@ -1109,7 +1122,7 @@ namespace netgen
for (int i = 1; i <= mesh.GetNOpenElements(); i++)
{
const Element2d & tri = mesh.OpenElement(i);
INDEX_3 i3 (tri[0], tri[1], tri[2]);
PointIndices<3> i3 (tri[0], tri[1], tri[2]);
i3.Sort();
boundaryfaces.Set (i3, 1);
}
@ -1122,16 +1135,13 @@ namespace netgen
for (auto & el : tempels)
for (int j = 0; j < 4; j++)
el.NB(j) = 0;
TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP());
/*
for (int i = 0; i < tempels.Size(); i++)
{
const DelaunayTet & el = tempels[i];
*/
TABLE<int,PointIndex::BASE> elsonpoint(mesh.GetNP());
for (const DelaunayTet & el : tempels)
{
INDEX_4 i4(el[0], el[1], el[2], el[3]);
PointIndices<4> i4(el[0], el[1], el[2], el[3]);
i4.Sort();
elsonpoint.IncSizePrepare (i4.I1());
elsonpoint.IncSizePrepare (i4.I2());
@ -1142,12 +1152,30 @@ namespace netgen
for (int i = 0; i < tempels.Size(); i++)
{
const DelaunayTet & el = tempels[i];
INDEX_4 i4(el[0], el[1], el[2], el[3]);
PointIndices<4> i4(el[0], el[1], el[2], el[3]);
i4.Sort();
elsonpoint.Add (i4.I1(), i+1);
elsonpoint.Add (i4.I2(), i+1);
}
*/
TableCreator<int, PointIndex> creator(mesh.GetNP());
while (!creator.Done())
{
for (int i = 0; i < tempels.Size(); i++)
{
const DelaunayTet & el = tempels[i];
PointIndices<4> i4(el[0], el[1], el[2], el[3]);
i4.Sort();
creator.Add (i4[0], i+1);
creator.Add (i4[1], i+1);
}
creator++;
}
auto elsonpoint = creator.MoveTable();
// cout << "elsonpoint mem: ";
// elsonpoint.PrintMemInfo(cout);
@ -1171,7 +1199,7 @@ namespace netgen
if (hel[0] == pi)
{
INDEX_3 i3(hel[0], hel[1], hel[2]);
PointIndices<3> i3(hel[0], hel[1], hel[2]);
if (!boundaryfaces.Used (i3))
{
@ -1186,7 +1214,7 @@ namespace netgen
{
hel.Invert();
hel.NormalizeNumbering();
INDEX_3 i3i(hel[0], hel[1], hel[2]);
PointIndices<3> i3i(hel[0], hel[1], hel[2]);
INDEX_2 i2(i, j);
faceht.Set (i3i, i2);
}
@ -1270,7 +1298,7 @@ namespace netgen
auto ne = tempels.Size();
NgBitArray inner(ne), outer(ne);
BitArray inner(ne+1), outer(ne+1);
inner.Clear();
outer.Clear();
NgArray<int> elstack;
@ -1315,7 +1343,7 @@ namespace netgen
Point3d ci = Center (p1, p2, p3, p4);
inside = adfront->Inside (ci);
inside = adfront.Inside (ci);
/*
cout << "startel: " << i << endl;
@ -1335,9 +1363,9 @@ namespace netgen
if (!inner.Test(ei) && !outer.Test(ei))
{
if (inside)
inner.Set(ei);
inner.SetBit(ei);
else
outer.Set(ei);
outer.SetBit(ei);
for (int j = 1; j <= 4; j++)
@ -1397,7 +1425,7 @@ namespace netgen
// if (adfront->Inside (ci) != adfront->Inside (Center (ci, p1)))
// cout << "ERROR: outer test unclear !!!" << endl;
if (inner.Test(i) != adfront->Inside (ci))
if (inner.Test(i) != adfront.Inside (ci))
{
/*
cout << "ERROR: outer test wrong !!!"
@ -1425,10 +1453,10 @@ namespace netgen
}
if (adfront->Inside(ci))
if (adfront.Inside(ci))
outer.Clear(i);
else
outer.Set(i);
outer.SetBit(i);
}
}
@ -1554,7 +1582,7 @@ namespace netgen
int np = mesh.GetNP();
Delaunay1 (mesh, mp, adfront, tempels, oldnp, startel, pmin, pmax);
Delaunay1 (mesh, domainnr, mp, *adfront, tempels, oldnp, startel, pmin, pmax);
{
// improve delaunay - mesh by swapping !!!!
@ -1657,7 +1685,7 @@ namespace netgen
NgArray<int> openels;
DelaunayRemoveTwoTriaTets(mesh, tempels, openels);
DelaunayRemoveIntersecting(mesh, tempels, openels, pmin, pmax);
DelaunayRemoveOuter(mesh, tempels, adfront);
DelaunayRemoveOuter(mesh, tempels, *adfront);
for (int i = 0; i < tempels.Size(); i++)
{

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

Some files were not shown because too many files have changed in this diff Show More