mirror of
https://github.com/NGSolve/netgen.git
synced 2025-05-10 12:40:49 +05:00
Compare commits
1596 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a9e8f2a1c9 | ||
![]() |
b84975586c | ||
![]() |
aa66cd11c4 | ||
![]() |
494b0ae37c | ||
![]() |
f42d0c0be4 | ||
![]() |
b43eb033d2 | ||
![]() |
1fc382867d | ||
![]() |
6ea09e1151 | ||
![]() |
36cbd5fc00 | ||
![]() |
3a9060fc2f | ||
![]() |
109e7ffcf7 | ||
![]() |
1db8ea3500 | ||
![]() |
b05c32675b | ||
![]() |
cb3eb0d355 | ||
![]() |
42294117bd | ||
![]() |
60c1151205 | ||
![]() |
3f28651e63 | ||
![]() |
5a66cbee72 | ||
![]() |
788c782455 | ||
![]() |
12ef984e93 | ||
![]() |
f15ba64a90 | ||
![]() |
3b79dbc8ff | ||
![]() |
7b13db740d | ||
![]() |
78994da199 | ||
![]() |
42c1818784 | ||
![]() |
97f869207e | ||
![]() |
951e20a7e4 | ||
![]() |
8cde49627b | ||
![]() |
36c9201ffc | ||
![]() |
8478ff5078 | ||
![]() |
714158e928 | ||
![]() |
9399f753c4 | ||
![]() |
8944322e60 | ||
![]() |
15bd6cbed0 | ||
![]() |
b8d722d6a8 | ||
![]() |
7aae5369c4 | ||
![]() |
787c6043fa | ||
![]() |
d240203932 | ||
![]() |
0c789fb04f | ||
![]() |
9204b079f6 | ||
![]() |
2778b934e6 | ||
![]() |
627e89d579 | ||
![]() |
bc194027a2 | ||
![]() |
d1a9f7ee3d | ||
![]() |
82befccada | ||
![]() |
9601f70c17 | ||
![]() |
5ab7a4995c | ||
![]() |
8b0b9e507f | ||
![]() |
f236648847 | ||
![]() |
2220fc093f | ||
![]() |
5e742f017c | ||
![]() |
fb399595fa | ||
![]() |
d2f7c24a5e | ||
![]() |
d7ae61e00a | ||
![]() |
058cdce84d | ||
![]() |
15ffcbae8e | ||
![]() |
913ede1cae | ||
![]() |
44fe189bf0 | ||
![]() |
b811162086 | ||
![]() |
12ff6d6f51 | ||
![]() |
b14a9e6d2b | ||
![]() |
d1228b6ce9 | ||
![]() |
7aff94046f | ||
![]() |
a8a75614c0 | ||
![]() |
6f574ec191 | ||
![]() |
20196cd8e9 | ||
![]() |
cf6c702d2c | ||
![]() |
5856001819 | ||
![]() |
49ecbd55ee | ||
![]() |
311ae9e89b | ||
![]() |
5292a09c94 | ||
![]() |
b79128fabf | ||
![]() |
886bb14299 | ||
![]() |
892271fd08 | ||
![]() |
c4985c49e1 | ||
![]() |
06e8764d01 | ||
![]() |
dcd6f6d60d | ||
![]() |
0a1fd5a2e2 | ||
![]() |
5642d435e1 | ||
![]() |
6af9b48bda | ||
![]() |
c0b33db5c0 | ||
![]() |
59e5974a28 | ||
![]() |
1f70e62fc7 | ||
![]() |
b1e840f7d8 | ||
![]() |
1ebc6a0e81 | ||
![]() |
63cb566b8d | ||
![]() |
9bc0273784 | ||
![]() |
c99f26ec12 | ||
![]() |
0b480f1eab | ||
![]() |
eefeca571b | ||
![]() |
58db55c2ff | ||
![]() |
0497dc25fd | ||
![]() |
2838327ba1 | ||
![]() |
566182f977 | ||
![]() |
dd508bf675 | ||
![]() |
643898c5e2 | ||
![]() |
3b3491a597 | ||
![]() |
e926071bb2 | ||
![]() |
ce5f6d695c | ||
![]() |
aca27f6421 | ||
![]() |
3185256ad3 | ||
![]() |
6d6e297a1f | ||
![]() |
bcbd390f7d | ||
![]() |
f117281ea4 | ||
![]() |
3362d91a37 | ||
![]() |
fe21b0bb8b | ||
![]() |
104c576caa | ||
![]() |
2fdc293b9a | ||
![]() |
2b75d091e9 | ||
![]() |
9bc9ee8e7d | ||
![]() |
3c273bf537 | ||
![]() |
990fb0657c | ||
![]() |
7fac77d28e | ||
![]() |
626507f8fb | ||
![]() |
9ab086f819 | ||
![]() |
b7b168e265 | ||
![]() |
9efaac072e | ||
![]() |
4ed519e819 | ||
![]() |
0e1bebaa1d | ||
![]() |
e57cc13047 | ||
![]() |
16962aea69 | ||
![]() |
e0abf93ce1 | ||
![]() |
95e9408db0 | ||
![]() |
4a9188da61 | ||
![]() |
bb37ae1987 | ||
![]() |
100279be6c | ||
![]() |
fd0421d573 | ||
![]() |
7afcaf3406 | ||
![]() |
a2ea0c407a | ||
![]() |
55474772cd | ||
![]() |
fa6f8c53ec | ||
![]() |
a5ce9915d1 | ||
![]() |
75032f9905 | ||
![]() |
00e3a3490b | ||
![]() |
00edc92c00 | ||
![]() |
10a56a9e86 | ||
![]() |
2291221719 | ||
![]() |
ceddf31f87 | ||
![]() |
0a7a206223 | ||
![]() |
c466fe8d07 | ||
![]() |
386edbf75e | ||
![]() |
f87aefbcc9 | ||
![]() |
c0080ae62e | ||
![]() |
1a610b060f | ||
![]() |
a675c42d89 | ||
![]() |
9c9b4ea880 | ||
![]() |
abe18a9b74 | ||
![]() |
209863d79e | ||
![]() |
b5fe5a4fb2 | ||
![]() |
0a8db69aa7 | ||
![]() |
73bcb1bd29 | ||
![]() |
31ed810144 | ||
![]() |
1aa34da6af | ||
![]() |
0e2eee3618 | ||
![]() |
bcc9f43f76 | ||
![]() |
34c3d971b0 | ||
![]() |
386c290dc0 | ||
![]() |
975414c2fe | ||
![]() |
8f73a00d2d | ||
![]() |
b560719a47 | ||
![]() |
07191d6e1b | ||
![]() |
b08a1a5db5 | ||
![]() |
868ee9643f | ||
![]() |
0bb738b29e | ||
![]() |
aa9f93a487 | ||
![]() |
7d0bbdab07 | ||
![]() |
ecc3db6760 | ||
![]() |
b808d84957 | ||
![]() |
36cdde4889 | ||
![]() |
c7adfee5d8 | ||
![]() |
6f8e4e9f5f | ||
![]() |
c3e27a1792 | ||
![]() |
27197f146c | ||
![]() |
519490ecee | ||
![]() |
3bfa6c19fa | ||
![]() |
0c1943c77b | ||
![]() |
32e0026128 | ||
![]() |
9935d877cc | ||
![]() |
8c1882226c | ||
![]() |
75504c3a6d | ||
![]() |
eead94dfc1 | ||
![]() |
ad5c50eef5 | ||
![]() |
a4c6655fa7 | ||
![]() |
516c089c42 | ||
![]() |
ebf4d4d1b8 | ||
![]() |
14c39f8283 | ||
![]() |
1c6d53f387 | ||
![]() |
7570468686 | ||
![]() |
a86d231714 | ||
![]() |
22797971f6 | ||
![]() |
dd6638b1ab | ||
![]() |
7d483dcade | ||
![]() |
3e30ad9b75 | ||
![]() |
44611e668c | ||
![]() |
9e80e5f195 | ||
![]() |
e2a20a44bc | ||
![]() |
69f5e8e572 | ||
![]() |
47ea05dc24 | ||
![]() |
fb41dddf3d | ||
![]() |
22a251e4fd | ||
![]() |
ddf64c8250 | ||
![]() |
629cca9413 | ||
![]() |
45acbbf6ef | ||
![]() |
9a7a9fa445 | ||
![]() |
6debf03402 | ||
![]() |
b981d45069 | ||
![]() |
db9aaef220 | ||
![]() |
141af42887 | ||
![]() |
75823e8244 | ||
![]() |
5b245d4de3 | ||
![]() |
587b766418 | ||
![]() |
e30677169b | ||
![]() |
ab985ba044 | ||
![]() |
8a049799e2 | ||
![]() |
a8309fae1c | ||
![]() |
267830387f | ||
![]() |
96bad51dd3 | ||
![]() |
12f42b30cd | ||
![]() |
1e20c1860b | ||
![]() |
c4dbe60f78 | ||
![]() |
ce3f627e36 | ||
![]() |
10986ffbab | ||
![]() |
3e279da9bf | ||
![]() |
6b662a9634 | ||
![]() |
7f8172aaf6 | ||
![]() |
2ff62bc283 | ||
![]() |
833a177e34 | ||
![]() |
592221ee19 | ||
![]() |
27b8b5e7c8 | ||
![]() |
fb39692f9c | ||
![]() |
61bed581ec | ||
![]() |
f3a2cee15b | ||
![]() |
13d962acdd | ||
![]() |
5e3743df31 | ||
![]() |
156a429898 | ||
![]() |
5c38bef3cf | ||
![]() |
451e59afa2 | ||
![]() |
5b6a659356 | ||
![]() |
9f6c64a4f9 | ||
![]() |
e51918df35 | ||
![]() |
c96eeee117 | ||
![]() |
0ddcfdd0c7 | ||
![]() |
ee6ba53d91 | ||
![]() |
7167b4cff9 | ||
![]() |
99b7533251 | ||
![]() |
449179bcec | ||
![]() |
e279140a4d | ||
![]() |
c20dfbbc39 | ||
![]() |
eaec560618 | ||
![]() |
d79b259ece | ||
![]() |
e94096e008 | ||
![]() |
d73cffd0c7 | ||
![]() |
876331afaf | ||
![]() |
1fb2501b7e | ||
![]() |
7656211b3e | ||
![]() |
827b02d94c | ||
![]() |
fe5a3acc8b | ||
![]() |
73c75240f8 | ||
![]() |
67a67a453d | ||
![]() |
cef04cfd2a | ||
![]() |
b955c377f1 | ||
![]() |
f807be50c2 | ||
![]() |
a504372f82 | ||
![]() |
bb3c3ff565 | ||
![]() |
c096536e32 | ||
![]() |
d014119b19 | ||
![]() |
508136b533 | ||
![]() |
00664898c3 | ||
![]() |
16c49d41eb | ||
![]() |
bda192ba90 | ||
![]() |
7f5df05bb7 | ||
![]() |
725576fc42 | ||
![]() |
18ea280388 | ||
![]() |
a009825d83 | ||
![]() |
fd7e5867b4 | ||
![]() |
79d385dc0b | ||
![]() |
1497bf36cc | ||
![]() |
69f2ea5635 | ||
![]() |
4964691fd9 | ||
![]() |
334c3fe702 | ||
![]() |
72e861be80 | ||
![]() |
2e3264ec69 | ||
![]() |
c032ad58ca | ||
![]() |
1772e01edb | ||
![]() |
0fb5b416ba | ||
![]() |
5103dac8d4 | ||
![]() |
c7800704b0 | ||
![]() |
d9247d094b | ||
![]() |
4f399675ce | ||
![]() |
945bf2b3a3 | ||
![]() |
d72801d19a | ||
![]() |
7f666547c9 | ||
![]() |
325175c88f | ||
![]() |
53b08efc6a | ||
![]() |
cb8c7850ba | ||
![]() |
487942bc22 | ||
![]() |
3c9f98b38d | ||
![]() |
8f762bc33d | ||
![]() |
62d2e4fba5 | ||
![]() |
4fd89120b8 | ||
![]() |
ad99e5fdea | ||
![]() |
ba472f7a11 | ||
![]() |
357ff7badf | ||
![]() |
b6b20be30b | ||
![]() |
e075d32f14 | ||
![]() |
bac10cf1fb | ||
![]() |
7968ae4588 | ||
![]() |
54d59cff1e | ||
![]() |
20e0b3efa5 | ||
![]() |
63986a4e5f | ||
![]() |
304ce7364a | ||
![]() |
f1e06f0a6d | ||
![]() |
5e9d22e496 | ||
![]() |
da743467fb | ||
![]() |
78832cb7c5 | ||
![]() |
151c8da887 | ||
![]() |
d987051f2b | ||
![]() |
000a312dc2 | ||
![]() |
6091669e28 | ||
![]() |
3974191ffa | ||
![]() |
a2d9455627 | ||
![]() |
73822401f1 | ||
![]() |
32f291c66e | ||
![]() |
e7e945a84c | ||
![]() |
f9d7d3a4fd | ||
![]() |
3709ea8f94 | ||
![]() |
af5e003790 | ||
![]() |
163135981e | ||
![]() |
c2f42f2f16 | ||
![]() |
eff5e946f7 | ||
![]() |
690eb2093a | ||
![]() |
15ee1c9fae | ||
![]() |
3329834560 | ||
![]() |
919000a5ef | ||
![]() |
c488fa936a | ||
![]() |
7ac609cbef | ||
![]() |
d9af1262a2 | ||
![]() |
cc3f27e514 | ||
![]() |
f5c9b87ee7 | ||
![]() |
bc392abb81 | ||
![]() |
8daef295f3 | ||
![]() |
eb98f59bc0 | ||
![]() |
eed9aa8ede | ||
![]() |
09ed8036e7 | ||
![]() |
236f14553c | ||
![]() |
2c7912e5dc | ||
![]() |
571cbbe4df | ||
![]() |
6d1c87f214 | ||
![]() |
f938b64397 | ||
![]() |
82472c7905 | ||
![]() |
9a2dd3b63e | ||
![]() |
1a72309c40 | ||
![]() |
3bb804eeaf | ||
![]() |
3029b5422a | ||
![]() |
0e0ea2d5f8 | ||
![]() |
fefea90133 | ||
![]() |
b887b5d7c7 | ||
![]() |
e475224359 | ||
![]() |
f70200e5aa | ||
![]() |
1e7624c7f5 | ||
![]() |
246dfd734d | ||
![]() |
9ca061eae5 | ||
![]() |
e404ce737b | ||
![]() |
35feeff7ab | ||
![]() |
eaa797d7f6 | ||
![]() |
e287ea4af5 | ||
![]() |
1dc353d3c5 | ||
![]() |
2072f70f7f | ||
![]() |
05c01ee884 | ||
![]() |
184a6ba4c5 | ||
![]() |
f2ea9cde4c | ||
![]() |
fece35b830 | ||
![]() |
a018931437 | ||
![]() |
a80ae826c6 | ||
![]() |
5e6f2ee045 | ||
![]() |
12aaaf1e6c | ||
![]() |
c2af423a5b | ||
![]() |
19731869d3 | ||
![]() |
bcfb52d3a5 | ||
![]() |
335b926f8b | ||
![]() |
08eec4460c | ||
![]() |
19fcfc7f44 | ||
![]() |
bb2989e1c5 | ||
![]() |
cdb5b74f53 | ||
![]() |
331e47830e | ||
![]() |
2982427d34 | ||
![]() |
f808a2bb64 | ||
![]() |
eef79e64f2 | ||
![]() |
65006d3436 | ||
![]() |
8045611375 | ||
![]() |
ce8eca4099 | ||
![]() |
a393a315d0 | ||
![]() |
6e2eae70ad | ||
![]() |
284024dca5 | ||
![]() |
9b9ad1fd82 | ||
![]() |
78a3d24fde | ||
![]() |
ff505f1e41 | ||
![]() |
db500f3cae | ||
![]() |
ea380ecb47 | ||
![]() |
d8beec758e | ||
![]() |
bfcd77ff9c | ||
![]() |
a4b2b46c0e | ||
![]() |
c53d0e29a7 | ||
![]() |
7c72410c84 | ||
![]() |
f96ccabeb6 | ||
![]() |
36367e4219 | ||
![]() |
7b54f95a27 | ||
![]() |
29c6b8e06f | ||
![]() |
dfba4edd26 | ||
![]() |
afb2f2f0ea | ||
![]() |
e5513d9417 | ||
![]() |
d4c211f04a | ||
![]() |
5e54efb57b | ||
![]() |
b090bd1937 | ||
![]() |
09769c3283 | ||
![]() |
fb6a34f7c9 | ||
![]() |
9cd533fbac | ||
![]() |
11e8914dd8 | ||
![]() |
5ac80f21d8 | ||
![]() |
d0ba2934df | ||
![]() |
43b707bcfb | ||
![]() |
486c7d9bcb | ||
![]() |
6b89d2cf62 | ||
![]() |
a5c11df37e | ||
![]() |
989216178a | ||
![]() |
5f0276179f | ||
![]() |
7e4f171b16 | ||
![]() |
bb7a3fe692 | ||
![]() |
70abacaf82 | ||
![]() |
1a213a1588 | ||
![]() |
37df61b233 | ||
![]() |
9e2e467751 | ||
![]() |
421c1ecb0e | ||
![]() |
4417b17d12 | ||
![]() |
56f86b0fba | ||
![]() |
b8aa568626 | ||
![]() |
ebcca37714 | ||
![]() |
caae0192f7 | ||
![]() |
f9820953be | ||
![]() |
231b7af795 | ||
![]() |
76c224c366 | ||
![]() |
13867ef1a0 | ||
![]() |
6be1c57999 | ||
![]() |
0d481b1104 | ||
![]() |
d3ea87bd1e | ||
![]() |
23c6b96b47 | ||
![]() |
e5b544e02b | ||
![]() |
4ff7a2261b | ||
![]() |
a65e61c95e | ||
![]() |
b959676534 | ||
![]() |
4f0b15ef55 | ||
![]() |
6813c519b6 | ||
![]() |
2e80cb34b6 | ||
![]() |
4e31878f89 | ||
![]() |
8e94de7a73 | ||
![]() |
07fb5d698e | ||
![]() |
259ea216cb | ||
![]() |
803eb73d2d | ||
![]() |
ddc50aa651 | ||
![]() |
cee5d55b7d | ||
![]() |
482bcb83d5 | ||
![]() |
dfaf270670 | ||
![]() |
18262a526d | ||
![]() |
c87aea14eb | ||
![]() |
759b66fb69 | ||
![]() |
b88535621f | ||
![]() |
97de13cf30 | ||
![]() |
e9ee45024c | ||
![]() |
3a2e3fa901 | ||
![]() |
e8a9131b31 | ||
![]() |
6622829e8f | ||
![]() |
61f34fc4ad | ||
![]() |
7d45d47260 | ||
![]() |
df7ea2b685 | ||
![]() |
beed254a7d | ||
![]() |
97709fca23 | ||
![]() |
996d2809c9 | ||
![]() |
069f42086f | ||
![]() |
000424f001 | ||
![]() |
0fab0ec1eb | ||
![]() |
761f896164 | ||
![]() |
282c3e5c0a | ||
![]() |
adbdf194e0 | ||
![]() |
1c48e552e9 | ||
![]() |
45362b588b | ||
![]() |
e155700bc3 | ||
![]() |
6533663b7f | ||
![]() |
61366f4c8e | ||
![]() |
fc70ba4f07 | ||
![]() |
0c885db5a4 | ||
![]() |
2ff886457f | ||
![]() |
cd8d43cbf9 | ||
![]() |
d87e5f102e | ||
![]() |
2024a67c74 | ||
![]() |
d7ffc68a30 | ||
![]() |
eb90c6ed3b | ||
![]() |
5a4b89c1ed | ||
![]() |
3dc0383f3f | ||
![]() |
cb7759cd0b | ||
![]() |
6c3fcf0188 | ||
![]() |
29f0a5d647 | ||
![]() |
87c4e543ad | ||
![]() |
d2bba6cb3c | ||
![]() |
00747fb947 | ||
![]() |
696620828f | ||
![]() |
890f59b8b4 | ||
![]() |
ed7d1dfdaf | ||
![]() |
c0d394ebf5 | ||
![]() |
6b346926ec | ||
![]() |
1ff8c97b1d | ||
![]() |
2d2503bbbb | ||
![]() |
48eb4fed07 | ||
![]() |
54287bbfbb | ||
![]() |
fda7cfa2bc | ||
![]() |
8362349bb8 | ||
![]() |
87b65fb5ff | ||
![]() |
ec0f848030 | ||
![]() |
fb211a5ee4 | ||
![]() |
9307b50155 | ||
![]() |
16e4a6e321 | ||
![]() |
e8bf5e6b4f | ||
![]() |
a272a8d420 | ||
![]() |
b26d8d5fb0 | ||
![]() |
239b2b5478 | ||
![]() |
c8f38486f1 | ||
![]() |
4648ac2768 | ||
![]() |
82fb39cef9 | ||
![]() |
b4d0e5f8fc | ||
![]() |
6bd09ee05e | ||
![]() |
3afdd80333 | ||
![]() |
6442b47b99 | ||
![]() |
12c8cda60a | ||
![]() |
5692604ab6 | ||
![]() |
ce8a73750e | ||
![]() |
69025e5ef4 | ||
![]() |
1565e149c0 | ||
![]() |
1d67567c02 | ||
![]() |
790f4784ed | ||
![]() |
b8fe52edf2 | ||
![]() |
c4bece8dc8 | ||
![]() |
fd3a5bbd34 | ||
![]() |
6e6c23b05e | ||
![]() |
93a76faca6 | ||
![]() |
5af59aba66 | ||
![]() |
cf0c8f1024 | ||
![]() |
5931376a57 | ||
![]() |
1f218835df | ||
![]() |
b93db976db | ||
![]() |
8c4384a02f | ||
![]() |
73c2eded15 | ||
![]() |
6f6b1fcb56 | ||
![]() |
987f0fcc07 | ||
![]() |
1b080b3384 | ||
![]() |
20fd3af5b4 | ||
![]() |
06d6780cc8 | ||
![]() |
dad62afcee | ||
![]() |
dd06cbaddd | ||
![]() |
a261b71ad0 | ||
![]() |
e2aa646b0e | ||
![]() |
556ec04b8e | ||
![]() |
a2b22bdaf8 | ||
![]() |
bd5751b26b | ||
![]() |
f695cbbace | ||
![]() |
82289f6eb3 | ||
![]() |
4ed8f04e1c | ||
![]() |
e742dc59b3 | ||
![]() |
bbb91b704d | ||
![]() |
7d409e6ec4 | ||
![]() |
04ad6239d2 | ||
![]() |
8d99756045 | ||
![]() |
b5260849bb | ||
![]() |
6db1c2d831 | ||
![]() |
d123c4a9f3 | ||
![]() |
b013a05dd5 | ||
![]() |
103a9c8cb7 | ||
![]() |
e0fa631ca9 | ||
![]() |
b6071dd1e4 | ||
![]() |
9593615da7 | ||
![]() |
1855b2cfa7 | ||
![]() |
c31ae245b1 | ||
![]() |
d726b22561 | ||
![]() |
960fe8a342 | ||
![]() |
9cf7db65e3 | ||
![]() |
8efc3a2fe2 | ||
![]() |
891e077b35 | ||
![]() |
50bb59f4fe | ||
![]() |
d069f57422 | ||
![]() |
f1ec19b35b | ||
![]() |
291a5e4aa6 | ||
![]() |
8955f572a1 | ||
![]() |
3c33c7c07a | ||
![]() |
15ddc4294b | ||
![]() |
e95966ee44 | ||
![]() |
3b04270006 | ||
![]() |
7d46b22f8e | ||
![]() |
d9d14ab4bf | ||
![]() |
a09bd78459 | ||
![]() |
b80d58a603 | ||
![]() |
48ce07a025 | ||
![]() |
03cd1817dd | ||
![]() |
6272121f25 | ||
![]() |
8066fb0e9c | ||
![]() |
f756aadf32 | ||
![]() |
f4284a7e60 | ||
![]() |
2285785af5 | ||
![]() |
63660682c2 | ||
![]() |
24d79dbfdd | ||
![]() |
ef93b7c145 | ||
![]() |
fe37f7d0b2 | ||
![]() |
c7e2a2ea7c | ||
![]() |
d4c8a94abb | ||
![]() |
b4dee312a4 | ||
![]() |
e345b3f97f | ||
![]() |
cacd9948f4 | ||
![]() |
bcab484095 | ||
![]() |
db98dbe216 | ||
![]() |
95ca834605 | ||
![]() |
125c21b200 | ||
![]() |
499c9086b0 | ||
![]() |
78e92c76df | ||
![]() |
62ebacd277 | ||
![]() |
74eff69410 | ||
![]() |
0043eee0e0 | ||
![]() |
c8888086ae | ||
![]() |
80098c1e93 | ||
![]() |
24cbbe588e | ||
![]() |
68b5490621 | ||
![]() |
40546340a4 | ||
![]() |
af345043af | ||
![]() |
4f83d8b1b6 | ||
![]() |
56d1dbb2b6 | ||
![]() |
a94a940fe3 | ||
![]() |
f86d019afc | ||
![]() |
7fa30dbfac | ||
![]() |
3ff2e46ddd | ||
![]() |
9712f7c959 | ||
![]() |
dd46634c83 | ||
![]() |
1276e64c8b | ||
![]() |
d9173d5223 | ||
![]() |
9c28bc2351 | ||
![]() |
5c87a797ff | ||
![]() |
f873de3e3b | ||
![]() |
b770c034c4 | ||
![]() |
18535405d7 | ||
![]() |
01ba8dd4d6 | ||
![]() |
90729810d4 | ||
![]() |
22b45dde67 | ||
![]() |
aeadc7f79a | ||
![]() |
9e4659f194 | ||
![]() |
b30b33e8a8 | ||
![]() |
8ada55ff3e | ||
![]() |
ea1c6ec0af | ||
![]() |
359d7d3da9 | ||
![]() |
a97ff0ea3d | ||
![]() |
927a76a490 | ||
![]() |
955540b90e | ||
![]() |
b053ddcd68 | ||
![]() |
06ae01b5a7 | ||
![]() |
c5b1177151 | ||
![]() |
4c21f4f904 | ||
![]() |
1e453d90c0 | ||
![]() |
0cb91aedb4 | ||
![]() |
bf71375952 | ||
![]() |
b4dffe266e | ||
![]() |
a311b5db39 | ||
![]() |
e1f7935f0b | ||
![]() |
1461ad34bb | ||
![]() |
d2870b3e36 | ||
![]() |
f0a73a3a4c | ||
![]() |
5c7d39b3fb | ||
![]() |
a8e41734cf | ||
![]() |
227b269b5c | ||
![]() |
35660c2ef7 | ||
![]() |
088434d2bb | ||
![]() |
11da083507 | ||
![]() |
a15bd179ba | ||
![]() |
a3ac409add | ||
![]() |
32320a48c1 | ||
![]() |
2b7c1af813 | ||
![]() |
35776ca894 | ||
![]() |
d429540a47 | ||
![]() |
0752aa7def | ||
![]() |
92902746cb | ||
![]() |
587b0ab87e | ||
![]() |
a7b26c0081 | ||
![]() |
11a8984428 | ||
![]() |
9ae05ab712 | ||
![]() |
356e78b809 | ||
![]() |
340c34bcf8 | ||
![]() |
caa8912d7f | ||
![]() |
8e6ee3cbb8 | ||
![]() |
ca5f562503 | ||
![]() |
93b39231c4 | ||
![]() |
b603ed7cfd | ||
![]() |
06070d49f3 | ||
![]() |
5b19ea6451 | ||
![]() |
82e88f3afb | ||
![]() |
ce8ec2eb7f | ||
![]() |
b8c2b08fdc | ||
![]() |
65d23bd022 | ||
![]() |
ea32b203d6 | ||
![]() |
97cc1d0621 | ||
![]() |
026d09353f | ||
![]() |
3f0f055b0c | ||
![]() |
72d8ef4783 | ||
![]() |
36f3f0d449 | ||
![]() |
9830eb4331 | ||
![]() |
62498f3bf8 | ||
![]() |
ef0e17c51e | ||
![]() |
d632ed3d75 | ||
![]() |
993ed0bde3 | ||
![]() |
fe770960b6 | ||
![]() |
e577c0a1a2 | ||
![]() |
0530775800 | ||
![]() |
8da01ff353 | ||
![]() |
143f113d78 | ||
![]() |
fffe1831a3 | ||
![]() |
9364274a6b | ||
![]() |
bb04f4063b | ||
![]() |
8288c66501 | ||
![]() |
4f3e0abd25 | ||
![]() |
64f16e0e6f | ||
![]() |
e53d559740 | ||
![]() |
2ad56cd7ef | ||
![]() |
54f0e1a0de | ||
![]() |
3ab8ffbdc1 | ||
![]() |
ec9d028c60 | ||
![]() |
ef393472b2 | ||
![]() |
2f98144324 | ||
![]() |
3e9eba7906 | ||
![]() |
971f7c6b07 | ||
![]() |
c1ed3e36ca | ||
![]() |
b1b2f17c09 | ||
![]() |
8374346023 | ||
![]() |
c899273397 | ||
![]() |
a1b43088a4 | ||
![]() |
472073c22b | ||
![]() |
f1162b6cc3 | ||
![]() |
e8286776df | ||
![]() |
f802197576 | ||
![]() |
2233275c0b | ||
![]() |
e4a2795414 | ||
![]() |
e308c1665e | ||
![]() |
6992a63cf8 | ||
![]() |
748e2c742c | ||
![]() |
dc2cbc01f1 | ||
![]() |
ea1b53eb20 | ||
![]() |
b06b86bce3 | ||
![]() |
9c0eeb5370 | ||
![]() |
8a79f91cb1 | ||
![]() |
fe3abbdec4 | ||
![]() |
39b21df7e6 | ||
![]() |
3124853a56 | ||
![]() |
35360df540 | ||
![]() |
875da8ee45 | ||
![]() |
96268d6691 | ||
![]() |
bdd15644d3 | ||
![]() |
9ed534c301 | ||
![]() |
6bfcd4ca6c | ||
![]() |
4ab01fa269 | ||
![]() |
7382661315 | ||
![]() |
6fcfdc7def | ||
![]() |
c14c798235 | ||
![]() |
a1c9483270 | ||
![]() |
8990c9c30a | ||
![]() |
ca18038c5d | ||
![]() |
b12d40a0c0 | ||
![]() |
9180f9b972 | ||
![]() |
aae0521057 | ||
![]() |
5d0c61b10f | ||
![]() |
8edb109d92 | ||
![]() |
9c1db9a6f3 | ||
![]() |
5b4af26d7d | ||
![]() |
4737063653 | ||
![]() |
d07321ad90 | ||
![]() |
832c17c834 | ||
![]() |
ad6ffaac05 | ||
![]() |
a12e9bec61 | ||
![]() |
867549c3af | ||
![]() |
72a34f9fe1 | ||
![]() |
482e78a18b | ||
![]() |
7e560e157d | ||
![]() |
e8c4c6c4c7 | ||
![]() |
1a6f52dfc4 | ||
![]() |
f5c86f136b | ||
![]() |
2344124f65 | ||
![]() |
0c5e8c8d70 | ||
![]() |
32f1b6177e | ||
![]() |
3e52c44aeb | ||
![]() |
99ea85a175 | ||
![]() |
ca173ea989 | ||
![]() |
16a0f52921 | ||
![]() |
2121ec33f7 | ||
![]() |
0ad5973101 | ||
![]() |
3085fac973 | ||
![]() |
618b81286a | ||
![]() |
c0f57369e5 | ||
![]() |
714b064666 | ||
![]() |
c6af357901 | ||
![]() |
a0b9dca246 | ||
![]() |
7f172344e8 | ||
![]() |
566c858771 | ||
![]() |
371aad4a65 | ||
![]() |
4d7829ae54 | ||
![]() |
50356b7c5e | ||
![]() |
33a76ad6ba | ||
![]() |
52763603d3 | ||
![]() |
5851b558bb | ||
![]() |
3746547466 | ||
![]() |
203dd2b89a | ||
![]() |
936159cfbb | ||
![]() |
1eb0fdfbb7 | ||
![]() |
219c2af686 | ||
![]() |
3e0ea3162e | ||
![]() |
71c9b9b9f1 | ||
![]() |
46d53168b8 | ||
![]() |
ecd077f154 | ||
![]() |
a8dcda69a3 | ||
![]() |
da278ac7d0 | ||
![]() |
ff65434e46 | ||
![]() |
cec87bb2ff | ||
![]() |
ca88e90a31 | ||
![]() |
ae6bb81069 | ||
![]() |
fc9846b035 | ||
![]() |
fafcf555ac | ||
![]() |
e64d07aab3 | ||
![]() |
8f11802953 | ||
![]() |
9eb959f608 | ||
![]() |
aa5dfdfa57 | ||
![]() |
4710d94fb7 | ||
![]() |
8745a12246 | ||
![]() |
2f4e52594e | ||
![]() |
d2f0182ee0 | ||
![]() |
290d0eee52 | ||
![]() |
8e8e0498e0 | ||
![]() |
bb25aa656a | ||
![]() |
1c0cbb7ea5 | ||
![]() |
e581c0d91c | ||
![]() |
e3772bf3af | ||
![]() |
9f2daabc0f | ||
![]() |
26d12898a6 | ||
![]() |
6789f58090 | ||
![]() |
c631efd6b5 | ||
![]() |
bda7ea5ac1 | ||
![]() |
36644161b3 | ||
![]() |
ee7bcf82be | ||
![]() |
7abda1151c | ||
![]() |
fef7cca030 | ||
![]() |
948a7bfc4d | ||
![]() |
52a71a5f76 | ||
![]() |
6d539e0213 | ||
![]() |
69892f39eb | ||
![]() |
d3a393a727 | ||
![]() |
1338cff45d | ||
![]() |
c622f39897 | ||
![]() |
6b846eeec2 | ||
![]() |
f3ba4e2706 | ||
![]() |
0aa20603d9 | ||
![]() |
0a8bef493b | ||
![]() |
d976e27b33 | ||
![]() |
e09a38d804 | ||
![]() |
f457009083 | ||
![]() |
2d022013ad | ||
![]() |
c18229535a | ||
![]() |
ee78c611e1 | ||
![]() |
71ef65cc86 | ||
![]() |
587843fded | ||
![]() |
c354118fb9 | ||
![]() |
ddc8282318 | ||
![]() |
d64df5b4b0 | ||
![]() |
413bdd44b7 | ||
![]() |
22d314a1ec | ||
![]() |
f87aa9e7d0 | ||
![]() |
d5221d191c | ||
![]() |
b2e8100545 | ||
![]() |
616c04934a | ||
![]() |
7a86aae0d1 | ||
![]() |
e0e3bf8b5f | ||
![]() |
b18719cd0b | ||
![]() |
bc8e7212f5 | ||
![]() |
17eeec6273 | ||
![]() |
e14e7e1b06 | ||
![]() |
fdac80d273 | ||
![]() |
95df669656 | ||
![]() |
17803d2d45 | ||
![]() |
a183380cc6 | ||
![]() |
bdc738f87e | ||
![]() |
4714aa9b31 | ||
![]() |
bce715acc9 | ||
![]() |
a005bfadd8 | ||
![]() |
d837d92f0f | ||
![]() |
a9234a589a | ||
![]() |
d2ab9f6c53 | ||
![]() |
dbba52409d | ||
![]() |
f09afb2025 | ||
![]() |
11f2ff0c76 | ||
![]() |
7bbaf3dfa7 | ||
![]() |
838450b7a8 | ||
![]() |
9443929806 | ||
![]() |
27679c231a | ||
![]() |
0170789bbf | ||
![]() |
85b909ef21 | ||
![]() |
b4ac7acd97 | ||
![]() |
8224f3cd2d | ||
![]() |
7712429cc2 | ||
![]() |
92fb557314 | ||
![]() |
19453911c6 | ||
![]() |
2fdb0a76b4 | ||
![]() |
308360f678 | ||
![]() |
2ae76d9a86 | ||
![]() |
fe1a615996 | ||
![]() |
20dccf5082 | ||
![]() |
9a2cc2ef83 | ||
![]() |
b40c1db612 | ||
![]() |
f91769d53d | ||
![]() |
f476380e2f | ||
![]() |
e49a028676 | ||
![]() |
95fdb53685 | ||
![]() |
1cf85fa3e7 | ||
![]() |
4eb380b7ad | ||
![]() |
be9e15e635 | ||
![]() |
a0007a0441 | ||
![]() |
81d9b0637b | ||
![]() |
249e3229b0 | ||
![]() |
6a8e03e286 | ||
![]() |
c18a317702 | ||
![]() |
79b266fac3 | ||
![]() |
9fc2abbf9a | ||
![]() |
d7c10a4d7c | ||
![]() |
9fea21a2a1 | ||
![]() |
a8737418b9 | ||
![]() |
81b0599a9e | ||
![]() |
9b58ece673 | ||
![]() |
3230021dec | ||
![]() |
f590c91dbd | ||
![]() |
d33d38f113 | ||
![]() |
09188b1a73 | ||
![]() |
61ea805bba | ||
![]() |
ae2dddcff7 | ||
![]() |
412fd372d0 | ||
![]() |
606485f00c | ||
![]() |
e05b8960d7 | ||
![]() |
78dfd10475 | ||
![]() |
85d4874320 | ||
![]() |
666fb2ee86 | ||
![]() |
7c2070ab0d | ||
![]() |
cee2ca18fc | ||
![]() |
54ee68d847 | ||
![]() |
43fbd57a67 | ||
![]() |
a6852cf41b | ||
![]() |
b7e0288a34 | ||
![]() |
82a59defc2 | ||
![]() |
ba20cfff5c | ||
![]() |
28efccccf4 | ||
![]() |
de0d706ec2 | ||
![]() |
27aaae9fb5 | ||
![]() |
456654dd6b | ||
![]() |
35337e083c | ||
![]() |
9130daa0b9 | ||
![]() |
b98a0e1f88 | ||
![]() |
56aa4581ea | ||
![]() |
78ec53424e | ||
![]() |
ec0fc05fd6 | ||
![]() |
42b92263fa | ||
![]() |
d36a6746b7 | ||
![]() |
4e860f4ca2 | ||
![]() |
71a2c4f6f4 | ||
![]() |
00a1d1a496 | ||
![]() |
354898498f | ||
![]() |
83b4fba403 | ||
![]() |
56ae4fdc48 | ||
![]() |
9468e476a7 | ||
![]() |
93842302b4 | ||
![]() |
e72662836c | ||
![]() |
ea071bed4f | ||
![]() |
0402ca07cd | ||
![]() |
cf992b04da | ||
![]() |
68a1a225b6 | ||
![]() |
0e45a07c6a | ||
![]() |
fa05864df4 | ||
![]() |
95b4b49fc7 | ||
![]() |
69f990d8bf | ||
![]() |
47de18a508 | ||
![]() |
00d6c94bd9 | ||
![]() |
99e463146f | ||
![]() |
6f0a486d20 | ||
![]() |
00d9583af3 | ||
![]() |
5acb38eabd | ||
![]() |
7eb76b67c7 | ||
![]() |
06f35594c6 | ||
![]() |
36ac5e5bcc | ||
![]() |
c6a4f90915 | ||
![]() |
c71d142738 | ||
![]() |
a3408b537a | ||
![]() |
6b12050fd1 | ||
![]() |
3531f9c9d4 | ||
![]() |
03e21d5c5f | ||
![]() |
8f33f4fed8 | ||
![]() |
1497404a4c | ||
![]() |
b113ec48ed | ||
![]() |
ca3cee02c3 | ||
![]() |
c9776a7c86 | ||
![]() |
668f0945c4 | ||
![]() |
95be76d8ee | ||
![]() |
e8ec2b3550 | ||
![]() |
bac77b1f58 | ||
![]() |
1a634c1957 | ||
![]() |
03332c1146 | ||
![]() |
81f5ed5415 | ||
![]() |
1a174508db | ||
![]() |
4f09633b80 | ||
![]() |
9b44069e54 | ||
![]() |
c61753d89d | ||
![]() |
cad2391e34 | ||
![]() |
165947295e | ||
![]() |
22e57a1159 | ||
![]() |
456cb927d1 | ||
![]() |
81b22633cd | ||
![]() |
03347e8e33 | ||
![]() |
a04b7b5d5d | ||
![]() |
66078cb285 | ||
![]() |
8076407e08 | ||
![]() |
b694b4667a | ||
![]() |
233dba2408 | ||
![]() |
8e25c382d9 | ||
![]() |
326e313d75 | ||
![]() |
6a8050998b | ||
![]() |
bf22f8d4df | ||
![]() |
aa00749f97 | ||
![]() |
db0339a143 | ||
![]() |
ab7f1be9ab | ||
![]() |
f082d89326 | ||
![]() |
712f6d4c87 | ||
![]() |
25df08f7a4 | ||
![]() |
6b36a2d9d8 | ||
![]() |
bac314a666 | ||
![]() |
41bd58dd31 | ||
![]() |
cf6c69ed69 | ||
![]() |
ab5b653133 | ||
![]() |
76c0c52bed | ||
![]() |
fd77d17e2b | ||
![]() |
b62c7b30ef | ||
![]() |
212c5dd130 | ||
![]() |
eef95eed52 | ||
![]() |
d165d67765 | ||
![]() |
9ceb2baeaa | ||
![]() |
1f793e66ea | ||
![]() |
c39dbd443e | ||
![]() |
7057406de0 | ||
![]() |
e0b6562b99 | ||
![]() |
2ee9dbeafd | ||
![]() |
1afcb30102 | ||
![]() |
054386388e | ||
![]() |
0605097bdc | ||
![]() |
6fd99a5a29 | ||
![]() |
4df5ed1536 | ||
![]() |
267959967d | ||
![]() |
480aa843c5 | ||
![]() |
27a6d29187 | ||
![]() |
6e18260ef7 | ||
![]() |
ae28716366 | ||
![]() |
718c876fa7 | ||
![]() |
eb8276c132 | ||
![]() |
5e977e819f | ||
![]() |
693135d52c | ||
![]() |
e4ff37887b | ||
![]() |
39cc7ae0a3 | ||
![]() |
63133b5058 | ||
![]() |
7e8a547a91 | ||
![]() |
a7a5067830 | ||
![]() |
ab462237af | ||
![]() |
9cc6fc933d | ||
![]() |
ed0f400f09 | ||
![]() |
9f9ad8fa2e | ||
![]() |
c29e93dd2b | ||
![]() |
adda364eaa | ||
![]() |
8c7d69c1d1 | ||
![]() |
0135559dd6 | ||
![]() |
a5ba7075e4 | ||
![]() |
f95e039c22 | ||
![]() |
7ad44b46fd | ||
![]() |
32cb8d546e | ||
![]() |
b66f3039be | ||
![]() |
3b29d03227 | ||
![]() |
e5056dcd57 | ||
![]() |
4565c8ef79 | ||
![]() |
409c460d2f | ||
![]() |
8fe5518c6c | ||
![]() |
1ac5415e94 | ||
![]() |
88f74fd6f2 | ||
![]() |
4cc758632d | ||
![]() |
d36b3d8b4e | ||
![]() |
1de4d6e1e5 | ||
![]() |
046443259e | ||
![]() |
132261ec4d | ||
![]() |
d6b6fc38a8 | ||
![]() |
4033fac1b3 | ||
![]() |
dc836ae7e4 | ||
![]() |
dcda14e6e7 | ||
![]() |
08f2835d8a | ||
![]() |
54dde2a10f | ||
![]() |
fed78f2ca0 | ||
![]() |
aa206c7bae | ||
![]() |
4bad16744b | ||
![]() |
a5acada9fc | ||
![]() |
c822caafe7 | ||
![]() |
94bd713310 | ||
![]() |
7791840a4a | ||
![]() |
4dbf1d2099 | ||
![]() |
2136269175 | ||
![]() |
7f8e0f1276 | ||
![]() |
842780feec | ||
![]() |
ac0326ce91 | ||
![]() |
154302605f | ||
![]() |
eea8054af6 | ||
![]() |
0d475f4c43 | ||
![]() |
b76ea76219 | ||
![]() |
1e6ab35f4d | ||
![]() |
679942033e | ||
![]() |
262fec4601 | ||
![]() |
0a99c169b6 | ||
![]() |
5272106a9c | ||
![]() |
21b263a0ba | ||
![]() |
8dd4c0c9e3 | ||
![]() |
97b9dae812 | ||
![]() |
8b8900e21d | ||
![]() |
2ffd3b6589 | ||
![]() |
c4b679ec5a | ||
![]() |
2b9d4596ae | ||
![]() |
8e861d1773 | ||
![]() |
f0b10d696e | ||
![]() |
d2348a7651 | ||
![]() |
c6c8f52878 | ||
![]() |
43382d4be8 | ||
![]() |
4e8fe77098 | ||
![]() |
3918990b0e | ||
![]() |
9730a383fd | ||
![]() |
36440970fb | ||
![]() |
e8c9d8e1fc | ||
![]() |
13a0b78e26 | ||
![]() |
016b1692e2 | ||
![]() |
aeb6a17255 | ||
![]() |
bcedbfd189 | ||
![]() |
3a86103392 | ||
![]() |
dabb3b9dbf | ||
![]() |
f6a7ffa4fe | ||
![]() |
1a589846d6 | ||
![]() |
2d70263cda | ||
![]() |
bf02481299 | ||
![]() |
d6770fda0c | ||
![]() |
f44c1894b8 | ||
![]() |
0379b737eb | ||
![]() |
8c2a056b52 | ||
![]() |
7f5b288c51 | ||
![]() |
715f86b3b5 | ||
![]() |
58af9adb03 | ||
![]() |
0f6dd37aa2 | ||
![]() |
231c6870d9 | ||
![]() |
922a0c5c86 | ||
![]() |
fe838fbd75 | ||
![]() |
9cd3c4ff14 | ||
![]() |
afa018049b | ||
![]() |
b2271ae71e | ||
![]() |
ea7e980c8d | ||
![]() |
cf59f297a7 | ||
![]() |
8f8a4a6dc8 | ||
![]() |
c5eeabace1 | ||
![]() |
1a44d665bb | ||
![]() |
eceb83171f | ||
![]() |
d3e0ae6fd7 | ||
![]() |
775b97f6b3 | ||
![]() |
fcfcd6d916 | ||
![]() |
daa2c69714 | ||
![]() |
8430bb82a2 | ||
![]() |
9290e3e29a | ||
![]() |
bb44c7b0c3 | ||
![]() |
56c86dfb49 | ||
![]() |
17e845df29 | ||
![]() |
d2378d9781 | ||
![]() |
6f4cc7c528 | ||
![]() |
15efa3a8b7 | ||
![]() |
cf8a6639a3 | ||
![]() |
a68cd9f89a | ||
![]() |
a399575a26 | ||
![]() |
4ebaefd10a | ||
![]() |
c856f9ae6e | ||
![]() |
77596aad96 | ||
![]() |
e2040ae953 | ||
![]() |
3ee29a1ace | ||
![]() |
6b28275b88 | ||
![]() |
ff8708d76b | ||
![]() |
5d624e3078 | ||
![]() |
376fe7c694 | ||
![]() |
2ce4412fb2 | ||
![]() |
67c031cb77 | ||
![]() |
79ff65d224 | ||
![]() |
c5886cfe05 | ||
![]() |
5f6b234262 | ||
![]() |
e86585c715 | ||
![]() |
935da1575c | ||
![]() |
7a10afc720 | ||
![]() |
51013105ed | ||
![]() |
947da90a00 | ||
![]() |
a2f7b9183c | ||
![]() |
4f4a3f7c92 | ||
![]() |
1222356cf4 | ||
![]() |
087b0e7b6a | ||
![]() |
9f9a7a3b71 | ||
![]() |
11f7d64c41 | ||
![]() |
a2827f896e | ||
![]() |
dbbe91018d | ||
![]() |
3c60c27e41 | ||
![]() |
82ec42b292 | ||
![]() |
1a010f2e57 | ||
![]() |
deaeeaaac5 | ||
![]() |
5fce0b48b8 | ||
![]() |
e4a0733024 | ||
![]() |
54246e12ad | ||
![]() |
86fd2983c7 | ||
![]() |
837575faf7 | ||
![]() |
1f23acac21 | ||
![]() |
1fbfc440ac | ||
![]() |
3ab8808fa3 | ||
![]() |
fd258a611f | ||
![]() |
bd85b7c638 | ||
![]() |
b6396c15c0 | ||
![]() |
6065fe40f4 | ||
![]() |
93de43456d | ||
![]() |
a6a7d278dc | ||
![]() |
e597ce996b | ||
![]() |
49cdba1046 | ||
![]() |
5f202fd4ea | ||
![]() |
439415bffe | ||
![]() |
2a77e9635a | ||
![]() |
c63a865ee3 | ||
![]() |
44d626f727 | ||
![]() |
093692f825 | ||
![]() |
88bb6ec6af | ||
![]() |
6656181e2b | ||
![]() |
8e38334b9a | ||
![]() |
f0b8b4fae9 | ||
![]() |
fe8c036204 | ||
![]() |
00e6d1d077 | ||
![]() |
55196514d2 | ||
![]() |
1e86bc2c59 | ||
![]() |
2d3c0e7186 | ||
![]() |
d467621edd | ||
![]() |
b7448ce2c1 | ||
![]() |
bf261d533f | ||
![]() |
de813df0c2 | ||
![]() |
4e755025d2 | ||
![]() |
44471fe649 | ||
![]() |
d7be2c8561 | ||
![]() |
329364e8e2 | ||
![]() |
fdf26641dd | ||
![]() |
9f83730fb5 | ||
![]() |
b8b802de6b | ||
![]() |
299717de55 | ||
![]() |
27a7a5ebcd | ||
![]() |
f5b7e27e5d | ||
![]() |
31fa22626c | ||
![]() |
193a7001e4 | ||
![]() |
263d44ab30 | ||
![]() |
a5aed39f9d | ||
![]() |
814cc59c08 | ||
![]() |
5cc3ce3300 | ||
![]() |
7bea19057e | ||
![]() |
c1d768a5b3 | ||
![]() |
ed0f8b8a53 | ||
![]() |
f74f648aa4 | ||
![]() |
8334d20c3a | ||
![]() |
92ade9d800 | ||
![]() |
8f77aa458b | ||
![]() |
c0d6f1588d | ||
![]() |
45bd63810a | ||
![]() |
7962f0a1bb | ||
![]() |
1c36ff9868 | ||
![]() |
72103d9bbc | ||
![]() |
378152d1c4 | ||
![]() |
8626262679 | ||
![]() |
d23eb4fe7e | ||
![]() |
1818ffd152 | ||
![]() |
86e7754c7a | ||
![]() |
564237032a | ||
![]() |
06031e665a | ||
![]() |
9537ccdb7a | ||
![]() |
bba4f414b7 | ||
![]() |
4701f03c7b | ||
![]() |
16b88e8e67 | ||
![]() |
2744d80aa3 | ||
![]() |
50e05f8a72 | ||
![]() |
8dfdfb9579 | ||
![]() |
f2c6a0f8c0 | ||
![]() |
e30daf4232 | ||
![]() |
74192981cf | ||
![]() |
3c4fe43fcc | ||
![]() |
9477fb0321 | ||
![]() |
8c9cdfbc34 | ||
![]() |
36f22a13ce | ||
![]() |
e0afa0a916 | ||
![]() |
17458889aa | ||
![]() |
4d7ef21791 | ||
![]() |
b63baa57be | ||
![]() |
f95332d0a1 | ||
![]() |
2724317985 | ||
![]() |
205e2c91aa | ||
![]() |
ea2b25f2e6 | ||
![]() |
81c1d46db0 | ||
![]() |
ffdb9378b5 | ||
![]() |
34cdd4a1d7 | ||
![]() |
dc4ba34657 | ||
![]() |
aa7f246c2e | ||
![]() |
35e5905cca | ||
![]() |
543d1a378a | ||
![]() |
0d4028ea7a | ||
![]() |
dc2eb66d43 | ||
![]() |
478aaf7788 | ||
![]() |
1eca091fd3 | ||
![]() |
50398c18c4 | ||
![]() |
6ae645ce33 | ||
![]() |
bd564931f8 | ||
![]() |
fdc04b7276 | ||
![]() |
14f32f73c0 | ||
![]() |
64e40a25e0 | ||
![]() |
239cdf694f | ||
![]() |
0da6aeb94f | ||
![]() |
b99b107bbc | ||
![]() |
928cb57448 | ||
![]() |
8efcd93db6 | ||
![]() |
dd5499a12e | ||
![]() |
b9ffae5c8d | ||
![]() |
225312b9d9 | ||
![]() |
10e3494de4 | ||
![]() |
d2f8910af2 | ||
![]() |
3910b29b0b | ||
![]() |
b258d7bd65 | ||
![]() |
ae2a05b6f2 | ||
![]() |
747367ab8a | ||
![]() |
ef1bf2f727 | ||
![]() |
5672e05a40 | ||
![]() |
cb0f4fe75e | ||
![]() |
5b0be52d35 | ||
![]() |
b28d6f5c4f | ||
![]() |
dbe9431fa9 | ||
![]() |
9245c3c32b | ||
![]() |
b914b6fe53 | ||
![]() |
6cd0d57c3d | ||
![]() |
68502ad77c | ||
![]() |
4cbfca6e4b | ||
![]() |
ed80150dd7 | ||
![]() |
df53ffe05b | ||
![]() |
0f598bffa3 | ||
![]() |
679fe05d19 | ||
![]() |
61a462b0be | ||
![]() |
147eac48ee | ||
![]() |
1cf9e3ff02 | ||
![]() |
f0e7f843c3 | ||
![]() |
93e188688a | ||
![]() |
d9e8b815f5 | ||
![]() |
d05e107f2e | ||
![]() |
93be5b1251 | ||
![]() |
dc57935468 | ||
![]() |
dbe1fb91db | ||
![]() |
e662449b69 | ||
![]() |
458ade64e6 | ||
![]() |
0b7d8d5a9b | ||
![]() |
c20480c662 | ||
![]() |
95301e11ba | ||
![]() |
04a31eeed3 | ||
![]() |
66a6fd46b8 | ||
![]() |
6e259868e3 | ||
![]() |
f38d258d15 | ||
![]() |
c8939fa6d8 | ||
![]() |
733824bffc | ||
![]() |
43182c80cc | ||
![]() |
dbd9c34d17 | ||
![]() |
6aa2d07f9e | ||
![]() |
5260e3500c | ||
![]() |
bd32e9d540 | ||
![]() |
4c326e8535 | ||
![]() |
b40e71575c | ||
![]() |
9efb9b1682 | ||
![]() |
c9f1db548c | ||
![]() |
e703ad75af | ||
![]() |
ea9c0cf524 | ||
![]() |
41d9fbf258 | ||
![]() |
5fc8f4b2c4 | ||
![]() |
5e05131d90 | ||
![]() |
f04040f409 | ||
![]() |
4dc1bfa99e | ||
![]() |
98d5c8a8aa | ||
![]() |
a2ee528dae | ||
![]() |
eab9cb4b5c | ||
![]() |
b4bf1172bc | ||
![]() |
3ecca3e86e | ||
![]() |
e6a6ab89e6 | ||
![]() |
ec96feb7f4 | ||
![]() |
e7de90a33f | ||
![]() |
1fd4835c72 | ||
![]() |
50ef307622 | ||
![]() |
06d20906c4 | ||
![]() |
596643a33c | ||
![]() |
a42f5525a3 | ||
![]() |
a8da814c19 | ||
![]() |
bd29763b16 | ||
![]() |
8760559690 | ||
![]() |
0862327937 | ||
![]() |
968658a70e | ||
![]() |
28a81c11d9 | ||
![]() |
839c6a23fa | ||
![]() |
2b7347ce07 | ||
![]() |
49a6172548 | ||
![]() |
6dfc78ca42 | ||
![]() |
00855acfec | ||
![]() |
559a9f2beb | ||
![]() |
6bbaa6bc69 | ||
![]() |
286f63f002 | ||
![]() |
06af8111e8 | ||
![]() |
4323371c53 | ||
![]() |
375eb541e9 | ||
![]() |
43fce48539 | ||
![]() |
db5acb5718 | ||
![]() |
be6dbdadbf | ||
![]() |
77b5346099 | ||
![]() |
60053c5e44 | ||
![]() |
22344e43a6 | ||
![]() |
31530e0791 | ||
![]() |
46a6062bdf | ||
![]() |
0c686e6b8b | ||
![]() |
6f5340eb84 | ||
![]() |
c9e33065af | ||
![]() |
95e09828a6 | ||
![]() |
d7a421b99a | ||
![]() |
6a0eb58a66 | ||
![]() |
5bfb5a6eac | ||
![]() |
bec02c79eb | ||
![]() |
8b2a2340e7 | ||
![]() |
9f756563c0 | ||
![]() |
8e519951f3 | ||
![]() |
e1d71a78ab | ||
![]() |
1c585e5d67 | ||
![]() |
992b47a561 | ||
![]() |
0a15ce5c2b | ||
![]() |
8b36df94a1 | ||
![]() |
8ae602b5bf | ||
![]() |
781ea7103e | ||
![]() |
94ee2b67ad | ||
![]() |
6a6a98dcea | ||
![]() |
93d3a7ce4b | ||
![]() |
9b3578740f | ||
![]() |
454b8ea760 | ||
![]() |
9d48602a2a | ||
![]() |
310a316127 | ||
![]() |
6bd9d83fce | ||
![]() |
1087e961ca | ||
![]() |
0b616dd90a | ||
![]() |
6ec277cd67 | ||
![]() |
b2afad9aec | ||
![]() |
8404fb8a40 | ||
![]() |
1f599e6e47 | ||
![]() |
5a82e18ed1 | ||
![]() |
77f07f8baf | ||
![]() |
27d8d42446 | ||
![]() |
9ddb034e55 | ||
![]() |
e05dc43f35 | ||
![]() |
94ec425a5e | ||
![]() |
e37706f934 | ||
![]() |
42faaacdb7 | ||
![]() |
467d0e5663 | ||
![]() |
ed2b67f5bd | ||
![]() |
2a4eaa60cd | ||
![]() |
cdecdb345b | ||
![]() |
1c6be3b363 | ||
![]() |
40daa0327c | ||
![]() |
11276dbbfa | ||
![]() |
bb54e40139 | ||
![]() |
e9fc5f12a1 | ||
![]() |
1b7aa9baf8 | ||
![]() |
80ba06d454 | ||
![]() |
5f64c127f8 | ||
![]() |
6a26125889 | ||
![]() |
6fa47a2a6e | ||
![]() |
093b8bf9d6 | ||
![]() |
f53dad83ae | ||
![]() |
aca46c49c8 | ||
![]() |
69c6f55961 | ||
![]() |
33722fcfd6 | ||
![]() |
44bd81f159 | ||
![]() |
9f34dfe149 | ||
![]() |
36a7b24315 | ||
![]() |
69f6a9cc90 | ||
![]() |
f856e90d15 | ||
![]() |
56fb4a72fc | ||
![]() |
08993ae5e2 | ||
![]() |
8c8d7420ed | ||
![]() |
b9588627f0 | ||
![]() |
bd5699d5f1 | ||
![]() |
2dc506fcfd | ||
![]() |
1774db10ff | ||
![]() |
ffc6d90094 | ||
![]() |
ab3801314c | ||
![]() |
97c4fa724b | ||
![]() |
5643a44287 | ||
![]() |
462a9ae64c | ||
![]() |
18c30805ab | ||
![]() |
eda914281a | ||
![]() |
0b926bcbf4 | ||
![]() |
cb5eb98f12 | ||
![]() |
42c0724886 | ||
![]() |
5264ff7e90 | ||
![]() |
a69eefa0db | ||
![]() |
0c809f4d2b | ||
![]() |
5ea2322865 | ||
![]() |
d6143de0a0 | ||
![]() |
f105a9b3cc | ||
![]() |
cd8b27dd73 | ||
![]() |
b041a5fb38 | ||
![]() |
eba02368a6 | ||
![]() |
9d2a436749 | ||
![]() |
97447d681f | ||
![]() |
880b21745b | ||
![]() |
01b26ef1d3 | ||
![]() |
8823101c77 | ||
![]() |
082c4742d1 | ||
![]() |
964a3cc06b | ||
![]() |
fb64f0d873 | ||
![]() |
3df3bbc948 | ||
![]() |
1c0cfd8965 | ||
![]() |
539798971c | ||
![]() |
c9fb364cc0 | ||
![]() |
ae6b23fffc | ||
![]() |
a7f836cb9a | ||
![]() |
2449b4c79c | ||
![]() |
d658985e69 | ||
![]() |
56c59353bb | ||
![]() |
73f387a7ed | ||
![]() |
561dadb877 | ||
![]() |
0de8254ea2 | ||
![]() |
d8b1ea33f8 | ||
![]() |
a0c99c848a | ||
![]() |
ea6f4d0713 | ||
![]() |
6c8107efc7 | ||
![]() |
3e8664b40e | ||
![]() |
4629bccd72 | ||
![]() |
bebbfc434c | ||
![]() |
ecfb7a3873 | ||
![]() |
028c8ce63d | ||
![]() |
87f796c6d9 | ||
![]() |
e1cefd14ca | ||
![]() |
a43c3ed28c | ||
![]() |
8334dd7378 | ||
![]() |
5ecb840c9c | ||
![]() |
e3562c29ef | ||
![]() |
2422318162 | ||
![]() |
62a0743e4e | ||
![]() |
b829c9bcc8 | ||
![]() |
62463b904e | ||
![]() |
751f193d81 | ||
![]() |
b22ae4f90d | ||
![]() |
66de9d4510 | ||
![]() |
293b08d759 | ||
![]() |
8f2e0611e0 | ||
![]() |
f2e8425145 | ||
![]() |
e4e1994a60 | ||
![]() |
42c6601aae | ||
![]() |
411a850d41 | ||
![]() |
4da7f6ac72 | ||
![]() |
e502eeee2f | ||
![]() |
d01bde60f6 | ||
![]() |
dd1c130721 | ||
![]() |
7e0f0326de | ||
![]() |
f3caa7182a | ||
![]() |
62217b7db6 | ||
![]() |
c0d9f3d95b | ||
![]() |
ca0201b301 | ||
![]() |
5066fe0fce | ||
![]() |
56e848eea9 | ||
![]() |
057d6a4ed4 | ||
![]() |
c543b03401 | ||
![]() |
54af8014c4 | ||
![]() |
157b246f7f | ||
![]() |
d783b71d49 | ||
![]() |
ee0bca464f | ||
![]() |
82a67b27b9 | ||
![]() |
48198d232d | ||
![]() |
2231c06efb | ||
![]() |
cf3963a357 | ||
![]() |
487c32bbb4 | ||
![]() |
117095823e | ||
![]() |
300835a446 | ||
![]() |
6f044faaba | ||
![]() |
8687b540c6 | ||
![]() |
e5e8882d07 | ||
![]() |
8e2cd17436 | ||
![]() |
d997ac0bbe | ||
![]() |
01175124c2 |
64
.clang-format
Normal file
64
.clang-format
Normal file
@ -0,0 +1,64 @@
|
||||
Language: Cpp
|
||||
BasedOnStyle: LLVM
|
||||
AlignAfterOpenBracket: Align
|
||||
AlignConsecutiveAssignments: false
|
||||
AlignConsecutiveDeclarations: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: true
|
||||
AlignTrailingComments: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
AllowShortCaseLabelsOnASingleLine: true
|
||||
AllowShortFunctionsOnASingleLine: InlineOnly
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: true
|
||||
AfterEnum: true
|
||||
AfterFunction: true
|
||||
AfterNamespace: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: true
|
||||
BreakBeforeTernaryOperators: true
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakInheritanceList: AfterColon
|
||||
ColumnLimit: 0
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
ConstructorInitializerIndentWidth: 2
|
||||
ContinuationIndentWidth: 2
|
||||
Cpp11BracedListStyle: true
|
||||
EmptyLineBeforeAccessModifier: Never
|
||||
IndentCaseLabels: false
|
||||
IndentPPDirectives: None
|
||||
IndentWidth: 2
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
PointerAlignment: Left
|
||||
ReflowComments: true
|
||||
SortIncludes: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceBeforeParens: Custom
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: true
|
||||
AfterFunctionDefinitionName: true
|
||||
AfterFunctionDeclarationName: true
|
||||
SpacesInAngles: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: Latest
|
||||
TabWidth: 2
|
||||
UseTab: Never
|
||||
|
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
*.whl
|
||||
dist
|
||||
build
|
||||
*.vol.gz
|
||||
*.vol
|
||||
*.ini
|
||||
__pycache__
|
||||
*.json
|
||||
*.zip
|
||||
.cache
|
||||
*.patch
|
123
.gitlab-ci.yml
123
.gitlab-ci.yml
@ -2,20 +2,20 @@ stages:
|
||||
- build
|
||||
- test
|
||||
- test_ngsolve
|
||||
- deploy
|
||||
- cleanup
|
||||
|
||||
push_github_sourceforge:
|
||||
push_github:
|
||||
stage: build
|
||||
tags:
|
||||
- linux
|
||||
- docker
|
||||
- bash
|
||||
script:
|
||||
- git remote add sourceforge ssh://mhochste@git.code.sf.net/p/netgen-mesher/git || true
|
||||
- git remote add github git@github.com:NGSolve/netgen.git || true
|
||||
- git remote update
|
||||
- git checkout master
|
||||
- git checkout --track origin/master
|
||||
- git pull origin master
|
||||
- git push sourceforge master --tags
|
||||
- git push github master --tags
|
||||
only:
|
||||
- master
|
||||
@ -30,15 +30,25 @@ push_github_sourceforge:
|
||||
- x64
|
||||
before_script:
|
||||
- "echo off"
|
||||
- 'call "%VS2017INSTALLDIR%\VC\Auxiliary\Build\vcvars64"'
|
||||
- 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,15 +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
|
||||
-DOCC_LIBRARY=C:/install_opencascade_7.4.0_static/win64/vc14/lib/TKernel.lib
|
||||
-DOCC_INCLUDE_DIR=C:/install_opencascade_7.4.0_static/inc
|
||||
-DOCC_LINK_FREETYPE=ON
|
||||
-DUSE_CCACHE=ON
|
||||
-DENABLE_UNIT_TESTS=ON
|
||||
-DENABLE_UNIT_TESTS=OFF
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
- cmake --build . --target install --config Release
|
||||
|
||||
@ -77,6 +86,21 @@ test_win:
|
||||
- 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
|
||||
when: always
|
||||
expire_in: 1 week
|
||||
|
||||
cleanup_win:
|
||||
<<: *win
|
||||
stage: cleanup
|
||||
@ -97,12 +121,14 @@ cleanup_win:
|
||||
.template_ubuntu: &ubuntu
|
||||
tags:
|
||||
- linux
|
||||
- bash
|
||||
before_script:
|
||||
- pwd
|
||||
- ls
|
||||
- docker info
|
||||
- export PYTHONPATH=/opt/netgen/`python3 -c "import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))"`
|
||||
variables:
|
||||
UBUNTU_VERSION: "18.04"
|
||||
UBUNTU_VERSION: "22.04"
|
||||
|
||||
build_ubuntu_debug:
|
||||
<<: *ubuntu
|
||||
@ -114,6 +140,7 @@ build_ubuntu_debug:
|
||||
docker run
|
||||
--cidfile netgen_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id
|
||||
-e CCACHE_DIR=/ccache
|
||||
-e PYTHONPATH=$PYTHONPATH
|
||||
-v /mnt/ccache:/ccache
|
||||
netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION}
|
||||
bash /root/src/netgen/tests/build_debug.sh
|
||||
@ -130,6 +157,7 @@ build_ubuntu_mpi:
|
||||
docker run>-
|
||||
--cidfile netgen_mpi_${CI_PIPELINE_ID}_${UBUNTU_VERSION}.id>-
|
||||
-e CCACHE_DIR=/ccache
|
||||
-e PYTHONPATH=$PYTHONPATH
|
||||
-e RUN_SLOW_TESTS=${RUN_SLOW_TESTS}
|
||||
-v /mnt/ccache:/ccache
|
||||
netgen_mpi_${CI_PIPELINE_ID}:${UBUNTU_VERSION}
|
||||
@ -143,8 +171,7 @@ test_ubuntu_debug:
|
||||
script:
|
||||
- >-
|
||||
docker run
|
||||
-e NETGENDIR=/opt/netgen/bin
|
||||
-e PYTHONPATH=/opt/netgen/lib/python3/dist-packages
|
||||
-e PYTHONPATH=$PYTHONPATH
|
||||
netgen_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}
|
||||
bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V --output-on-failure"'
|
||||
needs: ["build_ubuntu_debug"]
|
||||
@ -156,8 +183,7 @@ test_ubuntu_mpi:
|
||||
- >-
|
||||
docker run
|
||||
-e RUN_SLOW_TESTS=${RUN_SLOW_TESTS}
|
||||
-e NETGENDIR=/opt/netgen/bin
|
||||
-e PYTHONPATH=/opt/netgen/lib/python3/dist-packages
|
||||
-e PYTHONPATH=$PYTHONPATH
|
||||
netgen_mpi_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}
|
||||
bash -c 'cd /root/build/netgen && make test_netgen ARGS="-V --output-on-failure"'
|
||||
needs: ["build_ubuntu_mpi"]
|
||||
@ -170,7 +196,7 @@ test_build_ngsolve:
|
||||
- >-
|
||||
docker run
|
||||
-e NETGENDIR=/opt/netgen/bin
|
||||
-e PYTHONPATH=/opt/netgen/lib/python3/dist-packages
|
||||
-e PYTHONPATH=$PYTHONPATH
|
||||
-e MKLROOT=/opt/intel/mkl
|
||||
-v /opt/intel:/opt/intel
|
||||
-e CCACHE_DIR=/ccache
|
||||
@ -178,26 +204,11 @@ test_build_ngsolve:
|
||||
netgen_${CI_PIPELINE_ID}_installed:${UBUNTU_VERSION}
|
||||
bash -c 'cd /root/src/netgen/tests/ && ./build_ngsolve.sh'
|
||||
|
||||
# cpp guideline checks
|
||||
# test_guidelines:
|
||||
# <<: *ubuntu
|
||||
# stage: test
|
||||
# script:
|
||||
# - docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_guidelines.sh
|
||||
# when: always
|
||||
# allow_failure: true
|
||||
|
||||
# check if it compiles without spdlog
|
||||
test_noSpdlog:
|
||||
<<: *ubuntu
|
||||
stage: test
|
||||
script:
|
||||
- docker run -e CCACHE_DIR=/ccache -v /mnt/ccache:/ccache netgen_${CI_PIPELINE_ID}:${UBUNTU_VERSION} bash /root/src/netgen/tests/build_nospdlog.sh
|
||||
|
||||
cleanup_ubuntu:
|
||||
stage: cleanup
|
||||
tags:
|
||||
- linux
|
||||
- bash
|
||||
script:
|
||||
# remove intermediate and old docker images and containers
|
||||
- docker rm -f `docker ps --no-trunc -aq`
|
||||
@ -217,12 +228,13 @@ cleanup_ubuntu:
|
||||
.template_mac: &mac
|
||||
tags:
|
||||
- mac
|
||||
- x64
|
||||
before_script:
|
||||
- export ROOT_DIR=/tmp/$CI_PIPELINE_ID
|
||||
- export SRC_DIR=$ROOT_DIR/src
|
||||
- export BUILD_DIR=$ROOT_DIR/build
|
||||
- export CMAKE_INSTALL_PREFIX=/tmp/$CI_PIPELINE_ID/install/Netgen.app
|
||||
- export PYTHONPATH=$CMAKE_INSTALL_PREFIX/Contents/Resources/`python3 -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1,0,''))"`:.
|
||||
- export PYTHONPATH=$CMAKE_INSTALL_PREFIX/Contents/Resources/`python3 -c "import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))"`:.
|
||||
- export PATH=$CMAKE_INSTALL_PREFIX/Contents/MacOS:$PATH
|
||||
|
||||
build_mac:
|
||||
@ -244,13 +256,11 @@ build_mac:
|
||||
-DUSE_NATIVE_ARCH=OFF
|
||||
-DUSE_CCACHE=ON
|
||||
-DENABLE_UNIT_TESTS=ON
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.12
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15
|
||||
-DCMAKE_OSX_SYSROOT=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk
|
||||
-DUSE_CGNS=ON
|
||||
-DUSE_OCC=ON
|
||||
-DOCC_LIBRARY=/usr/local/opt/opencascade-7.4.0/lib/libTKernel.a
|
||||
-DOCC_INCLUDE_DIR=/usr/local/opt/opencascade-7.4.0/include/opencascade
|
||||
-DOCC_LINK_FREETYPE=ON
|
||||
-DPython3_ROOT_DIR=/Library/Frameworks/Python.framework/Versions/3.8/
|
||||
- make -j5 install
|
||||
|
||||
test_mac:
|
||||
@ -270,3 +280,40 @@ cleanup_mac:
|
||||
allow_failure: true
|
||||
needs: ["test_mac"]
|
||||
|
||||
pip_linux:
|
||||
image: quay.io/pypa/manylinux_2_28_x86_64
|
||||
stage: build
|
||||
tags:
|
||||
- pip
|
||||
- linux
|
||||
- docker
|
||||
script:
|
||||
- ./tests/build_pip.sh
|
||||
when: manual
|
||||
|
||||
pip_windows:
|
||||
stage: build
|
||||
tags:
|
||||
- pip
|
||||
- windows
|
||||
script:
|
||||
- .\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:
|
||||
stage: build
|
||||
tags:
|
||||
- pip
|
||||
- macosx
|
||||
- m1
|
||||
script:
|
||||
- ./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
|
||||
|
373
CMakeLists.txt
373
CMakeLists.txt
@ -2,20 +2,26 @@ if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING INTERNAL)
|
||||
endif(NOT CMAKE_BUILD_TYPE)
|
||||
|
||||
if(WIN32)
|
||||
# we are linking to object libraries on Windows
|
||||
cmake_minimum_required(VERSION 3.12)
|
||||
else(WIN32)
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
endif(WIN32)
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
cmake_policy(VERSION 3.16)
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.24.0")
|
||||
cmake_policy(SET CMP0135 NEW)
|
||||
endif()
|
||||
|
||||
include (CMakeDependentOption)
|
||||
option( USE_NATIVE_ARCH "build for native cpu architecture" ON)
|
||||
|
||||
option( USE_GUI "don't build netgen with GUI" ON )
|
||||
option( USE_GUI "build with GUI" ON )
|
||||
option( USE_PYTHON "build with python interface" ON )
|
||||
cmake_dependent_option( PREFER_SYSTEM_PYBIND11 "Use system wide PyBind11" OFF "USE_PYTHON" OFF)
|
||||
option( USE_MPI "enable mpi parallelization" OFF )
|
||||
option( USE_MPI4PY "enable mpi4py interface" ON )
|
||||
option( USE_OCC "(not supported) compile with OpenCascade geometry kernel" OFF)
|
||||
option( USE_MPI_WRAPPER "enable mpi wrapper (run-time dispatch of MPI library calls)" OFF )
|
||||
option( USE_OCC "build with OpenCascade geometry kernel interface" ON)
|
||||
option( USE_STLGEOM "build with STL geometry support" ON)
|
||||
option( USE_CSG "build with CSG kernel" ON)
|
||||
option( USE_INTERFACE "build nginterface" ON)
|
||||
option( USE_GEOM2D "build 2d geometry kernels" ON)
|
||||
option( USE_JPEG "enable snapshots using library libjpeg" OFF )
|
||||
option( USE_MPEG "enable video recording with FFmpeg, uses libavcodec" OFF )
|
||||
option( USE_CGNS "enable CGNS file read/write support" OFF )
|
||||
@ -26,17 +32,20 @@ option( USE_CCACHE "use ccache")
|
||||
option( USE_INTERNAL_TCL "Compile tcl files into the code and don't install them" ON)
|
||||
option( ENABLE_UNIT_TESTS "Enable Catch unit tests")
|
||||
option( ENABLE_CPP_CORE_GUIDELINES_CHECK "Enable cpp core guideline checks on ngcore" OFF)
|
||||
option( USE_SPDLOG "Enable spd log logging" OFF)
|
||||
option( DEBUG_LOG "Enable more debug output (may increase computation time) - only works with USE_SPDLOG=ON" OFF)
|
||||
option( CHECK_RANGE "Check array range access, automatically enabled if built in debug mode" OFF)
|
||||
option( BUILD_STUB_FILES "Build stub files for better autocompletion" ON)
|
||||
option( BUILD_FOR_CONDA "Link python libraries only to executables" OFF)
|
||||
|
||||
option( USE_SUPERBUILD "use ccache" ON)
|
||||
option( USE_SUPERBUILD "build dependencies automatically" ON)
|
||||
option( TRACE_MEMORY "Enable memory tracing" OFF)
|
||||
|
||||
set(NG_COMPILE_FLAGS "" CACHE STRING "Additional compile flags")
|
||||
|
||||
set(NGLIB_LIBRARY_TYPE SHARED CACHE STRING "nglib library type")
|
||||
set(NGCORE_LIBRARY_TYPE SHARED CACHE STRING "ngcore library type")
|
||||
set(NGGUI_LIBRARY_TYPE SHARED CACHE STRING "nggui library type")
|
||||
|
||||
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_modules")
|
||||
|
||||
if(APPLE)
|
||||
@ -65,19 +74,83 @@ endif(UNIX AND USE_SUPERBUILD)
|
||||
|
||||
if (USE_SUPERBUILD)
|
||||
project (SUPERBUILD)
|
||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR_DEFAULT}" CACHE PATH "Install directory" FORCE)
|
||||
else()
|
||||
project(Netgen)
|
||||
endif()
|
||||
|
||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR_DEFAULT}" CACHE PATH "Install directory" FORCE)
|
||||
endif()
|
||||
|
||||
set(NG_INSTALL_SUFFIX netgen CACHE STRING "Suffix appended to install directories (project name)")
|
||||
|
||||
if(USE_PYTHON)
|
||||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.18)
|
||||
find_package(Python3 REQUIRED COMPONENTS Development.Module)
|
||||
if(NOT EMSCRIPTEN)
|
||||
find_package(Python3 COMPONENTS Interpreter Development.Embed)
|
||||
endif()
|
||||
else()
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import os.path, sysconfig;print(os.path.relpath(sysconfig.get_path('platlib'), sysconfig.get_path('data')))" OUTPUT_VARIABLE PYTHON_PACKAGES_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
file(TO_CMAKE_PATH ${PYTHON_PACKAGES_INSTALL_DIR} PYTHON_PACKAGES_INSTALL_DIR)
|
||||
endif(NOT CMAKE_CROSSCOMPILING)
|
||||
endif(USE_PYTHON)
|
||||
|
||||
if(APPLE AND NOT EMSCRIPTEN)
|
||||
set(NG_INSTALL_DIR_BIN_DEFAULT Contents/MacOS)
|
||||
set(NG_INSTALL_DIR_LIB_DEFAULT Contents/MacOS)
|
||||
set(NG_INSTALL_DIR_CMAKE_DEFAULT Contents/Resources/CMake)
|
||||
set(NG_INSTALL_DIR_PYTHON_DEFAULT Contents/Resources/${PYTHON_PACKAGES_INSTALL_DIR})
|
||||
set(NG_INSTALL_DIR_RES_DEFAULT Contents/Resources/share)
|
||||
set(NG_INSTALL_DIR_INCLUDE_DEFAULT Contents/Resources/include)
|
||||
|
||||
set(NG_RPATH_TOKEN "@loader_path")
|
||||
else(APPLE AND NOT EMSCRIPTEN)
|
||||
set(NG_INSTALL_DIR_BIN_DEFAULT bin)
|
||||
set(NG_INSTALL_DIR_LIB_DEFAULT lib)
|
||||
if(WIN32)
|
||||
set(NG_INSTALL_DIR_CMAKE_DEFAULT cmake)
|
||||
else(WIN32)
|
||||
set(NG_INSTALL_DIR_CMAKE_DEFAULT lib/cmake/${NG_INSTALL_SUFFIX})
|
||||
endif(WIN32)
|
||||
set(NG_INSTALL_DIR_PYTHON_DEFAULT ${PYTHON_PACKAGES_INSTALL_DIR})
|
||||
set(NG_INSTALL_DIR_RES_DEFAULT share)
|
||||
set(NG_INSTALL_DIR_INCLUDE_DEFAULT include)
|
||||
|
||||
set(NG_RPATH_TOKEN "\$ORIGIN")
|
||||
endif(APPLE AND NOT EMSCRIPTEN)
|
||||
|
||||
set(NG_INSTALL_DIR_PYTHON ${NG_INSTALL_DIR_PYTHON_DEFAULT} CACHE STRING "Install directory for Python files")
|
||||
set(NG_INSTALL_DIR_BIN ${NG_INSTALL_DIR_BIN_DEFAULT} CACHE STRING "Install directory for executables")
|
||||
set(NG_INSTALL_DIR_LIB ${NG_INSTALL_DIR_LIB_DEFAULT} CACHE STRING "Install directory for libraries")
|
||||
set(NG_INSTALL_DIR_INCLUDE ${NG_INSTALL_DIR_INCLUDE_DEFAULT} CACHE STRING "Install directory for header files")
|
||||
set(NG_INSTALL_DIR_CMAKE ${NG_INSTALL_DIR_CMAKE_DEFAULT} CACHE STRING "Install directory for CMake files")
|
||||
set(NG_INSTALL_DIR_RES ${NG_INSTALL_DIR_RES_DEFAULT} CACHE STRING "Install directory for resources")
|
||||
|
||||
get_filename_component(NETGEN_CMAKE_DIR_ABSOLUTE ${NG_INSTALL_DIR_CMAKE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
get_filename_component(NETGEN_BINARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_BIN} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
get_filename_component(NETGEN_LIBRARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_LIB} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
get_filename_component(NETGEN_INCLUDE_DIR_ABSOLUTE ${NG_INSTALL_DIR_INCLUDE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
get_filename_component(NETGEN_RESOURCE_DIR_ABSOLUTE ${NG_INSTALL_DIR_RES} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
file(RELATIVE_PATH NETGEN_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${CMAKE_INSTALL_PREFIX})
|
||||
file(RELATIVE_PATH NETGEN_BINARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_BINARY_DIR_ABSOLUTE})
|
||||
file(RELATIVE_PATH NETGEN_LIBRARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})
|
||||
file(RELATIVE_PATH NETGEN_INCLUDE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_INCLUDE_DIR_ABSOLUTE})
|
||||
file(RELATIVE_PATH NETGEN_RESOURCE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_RESOURCE_DIR_ABSOLUTE})
|
||||
|
||||
file(RELATIVE_PATH NETGEN_RPATH ${NETGEN_BINARY_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})
|
||||
|
||||
if (USE_SUPERBUILD)
|
||||
# execute the superbuild (this script will be invoked again without the
|
||||
# USE_SUPERBUILD option this time)
|
||||
include (cmake/SuperBuild.cmake)
|
||||
return() # stop processing this file further
|
||||
else()
|
||||
project(Netgen)
|
||||
if (CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
|
||||
set(CMAKE_INSTALL_PREFIX "${INSTALL_DIR_DEFAULT}" CACHE PATH "Install directory" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
@ -91,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)
|
||||
|
||||
@ -119,61 +193,6 @@ include_directories ("${PROJECT_BINARY_DIR}")
|
||||
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
|
||||
if(USE_PYTHON)
|
||||
find_package(PythonInterp 3 REQUIRED)
|
||||
find_package(PythonLibs 3 REQUIRED)
|
||||
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from distutils.sysconfig import get_python_lib; print(get_python_lib(1,0,''))" OUTPUT_VARIABLE PYTHON_PACKAGES_INSTALL_DIR OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
file(TO_CMAKE_PATH ${PYTHON_PACKAGES_INSTALL_DIR} PYTHON_PACKAGES_INSTALL_DIR)
|
||||
endif(USE_PYTHON)
|
||||
|
||||
set(NG_INSTALL_SUFFIX netgen CACHE STRING "Suffix appended to install directories (project name)")
|
||||
|
||||
if(APPLE)
|
||||
set(NG_INSTALL_DIR_BIN_DEFAULT Contents/MacOS)
|
||||
set(NG_INSTALL_DIR_LIB_DEFAULT Contents/MacOS)
|
||||
set(NG_INSTALL_DIR_CMAKE_DEFAULT Contents/Resources/CMake)
|
||||
set(NG_INSTALL_DIR_PYTHON_DEFAULT Contents/Resources/${PYTHON_PACKAGES_INSTALL_DIR})
|
||||
set(NG_INSTALL_DIR_RES_DEFAULT Contents/Resources/share)
|
||||
set(NG_INSTALL_DIR_INCLUDE_DEFAULT Contents/Resources/include)
|
||||
|
||||
set(NG_RPATH_TOKEN "@loader_path")
|
||||
else(APPLE)
|
||||
set(NG_INSTALL_DIR_BIN_DEFAULT bin)
|
||||
set(NG_INSTALL_DIR_LIB_DEFAULT lib)
|
||||
if(WIN32)
|
||||
set(NG_INSTALL_DIR_CMAKE_DEFAULT cmake)
|
||||
else(WIN32)
|
||||
set(NG_INSTALL_DIR_CMAKE_DEFAULT lib/cmake/${NG_INSTALL_SUFFIX})
|
||||
endif(WIN32)
|
||||
set(NG_INSTALL_DIR_PYTHON_DEFAULT ${PYTHON_PACKAGES_INSTALL_DIR})
|
||||
set(NG_INSTALL_DIR_RES_DEFAULT share)
|
||||
set(NG_INSTALL_DIR_INCLUDE_DEFAULT include)
|
||||
|
||||
set(NG_RPATH_TOKEN "\$ORIGIN")
|
||||
endif(APPLE)
|
||||
|
||||
set(NG_INSTALL_DIR_PYTHON ${NG_INSTALL_DIR_PYTHON_DEFAULT} CACHE STRING "Install directory for Python files")
|
||||
set(NG_INSTALL_DIR_BIN ${NG_INSTALL_DIR_BIN_DEFAULT} CACHE STRING "Install directory for executables")
|
||||
set(NG_INSTALL_DIR_LIB ${NG_INSTALL_DIR_LIB_DEFAULT} CACHE STRING "Install directory for libraries")
|
||||
set(NG_INSTALL_DIR_INCLUDE ${NG_INSTALL_DIR_INCLUDE_DEFAULT} CACHE STRING "Install directory for header files")
|
||||
set(NG_INSTALL_DIR_CMAKE ${NG_INSTALL_DIR_CMAKE_DEFAULT} CACHE STRING "Install directory for CMake files")
|
||||
set(NG_INSTALL_DIR_RES ${NG_INSTALL_DIR_RES_DEFAULT} CACHE STRING "Install directory for resources")
|
||||
|
||||
get_filename_component(NETGEN_CMAKE_DIR_ABSOLUTE ${NG_INSTALL_DIR_CMAKE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
get_filename_component(NETGEN_BINARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_BIN} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
get_filename_component(NETGEN_LIBRARY_DIR_ABSOLUTE ${NG_INSTALL_DIR_LIB} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
get_filename_component(NETGEN_INCLUDE_DIR_ABSOLUTE ${NG_INSTALL_DIR_INCLUDE} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
get_filename_component(NETGEN_RESOURCE_DIR_ABSOLUTE ${NG_INSTALL_DIR_RES} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
|
||||
file(RELATIVE_PATH NETGEN_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${CMAKE_INSTALL_PREFIX})
|
||||
file(RELATIVE_PATH NETGEN_BINARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_BINARY_DIR_ABSOLUTE})
|
||||
file(RELATIVE_PATH NETGEN_LIBRARY_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})
|
||||
file(RELATIVE_PATH NETGEN_INCLUDE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_INCLUDE_DIR_ABSOLUTE})
|
||||
file(RELATIVE_PATH NETGEN_RESOURCE_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_RESOURCE_DIR_ABSOLUTE})
|
||||
|
||||
file(RELATIVE_PATH NETGEN_RPATH ${NETGEN_BINARY_DIR_ABSOLUTE} ${NETGEN_LIBRARY_DIR_ABSOLUTE})
|
||||
|
||||
if(USE_PYTHON)
|
||||
get_filename_component(NETGEN_PYTHON_DIR_ABSOLUTE ${NG_INSTALL_DIR_PYTHON} ABSOLUTE BASE_DIR ${CMAKE_INSTALL_PREFIX})
|
||||
file(RELATIVE_PATH NETGEN_PYTHON_DIR ${NETGEN_CMAKE_DIR_ABSOLUTE} ${NETGEN_PYTHON_DIR_ABSOLUTE})
|
||||
@ -189,6 +208,10 @@ install(EXPORT netgen-targets DESTINATION ${NG_INSTALL_DIR_CMAKE} COMPONENT netg
|
||||
|
||||
set(CMAKE_MACOSX_RPATH TRUE)
|
||||
set(CMAKE_INSTALL_RPATH "${NG_RPATH_TOKEN};${NG_RPATH_TOKEN}/${NETGEN_RPATH}")
|
||||
if(BUILD_FOR_CONDA)
|
||||
file(RELATIVE_PATH py_rpath "/bin" "/${NG_INSTALL_DIR_LIB}")
|
||||
set(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_RPATH};${py_rpath}")
|
||||
endif(BUILD_FOR_CONDA)
|
||||
|
||||
include (CheckIncludeFiles)
|
||||
check_include_files (dlfcn.h HAVE_DLFCN_H)
|
||||
@ -214,50 +237,75 @@ macro(get_dll_from_lib dll_path lib_path)
|
||||
get_filename_component(lib_name ${lib} name)
|
||||
endmacro()
|
||||
|
||||
set(CMAKE_CXX_VISIBILITY_PRESET hidden)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
if(WIN32)
|
||||
set(CMAKE_MFC_FLAG 0)
|
||||
# build convenience (aka object) libraries in windows)
|
||||
set(NG_LIB_TYPE OBJECT)
|
||||
else(WIN32)
|
||||
# build shared libraries
|
||||
set(NG_LIB_TYPE SHARED)
|
||||
endif(WIN32)
|
||||
if(APPLE)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -undefined dynamic_lookup")
|
||||
endif(APPLE)
|
||||
|
||||
#######################################################################
|
||||
add_library(nglib ${NGLIB_LIBRARY_TYPE})
|
||||
if(USE_GUI)
|
||||
add_library(nggui ${NGGUI_LIBRARY_TYPE})
|
||||
if(WIN32)
|
||||
set_target_properties( nggui PROPERTIES OUTPUT_NAME "libnggui")
|
||||
endif(WIN32)
|
||||
endif(USE_GUI)
|
||||
|
||||
#######################################################################
|
||||
if(NOT ZLIB_INCLUDE_DIRS)
|
||||
find_package(ZLIB REQUIRED)
|
||||
endif(NOT ZLIB_INCLUDE_DIRS)
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
target_include_directories(nglib PRIVATE ${ZLIB_INCLUDE_DIRS})
|
||||
if(USE_GUI)
|
||||
target_include_directories(nggui PRIVATE ${ZLIB_INCLUDE_DIRS})
|
||||
endif(USE_GUI)
|
||||
|
||||
#######################################################################
|
||||
if(WIN32)
|
||||
add_library(netgen_gui INTERFACE IMPORTED)
|
||||
else()
|
||||
add_library(netgen_gui INTERFACE)
|
||||
endif()
|
||||
|
||||
if (USE_GUI)
|
||||
find_package(TCL 8.5 REQUIRED)
|
||||
find_package(TclStub 8.5 REQUIRED)
|
||||
find_package(Threads REQUIRED)
|
||||
if(APPLE)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -framework AppKit")
|
||||
target_link_libraries(netgen_gui INTERFACE "-framework AppKit")
|
||||
else(APPLE)
|
||||
find_package(X11 REQUIRED)
|
||||
target_link_libraries( netgen_gui INTERFACE ${X11_Xmu_LIB} ${X11_X11_LIB})
|
||||
endif(APPLE)
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
add_definitions(-DTCL -DOPENGL -DUSE_TOGL_2)
|
||||
include_directories(${TCL_INCLUDE_PATH})
|
||||
include_directories(${TK_INCLUDE_PATH})
|
||||
set(LIBTOGL togl)
|
||||
target_compile_definitions(netgen_gui INTERFACE -DTCL -DOPENGL -DUSE_TOGL_2 -DUSE_TCL_STUBS -DUSE_TK_STUBS)
|
||||
target_include_directories(netgen_gui INTERFACE ${TCL_INCLUDE_PATH} ${TK_INCLUDE_PATH})
|
||||
target_link_libraries(netgen_gui INTERFACE ${TCL_STUB_LIBRARY} ${TK_STUB_LIBRARY})
|
||||
if(NOT EXISTS ${TK_INCLUDE_PATH}/tkWin.h AND EXISTS ${TK_INCLUDE_PATH}/../win/tkWin.h)
|
||||
target_include_directories(netgen_gui INTERFACE ${TK_INCLUDE_PATH}/../win)
|
||||
endif()
|
||||
if(NOT EXISTS ${TK_INCLUDE_PATH}/x11/Xlib.h AND EXISTS ${TK_INCLUDE_PATH}/../xlib/X11/Xlib.h)
|
||||
target_include_directories(netgen_gui INTERFACE ${TK_INCLUDE_PATH}/../xlib)
|
||||
endif()
|
||||
|
||||
target_link_libraries(nggui PUBLIC nglib togl PRIVATE "$<BUILD_INTERFACE:netgen_python>" )
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DTOGL_WGL)
|
||||
else(WIN32)
|
||||
if(APPLE)
|
||||
ADD_DEFINITIONS(-DTOGL_NSOPENGL)
|
||||
else(APPLE)
|
||||
ADD_DEFINITIONS(-DTOGL_X11)
|
||||
endif(APPLE)
|
||||
endif(WIN32)
|
||||
target_compile_definitions(netgen_gui INTERFACE -DTOGL_WGL)
|
||||
endif()
|
||||
if(APPLE)
|
||||
target_compile_definitions(netgen_gui INTERFACE -DTOGL_NSOPENGL)
|
||||
endif()
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_compile_definitions(netgen_gui INTERFACE -DTOGL_X11)
|
||||
endif()
|
||||
|
||||
endif (USE_GUI)
|
||||
|
||||
#######################################################################
|
||||
@ -268,55 +316,115 @@ else()
|
||||
endif()
|
||||
|
||||
if (USE_PYTHON)
|
||||
add_subdirectory(external_dependencies/pybind11)
|
||||
find_path(PYBIND_INCLUDE_DIR pybind11/pybind11.h HINTS ${PYTHON_INCLUDE_DIR})
|
||||
if( PYBIND_INCLUDE_DIR )
|
||||
message(STATUS "Found Pybind11: ${PYBIND_INCLUDE_DIR}")
|
||||
else( PYBIND_INCLUDE_DIR )
|
||||
message(FATAL_ERROR "Could NOT find pybind11!")
|
||||
endif( PYBIND_INCLUDE_DIR )
|
||||
if (PREFER_SYSTEM_PYBIND11)
|
||||
set(NG_INSTALL_PYBIND OFF)
|
||||
find_package(pybind11 CONFIG REQUIRED)
|
||||
else()
|
||||
add_subdirectory(external_dependencies/pybind11)
|
||||
endif()
|
||||
|
||||
target_include_directories(netgen_python INTERFACE ${PYBIND_INCLUDE_DIR} ${PYTHON_INCLUDE_DIRS})
|
||||
if(NOT ${BUILD_FOR_CONDA})
|
||||
# Don't link python libraries in conda environments
|
||||
target_link_libraries(netgen_python INTERFACE ${PYTHON_LIBRARIES})
|
||||
target_compile_definitions(netgen_python INTERFACE NG_PYTHON NETGEN_PYTHON)
|
||||
target_include_directories(netgen_python INTERFACE ${pybind11_INCLUDE_DIR} ${Python3_INCLUDE_DIRS})
|
||||
target_include_directories(nglib PRIVATE ${pybind11_INCLUDE_DIR} ${Python3_INCLUDE_DIRS})
|
||||
if(Python3_LIBRARIES AND (WIN32 OR NOT BUILD_FOR_CONDA))
|
||||
target_link_libraries(netgen_python INTERFACE ${Python3_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(NG_INSTALL_PYBIND)
|
||||
install(DIRECTORY ${PYBIND_INCLUDE_DIR}/pybind11 DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel)
|
||||
install(FILES ${PYBIND_INCLUDE_DIR}/../LICENSE DESTINATION ${NG_INSTALL_DIR_INCLUDE}/pybind11 COMPONENT netgen_devel)
|
||||
install(DIRECTORY ${pybind11_INCLUDE_DIR}/pybind11 DESTINATION ${NG_INSTALL_DIR_INCLUDE} COMPONENT netgen_devel)
|
||||
install(FILES ${pybind11_INCLUDE_DIR}/../LICENSE DESTINATION ${NG_INSTALL_DIR_INCLUDE}/pybind11 COMPONENT netgen_devel)
|
||||
endif(NG_INSTALL_PYBIND)
|
||||
endif (USE_PYTHON)
|
||||
|
||||
#######################################################################
|
||||
add_library(netgen_mpi INTERFACE)
|
||||
add_library(netgen_metis INTERFACE)
|
||||
if (USE_MPI)
|
||||
find_package(MPI REQUIRED)
|
||||
target_include_directories(netgen_mpi INTERFACE ${MPI_CXX_INCLUDE_PATH})
|
||||
target_link_libraries(netgen_mpi INTERFACE ${MPI_mpi_LIBRARY} ${MPI_CXX_LIBRARIES} )
|
||||
target_compile_definitions(netgen_mpi INTERFACE PARALLEL )
|
||||
set(MPI_DETERMINE_LIBRARY_VERSION TRUE)
|
||||
find_package(MPI)
|
||||
|
||||
find_package(METIS REQUIRED)
|
||||
target_include_directories(netgen_metis INTERFACE ${METIS_INCLUDE_DIR})
|
||||
target_link_libraries(netgen_metis INTERFACE ${METIS_LIBRARY} )
|
||||
target_compile_definitions(netgen_metis INTERFACE METIS )
|
||||
|
||||
if(USE_MPI4PY AND USE_PYTHON)
|
||||
execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import mpi4py;print(mpi4py.get_include())" OUTPUT_VARIABLE mpi4py_path OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
find_path(MPI4PY_INCLUDE_DIR mpi4py.h HINTS ${mpi4py_path}/mpi4py NO_DEFAULT_PATH REQUIRED)
|
||||
target_include_directories(netgen_metis INTERFACE ${MPI4PY_INCLUDE_DIR})
|
||||
target_compile_definitions(netgen_metis INTERFACE NG_MPI4PY )
|
||||
message(STATUS "Found mpi4py: ${MPI4PY_INCLUDE_DIR}")
|
||||
endif(USE_MPI4PY AND USE_PYTHON)
|
||||
endif (USE_MPI)
|
||||
install(TARGETS netgen_mpi netgen_metis ${NG_INSTALL_DIR})
|
||||
|
||||
#######################################################################
|
||||
add_library(occ_libs INTERFACE IMPORTED)
|
||||
if (USE_OCC)
|
||||
find_package(OpenCasCade REQUIRED)
|
||||
add_definitions(-DOCCGEOMETRY -D_OCC64)
|
||||
include_directories(${OCC_INCLUDE_DIR})
|
||||
find_package(OpenCascade NAMES OpenCASCADE opencascade REQUIRED CMAKE_FIND_ROOT_PATH_BOTH)
|
||||
add_definitions(-DOCCGEOMETRY)
|
||||
set(OCC_LIBRARIES
|
||||
TKBO
|
||||
TKBRep
|
||||
TKBool
|
||||
TKCAF
|
||||
TKCDF
|
||||
TKFillet
|
||||
TKG2d
|
||||
TKG3d
|
||||
TKGeomAlgo
|
||||
TKGeomBase
|
||||
TKHLR
|
||||
TKLCAF
|
||||
TKMath
|
||||
TKMesh
|
||||
TKOffset
|
||||
TKPrim
|
||||
TKService
|
||||
TKShHealing
|
||||
TKTopAlgo
|
||||
TKV3d
|
||||
TKVCAF
|
||||
TKXCAF
|
||||
TKXSBase
|
||||
TKernel
|
||||
)
|
||||
if(${OpenCASCADE_MAJOR_VERSION}.${OpenCASCADE_MINOR_VERSION} VERSION_GREATER_EQUAL 7.8)
|
||||
list(APPEND OCC_LIBRARIES TKDEIGES TKDESTEP TKDESTL)
|
||||
else()
|
||||
list(APPEND OCC_LIBRARIES
|
||||
TKIGES
|
||||
TKSTEP
|
||||
TKSTL
|
||||
TKXDEIGES
|
||||
TKXDESTEP
|
||||
TKSTEP209
|
||||
TKSTEPAttr
|
||||
TKSTEPBase
|
||||
)
|
||||
endif()
|
||||
if(UNIX AND NOT APPLE)
|
||||
list(PREPEND OCC_LIBRARIES -Wl,--start-group)
|
||||
list(APPEND OCC_LIBRARIES -Wl,--end-group)
|
||||
endif()
|
||||
|
||||
target_link_libraries(occ_libs INTERFACE ${OCC_LIBRARIES})
|
||||
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})
|
||||
list(APPEND OCC_LIBRARIES ${FREETYPE})
|
||||
target_link_libraries(occ_libs INTERFACE ${FREETYPE})
|
||||
if(UNIX AND NOT APPLE)
|
||||
find_package(Fontconfig REQUIRED)
|
||||
target_link_libraries(occ_libs INTERFACE ${Fontconfig_LIBRARIES})
|
||||
endif()
|
||||
endif(OpenCASCADE_WITH_FREETYPE)
|
||||
set(THREADS_PREFER_PTHREAD_FLAG ON)
|
||||
find_package(Threads REQUIRED)
|
||||
target_link_libraries(occ_libs INTERFACE Threads::Threads)
|
||||
endif()
|
||||
if(WIN32 AND USE_GUI)
|
||||
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)
|
||||
|
||||
#######################################################################
|
||||
@ -418,6 +526,9 @@ endif(USE_CGNS)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/netgen_version.hpp ${CMAKE_CURRENT_BINARY_DIR}/netgen_config.hpp DESTINATION ${NG_INSTALL_DIR_INCLUDE}/include COMPONENT netgen_devel)
|
||||
|
||||
# include instead of add_subdirectory to recognize the generated source files properly
|
||||
include(rules/CMakeLists.txt)
|
||||
|
||||
add_subdirectory(windows)
|
||||
add_subdirectory(libsrc)
|
||||
add_subdirectory(ng)
|
||||
@ -425,9 +536,6 @@ add_subdirectory(tutorials)
|
||||
add_subdirectory(py_tutorials)
|
||||
add_subdirectory(doc)
|
||||
add_subdirectory(nglib)
|
||||
if (USE_PYTHON)
|
||||
add_subdirectory(python)
|
||||
endif (USE_PYTHON)
|
||||
add_subdirectory(tests)
|
||||
|
||||
#######################################################################
|
||||
@ -485,6 +593,9 @@ if(USE_NATIVE_ARCH)
|
||||
endif(APPLE)
|
||||
endif(USE_NATIVE_ARCH)
|
||||
|
||||
if (USE_PYTHON)
|
||||
add_subdirectory(python)
|
||||
endif (USE_PYTHON)
|
||||
|
||||
#######################################################################
|
||||
# Debian packager
|
||||
@ -522,7 +633,17 @@ if(UNIX)
|
||||
endif(temp)
|
||||
endif(UNIX)
|
||||
|
||||
if(APPLE)
|
||||
if(USE_PYTHON AND NOT SKBUILD)
|
||||
# install egg file to let python/pip know that Netgen ist installed
|
||||
file( WRITE "netgen_mesher-py3.egg-info"
|
||||
"Metadata-Version: 2.1
|
||||
Name: netgen-mesher
|
||||
Version: ${NETGEN_VERSION_MAJOR}.${NETGEN_VERSION_MINOR}.${NETGEN_VERSION_PATCH}.post${NETGEN_VERSION_TWEAK}
|
||||
")
|
||||
install(FILES netgen_mesher-py3.egg-info DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen)
|
||||
endif()
|
||||
|
||||
if(APPLE AND NOT SKBUILD)
|
||||
# create some auxiliary files
|
||||
set(mac_startup ${CMAKE_CURRENT_BINARY_DIR}/startup.sh)
|
||||
file(WRITE ${mac_startup} "\
|
||||
@ -567,7 +688,7 @@ open -a /Applications/Utilities/Terminal.app $Netgen_MACOS/startup.sh || open -a
|
||||
install(FILES ${mac_plist} DESTINATION ${NG_INSTALL_DIR_BIN}/../)
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/netgen.icns DESTINATION ${NG_INSTALL_DIR_RES}/../ RENAME Netgen.icns)
|
||||
|
||||
endif(APPLE)
|
||||
endif(APPLE AND NOT SKBUILD)
|
||||
|
||||
if(NOT APPLE)
|
||||
include(CPack)
|
||||
|
@ -1,3 +1,7 @@
|
||||
Netgen mesh generator
|
||||
|
||||
NETGEN is an automatic 3d tetrahedral mesh generator. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STL file format. The connection to a geometry kernel allows the handling of IGES and STEP files. NETGEN contains modules for mesh optimization and hierarchical mesh refinement. Netgen 6.x supports scripting via a Python interface. Netgen is open source based on the LGPL license. It is available for Unix/Linux, Windows, and OSX.
|
||||
NETGEN is an automatic 3d tetrahedral mesh generator. It accepts input from constructive solid geometry (CSG) or boundary representation (BRep) from STL file format. The connection to a geometry kernel allows the handling of IGES and STEP files. NETGEN contains modules for mesh optimization and hierarchical mesh refinement. Netgen 6.x supports scripting via a Python interface. Netgen is open source based on the LGPL license. It is available for Unix/Linux, Windows, and OSX.
|
||||
|
||||
Find the Open Source Community on https://ngsolve.org
|
||||
Support & Services: https://cerbsim.com
|
||||
|
||||
|
@ -32,19 +32,20 @@ set(NETGEN_MKL_LIBRARIES "@MKL_LIBRARIES@")
|
||||
set(NETGEN_MPI_CXX_INCLUDE_PATH "@MPI_CXX_INCLUDE_PATH@")
|
||||
set(NETGEN_MPI_CXX_LIBRARIES "@MPI_CXX_LIBRARIES@")
|
||||
set(NETGEN_NUMA_LIBRARY "@NUMA_LIBRARY@")
|
||||
set(NETGEN_OCC_INCLUDE_DIR "@OCC_INCLUDE_DIR@")
|
||||
set(NETGEN_OCC_LIBRARIES_BIN "@OCC_LIBRARIES_BIN@")
|
||||
set(NETGEN_OCC_DIR "@OpenCasCade_DIR@")
|
||||
set(NETGEN_OCC_INCLUDE_DIR "@OpenCASCADE_INCLUDE_DIR@")
|
||||
set(NETGEN_OCC_LIBRARIES_BIN "@OpenCASCADE_BINARY_DIR@")
|
||||
set(NETGEN_OCC_LIBRARIES "@OCC_LIBRARIES@")
|
||||
set(NETGEN_OCC_LIBRARY_DIR "@OCC_LIBRARY_DIR@")
|
||||
set(NETGEN_OCC_LIBRARY_DIR "@OpenCASCADE_LIBRARY_DIR@")
|
||||
set(NETGEN_OPENGL_LIBRARIES "@OPENGL_LIBRARIES@")
|
||||
set(NETGEN_PYTHON_EXECUTABLE "@PYTHON_EXECUTABLE@")
|
||||
set(NETGEN_PYTHON_INCLUDE_DIRS "@PYTHON_INCLUDE_DIRS@")
|
||||
set(NETGEN_PYTHON_LIBRARIES "@PYTHON_LIBRARIES@")
|
||||
set(NETGEN_PYTHON_EXECUTABLE "@Python3_EXECUTABLE@")
|
||||
set(NETGEN_PYTHON_INCLUDE_DIRS "@Python3_INCLUDE_DIRS@")
|
||||
set(NETGEN_PYTHON_LIBRARIES "@Python3_LIBRARIES@")
|
||||
set(NETGEN_TCL_INCLUDE_PATH "@TCL_INCLUDE_PATH@")
|
||||
set(NETGEN_TCL_LIBRARY "@TCL_LIBRARY@")
|
||||
set(NETGEN_TCL_LIBRARY "@TCL_STUB_LIBRARY@")
|
||||
set(NETGEN_TK_DND_LIBRARY "@TK_DND_LIBRARY@")
|
||||
set(NETGEN_TK_INCLUDE_PATH "@TK_INCLUDE_PATH@")
|
||||
set(NETGEN_TK_LIBRARY "@TK_LIBRARY@")
|
||||
set(NETGEN_TK_LIBRARY "@TK_STUB_LIBRARY@")
|
||||
set(NETGEN_X11_X11_LIB "@X11_X11_LIB@")
|
||||
set(NETGEN_X11_Xmu_LIB "@X11_Xmu_LIB@")
|
||||
set(NETGEN_ZLIB_INCLUDE_DIRS "@ZLIB_INCLUDE_DIRS@")
|
||||
|
@ -1,27 +1,80 @@
|
||||
include (ExternalProject)
|
||||
|
||||
option( BUILD_ZLIB "Build and link static version of zlib (useful for pip binaries)" OFF )
|
||||
option( BUILD_OCC "Build and link static version of occ (useful for pip binaries)" OFF )
|
||||
set_property (DIRECTORY PROPERTY EP_PREFIX dependencies)
|
||||
|
||||
set (NETGEN_DEPENDENCIES)
|
||||
set (LAPACK_DEPENDENCIES)
|
||||
set (NETGEN_CMAKE_ARGS "" CACHE INTERNAL "")
|
||||
set (SUBPROJECT_CMAKE_ARGS "" CACHE INTERNAL "")
|
||||
|
||||
set (SUBPROJECT_ARGS
|
||||
LIST_SEPARATOR |
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dependencies
|
||||
)
|
||||
|
||||
if (EMSCRIPTEN)
|
||||
set (SUBPROJECT_ARGS
|
||||
${SUBPROJECT_ARGS}
|
||||
CMAKE_COMMAND emcmake ${CMAKE_COMMAND})
|
||||
endif()
|
||||
|
||||
# only show output on failure in ci-builds
|
||||
if(DEFINED ENV{CI})
|
||||
set (SUBPROJECT_ARGS
|
||||
${SUBPROJECT_ARGS}
|
||||
LOG_DOWNLOAD ON
|
||||
LOG_BUILD ON
|
||||
LOG_INSTALL ON
|
||||
LOG_CONFIGURE ON
|
||||
)
|
||||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.14.0")
|
||||
set (SUBPROJECT_ARGS
|
||||
${SUBPROJECT_ARGS}
|
||||
LOG_OUTPUT_ON_FAILURE ON
|
||||
LOG_MERGED_STDOUTERR ON
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
set (NETGEN_CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} )
|
||||
|
||||
macro(set_vars VAR_OUT)
|
||||
foreach(varname ${ARGN})
|
||||
if(NOT "${${varname}}" STREQUAL "")
|
||||
string(REPLACE ";" "$<SEMICOLON>" varvalue "${${varname}}" )
|
||||
set(${VAR_OUT} ${${VAR_OUT}};-D${varname}=${varvalue} CACHE INTERNAL "")
|
||||
string(REPLACE ";" "|" varvalue "${${varname}}" )
|
||||
set(${VAR_OUT} "${${VAR_OUT}};-D${varname}=${varvalue}" CACHE INTERNAL "")
|
||||
endif()
|
||||
endforeach()
|
||||
endmacro()
|
||||
#######################################################################
|
||||
|
||||
set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_OSX_DEPLOYMENT_TARGET)
|
||||
set_vars(SUBPROJECT_CMAKE_ARGS CMAKE_OSX_SYSROOT)
|
||||
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;-DCMAKE_POLICY_VERSION_MINIMUM=3.5" CACHE INTERNAL "")
|
||||
|
||||
if(USE_CCACHE)
|
||||
find_program(CCACHE_FOUND NAMES ccache ccache.bat)
|
||||
if(CCACHE_FOUND)
|
||||
set(SUBPROJECT_CMAKE_ARGS "${SUBPROJECT_CMAKE_ARGS};-DCMAKE_CXX_COMPILER_LAUNCHER=${CCACHE_FOUND}" CACHE INTERNAL "")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#######################################################################
|
||||
set (DEPS_DOWNLOAD_URL "https://github.com/NGSolve/ngsolve_dependencies/releases/download/v1.0.0" CACHE STRING INTERNAL)
|
||||
set (OCC_DOWNLOAD_URL_WIN "${DEPS_DOWNLOAD_URL}/occ_win64.zip" CACHE STRING INTERNAL)
|
||||
set (OCC_DOWNLOAD_URL_WIN "${DEPS_DOWNLOAD_URL}/occ75_win64.zip" CACHE STRING INTERNAL)
|
||||
set (TCLTK_DOWNLOAD_URL_WIN "${DEPS_DOWNLOAD_URL}/tcltk_win64.zip" CACHE STRING INTERNAL)
|
||||
set (ZLIB_DOWNLOAD_URL_WIN "${DEPS_DOWNLOAD_URL}/zlib_win64.zip" CACHE STRING INTERNAL)
|
||||
set (CGNS_DOWNLOAD_URL_WIN "${DEPS_DOWNLOAD_URL}/cgns_win64.zip" CACHE STRING INTERNAL)
|
||||
set (CGNS_DOWNLOAD_URL_MAC "${DEPS_DOWNLOAD_URL}/cgns_mac.zip" CACHE STRING INTERNAL)
|
||||
|
||||
|
||||
if(UNIX)
|
||||
message("Checking for write permissions in install directory...")
|
||||
execute_process(COMMAND mkdir -p ${CMAKE_INSTALL_PREFIX})
|
||||
@ -31,10 +84,82 @@ if(UNIX)
|
||||
endif()
|
||||
endif(UNIX)
|
||||
|
||||
if(NOT WIN32)
|
||||
find_package(ZLIB REQUIRED)
|
||||
set_vars(NETGEN_CMAKE_ARGS ZLIB_INCLUDE_DIRS ZLIB_LIBRARIES)
|
||||
endif(NOT WIN32)
|
||||
if(USE_OCC)
|
||||
if(BUILD_OCC)
|
||||
set(OCC_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/occ)
|
||||
|
||||
ExternalProject_Add(project_occ
|
||||
# URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_6_3.zip
|
||||
# URL_MD5 2426e373903faabbd4f96a01a934b66d
|
||||
# URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_7_2.zip
|
||||
# URL_MD5 533eb4f18af0f77ae321b158caeaee79
|
||||
URL https://github.com/Open-Cascade-SAS/OCCT/archive/refs/tags/V7_8_1.zip
|
||||
URL_MD5 bf62952a03696dab9e4272aa8efacb1a
|
||||
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies
|
||||
${SUBPROJECT_ARGS}
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX=${OCC_DIR}
|
||||
-DCMAKE_PREFIX_PATH=${OCC_DIR}
|
||||
-DBUILD_LIBRARY_TYPE:STRING=Static
|
||||
-DBUILD_MODULE_FoundationClasses:BOOL=ON
|
||||
-DBUILD_MODULE_ModelingData:BOOL=ON
|
||||
-DBUILD_MODULE_ModelingAlgorithms:BOOL=ON
|
||||
-DBUILD_MODULE_DataExchange:BOOL=ON
|
||||
-DBUILD_MODULE_Visualization:BOOL=OFF
|
||||
-DBUILD_MODULE_ApplicationFramework:BOOL=OFF
|
||||
-DBUILD_MODULE_Draw:BOOL=OFF
|
||||
-DBUILD_MODULE_DETools:BOOL=OFF
|
||||
-DUSE_FREETYPE:BOOL=OFF
|
||||
-DUSE_OPENGL:BOOL=OFF
|
||||
-DUSE_XLIB:BOOL=OFF
|
||||
-DBUILD_DOC_Overview:BOOL=OFF
|
||||
${SUBPROJECT_CMAKE_ARGS}
|
||||
UPDATE_COMMAND ""
|
||||
)
|
||||
|
||||
list(APPEND NETGEN_DEPENDENCIES project_occ)
|
||||
set(OpenCascade_ROOT ${OCC_DIR})
|
||||
else(BUILD_OCC)
|
||||
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)
|
||||
|
||||
if(BUILD_ZLIB)
|
||||
set(ZLIB_ROOT ${CMAKE_CURRENT_BINARY_DIR}/dependencies/zlib)
|
||||
ExternalProject_Add(project_zlib
|
||||
${SUBPROJECT_ARGS}
|
||||
URL https://github.com/madler/zlib/archive/refs/tags/v1.2.11.zip
|
||||
URL_MD5 9d6a627693163bbbf3f26403a3a0b0b1
|
||||
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies
|
||||
CMAKE_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX=${ZLIB_ROOT}
|
||||
${SUBPROJECT_CMAKE_ARGS}
|
||||
UPDATE_COMMAND "" # Disable update
|
||||
BUILD_IN_SOURCE 1
|
||||
)
|
||||
|
||||
list(APPEND NETGEN_DEPENDENCIES project_zlib)
|
||||
if(WIN32)
|
||||
# force linking the static library
|
||||
set(ZLIB_INCLUDE_DIRS ${ZLIB_ROOT}/include)
|
||||
set(ZLIB_LIBRARIES ${ZLIB_ROOT}/lib/zlibstatic.lib)
|
||||
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)
|
||||
endif()
|
||||
|
||||
#######################################################################
|
||||
if (USE_PYTHON)
|
||||
@ -50,14 +175,20 @@ if (USE_PYTHON)
|
||||
else( PYBIND_INCLUDE_DIR )
|
||||
message(FATAL_ERROR "Could NOT find pybind11!")
|
||||
endif( PYBIND_INCLUDE_DIR )
|
||||
find_package(PythonInterp 3 REQUIRED)
|
||||
find_package(PythonLibs 3 REQUIRED)
|
||||
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.18)
|
||||
find_package(Python3 COMPONENTS Interpreter Development.Module)
|
||||
if(NOT EMSCRIPTEN)
|
||||
find_package(Python3 COMPONENTS Interpreter Development.Embed)
|
||||
endif()
|
||||
else()
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
|
||||
endif()
|
||||
|
||||
set_vars(NETGEN_CMAKE_ARGS
|
||||
PYTHON_INCLUDE_DIRS
|
||||
PYTHON_LIBRARIES
|
||||
PYTHON_EXECUTABLE
|
||||
PYTHON_VERSION
|
||||
Python3_INCLUDE_DIRS
|
||||
Python3_LIBRARIES
|
||||
Python3_EXECUTABLE
|
||||
Python3_VERSION
|
||||
PYBIND_INCLUDE_DIR
|
||||
NG_INSTALL_PYBIND
|
||||
)
|
||||
@ -65,23 +196,6 @@ endif (USE_PYTHON)
|
||||
|
||||
#######################################################################
|
||||
|
||||
if(USE_OCC AND WIN32 AND NOT OCC_INCLUDE_DIR)
|
||||
ExternalProject_Add(win_download_occ
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/tcl
|
||||
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}
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
list(APPEND NETGEN_DEPENDENCIES win_download_occ)
|
||||
endif(USE_OCC AND WIN32 AND NOT OCC_INCLUDE_DIR)
|
||||
|
||||
#######################################################################
|
||||
|
||||
include(cmake/external_projects/zlib.cmake)
|
||||
if(USE_GUI)
|
||||
include(cmake/external_projects/tcltk.cmake)
|
||||
endif(USE_GUI)
|
||||
@ -92,7 +206,6 @@ endif(USE_CGNS)
|
||||
|
||||
#######################################################################
|
||||
if(USE_MPI)
|
||||
if(UNIX)
|
||||
if (METIS_DIR)
|
||||
message(STATUS "Using external METIS at: ${METIS_DIR}")
|
||||
else (METIS_DIR)
|
||||
@ -103,27 +216,24 @@ if(USE_MPI)
|
||||
include(cmake/external_projects/metis.cmake)
|
||||
endif(NOT METIS_FOUND)
|
||||
endif(METIS_DIR)
|
||||
else(UNIX)
|
||||
find_package(METIS REQUIRED)
|
||||
endif(UNIX)
|
||||
endif(USE_MPI)
|
||||
|
||||
|
||||
#######################################################################
|
||||
# propagate cmake variables to Netgen subproject
|
||||
set_vars( NETGEN_CMAKE_ARGS
|
||||
CMAKE_CXX_COMPILER
|
||||
CMAKE_BUILD_TYPE
|
||||
CMAKE_MODULE_LINKER_FLAGS
|
||||
CMAKE_MODULE_LINKER_FLAGS_RELEASE
|
||||
CMAKE_SHARED_LINKER_FLAGS
|
||||
CMAKE_SHARED_LINKER_FLAGS_RELEASE
|
||||
CMAKE_CXX_FLAGS
|
||||
CMAKE_CXX_FLAGS_RELEASE
|
||||
CMAKE_OSX_DEPLOYMENT_TARGET
|
||||
CMAKE_OSX_SYSROOT
|
||||
CMAKE_STRIP
|
||||
|
||||
USE_GUI
|
||||
USE_PYTHON
|
||||
USE_MPI
|
||||
USE_MPI_WRAPPER
|
||||
USE_VT
|
||||
USE_VTUNE
|
||||
USE_NUMA
|
||||
@ -136,7 +246,6 @@ set_vars( NETGEN_CMAKE_ARGS
|
||||
USE_INTERNAL_TCL
|
||||
INSTALL_PROFILES
|
||||
INTEL_MIC
|
||||
CMAKE_PREFIX_PATH
|
||||
CMAKE_INSTALL_PREFIX
|
||||
ENABLE_UNIT_TESTS
|
||||
ENABLE_CPP_CORE_GUIDELINES_CHECK
|
||||
@ -147,6 +256,23 @@ set_vars( NETGEN_CMAKE_ARGS
|
||||
BUILD_STUB_FILES
|
||||
BUILD_FOR_CONDA
|
||||
NG_COMPILE_FLAGS
|
||||
OpenCascade_ROOT
|
||||
ZLIB_INCLUDE_DIRS
|
||||
ZLIB_LIBRARIES
|
||||
ZLIB_LIBRARY_RELEASE
|
||||
ZLIB_ROOT
|
||||
|
||||
NGLIB_LIBRARY_TYPE
|
||||
NGCORE_LIBRARY_TYPE
|
||||
NGGUI_LIBRARY_TYPE
|
||||
|
||||
NG_INSTALL_DIR_PYTHON
|
||||
NG_INSTALL_DIR_BIN
|
||||
NG_INSTALL_DIR_LIB
|
||||
NG_INSTALL_DIR_INCLUDE
|
||||
NG_INSTALL_DIR_CMAKE
|
||||
NG_INSTALL_DIR_RES
|
||||
NG_INSTALL_SUFFIX
|
||||
)
|
||||
|
||||
# propagate all variables set on the command line using cmake -DFOO=BAR
|
||||
@ -154,9 +280,10 @@ set_vars( NETGEN_CMAKE_ARGS
|
||||
get_cmake_property(CACHE_VARS CACHE_VARIABLES)
|
||||
foreach(CACHE_VAR ${CACHE_VARS})
|
||||
get_property(CACHE_VAR_HELPSTRING CACHE ${CACHE_VAR} PROPERTY HELPSTRING)
|
||||
if(CACHE_VAR_HELPSTRING STREQUAL "No help, variable specified on the command line.")
|
||||
if(CACHE_VAR_HELPSTRING STREQUAL "No help, variable specified on the command line." AND NOT CACHE_VAR STREQUAL "CMAKE_OSX_ARCHITECTURES")
|
||||
get_property(CACHE_VAR_TYPE CACHE ${CACHE_VAR} PROPERTY TYPE)
|
||||
set(NETGEN_CMAKE_ARGS ${NETGEN_CMAKE_ARGS};-D${CACHE_VAR}:${CACHE_VAR_TYPE}=${${CACHE_VAR}} CACHE INTERNAL "")
|
||||
string(REPLACE ";" "|" varvalue "${${CACHE_VAR}}" )
|
||||
set(NETGEN_CMAKE_ARGS ${NETGEN_CMAKE_ARGS};-D${CACHE_VAR}:${CACHE_VAR_TYPE}=${varvalue} CACHE INTERNAL "")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
@ -166,19 +293,21 @@ else()
|
||||
set(NETGEN_BUILD_COMMAND ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_BINARY_DIR}/netgen --config ${CMAKE_BUILD_TYPE})
|
||||
endif()
|
||||
|
||||
if(DEFINED ENV{CI} AND WIN32)
|
||||
set(log_output LOG_BUILD ON LOG_MERGED_STDOUTERR ON LOG_OUTPUT_ON_FAILURE ON)
|
||||
endif()
|
||||
|
||||
string(REPLACE ";" "|" NETGEN_CMAKE_PREFIX_PATH_ALT_SEP "${NETGEN_CMAKE_PREFIX_PATH}")
|
||||
ExternalProject_Add (netgen
|
||||
${SUBPROJECT_ARGS}
|
||||
DEPENDS ${NETGEN_DEPENDENCIES}
|
||||
SOURCE_DIR ${PROJECT_SOURCE_DIR}
|
||||
CMAKE_ARGS -DUSE_SUPERBUILD=OFF ${NETGEN_CMAKE_ARGS}
|
||||
CMAKE_ARGS
|
||||
-DUSE_SUPERBUILD=OFF
|
||||
${NETGEN_CMAKE_ARGS}
|
||||
${SUBPROJECT_CMAKE_ARGS}
|
||||
-DCMAKE_PREFIX_PATH=${NETGEN_CMAKE_PREFIX_PATH_ALT_SEP}
|
||||
INSTALL_COMMAND ""
|
||||
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/netgen
|
||||
BUILD_COMMAND ${NETGEN_BUILD_COMMAND}
|
||||
STEP_TARGETS build
|
||||
${log_output}
|
||||
)
|
||||
|
||||
# Check if the git submodules (i.e. pybind11) are up to date
|
||||
|
@ -1,105 +0,0 @@
|
||||
# Try to find OCC
|
||||
# Once done this will define
|
||||
#
|
||||
# OCC_FOUND - system has OCC - OpenCASCADE
|
||||
# OCC_INCLUDE_DIR - where the OCC include directory can be found
|
||||
# OCC_LIBRARY_DIR - where the OCC library directory can be found
|
||||
# OCC_LIBRARIES - Link this to use OCC
|
||||
|
||||
if(WIN32)
|
||||
find_path(OCC_INCLUDE_DIR Standard_Version.hxx PATH_SUFFIXES inc ../inc)
|
||||
find_library(OCC_LIBRARY TKernel)
|
||||
else(WIN32)
|
||||
find_path(OCC_INCLUDE_DIR Standard_Version.hxx
|
||||
/usr/include/opencascade
|
||||
/usr/local/include/opencascade
|
||||
/usr/include/oce
|
||||
/usr/local/include/oce
|
||||
/opt/opencascade/include
|
||||
/opt/opencascade/inc
|
||||
)
|
||||
find_library(OCC_LIBRARY TKernel
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
/opt/opencascade/lib
|
||||
)
|
||||
endif(WIN32)
|
||||
|
||||
if(OCC_LIBRARY AND NOT OCC_LIBRARY_DIR)
|
||||
get_filename_component(OCC_LIBRARY_DIR ${OCC_LIBRARY} PATH)
|
||||
endif(OCC_LIBRARY AND NOT OCC_LIBRARY_DIR)
|
||||
|
||||
if(OCC_INCLUDE_DIR)
|
||||
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAJOR
|
||||
REGEX "#define OCC_VERSION_MAJOR.*"
|
||||
)
|
||||
string(REGEX MATCH "[0-9]+" OCC_MAJOR ${OCC_MAJOR})
|
||||
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MINOR
|
||||
REGEX "#define OCC_VERSION_MINOR.*"
|
||||
)
|
||||
string(REGEX MATCH "[0-9]+" OCC_MINOR ${OCC_MINOR})
|
||||
file(STRINGS ${OCC_INCLUDE_DIR}/Standard_Version.hxx OCC_MAINT
|
||||
REGEX "#define OCC_VERSION_MAINTENANCE.*"
|
||||
)
|
||||
string(REGEX MATCH "[0-9]+" OCC_MAINT ${OCC_MAINT})
|
||||
|
||||
set(OCC_VERSION_STRING "${OCC_MAJOR}.${OCC_MINOR}.${OCC_MAINT}")
|
||||
endif(OCC_INCLUDE_DIR)
|
||||
|
||||
|
||||
set(OCC_LIBRARY_NAMES
|
||||
TKBO
|
||||
TKBool
|
||||
TKBRep
|
||||
TKCAF
|
||||
TKCDF
|
||||
TKernel
|
||||
TKG2d
|
||||
TKG3d
|
||||
TKGeomAlgo
|
||||
TKGeomBase
|
||||
TKHLR
|
||||
TKIGES
|
||||
TKLCAF
|
||||
TKMath
|
||||
TKMesh
|
||||
TKOffset
|
||||
TKPrim
|
||||
TKService
|
||||
TKShHealing
|
||||
TKSTEP
|
||||
TKSTEP209
|
||||
TKSTEPAttr
|
||||
TKSTEPBase
|
||||
TKSTL
|
||||
TKTopAlgo
|
||||
TKV3d
|
||||
TKXCAF
|
||||
TKXDEIGES
|
||||
TKXDESTEP
|
||||
TKXSBase
|
||||
)
|
||||
|
||||
if(OCC_LINK_FREETYPE)
|
||||
set(OCC_LIBRARY_NAMES ${OCC_LIBRARY_NAMES} freetype)
|
||||
endif(OCC_LINK_FREETYPE)
|
||||
|
||||
if(OCC_VERSION_STRING VERSION_GREATER_EQUAL "7.3.0")
|
||||
set(OCC_LIBRARY_NAMES ${OCC_LIBRARY_NAMES} TKVCAF)
|
||||
endif()
|
||||
|
||||
foreach( libname ${OCC_LIBRARY_NAMES} )
|
||||
find_library( ${libname} ${libname} ${OCC_LIBRARY_DIR} NO_DEFAULT_PATH)
|
||||
set(OCC_LIBRARIES ${OCC_LIBRARIES} ${${libname}})
|
||||
endforeach()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(OCC REQUIRED_VARS OCC_INCLUDE_DIR VERSION_VAR OCC_VERSION_STRING ${OCC_LIBRARIY_NAMES})
|
||||
|
||||
if(OCC_FOUND)
|
||||
message(STATUS "-- Found OpenCASCADE version: ${OCC_VERSION_STRING}")
|
||||
message(STATUS "-- OpenCASCADE include directory: ${OCC_INCLUDE_DIR}")
|
||||
message(STATUS "-- OpenCASCADE shared libraries directory: ${OCC_LIBRARY_DIR}")
|
||||
message(STATUS "-- OpenCASCADE shared libraries :\n ${OCC_LIBRARIES}")
|
||||
endif(OCC_FOUND)
|
||||
|
@ -4,7 +4,7 @@ ExternalProject_Add(
|
||||
project_catch
|
||||
PREFIX ${CMAKE_BINARY_DIR}/catch
|
||||
GIT_REPOSITORY https://github.com/catchorg/Catch2.git
|
||||
GIT_TAG v2.0.1
|
||||
GIT_TAG v2.13.7
|
||||
TIMEOUT 10
|
||||
UPDATE_COMMAND "" # ${GIT_EXECUTABLE} pull
|
||||
CONFIGURE_COMMAND ""
|
||||
|
@ -3,8 +3,8 @@ set(METIS_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/metis)
|
||||
|
||||
ExternalProject_Add(project_metis
|
||||
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/dependencies
|
||||
URL https://bitbucket.org/petsc/pkg-metis/get/v5.1.0-p6.tar.gz
|
||||
URL_MD5 55fc654bb838846b856ba898795143f1
|
||||
URL https://bitbucket.org/petsc/pkg-metis/get/v5.1.0-p12.tar.gz
|
||||
URL_MD5 6cd66f75f88dfa2cf043de011f85d8bc
|
||||
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies
|
||||
CMAKE_ARGS
|
||||
-DGKLIB_PATH=${METIS_SRC_DIR}/GKlib
|
||||
|
@ -1,3 +1,73 @@
|
||||
if(UNIX AND NOT APPLE)
|
||||
set (LINUX TRUE)
|
||||
endif()
|
||||
if(LINUX)
|
||||
find_package(TclStub 8.5 REQUIRED)
|
||||
else(LINUX)
|
||||
if(SKBUILD)
|
||||
# we are building a pip package - download the tcl/tk sources matching the tkinter version (for private headers not shipped with python)
|
||||
|
||||
execute_process(COMMAND ${Python3_EXECUTABLE} -c
|
||||
"import tkinter;print(tkinter.Tcl().eval('info patchlevel').replace('.','-'))"
|
||||
OUTPUT_VARIABLE PYTHON_TCL_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
set(TCL_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tcl)
|
||||
set(TK_DIR ${CMAKE_CURRENT_BINARY_DIR}/dependencies/src/project_tk)
|
||||
|
||||
ExternalProject_Add(project_tcl
|
||||
URL "https://github.com/tcltk/tcl/archive/refs/tags/core-${PYTHON_TCL_VERSION}.zip"
|
||||
UPDATE_COMMAND ""
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
${SUBPROJECT_ARGS}
|
||||
DOWNLOAD_DIR download_tcl
|
||||
)
|
||||
ExternalProject_Add(project_tk
|
||||
URL "https://github.com/tcltk/tk/archive/refs/tags/core-${PYTHON_TCL_VERSION}.zip"
|
||||
UPDATE_COMMAND ""
|
||||
CONFIGURE_COMMAND ""
|
||||
INSTALL_COMMAND ""
|
||||
BUILD_COMMAND ${CMAKE_COMMAND} -E copy_directory macosx generic
|
||||
${SUBPROJECT_ARGS}
|
||||
DOWNLOAD_DIR download_tk
|
||||
BUILD_IN_SOURCE 1
|
||||
)
|
||||
|
||||
set(TCL_INCLUDE_PATH ${TCL_DIR}/generic)
|
||||
set(TK_INCLUDE_PATH ${TK_DIR}/generic)
|
||||
list(APPEND NETGEN_DEPENDENCIES project_tcl project_tk)
|
||||
|
||||
if(APPLE OR WIN32)
|
||||
execute_process(COMMAND ${Python3_EXECUTABLE} -c "import sys; print(sys.prefix)" OUTPUT_VARIABLE PYTHON_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
file(TO_CMAKE_PATH ${PYTHON_PREFIX} PYTHON_PREFIX)
|
||||
|
||||
set(tcl_find_args
|
||||
REQUIRED
|
||||
NO_DEFAULT_PATH
|
||||
NO_PACKAGE_ROOT_PATH
|
||||
NO_CMAKE_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH
|
||||
NO_CMAKE_FIND_ROOT_PATH
|
||||
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 ${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)
|
||||
endif()
|
||||
|
||||
else(SKBUILD)
|
||||
if(APPLE)
|
||||
set(tcl_prefix ${CMAKE_INSTALL_PREFIX})
|
||||
# URL "http://sourceforge.net/projects/tcl/files/Tcl/8.6.9/tcl8.6.9-src.tar.gz"
|
||||
@ -10,10 +80,7 @@ if(APPLE)
|
||||
CONFIGURE_COMMAND ../project_tcl/macosx/configure --enable-threads --enable-framework --prefix=${tcl_prefix} --libdir=${tcl_prefix}/Contents/Frameworks --bindir=${tcl_prefix}/Contents/Frameworks/Tcl.framework/bin
|
||||
BUILD_COMMAND make -j4 binaries libraries
|
||||
INSTALL_COMMAND make install-binaries install-headers install-libraries install-private-headers
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_BUILD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_INSTALL 1
|
||||
${SUBPROJECT_ARGS}
|
||||
)
|
||||
|
||||
# URL "http://sourceforge.net/projects/tcl/files/Tcl/8.6.9/tk8.6.9.1-src.tar.gz"
|
||||
@ -27,14 +94,11 @@ if(APPLE)
|
||||
CONFIGURE_COMMAND ../project_tk/macosx/configure --enable-aqua=yes --enable-threads --enable-framework --prefix=${tcl_prefix} --libdir=${tcl_prefix}/Contents/Frameworks --bindir=${tcl_prefix}/Contents/Frameworks/Tcl.framework/bin --with-tcl=${tcl_prefix}/Contents/Frameworks/Tcl.framework
|
||||
BUILD_COMMAND make -j4 binaries libraries
|
||||
INSTALL_COMMAND make install-binaries install-headers install-libraries install-private-headers
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_BUILD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_INSTALL 1
|
||||
${SUBPROJECT_ARGS}
|
||||
)
|
||||
|
||||
ExternalProject_Add(project_tkdnd
|
||||
URL "http://sourceforge.net/projects/tkdnd/files/TkDND/TkDND%202.8/tkdnd2.8-src.tar.gz"
|
||||
URL "https://src.fedoraproject.org/repo/pkgs/tkdnd/tkdnd2.8-src.tar.gz/a6d47a996ea957416469b12965d4db91/tkdnd2.8-src.tar.gz"
|
||||
URL_MD5 a6d47a996ea957416469b12965d4db91
|
||||
DEPENDS project_tcl project_tk
|
||||
DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external_dependencies
|
||||
@ -45,10 +109,8 @@ 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
|
||||
LOG_DOWNLOAD 1
|
||||
LOG_CONFIGURE 1
|
||||
LOG_BUILD 1
|
||||
LOG_INSTALL 1
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5
|
||||
${SUBPROJECT_ARGS}
|
||||
)
|
||||
|
||||
list(APPEND NETGEN_DEPENDENCIES project_tcl project_tk project_tkdnd)
|
||||
@ -58,6 +120,9 @@ if(APPLE)
|
||||
set(TK_LIBRARY ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework)
|
||||
set(TK_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/Headers)
|
||||
|
||||
set(TCL_STUB_LIBRARY ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tcl.framework/libtclstub8.6.a)
|
||||
set(TK_STUB_LIBRARY ${CMAKE_INSTALL_PREFIX}/Contents/Frameworks/Tk.framework/libtkstub8.6.a)
|
||||
|
||||
# # use system tcl/tk
|
||||
# if((${PYTHON_VERSION_STRING} VERSION_EQUAL "3.7") OR (${PYTHON_VERSION_STRING} VERSION_GREATER "3.7"))
|
||||
# # fetch tcl/tk sources to match the one used in Python 3.7
|
||||
@ -124,14 +189,19 @@ elseif(WIN32)
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}
|
||||
LOG_DOWNLOAD 1
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory lib ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory bin ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_BIN}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory include ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_INCLUDE}
|
||||
|
||||
${SUBPROJECT_ARGS}
|
||||
)
|
||||
|
||||
set (TK_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/include)
|
||||
set (TCL_INCLUDE_PATH ${CMAKE_INSTALL_PREFIX}/include)
|
||||
set (TCL_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tcl86t.lib)
|
||||
set (TK_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tk86t.lib)
|
||||
set (TCL_STUB_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tclstub86.lib)
|
||||
set (TK_STUB_LIBRARY ${CMAKE_INSTALL_PREFIX}/lib/tkstub86.lib)
|
||||
|
||||
list(APPEND NETGEN_DEPENDENCIES project_win_tcltk)
|
||||
else(WIN32)
|
||||
@ -148,6 +218,8 @@ else(WIN32)
|
||||
# )
|
||||
# list(APPEND NETGEN_DEPENDENCIES project_tkdnd)
|
||||
endif(APPLE)
|
||||
endif(SKBUILD)
|
||||
endif(LINUX)
|
||||
|
||||
# Propagate settings to Netgen subproject
|
||||
set_vars(NETGEN_CMAKE_ARGS TCL_INCLUDE_PATH TCL_LIBRARY TK_LIBRARY TK_INCLUDE_PATH TCL_TCLSH TK_WISH)
|
||||
set_vars(NETGEN_CMAKE_ARGS TCL_INCLUDE_PATH TCL_STUB_LIBRARY TCL_LIBRARY TK_STUB_LIBRARY TK_LIBRARY TK_INCLUDE_PATH TCL_TCLSH TK_WISH)
|
||||
|
@ -6,7 +6,9 @@ if(WIN32)
|
||||
BUILD_IN_SOURCE 1
|
||||
CONFIGURE_COMMAND ""
|
||||
BUILD_COMMAND ""
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory . ${CMAKE_INSTALL_PREFIX}
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory lib ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_LIB}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory bin ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_BIN}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy_directory include ${CMAKE_INSTALL_PREFIX}/${NG_INSTALL_DIR_INCLUDE}
|
||||
LOG_DOWNLOAD 1
|
||||
)
|
||||
|
||||
|
@ -2,8 +2,17 @@ if(NOT BDIR)
|
||||
set(BDIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||
endif()
|
||||
|
||||
find_package(Git REQUIRED)
|
||||
execute_process(COMMAND git describe --tags --match "v[0-9]*" --long --dirty WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR} OUTPUT_VARIABLE git_version_string RESULT_VARIABLE status ERROR_QUIET)
|
||||
if(NETGEN_VERSION_GIT)
|
||||
set(git_version_string ${NETGEN_VERSION_GIT})
|
||||
else()
|
||||
find_package(Git REQUIRED)
|
||||
execute_process(COMMAND git describe --tags --match "v[0-9]*" --long --dirty
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
|
||||
OUTPUT_VARIABLE git_version_string
|
||||
RESULT_VARIABLE status
|
||||
ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||
)
|
||||
endif()
|
||||
|
||||
if(status AND NOT status EQUAL 0)
|
||||
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/../version.txt)
|
||||
@ -15,10 +24,11 @@ if(status AND NOT status EQUAL 0)
|
||||
string(REGEX REPLACE "^netgen(.*)" "\\1" git_version_string "${git_version_string}")
|
||||
endif()
|
||||
else()
|
||||
MESSAGE(WARNING "Could not determine git-version from source code - assuming 6.2.0.0")
|
||||
set(git_version_string "v6.2.0.0")
|
||||
MESSAGE(WARNING "Could not determine git-version from source code - assuming 6.2.0-0")
|
||||
set(git_version_string "v6.2.0-0")
|
||||
endif()
|
||||
endif()
|
||||
string(STRIP ${git_version_string} git_version_string)
|
||||
|
||||
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" NETGEN_VERSION_MAJOR "${git_version_string}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" NETGEN_VERSION_MINOR "${git_version_string}")
|
||||
@ -39,6 +49,15 @@ endif()
|
||||
|
||||
set(NETGEN_VERSION_LONG ${NETGEN_VERSION_SHORT}-${NETGEN_VERSION_TWEAK}-${NETGEN_VERSION_HASH})
|
||||
|
||||
if(NOT NETGEN_VERSION_GIT)
|
||||
set(NETGEN_VERSION_GIT ${NETGEN_VERSION_LONG})
|
||||
endif()
|
||||
|
||||
if(NOT NETGEN_VERSION_PYTHON)
|
||||
set(NETGEN_VERSION_PYTHON ${NETGEN_VERSION_TWEAK})
|
||||
endif()
|
||||
|
||||
|
||||
set(version_file ${BDIR}/netgen_version.hpp)
|
||||
set(new_version_file_string "\
|
||||
#ifndef NETGEN_VERSION_HPP_INCLUDED
|
||||
@ -87,6 +106,7 @@ file(GENERATE OUTPUT netgen_config.hpp CONTENT
|
||||
#define NETGEN_USE_CHECK_RANGE $<BOOL:${CHECK_RANGE}>
|
||||
#define NETGEN_BUILD_STUB_FILES $<BOOL:${BUILD_STUB_FILES}>
|
||||
#define NETGEN_BUILD_FOR_CONDA $<BOOL:${BUILD_FOR_CONDA}>
|
||||
#define NETGEN_SHARED_LIBRARY_SUFFIX \"${CMAKE_SHARED_LIBRARY_SUFFIX}\"
|
||||
|
||||
#endif // NETGEN_CONFIG_HPP_INCLUDED___
|
||||
")
|
||||
|
282
doc/element_types.tex
Normal file
282
doc/element_types.tex
Normal file
@ -0,0 +1,282 @@
|
||||
\documentclass[convert=pdf2svg]{standalone}
|
||||
% \documentclass{article}
|
||||
|
||||
\usepackage[T1]{fontenc}
|
||||
\usepackage{lmodern}
|
||||
\renewcommand{\familydefault}{\sfdefault}
|
||||
\usepackage{tikz}
|
||||
\usepackage{tikz-3dplot}
|
||||
\usetikzlibrary{external}
|
||||
\tikzset{external/force remake}
|
||||
\tikzset{external/disable dependency files}
|
||||
\tikzset{external/aux in dpth={false}}
|
||||
% uncomment this to generate a figure for each cell type (and change documentclass to article)
|
||||
% \tikzexternalize
|
||||
|
||||
\tikzstyle{vertex} = [circle,draw=black,fill=black,scale = 0.5]
|
||||
\tdplotsetmaincoords{70}{110}
|
||||
|
||||
% cnode(tag,x,y,z,label,label_pos)
|
||||
\def\cnode(#1,#2,#3,#4,#5,#6){
|
||||
\node (#1) at (#2,#3,#4) [vertex,label=#6:$\mathsf{#5}$] {};
|
||||
}
|
||||
|
||||
\pagestyle{empty}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{tabular}{cc}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
SEGMENT &
|
||||
SEGMENT3
|
||||
\\
|
||||
\tikzsetnextfilename{line}
|
||||
\begin{tikzpicture}[scale = 2]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,2,below right);
|
||||
\draw (n0) -- (n1);
|
||||
\end{tikzpicture}
|
||||
&
|
||||
\tikzsetnextfilename{line3}
|
||||
\begin{tikzpicture}[scale = 2]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,2,below right);
|
||||
\cnode(n2,1,0,0,3,below right);
|
||||
\draw (n0) -- (n2) -- (n1);
|
||||
\end{tikzpicture}
|
||||
\\[1 em]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
TRIG &
|
||||
TRIG6
|
||||
\\
|
||||
\tikzsetnextfilename{triangle}
|
||||
\begin{tikzpicture}[scale = 2]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,2,below right);
|
||||
\cnode(n2,0,2,0,3,right);
|
||||
\draw (n0) -- (n1) -- (n2) -- (n0);
|
||||
\end{tikzpicture}
|
||||
&
|
||||
\tikzsetnextfilename{triangle6}
|
||||
\begin{tikzpicture}[scale = 2]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,2,below right);
|
||||
\cnode(n2,0,2,0,3,right);
|
||||
\cnode(n3,1,0,0,6,below right);
|
||||
\cnode(n4,1,1,0,4,right);
|
||||
\cnode(n5,0,1,0,5,below right);
|
||||
\draw (n0) -- (n3) -- (n1) -- (n4) -- (n2) -- (n5) -- (n0);
|
||||
\end{tikzpicture}
|
||||
\\[1 em]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
QUAD &
|
||||
QUAD8
|
||||
\\
|
||||
\tikzsetnextfilename{quad}
|
||||
\begin{tikzpicture}[scale = 2]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,2,below right);
|
||||
\cnode(n2,2,2,0,3,below right);
|
||||
\cnode(n3,0,2,0,4,below right);
|
||||
\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0);
|
||||
\end{tikzpicture}
|
||||
&
|
||||
\tikzsetnextfilename{quad8}
|
||||
\begin{tikzpicture}[scale = 2]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,2,below right);
|
||||
\cnode(n2,2,2,0,3,below right);
|
||||
\cnode(n3,0,2,0,4,below right);
|
||||
\cnode(n4,1,0,0,5,below right);
|
||||
\cnode(n5,2,1,0,8,below right);
|
||||
\cnode(n6,1,2,0,6,below right);
|
||||
\cnode(n7,0,1,0,7,below right);
|
||||
\draw (n0) -- (n4) -- (n1) -- (n5) -- (n2) -- (n6) -- (n3) -- (n7) -- (n0);
|
||||
\end{tikzpicture}
|
||||
\\[1 em]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
TET &
|
||||
TET10
|
||||
\\
|
||||
\tikzsetnextfilename{tetra}
|
||||
\begin{tikzpicture}[scale = 2, tdplot_main_coords]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,3,below right);
|
||||
\cnode(n2,0,2,0,2,below right);
|
||||
\cnode(n3,0,0,2,4,right);
|
||||
\draw (n0) -- (n1) -- (n2) -- (n0);
|
||||
\draw (n0) -- (n3);
|
||||
\draw (n1) -- (n3);
|
||||
\draw (n2) -- (n3);
|
||||
\end{tikzpicture}
|
||||
&
|
||||
\tikzsetnextfilename{tetra10} % VTK
|
||||
\begin{tikzpicture}[scale = 2, tdplot_main_coords]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,3,below right);
|
||||
\cnode(n2,0,2,0,2,below right);
|
||||
\cnode(n3,0,0,2,4,right);
|
||||
\cnode(n4,1,0,0,6,below right);
|
||||
\cnode(n5,1,1,0,8,below right);
|
||||
\cnode(n6,0,1,0,5,below right);
|
||||
\cnode(n7,0,0,1,7,below right);
|
||||
\cnode(n8,1,0,1,10,below right);
|
||||
\cnode(n9,0,1,1,9,right);
|
||||
\draw (n0) -- (n4) -- (n1) -- (n5) -- (n2) -- (n6) -- (n0);
|
||||
\draw (n0) -- (n7) -- (n3);
|
||||
\draw (n1) -- (n8) -- (n3);
|
||||
\draw (n2) -- (n9) -- (n3);
|
||||
\end{tikzpicture}
|
||||
\\[1 em]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
PYRAMID &
|
||||
PYRAMID13
|
||||
\\
|
||||
\tikzsetnextfilename{pyramid}
|
||||
\begin{tikzpicture}[scale = 2, tdplot_main_coords]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,4,below right);
|
||||
\cnode(n2,2,2,0,3,below right);
|
||||
\cnode(n3,0,2,0,2,below right);
|
||||
\cnode(n4,1,1,2,5,right);
|
||||
\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0);
|
||||
\draw (n0) -- (n4);
|
||||
\draw (n1) -- (n4);
|
||||
\draw (n2) -- (n4);
|
||||
\draw (n3) -- (n4);
|
||||
\end{tikzpicture}
|
||||
&
|
||||
\tikzsetnextfilename{pyramid13} % VTK != gmsh
|
||||
\begin{tikzpicture}[scale = 2, tdplot_main_coords]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,4,below right);
|
||||
\cnode(n2,2,2,0,3,below right);
|
||||
\cnode(n3,0,2,0,2,below right);
|
||||
\cnode(n4,1,1,2,5,right);
|
||||
\cnode(n5,1,0,0,8,below right);
|
||||
\cnode(n6,2,1,0,7,below right);
|
||||
\cnode(n7,1,2,0,9,below right);
|
||||
\cnode(n8,0,1,0,6,below right);
|
||||
\cnode(n9,0.5,0.5,1,10,below right);
|
||||
\cnode(n10,1.5,0.5,1,13,below right);
|
||||
\cnode(n11,1.5,1.5,1,12,below right);
|
||||
\cnode(n12,0.5,1.5,1,11,right);
|
||||
\draw (n0) -- (n5) -- (n1) -- (n6) -- (n2) -- (n7) -- (n3) -- (n8) -- (n0);
|
||||
\draw (n0) -- (n9) -- (n4);
|
||||
\draw (n1) -- (n10) -- (n4);
|
||||
\draw (n2) -- (n11) -- (n4);
|
||||
\draw (n3) -- (n12) -- (n4);
|
||||
\end{tikzpicture}
|
||||
\\[1 em]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
PRISM &
|
||||
PRISM15
|
||||
\\
|
||||
\tikzsetnextfilename{wedge} % gmsh != VTK
|
||||
\begin{tikzpicture}[scale = 2, tdplot_main_coords]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,3,below right);
|
||||
\cnode(n2,0,2,0,2,below right);
|
||||
\cnode(n3,0,0,2,4,below right);
|
||||
\cnode(n4,2,0,2,6,below right);
|
||||
\cnode(n5,0,2,2,5,below right);
|
||||
\draw (n0) -- (n1) -- (n2) -- (n0);
|
||||
\draw (n3) -- (n4) -- (n5) -- (n3);
|
||||
\draw (n0) -- (n3);
|
||||
\draw (n1) -- (n4);
|
||||
\draw (n2) -- (n5);
|
||||
\end{tikzpicture}
|
||||
&
|
||||
\tikzsetnextfilename{wedge15} % VTK != gmsh
|
||||
\begin{tikzpicture}[scale = 2, tdplot_main_coords]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,3,below right);
|
||||
\cnode(n2,0,2,0,2,below right);
|
||||
\cnode(n3,0,0,2,4,below right);
|
||||
\cnode(n4,2,0,2,6,below right);
|
||||
\cnode(n5,0,2,2,5,below right);
|
||||
\cnode(n6,1,0,0,8,below right);
|
||||
\cnode(n7,1,1,0,9,below right);
|
||||
\cnode(n8,0,1,0,7,below right);
|
||||
\cnode(n9,1,0,2,14,below right);
|
||||
\cnode(n10,1,1,2,15,below right);
|
||||
\cnode(n11,0,1,2,13,below right);
|
||||
\cnode(n12,0,0,1,10,below right);
|
||||
\cnode(n13,2,0,1,12,below right);
|
||||
\cnode(n14,0,2,1,11,below right);
|
||||
\draw (n0) -- (n6) -- (n1) -- (n7) -- (n2) -- (n8) -- (n0);
|
||||
\draw (n3) -- (n9) -- (n4) -- (n10) -- (n5) -- (n11) -- (n3);
|
||||
\draw (n0) -- (n12) -- (n3);
|
||||
\draw (n1) -- (n13) -- (n4);
|
||||
\draw (n2) -- (n14) -- (n5);
|
||||
\end{tikzpicture}
|
||||
\\[1 em]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
HEX &
|
||||
HEX20
|
||||
\\
|
||||
\tikzsetnextfilename{hexahedron}
|
||||
\begin{tikzpicture}[scale = 2, tdplot_main_coords]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,4,below right);
|
||||
\cnode(n2,2,2,0,3,below right);
|
||||
\cnode(n3,0,2,0,2,below right);
|
||||
\cnode(n4,0,0,2,5,below right);
|
||||
\cnode(n5,2,0,2,8,below right);
|
||||
\cnode(n6,2,2,2,7,below right);
|
||||
\cnode(n7,0,2,2,6,below right);
|
||||
\draw (n0) -- (n1) -- (n2) -- (n3) -- (n0);
|
||||
\draw (n4) -- (n5) -- (n6) -- (n7) -- (n4);
|
||||
\draw (n0) -- (n4);
|
||||
\draw (n1) -- (n5);
|
||||
\draw (n2) -- (n6);
|
||||
\draw (n3) -- (n7);
|
||||
\end{tikzpicture}
|
||||
&
|
||||
\tikzsetnextfilename{hexahedron20} % VTK != gmsh
|
||||
\begin{tikzpicture}[scale = 2, tdplot_main_coords]
|
||||
\cnode(n0,0,0,0,1,below right);
|
||||
\cnode(n1,2,0,0,4,below right);
|
||||
\cnode(n2,2,2,0,3,below right);
|
||||
\cnode(n3,0,2,0,2,below right);
|
||||
\cnode(n4,0,0,2,5,below right);
|
||||
\cnode(n5,2,0,2,8,below right);
|
||||
\cnode(n6,2,2,2,7,below right);
|
||||
\cnode(n7,0,2,2,6,below right);
|
||||
\cnode(n8,1,0,0,11,below right);
|
||||
\cnode(n9,2,1,0,10,below right);
|
||||
\cnode(n10,1,2,0,12,below right);
|
||||
\cnode(n11,0,1,0,9,below right);
|
||||
\cnode(n12,1,0,2,15,below right);
|
||||
\cnode(n13,2,1,2,14,below right);
|
||||
\cnode(n14,1,2,2,16,below right);
|
||||
\cnode(n15,0,1,2,13,below right);
|
||||
\cnode(n16,0,0,1,17,below right);
|
||||
\cnode(n17,2,0,1,20,below right);
|
||||
\cnode(n18,2,2,1,19,below right);
|
||||
\cnode(n19,0,2,1,18,below right);
|
||||
\draw (n0) -- (n8) -- (n1) -- (n9) -- (n2) -- (n10) -- (n3) -- (n11) -- (n0);
|
||||
\draw (n4) -- (n12) -- (n5) -- (n13) -- (n6) -- (n14) -- (n7) -- (n15) -- (n4);
|
||||
\draw (n0) -- (n16) -- (n4);
|
||||
\draw (n1) -- (n17) -- (n5);
|
||||
\draw (n2) -- (n18) -- (n6);
|
||||
\draw (n3) -- (n19) -- (n7);
|
||||
\end{tikzpicture}
|
||||
|
||||
|
||||
|
||||
\end{tabular}
|
||||
|
||||
\end{document}
|
14
doc/ng4.tex
14
doc/ng4.tex
@ -176,7 +176,7 @@ Lines starting with $\#$ are comment lines. Every CSG file must contain the
|
||||
keyword {\tt algebraic3d} before any non-comment line.
|
||||
The keyword {\tt solid} defines a named solid, here the solid {\it cube}
|
||||
is defined. A solid is defined by the Eulerian operations applied to
|
||||
primitives. Here, the solid is just the primitve defined by {\tt orthobrick}.
|
||||
primitives. Here, the solid is just the primitive defined by {\tt orthobrick}.
|
||||
This is a brick parallel to the axis, specified by the minimal $x$, $y$, and
|
||||
$z$ coordinates, and the maximal $x$, $y$, and $z$ coordinates. The present
|
||||
definition gives the cube $[0,1]^3$. Finally, the definition {\tt tlo cube}
|
||||
@ -260,7 +260,7 @@ amount of red, green and blue (RGB) values. The flag {\tt
|
||||
-transparent} makes the solid appear transparent.
|
||||
|
||||
|
||||
It is possible to specify bounday condition numbers for individual
|
||||
It is possible to specify boundary condition numbers for individual
|
||||
surfaces of a solid. The flag {\tt -bc} assigns the bc to all
|
||||
surfaces of that solid-tree. If several flags are given the one closest
|
||||
to the leaves of the tree dominates. The following file defines a
|
||||
@ -536,7 +536,7 @@ STL is a standardized file format to describe (approximate) geometies
|
||||
by triangulated surfaces. It is useful to describe complicated parts
|
||||
which are modeled with some CAD programmes. Also, some users have written
|
||||
their own (C) programmes to define STL geometries, where was not so easy
|
||||
to use the CSG format. The syntac of STL files is as follos
|
||||
to use the CSG format. The syntax of STL files is as follows
|
||||
\begin{quote}
|
||||
(not available yet. please figure out the syntax from the examples)
|
||||
\end{quote}
|
||||
@ -593,10 +593,10 @@ Finally, the refinement factor along the line follows.
|
||||
\chapter{Mesh and Solution Formats}
|
||||
|
||||
You can export meshes to a couple of file formats. Some are self-defined,
|
||||
some other are standard formats. The self-defined are the followings:
|
||||
some other are standard formats. The self-defined are the following:
|
||||
|
||||
\section{Mesh Size File}
|
||||
By means of a mesh size file you can provide a local mesh size density. The file extension must be {\it .msz}. If you want to use the mesh size file, you specify it in the ``Meshing Options'', doalog box, page ``Mesh Size''.
|
||||
By means of a mesh size file you can provide a local mesh size density. The file extension must be {\it .msz}. If you want to use the mesh size file, you specify it in the ``Meshing Options'', dialog box, page ``Mesh Size''.
|
||||
|
||||
The syntay is:
|
||||
\begin{verbatim}
|
||||
@ -643,7 +643,7 @@ The Fepp 2D format contains the following sections:
|
||||
|
||||
\begin{enumerate}
|
||||
\item
|
||||
boundary segmetns \\
|
||||
boundary segments \\
|
||||
After the number of boundary segments there follows a list of
|
||||
segments. Each segment is specified by the spline - patch number,
|
||||
and the two node indices. Counting starts with 1
|
||||
@ -749,7 +749,7 @@ the bottom, and the large drawing window. The menu items will be explained in
|
||||
\item Quit \newline
|
||||
Terminate Netgen
|
||||
\item Generate mesh \newline
|
||||
Performe mesh generation
|
||||
Perform mesh generation
|
||||
\item Stop Meshing \newline
|
||||
Stop mesh generation
|
||||
\item Geometry/Edges/Mesh/Solution \newline
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit c16da993094988141101ac4d96a9b2c92f9ac714
|
||||
Subproject commit 38bf7b174875c27c1ba98bdf5a9bf13d967f14d4
|
@ -4,10 +4,21 @@ add_subdirectory(gprim)
|
||||
add_subdirectory(linalg)
|
||||
add_subdirectory(include)
|
||||
add_subdirectory(meshing)
|
||||
add_subdirectory(visualization)
|
||||
add_subdirectory(csg)
|
||||
add_subdirectory(geom2d)
|
||||
add_subdirectory(occ)
|
||||
add_subdirectory(stlgeom)
|
||||
add_subdirectory(interface)
|
||||
|
||||
if(USE_OCC)
|
||||
add_subdirectory(occ)
|
||||
endif(USE_OCC)
|
||||
if(USE_STLGEOM)
|
||||
add_subdirectory(stlgeom)
|
||||
endif(USE_STLGEOM)
|
||||
if(USE_GUI)
|
||||
add_subdirectory(visualization)
|
||||
endif(USE_GUI)
|
||||
if(USE_INTERFACE)
|
||||
add_subdirectory(interface)
|
||||
endif(USE_INTERFACE)
|
||||
if(USE_CSG)
|
||||
add_subdirectory(csg)
|
||||
endif(USE_CSG)
|
||||
if(USE_GEOM2D)
|
||||
add_subdirectory(geom2d)
|
||||
endif(USE_GEOM2D)
|
||||
|
@ -1,4 +1,4 @@
|
||||
Checks: '*,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers'
|
||||
Checks: '*,-cppcoreguidelines-avoid-non-const-global-variables,-llvmlibc-restrict-system-libc-headers,-clang-analyzer-alpha.*,-*braces-around-statements,-fuchsia-*,-google-runtime-references,-readability-implicit-bool-conversion,-google-explicit-constructor,-hicpp-explicit-conversions,-google-runtime-int,-llvm-header-guard,-modernize-pass-by-value,-cppcoreguidelines-non-private-member-variables-in-classes,-misc-non-private-member-variables-in-classes,-readability-magic-numbers,-cppcoreguidelines-avoid-magic-numbers'
|
||||
CheckOptions:
|
||||
- key: cppcoreguidelines-special-member-functions.AllowSoleDefaultDtor
|
||||
value: 1
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
add_library(ngcore SHARED
|
||||
add_library(ngcore ${NGCORE_LIBRARY_TYPE}
|
||||
archive.cpp
|
||||
bitarray.cpp
|
||||
exception.cpp
|
||||
@ -12,52 +12,72 @@ add_library(ngcore SHARED
|
||||
taskmanager.cpp
|
||||
utils.cpp
|
||||
version.cpp
|
||||
ng_mpi_wrapper.cpp
|
||||
)
|
||||
|
||||
target_compile_options(ngcore PUBLIC "${NG_COMPILE_FLAGS}")
|
||||
string(REPLACE "|" ";" ng_compile_flags_replace_sep "${NG_COMPILE_FLAGS}")
|
||||
target_compile_options(ngcore PUBLIC ${ng_compile_flags_replace_sep})
|
||||
|
||||
# Pybind11 2.3 Issue https://github.com/pybind/pybind11/issues/1604
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
target_compile_options(ngcore PUBLIC -fsized-deallocation -faligned-allocation)
|
||||
if(EMSCRIPTEN)
|
||||
set(PYTHON_MODULE_EXTENSION ".so")
|
||||
target_link_options(ngcore PUBLIC -sALLOW_MEMORY_GROWTH -sENVIRONMENT=web)
|
||||
target_compile_options(ngcore PUBLIC -sNO_DISABLE_EXCEPTION_CATCHING)
|
||||
endif()
|
||||
|
||||
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(
|
||||
ret_val can_compile
|
||||
${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/_get_glibcxx_use_cxx11_abi.cpp
|
||||
RUN_OUTPUT_VARIABLE use_glibcxx_cxx11_abi
|
||||
)
|
||||
target_compile_definitions(ngcore PUBLIC -D_GLIBCXX_USE_CXX11_ABI=${use_glibcxx_cxx11_abi})
|
||||
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()
|
||||
message(STATUS "GNU C++ ABI version: ${cxx_abi_version}")
|
||||
target_compile_options(ngcore PUBLIC "-fabi-version=${cxx_abi_version}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(USE_PYTHON)
|
||||
target_sources(ngcore PRIVATE python_ngcore.cpp)
|
||||
target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON NG_PYTHON)
|
||||
target_compile_definitions(ngcore PUBLIC NETGEN_PYTHON NG_PYTHON PYBIND11_SIMPLE_GIL_MANAGEMENT)
|
||||
endif(USE_PYTHON)
|
||||
|
||||
if(WIN32)
|
||||
target_compile_options(ngcore PUBLIC /bigobj /MP /W1 /wd4068)
|
||||
target_compile_options(ngcore PUBLIC /bigobj $<BUILD_INTERFACE:/MP;/W1;/wd4068>)
|
||||
get_WIN32_WINNT(ver)
|
||||
target_compile_definitions(ngcore PUBLIC _WIN32_WINNT=${ver} WNT WNT_WINDOW NOMINMAX MSVC_EXPRESS _CRT_SECURE_NO_WARNINGS HAVE_STRUCT_TIMESPEC)
|
||||
target_compile_definitions(ngcore PUBLIC _WIN32_WINNT=${ver} WNT WNT_WINDOW NOMINMAX MSVC_EXPRESS _CRT_SECURE_NO_WARNINGS HAVE_STRUCT_TIMESPEC WIN32)
|
||||
target_link_options(ngcore PUBLIC /ignore:4273 /ignore:4217 /ignore:4049)
|
||||
else(WIN32)
|
||||
target_compile_options(ngcore PRIVATE -fvisibility=hidden)
|
||||
target_link_libraries(ngcore PUBLIC dl)
|
||||
endif(WIN32)
|
||||
|
||||
target_compile_definitions(ngcore PRIVATE NGCORE_EXPORTS)
|
||||
target_include_directories(ngcore INTERFACE $<INSTALL_INTERFACE:${NG_INSTALL_DIR_INCLUDE}> $<INSTALL_INTERFACE:${NG_INSTALL_DIR_INCLUDE}/include>)
|
||||
|
||||
if(CHECK_RANGE OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
if(CHECK_RANGE)
|
||||
target_compile_definitions(ngcore PUBLIC NETGEN_ENABLE_CHECK_RANGE)
|
||||
endif(CHECK_RANGE OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
endif(CHECK_RANGE)
|
||||
|
||||
if(TRACE_MEMORY OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
target_compile_definitions(ngcore PUBLIC _DEBUG NETGEN_ENABLE_CHECK_RANGE)
|
||||
endif(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
|
||||
if(TRACE_MEMORY)
|
||||
target_compile_definitions(ngcore PUBLIC NETGEN_TRACE_MEMORY)
|
||||
endif(TRACE_MEMORY OR CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "DEBUG")
|
||||
|
||||
|
||||
if(USE_SPDLOG)
|
||||
include_directories(${SPDLOG_INCLUDE_DIR})
|
||||
install(DIRECTORY ${SPDLOG_INCLUDE_DIR}
|
||||
DESTINATION ${NG_INSTALL_DIR_INCLUDE}
|
||||
)
|
||||
add_dependencies(ngcore project_spdlog)
|
||||
target_compile_definitions(ngcore PUBLIC NETGEN_USE_SPDLOG)
|
||||
if(DEBUG_LOG)
|
||||
target_compile_definitions(ngcore PUBLIC NETGEN_LOG_DEBUG)
|
||||
endif(DEBUG_LOG)
|
||||
endif(USE_SPDLOG)
|
||||
endif(TRACE_MEMORY)
|
||||
|
||||
if(USE_NUMA)
|
||||
find_library(NUMA_LIBRARY libnuma.so)
|
||||
@ -67,13 +87,15 @@ endif(USE_NUMA)
|
||||
|
||||
install(TARGETS ngcore DESTINATION ${NG_INSTALL_DIR} COMPONENT netgen)
|
||||
|
||||
target_link_libraries(ngcore PUBLIC netgen_mpi PRIVATE "$<BUILD_INTERFACE:netgen_python>" ${CMAKE_THREAD_LIBS_INIT})
|
||||
target_link_libraries(ngcore PRIVATE "$<BUILD_INTERFACE:netgen_python>" ${CMAKE_THREAD_LIBS_INIT})
|
||||
|
||||
install(FILES ngcore.hpp archive.hpp type_traits.hpp version.hpp ngcore_api.hpp logging.hpp memtracer.hpp
|
||||
exception.hpp symboltable.hpp paje_trace.hpp utils.hpp profiler.hpp mpi_wrapper.hpp
|
||||
array.hpp taskmanager.hpp concurrentqueue.h localheap.hpp python_ngcore.hpp flags.hpp
|
||||
xbool.hpp signal.hpp bitarray.hpp table.hpp hashtable.hpp ranges.hpp
|
||||
xbool.hpp signal.hpp bitarray.hpp table.hpp hashtable.hpp ranges.hpp ngstream.hpp
|
||||
simd.hpp simd_avx.hpp simd_avx512.hpp simd_generic.hpp simd_sse.hpp simd_arm64.hpp
|
||||
register_archive.hpp autodiff.hpp autodiffdiff.hpp
|
||||
ng_mpi.hpp ng_mpi_generated_declarations.hpp mpi4py_pycapi.h ng_mpi_native.hpp
|
||||
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/core COMPONENT netgen_devel)
|
||||
|
||||
if(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
||||
@ -83,9 +105,71 @@ endif(ENABLE_CPP_CORE_GUIDELINES_CHECK)
|
||||
add_dependencies(ngcore ng_generate_version_file)
|
||||
|
||||
if(USE_PYTHON)
|
||||
pybind11_add_module(pyngcore SHARED python_ngcore_export.cpp)
|
||||
target_link_libraries(pyngcore PUBLIC ngcore netgen_python)
|
||||
set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/${NETGEN_PYTHON_RPATH}")
|
||||
install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON} COMPONENT netgen)
|
||||
pybind11_add_module(pyngcore MODULE python_ngcore_export.cpp)
|
||||
target_link_libraries(pyngcore PUBLIC ngcore PRIVATE netgen_python)
|
||||
set_target_properties(pyngcore PROPERTIES INSTALL_RPATH "${NG_RPATH_TOKEN}/../${NETGEN_PYTHON_RPATH}")
|
||||
if(EMSCRIPTEN)
|
||||
target_compile_definitions(pyngcore PRIVATE NGCORE_EXPORTS)
|
||||
endif(EMSCRIPTEN)
|
||||
install(TARGETS pyngcore DESTINATION ${NG_INSTALL_DIR_PYTHON}/pyngcore COMPONENT netgen)
|
||||
endif(USE_PYTHON)
|
||||
|
||||
function (build_mpi_variant)
|
||||
set(target ng_${ARGV0})
|
||||
set(include_dir ${ARGV1})
|
||||
message("1Building MPI variant: ${ARGV0} ${ARGV1}")
|
||||
add_library(${target} SHARED ng_mpi.cpp)
|
||||
target_link_libraries(${target} PUBLIC ngcore PRIVATE netgen_python)
|
||||
target_compile_definitions(${target} PUBLIC PARALLEL NG_MPI_WRAPPER)
|
||||
target_include_directories(${target} PRIVATE ${include_dir})
|
||||
set_target_properties(${target} PROPERTIES PREFIX "")
|
||||
install(TARGETS ${target} RUNTIME DESTINATION ${NG_INSTALL_DIR_BIN} LIBRARY DESTINATION ${NG_INSTALL_DIR_LIB} COMPONENT netgen)
|
||||
endfunction()
|
||||
|
||||
if(USE_MPI)
|
||||
target_compile_definitions(ngcore PUBLIC PARALLEL)
|
||||
|
||||
message(STATUS "Found MPI version\n${MPI_C_LIBRARY_VERSION_STRING}")
|
||||
|
||||
if(USE_MPI_WRAPPER)
|
||||
target_compile_definitions(ngcore PUBLIC NG_MPI_WRAPPER)
|
||||
if(MPI_C_LIBRARY_VERSION_STRING MATCHES "Microsoft MPI.*")
|
||||
set(MICROSOFT_MPI_INCLUDE_DIR ${MPI_C_HEADER_DIR})
|
||||
set(MICROSOFT_MPI_LIBRARY ${MPI_msmpi_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(MPI_C_LIBRARY_VERSION_STRING MATCHES "Open MPI.*")
|
||||
set(OPENMPI_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})
|
||||
endif()
|
||||
|
||||
if(MPI_C_LIBRARY_VERSION_STRING MATCHES "MPICH.*")
|
||||
set(MPICH_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})
|
||||
endif()
|
||||
|
||||
if(MPI_C_LIBRARY_VERSION_STRING MATCHES "Intel.*")
|
||||
set(INTEL_MPI_INCLUDE_DIR ${MPI_C_INCLUDE_PATH})
|
||||
endif()
|
||||
|
||||
if(OPENMPI_INCLUDE_DIR)
|
||||
build_mpi_variant(openmpi ${OPENMPI_INCLUDE_DIR})
|
||||
endif()
|
||||
if(MPICH_INCLUDE_DIR)
|
||||
build_mpi_variant(mpich ${MPICH_INCLUDE_DIR})
|
||||
endif()
|
||||
if(INTEL_MPI_INCLUDE_DIR)
|
||||
build_mpi_variant(intel_mpi ${INTEL_MPI_INCLUDE_DIR})
|
||||
if(WIN32)
|
||||
target_link_libraries(ng_intel_mpi PUBLIC ${INTEL_MPI_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
if(MICROSOFT_MPI_INCLUDE_DIR)
|
||||
build_mpi_variant(microsoft_mpi ${MICROSOFT_MPI_INCLUDE_DIR})
|
||||
target_link_libraries(ng_microsoft_mpi PUBLIC ${MICROSOFT_MPI_LIBRARY})
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(ngcore PUBLIC ${MPI_C_LIBRARIES})
|
||||
target_include_directories(ngcore PUBLIC ${MPI_C_INCLUDE_PATH})
|
||||
endif(USE_MPI_WRAPPER)
|
||||
|
||||
endif(USE_MPI)
|
||||
|
||||
|
13
libsrc/core/_get_glibcxx_use_cxx11_abi.cpp
Normal file
13
libsrc/core/_get_glibcxx_use_cxx11_abi.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
#ifdef _GLIBCXX_USE_CXX11_ABI
|
||||
if(_GLIBCXX_USE_CXX11_ABI)
|
||||
std::cout << 1;
|
||||
else
|
||||
std::cout << 0;
|
||||
#else // _GLIBCXX_USE_CXX11_ABI
|
||||
std::cout << 0;
|
||||
#endif // _GLIBCXX_USE_CXX11_ABI
|
||||
return 0;
|
||||
}
|
7
libsrc/core/_get_gxx_abi.cpp
Normal file
7
libsrc/core/_get_gxx_abi.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
#include <iostream>
|
||||
|
||||
int main() {
|
||||
if (__GXX_ABI_VERSION >= 2000 || __GXX_ABI_VERSION < 1000) return 1;
|
||||
std::cout << (__GXX_ABI_VERSION % 100);
|
||||
return 0;
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
|
||||
#include "archive.hpp"
|
||||
#include "register_archive.hpp"
|
||||
#include "version.hpp"
|
||||
|
||||
#ifndef WIN32
|
||||
@ -9,28 +10,39 @@
|
||||
namespace ngcore
|
||||
{
|
||||
// clang-tidy should ignore this static object
|
||||
static std::unique_ptr<std::map<std::string, detail::ClassArchiveInfo>> type_register; // NOLINT
|
||||
// static std::map<std::string, detail::ClassArchiveInfo> type_register; // NOLINT
|
||||
|
||||
auto& GetTypeRegister()
|
||||
{
|
||||
static std::map<std::string, detail::ClassArchiveInfo> type_register;
|
||||
return type_register;
|
||||
}
|
||||
|
||||
const detail::ClassArchiveInfo& Archive :: GetArchiveRegister(const std::string& classname)
|
||||
{
|
||||
if(type_register == nullptr) type_register =
|
||||
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
|
||||
return (*type_register)[classname];
|
||||
// if(type_register == nullptr) type_register =
|
||||
// std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
|
||||
return GetTypeRegister()[classname];
|
||||
}
|
||||
void Archive :: SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info)
|
||||
{
|
||||
if(type_register == nullptr) type_register =
|
||||
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
|
||||
(*type_register)[classname] = info;
|
||||
}
|
||||
void Archive :: RemoveArchiveRegister(const std::string& classname)
|
||||
{
|
||||
if(IsRegistered(classname))
|
||||
type_register->erase(classname);
|
||||
// if(type_register == nullptr) type_register =
|
||||
// std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
|
||||
GetTypeRegister()[classname] = info;
|
||||
}
|
||||
bool Archive :: IsRegistered(const std::string& classname)
|
||||
{
|
||||
if(type_register == nullptr) type_register =
|
||||
std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
|
||||
return type_register->count(classname) != 0;
|
||||
// if(type_register == nullptr) type_register =
|
||||
// std::make_unique<std::map<std::string, detail::ClassArchiveInfo>>();
|
||||
return GetTypeRegister().count(classname) != 0;
|
||||
}
|
||||
|
||||
#ifdef NETGEN_PYTHON
|
||||
pybind11::object CastAnyToPy(const std::any& a)
|
||||
{
|
||||
auto info = Archive::GetArchiveRegister(Demangle(a.type().name()));
|
||||
return info.anyToPyCaster(a);
|
||||
}
|
||||
#endif // NETGEN_PYTHON
|
||||
|
||||
} // namespace ngcore
|
||||
|
@ -1,22 +1,26 @@
|
||||
#ifndef NETGEN_CORE_ARCHIVE_HPP
|
||||
#define NETGEN_CORE_ARCHIVE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <any>
|
||||
#include <array> // for array
|
||||
#include <complex> // for complex
|
||||
#include <cstring> // for size_t, strlen
|
||||
#include <filesystem> // for path
|
||||
#include <fstream> // for ifstream, ofstream
|
||||
#include <functional> // for function
|
||||
#include <map> // for map
|
||||
#include <memory> // for shared_ptr
|
||||
#include <optional> // for optional
|
||||
#include <string> // for string
|
||||
#include <type_traits> // for declval, enable_if_t, false_type, is_co...
|
||||
#include <cstddef> // for std::byte
|
||||
#include <set> // for set
|
||||
#include <typeinfo> // for type_info
|
||||
#include <utility> // for move, swap, pair
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "exception.hpp" // for UnreachableCodeException, Exception
|
||||
#include "logging.hpp" // for logger
|
||||
#include "ngcore_api.hpp" // for NGCORE_API
|
||||
#include "type_traits.hpp" // for all_of_tmpl
|
||||
#include "utils.hpp" // for Demangle, unlikely
|
||||
@ -31,21 +35,77 @@ namespace pybind11
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
template <typename T>
|
||||
struct Shallow {
|
||||
T val;
|
||||
Shallow() = default;
|
||||
Shallow(T aval) : val(aval) { ; }
|
||||
operator T&() { return val; }
|
||||
};
|
||||
|
||||
// Helper to detect shared_from_this
|
||||
template <typename T>
|
||||
class has_shared_from_this2
|
||||
{
|
||||
private:
|
||||
// typedef T* T_ptr;
|
||||
template <typename C> static std::true_type test(decltype(((C*)nullptr)->shared_from_this()));
|
||||
template <typename C> static std::false_type test(...);
|
||||
|
||||
public:
|
||||
// If the test returns true_type, then T has shared_from_this
|
||||
static constexpr bool value = decltype(test<T>(0))::value;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename T, typename = void>
|
||||
class has_shallow_archive : public std::false_type {};
|
||||
|
||||
template <typename T>
|
||||
class has_shallow_archive<T, std::void_t<decltype(T::shallow_archive)>>
|
||||
: public std::is_same<decltype(T::shallow_archive), std::true_type> {};
|
||||
|
||||
|
||||
|
||||
#ifdef NETGEN_PYTHON
|
||||
pybind11::object CastAnyToPy(const std::any& a);
|
||||
#endif // NETGEN_PYTHON
|
||||
|
||||
class NGCORE_API Archive;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
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::move(tuple))...};
|
||||
}
|
||||
|
||||
template <class T, class Tuple>
|
||||
T* construct_from_tuple(Tuple&& tuple) {
|
||||
return construct_from_tuple<T>(std::forward<Tuple>(tuple),
|
||||
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}
|
||||
);
|
||||
}
|
||||
|
||||
// create new pointer of type T if it is default constructible, else throw
|
||||
template<typename T, typename ...Rest>
|
||||
T* constructIfPossible_impl(Rest... /*unused*/)
|
||||
{ throw Exception(std::string(Demangle(typeid(T).name())) + " is not default constructible!"); }
|
||||
template<typename T, typename... TArgs>
|
||||
T* constructIfPossible(std::tuple<TArgs...> args)
|
||||
{
|
||||
if constexpr(std::is_constructible_v<T, TArgs...>)
|
||||
return construct_from_tuple<T>(args);
|
||||
throw Exception(std::string(Demangle(typeid(T).name())) +
|
||||
" is not constructible!");
|
||||
}
|
||||
|
||||
template<typename T, typename= std::enable_if_t<std::is_constructible<T>::value>>
|
||||
T* constructIfPossible_impl(int /*unused*/) { return new T; } // NOLINT
|
||||
|
||||
template<typename T>
|
||||
T* constructIfPossible() { return constructIfPossible_impl<T>(int{}); }
|
||||
template <typename T> T *constructIfPossible()
|
||||
{
|
||||
if constexpr(std::is_constructible_v<T>)
|
||||
return new T();
|
||||
throw Exception(std::string(Demangle(typeid(T).name())) +
|
||||
" is not default constructible!");
|
||||
}
|
||||
|
||||
//Type trait to check if a class implements a 'void DoArchive(Archive&)' function
|
||||
template<typename T>
|
||||
@ -77,17 +137,54 @@ namespace ngcore
|
||||
NGCORE_API static constexpr bool value = type::value;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct has_GetCArgs
|
||||
{
|
||||
template <typename C> static std::true_type check( decltype( sizeof(&C::GetCArgs )) ) { return std::true_type(); }
|
||||
template <typename> static std::false_type check(...) { return std::false_type(); }
|
||||
typedef decltype( check<T>(sizeof(char)) ) type;
|
||||
static constexpr type value = type();
|
||||
};
|
||||
template<typename T>
|
||||
constexpr bool has_GetCArgs_v = has_GetCArgs<T>::value;
|
||||
|
||||
template<typename T,
|
||||
typename std::enable_if<!has_GetCArgs_v<T>>::type* = nullptr>
|
||||
std::tuple<> GetCArgs(T&val) { return {}; }
|
||||
|
||||
template<typename T,
|
||||
typename std::enable_if<has_GetCArgs_v<T>>::type* = nullptr>
|
||||
auto GetCArgs(T&val) {
|
||||
return val.GetCArgs();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
using TCargs = decltype(GetCArgs<T>(*static_cast<T*>(nullptr)));
|
||||
|
||||
|
||||
struct ClassArchiveInfo
|
||||
{
|
||||
// create new object of this type and return a void* pointer that is points to the location
|
||||
// of the (base)class given by type_info
|
||||
std::function<void*(const std::type_info&)> creator;
|
||||
// std::function<void*(const std::type_info&)> creator;
|
||||
void* (*creator)(const std::type_info&, Archive&);
|
||||
// This caster takes a void* pointer to the type stored in this info and casts it to a
|
||||
// void* pointer pointing to the (base)class type_info
|
||||
std::function<void*(const std::type_info&, void*)> upcaster;
|
||||
// std::function<void*(const std::type_info&, void*)> upcaster;
|
||||
void* (*upcaster) (const std::type_info&, void*);
|
||||
// This caster takes a void* pointer to the (base)class type_info and returns void* pointing
|
||||
// to the type stored in this info
|
||||
std::function<void*(const std::type_info&, void*)> downcaster;
|
||||
// std::function<void*(const std::type_info&, void*)> downcaster;
|
||||
void* (*downcaster)(const std::type_info&, void*);
|
||||
|
||||
// Archive constructor arguments
|
||||
// std::function<void(Archive&, void*)> cargs_archiver;
|
||||
void (*cargs_archiver)(Archive&, void*);
|
||||
|
||||
#ifdef NETGEN_PYTHON
|
||||
// std::function<pybind11::object(const std::any&)> anyToPyCaster;
|
||||
pybind11::object (*anyToPyCaster)(const std::any&);
|
||||
#endif // NETGEN_PYTHON
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
@ -119,8 +216,10 @@ namespace ngcore
|
||||
protected:
|
||||
bool shallow_to_python = false;
|
||||
std::map<std::string, VersionInfo> version_map = GetLibraryVersions();
|
||||
std::shared_ptr<Logger> logger = GetLogger("Archive");
|
||||
public:
|
||||
template<typename T>
|
||||
static constexpr bool is_archivable = detail::is_Archivable_struct<T>::value;
|
||||
|
||||
Archive() = delete;
|
||||
Archive(const Archive&) = delete;
|
||||
Archive(Archive&&) = delete;
|
||||
@ -237,7 +336,6 @@ namespace ngcore
|
||||
// don't use it that often anyway)
|
||||
Archive& operator& (std::vector<bool>& v)
|
||||
{
|
||||
logger->debug("In special archive for std::vector<bool>");
|
||||
size_t size;
|
||||
if(Output())
|
||||
size = v.size();
|
||||
@ -282,6 +380,44 @@ namespace ngcore
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
template<typename T>
|
||||
Archive& operator& (std::optional<T>& opt)
|
||||
{
|
||||
bool has_value = opt.has_value();
|
||||
(*this) & has_value;
|
||||
if(has_value)
|
||||
{
|
||||
if(Output())
|
||||
(*this) << *opt;
|
||||
else
|
||||
{
|
||||
T value;
|
||||
(*this) & value;
|
||||
opt = value;
|
||||
}
|
||||
}
|
||||
return (*this);
|
||||
}
|
||||
template <typename T>
|
||||
Archive& operator&(std::set<T> &s)
|
||||
{
|
||||
auto size = s.size();
|
||||
(*this) & size;
|
||||
if(Output())
|
||||
for(const auto & val : s)
|
||||
(*this) << val;
|
||||
else
|
||||
{
|
||||
for(size_t i=0; i<size; i++)
|
||||
{
|
||||
T val;
|
||||
(*this) & val;
|
||||
s.insert(val);
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Archive arrays =====================================================
|
||||
// this functions can be overloaded in Archive implementations for more efficiency
|
||||
template <typename T, typename = std::enable_if_t<is_archivable<T>>>
|
||||
@ -366,30 +502,36 @@ namespace ngcore
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
Archive& operator & (ngcore::Shallow<T>& shallow)
|
||||
{
|
||||
this->Shallow(shallow.val);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
// Archive shared_ptrs =================================================
|
||||
template <typename T>
|
||||
Archive& operator & (std::shared_ptr<T>& ptr)
|
||||
{
|
||||
if constexpr(has_shallow_archive<T>::value)
|
||||
if (shallow_to_python)
|
||||
{
|
||||
Shallow (ptr);
|
||||
return *this;
|
||||
}
|
||||
|
||||
if(Output())
|
||||
{
|
||||
logger->debug("Store shared ptr of type {}", Demangle(typeid(T).name()));
|
||||
// save -2 for nullptr
|
||||
if(!ptr)
|
||||
{
|
||||
logger->debug("Storing nullptr");
|
||||
return (*this) << -2;
|
||||
}
|
||||
return (*this) << -2;
|
||||
|
||||
void* reg_ptr = ptr.get();
|
||||
bool neededDowncast = false;
|
||||
// Downcasting is only possible for our registered classes
|
||||
if(typeid(T) != typeid(*ptr))
|
||||
{
|
||||
logger->debug("Typids are different: {} vs {}",
|
||||
Demangle(typeid(T).name()),
|
||||
Demangle(typeid(*ptr).name()));
|
||||
if(!IsRegistered(Demangle(typeid(*ptr).name())))
|
||||
throw Exception(std::string("Archive error: Polymorphic type ")
|
||||
+ Demangle(typeid(*ptr).name())
|
||||
@ -397,17 +539,12 @@ namespace ngcore
|
||||
reg_ptr = GetArchiveRegister(Demangle(typeid(*ptr).name())).downcaster(typeid(T), ptr.get());
|
||||
// if there was a true downcast we have to store more information
|
||||
if(reg_ptr != static_cast<void*>(ptr.get()))
|
||||
{
|
||||
logger->debug("Multiple/Virtual inheritance involved, need to cast pointer");
|
||||
neededDowncast = true;
|
||||
}
|
||||
neededDowncast = true;
|
||||
}
|
||||
auto pos = shared_ptr2nr.find(reg_ptr);
|
||||
// if not found store -1 and the pointer
|
||||
if(pos == shared_ptr2nr.end())
|
||||
{
|
||||
logger->debug("Didn't find the shared_ptr, create new registry entry at {}",
|
||||
shared_ptr_count);
|
||||
auto p = ptr.get();
|
||||
(*this) << -1;
|
||||
(*this) & neededDowncast & p;
|
||||
@ -418,27 +555,23 @@ namespace ngcore
|
||||
return *this;
|
||||
}
|
||||
// if found store the position and if it has to be downcasted and how
|
||||
logger->debug("Found shared_ptr at position {}", pos->second);
|
||||
(*this) << pos->second << neededDowncast;
|
||||
if(neededDowncast)
|
||||
(*this) << Demangle(typeid(*ptr).name());
|
||||
}
|
||||
else // Input
|
||||
{
|
||||
logger->debug("Reading shared_ptr of type {}", Demangle(typeid(T).name()));
|
||||
int nr;
|
||||
(*this) & nr;
|
||||
// -2 restores a nullptr
|
||||
if(nr == -2)
|
||||
{
|
||||
logger->debug("Reading a nullptr");
|
||||
ptr = nullptr;
|
||||
return *this;
|
||||
}
|
||||
// -1 restores a new shared ptr by restoring the inner pointer and creating a shared_ptr to it
|
||||
if (nr == -1)
|
||||
{
|
||||
logger->debug("Createing new shared_ptr");
|
||||
T* p = nullptr;
|
||||
bool neededDowncast;
|
||||
(*this) & neededDowncast & p;
|
||||
@ -446,7 +579,6 @@ namespace ngcore
|
||||
// if we did downcast we need to store a shared_ptr<void> to the true object
|
||||
if(neededDowncast)
|
||||
{
|
||||
logger->debug("Shared pointer needed downcasting");
|
||||
std::string name;
|
||||
(*this) & name;
|
||||
auto info = GetArchiveRegister(name);
|
||||
@ -457,20 +589,15 @@ namespace ngcore
|
||||
ptr.get())));
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->debug("Shared pointer didn't need downcasting");
|
||||
nr2shared_ptr.push_back(ptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->debug("Reading already existing pointer at entry {}", nr);
|
||||
auto other = nr2shared_ptr[nr];
|
||||
bool neededDowncast;
|
||||
(*this) & neededDowncast;
|
||||
if(neededDowncast)
|
||||
{
|
||||
logger->debug("Shared pointer needed pointer downcast");
|
||||
// if there was a downcast we can expect the class to be registered (since archiving
|
||||
// wouldn't have worked else)
|
||||
std::string name;
|
||||
@ -484,7 +611,6 @@ namespace ngcore
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->debug("Shared pointer didn't need pointer casts");
|
||||
ptr = std::static_pointer_cast<T>(other);
|
||||
}
|
||||
}
|
||||
@ -498,45 +624,39 @@ namespace ngcore
|
||||
{
|
||||
if (Output())
|
||||
{
|
||||
logger->debug("Store pointer of type {}",Demangle(typeid(T).name()));
|
||||
// if the pointer is null store -2
|
||||
if (!p)
|
||||
{
|
||||
logger->debug("Storing nullptr");
|
||||
return (*this) << -2;
|
||||
}
|
||||
auto reg_ptr = static_cast<void*>(p);
|
||||
if(typeid(T) != typeid(*p))
|
||||
{
|
||||
logger->debug("Typeids are different: {} vs {}",
|
||||
Demangle(typeid(T).name()),
|
||||
Demangle(typeid(*p).name()));
|
||||
if(!IsRegistered(Demangle(typeid(*p).name())))
|
||||
throw Exception(std::string("Archive error: Polymorphic type ")
|
||||
+ Demangle(typeid(*p).name())
|
||||
+ " not registered for archive");
|
||||
reg_ptr = GetArchiveRegister(Demangle(typeid(*p).name())).downcaster(typeid(T), static_cast<void*>(p));
|
||||
if(reg_ptr != static_cast<void*>(p))
|
||||
{
|
||||
logger->debug("Multiple/Virtual inheritance involved, need to cast pointer");
|
||||
}
|
||||
}
|
||||
auto pos = ptr2nr.find(reg_ptr);
|
||||
// if the pointer is not found in the map create a new entry
|
||||
if (pos == ptr2nr.end())
|
||||
{
|
||||
logger->debug("Didn't find pointer, create new registry entry at {}",
|
||||
ptr_count);
|
||||
ptr2nr[reg_ptr] = ptr_count++;
|
||||
if(typeid(*p) == typeid(T))
|
||||
if (std::is_constructible<T>::value)
|
||||
{
|
||||
logger->debug("Store standard class pointer (no virt. inh,...)");
|
||||
return (*this) << -1 & (*p);
|
||||
}
|
||||
return (*this) << -1 & (*p);
|
||||
else
|
||||
throw Exception(std::string("Archive error: Class ") +
|
||||
Demangle(typeid(*p).name()) + " does not provide a default constructor!");
|
||||
{
|
||||
if (IsRegistered(Demangle(typeid(*p).name())))
|
||||
{
|
||||
(*this) << -3 << Demangle(typeid(*p).name());
|
||||
GetArchiveRegister(Demangle(typeid(*p).name())).
|
||||
cargs_archiver(*this, p);
|
||||
return (*this) & (*p);
|
||||
}
|
||||
else
|
||||
throw Exception(std::string("Archive error: Class ") +
|
||||
Demangle(typeid(*p).name()) + " does not provide a default constructor!");
|
||||
}
|
||||
else
|
||||
{
|
||||
// if a pointer to a base class is archived, the class hierarchy must be registered
|
||||
@ -547,49 +667,41 @@ namespace ngcore
|
||||
throw Exception(std::string("Archive error: Polymorphic type ")
|
||||
+ Demangle(typeid(*p).name())
|
||||
+ " not registered for archive");
|
||||
logger->debug("Store a possibly more complicated pointer");
|
||||
return (*this) << -3 << Demangle(typeid(*p).name()) & (*p);
|
||||
(*this) << -3 << Demangle(typeid(*p).name());
|
||||
GetArchiveRegister(Demangle(typeid(*p).name())).
|
||||
cargs_archiver(*this, p);
|
||||
return (*this) & (*p);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
(*this) & pos->second;
|
||||
bool downcasted = !(reg_ptr == static_cast<void*>(p) );
|
||||
logger->debug("Store a the existing position in registry at {}", pos->second);
|
||||
logger->debug("Pointer {} downcasting", downcasted ? "needs" : "doesn't need");
|
||||
// store if the class has been downcasted and the name
|
||||
(*this) << downcasted << Demangle(typeid(*p).name());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->debug("Reading pointer of type {}", Demangle(typeid(T).name()));
|
||||
int nr;
|
||||
(*this) & nr;
|
||||
if (nr == -2) // restore a nullptr
|
||||
{
|
||||
logger->debug("Loading a nullptr");
|
||||
p = nullptr;
|
||||
}
|
||||
else if (nr == -1) // create a new pointer of standard type (no virtual or multiple inheritance,...)
|
||||
{
|
||||
logger->debug("Load a new pointer to a simple class");
|
||||
p = detail::constructIfPossible<T>();
|
||||
nr2ptr.push_back(p);
|
||||
(*this) & *p;
|
||||
}
|
||||
else if(nr == -3) // restore one of our registered classes that can have multiple inheritance,...
|
||||
{
|
||||
logger->debug("Load a new pointer to a potentially more complicated class "
|
||||
"(allows for multiple/virtual inheritance,...)");
|
||||
// As stated above, we want this special behaviour only for our classes that implement DoArchive
|
||||
std::string name;
|
||||
(*this) & name;
|
||||
logger->debug("Name = {}", name);
|
||||
auto info = GetArchiveRegister(name);
|
||||
// the creator creates a new object of type name, and returns a void* pointing
|
||||
// to T (which may have an offset)
|
||||
p = static_cast<T*>(info.creator(typeid(T)));
|
||||
p = static_cast<T*>(info.creator(typeid(T), *this));
|
||||
// we store the downcasted pointer (to be able to find it again from
|
||||
// another class in a multiple inheritance tree)
|
||||
nr2ptr.push_back(info.downcaster(typeid(T),p));
|
||||
@ -597,11 +709,9 @@ namespace ngcore
|
||||
}
|
||||
else
|
||||
{
|
||||
logger->debug("Restoring pointer to already existing object at registry position {}", nr);
|
||||
bool downcasted;
|
||||
std::string name;
|
||||
(*this) & downcasted & name;
|
||||
logger->debug("{} object of type {}", downcasted ? "Downcasted" : "Not downcasted", name);
|
||||
if(downcasted)
|
||||
{
|
||||
// if the class has been downcasted we can assume it is in the register
|
||||
@ -615,6 +725,16 @@ namespace ngcore
|
||||
return *this;
|
||||
}
|
||||
|
||||
Archive& operator&(std::tuple<>&) { return *this; }
|
||||
|
||||
template <typename... T>
|
||||
Archive& operator&(std::tuple<T...> &t)
|
||||
{
|
||||
// call operator& for each element of the tuple
|
||||
std::apply([this](auto&... arg) { std::make_tuple(((*this) & arg).IsParallel()...);}, t);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// const ptr
|
||||
template<typename T>
|
||||
Archive& operator &(const T*& t)
|
||||
@ -638,15 +758,18 @@ namespace ngcore
|
||||
void SetParallel (bool _parallel) { parallel = _parallel; }
|
||||
|
||||
private:
|
||||
template<typename T, typename ... Bases>
|
||||
template<typename T, typename Bases>
|
||||
friend class RegisterClassForArchive;
|
||||
|
||||
#ifdef NETGEN_PYTHON
|
||||
friend pybind11::object CastAnyToPy(const std::any&);
|
||||
#endif // NETGEN_PYTHON
|
||||
|
||||
// Returns ClassArchiveInfo of Demangled typeid
|
||||
static const detail::ClassArchiveInfo& GetArchiveRegister(const std::string& classname);
|
||||
// Set ClassArchiveInfo for Demangled typeid, this is done by creating an instance of
|
||||
// RegisterClassForArchive<type, bases...>
|
||||
static void SetArchiveRegister(const std::string& classname, const detail::ClassArchiveInfo& info);
|
||||
static void RemoveArchiveRegister(const std::string& classname);
|
||||
static bool IsRegistered(const std::string& classname);
|
||||
|
||||
// Helper class for up-/downcasting
|
||||
@ -654,7 +777,7 @@ namespace ngcore
|
||||
struct Caster{};
|
||||
|
||||
template<typename T>
|
||||
struct Caster<T>
|
||||
struct Caster<T, std::tuple<>>
|
||||
{
|
||||
static void* tryUpcast (const std::type_info& /*unused*/, T* /*unused*/)
|
||||
{
|
||||
@ -666,8 +789,37 @@ namespace ngcore
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename B1>
|
||||
struct Caster<T,B1>
|
||||
{
|
||||
static void* tryUpcast(const std::type_info& ti, T* p)
|
||||
{
|
||||
try {
|
||||
return GetArchiveRegister(Demangle(typeid(B1).name()))
|
||||
.upcaster(ti, static_cast<void *>(dynamic_cast<B1 *>(p)));
|
||||
} catch (const Exception &) {
|
||||
throw Exception("Upcast not successful, some classes are not "
|
||||
"registered properly for archiving!");
|
||||
}
|
||||
}
|
||||
|
||||
static void* tryDowncast(const std::type_info& ti, void* p)
|
||||
{
|
||||
if(typeid(B1) == ti)
|
||||
return dynamic_cast<T*>(static_cast<B1*>(p));
|
||||
try
|
||||
{
|
||||
return dynamic_cast<T*>(static_cast<B1*>(GetArchiveRegister(Demangle(typeid(B1).name())).
|
||||
downcaster(ti, p)));
|
||||
} catch (const Exception &) {
|
||||
throw Exception("Downcast not successful, some classes are not "
|
||||
"registered properly for archiving!");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename B1, typename ... Brest>
|
||||
struct Caster<T,B1,Brest...>
|
||||
struct Caster<T,std::tuple<B1, Brest...>>
|
||||
{
|
||||
static void* tryUpcast(const std::type_info& ti, T* p)
|
||||
{
|
||||
@ -675,7 +827,7 @@ namespace ngcore
|
||||
{ return GetArchiveRegister(Demangle(typeid(B1).name())).
|
||||
upcaster(ti, static_cast<void*>(dynamic_cast<B1*>(p))); }
|
||||
catch(const Exception&)
|
||||
{ return Caster<T, Brest...>::tryUpcast(ti, p); }
|
||||
{ return Caster<T, std::tuple<Brest...>>::tryUpcast(ti, p); }
|
||||
}
|
||||
|
||||
static void* tryDowncast(const std::type_info& ti, void* p)
|
||||
@ -689,38 +841,12 @@ namespace ngcore
|
||||
}
|
||||
catch(const Exception&)
|
||||
{
|
||||
return Caster<T, Brest...>::tryDowncast(ti, p);
|
||||
return Caster<T, std::tuple<Brest...>>::tryDowncast(ti, p);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename T, typename ... Bases>
|
||||
class RegisterClassForArchive
|
||||
{
|
||||
public:
|
||||
RegisterClassForArchive()
|
||||
{
|
||||
static_assert(detail::all_of_tmpl<std::is_base_of<Bases,T>::value...>,
|
||||
"Variadic template arguments must be base classes of T");
|
||||
detail::ClassArchiveInfo info {};
|
||||
info.creator = [](const std::type_info& ti) -> void*
|
||||
{ return typeid(T) == ti ? detail::constructIfPossible<T>()
|
||||
: Archive::Caster<T, Bases...>::tryUpcast(ti, detail::constructIfPossible<T>()); };
|
||||
info.upcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
|
||||
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryUpcast(ti, static_cast<T*>(p)); };
|
||||
info.downcaster = [/*this*/](const std::type_info& ti, void* p) -> void*
|
||||
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases...>::tryDowncast(ti, p); };
|
||||
Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info);
|
||||
}
|
||||
~RegisterClassForArchive()
|
||||
{
|
||||
Archive::RemoveArchiveRegister(std::string(Demangle(typeid(T).name())));
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
// BinaryOutArchive ======================================================================
|
||||
class NGCORE_API BinaryOutArchive : public Archive
|
||||
{
|
||||
@ -736,7 +862,7 @@ namespace ngcore
|
||||
BinaryOutArchive(std::shared_ptr<std::ostream>&& astream)
|
||||
: Archive(true), stream(std::move(astream))
|
||||
{ }
|
||||
BinaryOutArchive(const std::string& filename)
|
||||
BinaryOutArchive(const std::filesystem::path& filename)
|
||||
: BinaryOutArchive(std::make_shared<std::ofstream>(filename)) {}
|
||||
~BinaryOutArchive () override { FlushBuffer(); }
|
||||
|
||||
@ -757,11 +883,19 @@ namespace ngcore
|
||||
Archive & operator & (long & i) override
|
||||
{
|
||||
// for platform independence
|
||||
int64_t tmp = i;
|
||||
return Write(tmp);
|
||||
if constexpr (sizeof(long) == 8)
|
||||
return Write(i);
|
||||
else
|
||||
return Write(static_cast<int64_t>(i));
|
||||
}
|
||||
Archive & operator & (size_t & i) override
|
||||
{ return Write(i); }
|
||||
{
|
||||
// for platform independence
|
||||
if constexpr (sizeof(size_t) == 8)
|
||||
return Write(i);
|
||||
else
|
||||
return Write(static_cast<uint64_t>(i));
|
||||
}
|
||||
Archive & operator & (unsigned char & i) override
|
||||
{ return Write(i); }
|
||||
Archive & operator & (bool & b) override
|
||||
@ -824,7 +958,7 @@ namespace ngcore
|
||||
BinaryInArchive (std::shared_ptr<std::istream>&& astream)
|
||||
: Archive(false), stream(std::move(astream))
|
||||
{ }
|
||||
BinaryInArchive (const std::string& filename)
|
||||
BinaryInArchive (const std::filesystem::path& filename)
|
||||
: BinaryInArchive(std::make_shared<std::ifstream>(filename)) { ; }
|
||||
|
||||
using Archive::operator&;
|
||||
@ -840,13 +974,30 @@ namespace ngcore
|
||||
{ Read(i); return *this; }
|
||||
Archive & operator & (long & i) override
|
||||
{
|
||||
int64_t tmp;
|
||||
Read(tmp);
|
||||
i = tmp;
|
||||
// for platform independence
|
||||
if constexpr (sizeof(long) == 8)
|
||||
Read(i);
|
||||
else
|
||||
{
|
||||
int64_t tmp = 0;
|
||||
Read(tmp);
|
||||
i = tmp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Archive & operator & (size_t & i) override
|
||||
{ Read(i); return *this; }
|
||||
{
|
||||
// for platform independence
|
||||
if constexpr (sizeof(long) == 8)
|
||||
Read(i);
|
||||
else
|
||||
{
|
||||
uint64_t tmp = 0;
|
||||
Read(tmp);
|
||||
i = tmp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
Archive & operator & (unsigned char & i) override
|
||||
{ Read(i); return *this; }
|
||||
Archive & operator & (bool & b) override
|
||||
@ -882,7 +1033,15 @@ namespace ngcore
|
||||
Archive & Do (int * i, size_t n) override
|
||||
{ stream->read(reinterpret_cast<char*>(i), n*sizeof(int)); return *this; } // NOLINT
|
||||
Archive & Do (size_t * i, size_t n) override
|
||||
{ stream->read(reinterpret_cast<char*>(i), n*sizeof(size_t)); return *this; } // NOLINT
|
||||
{
|
||||
// for platform independence
|
||||
if constexpr (sizeof(long) == 8)
|
||||
stream->read(reinterpret_cast<char*>(i), n*sizeof(size_t)); // NOLINT
|
||||
else
|
||||
for(size_t j = 0; j < n; j++)
|
||||
(*this) & i[j];
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T>
|
||||
@ -899,12 +1058,12 @@ namespace ngcore
|
||||
TextOutArchive (std::shared_ptr<std::ostream>&& astream)
|
||||
: Archive(true), stream(std::move(astream))
|
||||
{ }
|
||||
TextOutArchive (const std::string& filename) :
|
||||
TextOutArchive (const std::filesystem::path& filename) :
|
||||
TextOutArchive(std::make_shared<std::ofstream>(filename)) { }
|
||||
|
||||
using Archive::operator&;
|
||||
Archive & operator & (std::byte & d) override
|
||||
{ *stream << std::hex << int(d) << ' '; return *this; }
|
||||
{ *stream << int(d) << ' '; return *this; }
|
||||
Archive & operator & (float & f) override
|
||||
{ *stream << f << '\n'; return *this; }
|
||||
Archive & operator & (double & d) override
|
||||
@ -954,12 +1113,12 @@ namespace ngcore
|
||||
TextInArchive (std::shared_ptr<std::istream>&& astream) :
|
||||
Archive(false), stream(std::move(astream))
|
||||
{ }
|
||||
TextInArchive (const std::string& filename)
|
||||
TextInArchive (const std::filesystem::path& filename)
|
||||
: TextInArchive(std::make_shared<std::ifstream>(filename)) {}
|
||||
|
||||
using Archive::operator&;
|
||||
Archive & operator & (std::byte & d) override
|
||||
{ int tmp; *stream >> std::hex >> tmp; d = std::byte(tmp); return *this; }
|
||||
{ int tmp; *stream >> tmp; d = std::byte(tmp); return *this; }
|
||||
Archive & operator & (float & f) override
|
||||
{ *stream >> f; return *this; }
|
||||
Archive & operator & (double & d) override
|
||||
@ -978,13 +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
|
||||
@ -1001,6 +1179,8 @@ namespace ngcore
|
||||
if(len)
|
||||
{
|
||||
stream->get(ch); // \n
|
||||
if(ch == '\r') // windows line endings, read \n as well
|
||||
stream->get(ch);
|
||||
stream->get(&str[0], len+1, '\0'); // NOLINT
|
||||
}
|
||||
str[len] = '\0'; // NOLINT
|
||||
|
@ -7,9 +7,13 @@
|
||||
/* Date: 01. Jun. 95 */
|
||||
/**************************************************************************/
|
||||
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
#include "archive.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "logging.hpp" // for logger
|
||||
#include "ngcore_api.hpp" // for NGCORE_API
|
||||
#include "type_traits.hpp" // for all_of_tmpl
|
||||
#include "localheap.hpp"
|
||||
#include "memtracer.hpp"
|
||||
#include "utils.hpp"
|
||||
@ -212,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
|
||||
{
|
||||
@ -274,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()) { ; }
|
||||
@ -290,9 +299,9 @@ namespace ngcore
|
||||
NETGEN_INLINE ArrayRangeIterator<T> begin() const { return first; }
|
||||
NETGEN_INLINE ArrayRangeIterator<T> end() const { return next; }
|
||||
|
||||
T_Range Split (size_t nr, int tot) const
|
||||
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);
|
||||
}
|
||||
@ -500,7 +509,8 @@ namespace ngcore
|
||||
return *this;
|
||||
}
|
||||
|
||||
NETGEN_INLINE const FlatArray & operator= (const std::function<T(int)> & func) const
|
||||
template <typename T2, std::enable_if_t<std::is_function<T2>::value>>
|
||||
NETGEN_INLINE const FlatArray & operator= (const T2 & func) const
|
||||
{
|
||||
for (size_t i = 0; i < size; i++)
|
||||
data[i] = func(i+BASE);
|
||||
@ -549,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
|
||||
{
|
||||
@ -615,15 +632,15 @@ namespace ngcore
|
||||
|
||||
//auto begin() const { return ArrayIterator<T,IndexType> (*this, BASE); }
|
||||
// auto end() const { return ArrayIterator<T,IndexType> (*this, size+BASE); }
|
||||
auto begin() const { return data; }
|
||||
auto end() const { return data+Size(); }
|
||||
NETGEN_INLINE auto begin() const { return data; }
|
||||
NETGEN_INLINE auto end() const { return data+Size(); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
FlatArray<T> View (FlatArray<T> fa) { return fa; }
|
||||
|
||||
template <typename T, typename TI>
|
||||
auto Max (FlatArray<T,TI> array, T max = std::numeric_limits<T>::min()) -> T
|
||||
auto Max (FlatArray<T,TI> array, typename std::remove_const<T>::type max = std::numeric_limits<T>::min()) -> T
|
||||
{
|
||||
for (auto & v : array)
|
||||
if (v > max) max = v;
|
||||
@ -631,7 +648,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
template <typename T, typename TI>
|
||||
auto Min (FlatArray<T,TI> array, T min = std::numeric_limits<T>::max()) -> T
|
||||
auto Min (FlatArray<T,TI> array, typename std::remove_const<T>::type min = std::numeric_limits<T>::max()) -> T
|
||||
{
|
||||
for (auto & v : array)
|
||||
if (v < min) min = v;
|
||||
@ -658,7 +675,13 @@ namespace ngcore
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template <class T1, class T2>
|
||||
inline bool operator!= (const FlatArray<T1> & a1,
|
||||
const FlatArray<T2> & a2)
|
||||
{
|
||||
return !(a1==a2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Dynamic array container.
|
||||
@ -676,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;
|
||||
@ -697,6 +721,7 @@ namespace ngcore
|
||||
{
|
||||
allocsize = asize;
|
||||
mem_to_delete = data;
|
||||
mt.Alloc(sizeof(T)*asize);
|
||||
}
|
||||
|
||||
|
||||
@ -706,7 +731,10 @@ namespace ngcore
|
||||
{
|
||||
allocsize = asize;
|
||||
if(ownMemory)
|
||||
{
|
||||
mem_to_delete = adata;
|
||||
mt.Alloc(sizeof(T)*asize);
|
||||
}
|
||||
else
|
||||
mem_to_delete = nullptr;
|
||||
}
|
||||
@ -722,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;
|
||||
@ -742,11 +769,16 @@ 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];
|
||||
}
|
||||
|
||||
// #ifdef __cpp_exceptions
|
||||
#ifndef __CUDA_ARCH__
|
||||
else
|
||||
throw Exception(std::string("cannot copy-construct Array of type ") + typeid(T).name());
|
||||
throw Exception(std::string("cannot copy-construct Array of type ") + typeid(T).name());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -757,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];
|
||||
@ -773,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;
|
||||
@ -785,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++)
|
||||
@ -800,8 +835,9 @@ namespace ngcore
|
||||
}
|
||||
|
||||
// Only provide this function if T is archivable
|
||||
template<typename T2=T>
|
||||
auto DoArchive(Archive& archive) -> typename std::enable_if_t<is_archivable<T2>, void>
|
||||
template<typename ARCHIVE>
|
||||
auto DoArchive(ARCHIVE& archive)
|
||||
-> typename std::enable_if_t<ARCHIVE::template is_archivable<T>, void>
|
||||
{
|
||||
if(archive.Output())
|
||||
archive << size;
|
||||
@ -818,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.
|
||||
@ -931,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]);
|
||||
@ -940,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--;
|
||||
}
|
||||
@ -985,16 +1024,17 @@ namespace ngcore
|
||||
data[i] = a2.data[i];
|
||||
return *this;
|
||||
}
|
||||
#ifndef __CUDA_ARCH__
|
||||
else
|
||||
throw Exception(std::string("cannot copy Array of type ") + typeid(T).name());
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// 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);
|
||||
@ -1068,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);
|
||||
@ -1078,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; }
|
||||
@ -1087,7 +1127,6 @@ namespace ngcore
|
||||
|
||||
/// resize array, at least to size minsize. copy contents
|
||||
NETGEN_INLINE void ReSize (size_t minsize);
|
||||
MemoryTracer mt;
|
||||
};
|
||||
|
||||
|
||||
@ -1140,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:
|
||||
@ -1153,6 +1193,7 @@ namespace ngcore
|
||||
data = new T[asize];
|
||||
allocsize = size;
|
||||
mem_to_delete = data;
|
||||
mt.Alloc(sizeof(T)*asize);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1173,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;
|
||||
@ -1215,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);
|
||||
@ -1347,6 +1390,12 @@ namespace ngcore
|
||||
return array;
|
||||
}
|
||||
|
||||
template <typename T, typename T2>
|
||||
inline Array<T> operator+= (Array<T> && array, const BaseArrayObject<T2> & a2)
|
||||
{
|
||||
array += a2;
|
||||
return std::move(array);
|
||||
}
|
||||
|
||||
|
||||
/// bubble sort array
|
||||
@ -1504,6 +1553,8 @@ namespace ngcore
|
||||
}
|
||||
|
||||
|
||||
struct HTAHelp { };
|
||||
|
||||
// head-tail array
|
||||
template <size_t S, typename T>
|
||||
class HTArray
|
||||
@ -1511,8 +1562,23 @@ 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>
|
||||
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;
|
||||
|
||||
T * Ptr () { return tail.Ptr(); }
|
||||
@ -1522,6 +1588,9 @@ namespace ngcore
|
||||
const T & operator[] (size_t i) const { return Ptr()[i]; }
|
||||
template <int NR>
|
||||
T & Elem() { return (NR==S-1) ? head : tail.template Elem<NR>(); }
|
||||
|
||||
auto Tail() const { return tail; }
|
||||
auto Head() const { return head; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -1529,8 +1598,16 @@ namespace ngcore
|
||||
{
|
||||
T head;
|
||||
public:
|
||||
HTArray () = default;
|
||||
HTArray (const HTArray &) = default;
|
||||
constexpr HTArray () = default;
|
||||
constexpr HTArray (const HTArray &) = default;
|
||||
template <typename T2>
|
||||
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;
|
||||
|
||||
T * Ptr () { return &head; }
|
||||
@ -1544,6 +1621,8 @@ namespace ngcore
|
||||
// assert(NR==0, "HTArray index error");
|
||||
return head;
|
||||
}
|
||||
|
||||
auto Head() const { return head; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
@ -1553,6 +1632,9 @@ namespace ngcore
|
||||
public:
|
||||
HTArray () = default;
|
||||
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;
|
||||
|
||||
/*
|
||||
@ -1592,6 +1674,64 @@ namespace ngcore
|
||||
{
|
||||
return ar.Ptr()+i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <typename TIA, typename TIB>
|
||||
class IteratorPair
|
||||
{
|
||||
TIA a;
|
||||
TIB b;
|
||||
public:
|
||||
IteratorPair (TIA _a, TIB _b) : a(_a), b(_b) { ; }
|
||||
|
||||
IteratorPair & operator++() { ++a; ++b; return *this; }
|
||||
bool operator!= (const IteratorPair & it2) { return a != it2.a; }
|
||||
|
||||
auto operator*()
|
||||
{
|
||||
// return pair(*a,*b);
|
||||
return std::pair<decltype(*a), decltype(*b)> (*a, *b); // keep reference
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template <typename TA, typename TB>
|
||||
class Zip
|
||||
{
|
||||
const TA & a;
|
||||
const TB & b;
|
||||
public:
|
||||
Zip(const TA & _a, const TB & _b) : a(_a), b(_b) { ; }
|
||||
auto begin() const { return IteratorPair(a.begin(), b.begin()); }
|
||||
auto end() const { return IteratorPair(a.end(), b.end()); }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline size_t size (const BaseArrayObject<T> & ao) { return ao.Size(); }
|
||||
|
||||
template <typename TA>
|
||||
class Enumerate
|
||||
{
|
||||
IntRange r;
|
||||
const TA & a;
|
||||
public:
|
||||
Enumerate(const TA & _a) : r(size(_a)), a(_a) { ; }
|
||||
auto begin() const { return IteratorPair(r.begin(), a.begin()); }
|
||||
auto end() const { return IteratorPair(r.end(), a.end()); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
1131
libsrc/core/autodiff.hpp
Normal file
1131
libsrc/core/autodiff.hpp
Normal file
File diff suppressed because it is too large
Load Diff
733
libsrc/core/autodiffdiff.hpp
Normal file
733
libsrc/core/autodiffdiff.hpp
Normal file
@ -0,0 +1,733 @@
|
||||
#ifndef FILE_AUTODIFFDIFF
|
||||
#define FILE_AUTODIFFDIFF
|
||||
|
||||
/**************************************************************************/
|
||||
/* File: autodiffdiff.hpp */
|
||||
/* Author: Joachim Schoeberl */
|
||||
/* Date: 13. June. 05 */
|
||||
/**************************************************************************/
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
using ngcore::IfPos;
|
||||
|
||||
// Automatic second differentiation datatype
|
||||
|
||||
|
||||
/**
|
||||
Datatype for automatic differentiation. Contains function value,
|
||||
D first derivatives, and D*D second derivatives. Algebraic operations are
|
||||
overloaded by using product-rule etc. etc.
|
||||
**/
|
||||
template <int D, typename SCAL = double>
|
||||
class AutoDiffDiff
|
||||
{
|
||||
SCAL val;
|
||||
SCAL dval[D?D:1];
|
||||
SCAL ddval[D?D*D:1];
|
||||
public:
|
||||
|
||||
typedef AutoDiffDiff<D, SCAL> TELEM;
|
||||
|
||||
|
||||
/// elements are undefined
|
||||
AutoDiffDiff () throw() { ; }
|
||||
|
||||
/// copy constructor
|
||||
AutoDiffDiff (const AutoDiffDiff & ad2) throw()
|
||||
{
|
||||
val = ad2.val;
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] = ad2.dval[i];
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] = ad2.ddval[i];
|
||||
}
|
||||
|
||||
/// initial object with constant value
|
||||
AutoDiffDiff (SCAL aval) throw()
|
||||
{
|
||||
val = aval;
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] = 0;
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] = 0;
|
||||
}
|
||||
|
||||
/// initial object with value and derivative
|
||||
AutoDiffDiff (const AutoDiff<D, SCAL> & ad2) throw()
|
||||
{
|
||||
val = ad2.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] = ad2.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] = 0;
|
||||
}
|
||||
|
||||
/// init object with (val, e_diffindex)
|
||||
AutoDiffDiff (SCAL aval, int diffindex) throw()
|
||||
{
|
||||
val = aval;
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] = 0;
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] = 0;
|
||||
dval[diffindex] = 1;
|
||||
}
|
||||
|
||||
NETGEN_INLINE AutoDiffDiff (SCAL aval, const SCAL * grad)
|
||||
{
|
||||
val = aval;
|
||||
LoadGradient (grad);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] = 0;
|
||||
}
|
||||
|
||||
NETGEN_INLINE AutoDiffDiff (SCAL aval, const SCAL * grad, const SCAL * hesse)
|
||||
{
|
||||
val = aval;
|
||||
LoadGradient (grad);
|
||||
LoadHessian (hesse);
|
||||
}
|
||||
|
||||
/// assign constant value
|
||||
AutoDiffDiff & operator= (SCAL aval) throw()
|
||||
{
|
||||
val = aval;
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] = 0;
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
NETGEN_INLINE void StoreGradient (SCAL * p) const
|
||||
{
|
||||
for (int i = 0; i < D; i++)
|
||||
p[i] = dval[i];
|
||||
}
|
||||
|
||||
NETGEN_INLINE void LoadGradient (const SCAL * p)
|
||||
{
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] = p[i];
|
||||
}
|
||||
|
||||
NETGEN_INLINE void StoreHessian (SCAL * p) const
|
||||
{
|
||||
for (int i = 0; i < D*D; i++)
|
||||
p[i] = ddval[i];
|
||||
}
|
||||
|
||||
NETGEN_INLINE void LoadHessian (const SCAL * p)
|
||||
{
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] = p[i];
|
||||
}
|
||||
|
||||
/// returns value
|
||||
SCAL Value() const throw() { return val; }
|
||||
|
||||
/// returns partial derivative
|
||||
SCAL DValue (int i) const throw() { return dval[i]; }
|
||||
|
||||
AutoDiff<D,SCAL> DValueAD (int i) const
|
||||
{
|
||||
AutoDiff<D,SCAL> r(dval[i]);
|
||||
for (int j = 0; j < D; j++)
|
||||
r.DValue(j) = ddval[i*D+j];
|
||||
return r;
|
||||
}
|
||||
|
||||
/// returns partial derivative
|
||||
SCAL DDValue (int i) const throw() { return ddval[i]; }
|
||||
|
||||
/// returns partial derivative
|
||||
SCAL DDValue (int i, int j) const throw() { return ddval[i*D+j]; }
|
||||
|
||||
/// access value
|
||||
SCAL & Value() throw() { return val; }
|
||||
|
||||
/// accesses partial derivative
|
||||
SCAL & DValue (int i) throw() { return dval[i]; }
|
||||
|
||||
/// accesses partial derivative
|
||||
SCAL & DDValue (int i) throw() { return ddval[i]; }
|
||||
|
||||
/// accesses partial derivative
|
||||
SCAL & DDValue (int i, int j) throw() { return ddval[i*D+j]; }
|
||||
|
||||
explicit operator AutoDiff<D,SCAL> () const
|
||||
{ return AutoDiff<D,SCAL> (val, &dval[0]); }
|
||||
|
||||
/// add autodiffdiff object
|
||||
AutoDiffDiff<D, SCAL> & operator+= (const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
val += y.val;
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] += y.dval[i];
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] += y.ddval[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// subtract autodiffdiff object
|
||||
AutoDiffDiff<D, SCAL> & operator-= (const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
val -= y.val;
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] -= y.dval[i];
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] -= y.ddval[i];
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// multiply with autodiffdiff object
|
||||
AutoDiffDiff<D, SCAL> & operator*= (const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ddval[i] = val * y.ddval[i] + y.val * ddval[i];
|
||||
|
||||
for (int i = 0; i < D; i++)
|
||||
for (int j = 0; j < D; j++)
|
||||
ddval[i*D+j] += dval[i] * y.dval[j] + dval[j] * y.dval[i];
|
||||
|
||||
for (int i = 0; i < D; i++)
|
||||
{
|
||||
dval[i] *= y.val;
|
||||
dval[i] += val * y.dval[i];
|
||||
}
|
||||
val *= y.val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// multiply with scalar
|
||||
AutoDiffDiff<D, SCAL> & operator*= (const SCAL & y) throw()
|
||||
{
|
||||
for ( int i = 0; i < D*D; i++ )
|
||||
ddval[i] *= y;
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] *= y;
|
||||
val *= y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// divide by scalar
|
||||
AutoDiffDiff<D, SCAL> & operator/= (const SCAL & y) throw()
|
||||
{
|
||||
SCAL iy = 1.0 / y;
|
||||
for ( int i = 0; i < D*D; i++ )
|
||||
ddval[i] *= iy;
|
||||
for (int i = 0; i < D; i++)
|
||||
dval[i] *= iy;
|
||||
val *= iy;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// same value
|
||||
bool operator== (SCAL val2) throw()
|
||||
{
|
||||
return val == val2;
|
||||
}
|
||||
|
||||
/// different values
|
||||
bool operator!= (SCAL val2) throw()
|
||||
{
|
||||
return val != val2;
|
||||
}
|
||||
|
||||
/// less
|
||||
bool operator< (SCAL val2) throw()
|
||||
{
|
||||
return val < val2;
|
||||
}
|
||||
|
||||
/// greater
|
||||
bool operator> (SCAL val2) throw()
|
||||
{
|
||||
return val > val2;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//@{ AutoDiff helper functions.
|
||||
|
||||
/// Prints AudoDiffDiff
|
||||
template<int D, typename SCAL>
|
||||
inline ostream & operator<< (ostream & ost, const AutoDiffDiff<D, SCAL> & x)
|
||||
{
|
||||
ost << x.Value() << ", D = ";
|
||||
for (int i = 0; i < D; i++)
|
||||
ost << x.DValue(i) << " ";
|
||||
ost << ", DD = ";
|
||||
for (int i = 0; i < D*D; i++)
|
||||
ost << x.DDValue(i) << " ";
|
||||
return ost;
|
||||
}
|
||||
|
||||
///
|
||||
template<int D, typename SCAL>
|
||||
inline AutoDiffDiff<D, SCAL> operator+ (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value () = x.Value()+y.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = x.DValue(i) + y.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = x.DDValue(i) + y.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
template<int D, typename SCAL>
|
||||
inline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = x.Value()-y.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = x.DValue(i) - y.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = x.DDValue(i) - y.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
template<int D, typename SCAL, typename SCAL2,
|
||||
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
|
||||
inline AutoDiffDiff<D, SCAL> operator+ (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = x+y.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = y.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = y.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
///
|
||||
template<int D, typename SCAL, typename SCAL2,
|
||||
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
|
||||
inline AutoDiffDiff<D, SCAL> operator+ (const AutoDiffDiff<D, SCAL> & y, SCAL2 x) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = x+y.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = y.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = y.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
template<int D, typename SCAL>
|
||||
inline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = -x.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = -x.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = -x.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
///
|
||||
template<int D, typename SCAL, typename SCAL2,
|
||||
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
|
||||
inline AutoDiffDiff<D, SCAL> operator- (const AutoDiffDiff<D, SCAL> & x, SCAL2 y) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = x.Value()-y;
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = x.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = x.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
///
|
||||
template<int D, typename SCAL, typename SCAL2,
|
||||
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
|
||||
inline AutoDiffDiff<D, SCAL> operator- (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = x-y.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = -y.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = -y.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
template<int D, typename SCAL, typename SCAL2,
|
||||
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
|
||||
inline AutoDiffDiff<D, SCAL> operator* (SCAL2 x, const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = x*y.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = x*y.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = x*y.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
///
|
||||
template<int D, typename SCAL, typename SCAL2,
|
||||
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
|
||||
inline AutoDiffDiff<D, SCAL> operator* (const AutoDiffDiff<D, SCAL> & y, SCAL2 x) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = x*y.Value();
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = x*y.DValue(i);
|
||||
for (int i = 0; i < D*D; i++)
|
||||
res.DDValue(i) = x*y.DDValue(i);
|
||||
return res;
|
||||
}
|
||||
|
||||
///
|
||||
template<int D, typename SCAL>
|
||||
inline AutoDiffDiff<D, SCAL> operator* (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y) throw()
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
SCAL hx = x.Value();
|
||||
SCAL hy = y.Value();
|
||||
|
||||
res.Value() = hx*hy;
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = hx*y.DValue(i) + hy*x.DValue(i);
|
||||
|
||||
for (int i = 0; i < D; i++)
|
||||
for (int j = 0; j < D; j++)
|
||||
res.DDValue(i,j) = hx * y.DDValue(i,j) + hy * x.DDValue(i,j)
|
||||
+ x.DValue(i) * y.DValue(j) + x.DValue(j) * y.DValue(i);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<int D, typename SCAL>
|
||||
inline AutoDiffDiff<D, SCAL> Inv (const AutoDiffDiff<D, SCAL> & x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res(1.0 / x.Value());
|
||||
for (int i = 0; i < D; i++)
|
||||
res.DValue(i) = -x.DValue(i) / (x.Value() * x.Value());
|
||||
|
||||
SCAL fac1 = 2/(x.Value()*x.Value()*x.Value());
|
||||
SCAL fac2 = 1/sqr(x.Value());
|
||||
for (int i = 0; i < D; i++)
|
||||
for (int j = 0; j < D; j++)
|
||||
res.DDValue(i,j) = fac1*x.DValue(i)*x.DValue(j) - fac2*x.DDValue(i,j);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
template<int D, typename SCAL>
|
||||
inline AutoDiffDiff<D, SCAL> operator/ (const AutoDiffDiff<D, SCAL> & x, const AutoDiffDiff<D, SCAL> & y)
|
||||
{
|
||||
return x * Inv (y);
|
||||
}
|
||||
|
||||
template<int D, typename SCAL, typename SCAL2,
|
||||
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
|
||||
inline AutoDiffDiff<D, SCAL> operator/ (const AutoDiffDiff<D, SCAL> & x, SCAL2 y)
|
||||
{
|
||||
return (1/y) * x;
|
||||
}
|
||||
|
||||
template<int D, typename SCAL, typename SCAL2,
|
||||
typename std::enable_if<std::is_convertible<SCAL2,SCAL>::value, int>::type = 0>
|
||||
inline AutoDiffDiff<D, SCAL> operator/ (SCAL2 x, const AutoDiffDiff<D, SCAL> & y)
|
||||
{
|
||||
return x * Inv(y);
|
||||
}
|
||||
|
||||
|
||||
template<int D, typename SCAL>
|
||||
inline AutoDiffDiff<D, SCAL> sqrt (const AutoDiffDiff<D, SCAL> & x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = sqrt(x.Value());
|
||||
for (int j = 0; j < D; j++)
|
||||
res.DValue(j) = IfZero(x.DValue(j),SCAL{0.},0.5 / res.Value() * x.DValue(j));
|
||||
|
||||
|
||||
for (int i = 0; i < D; i++)
|
||||
for (int j = 0; j < D; j++)
|
||||
res.DDValue(i,j) = IfZero(x.DDValue(i,j)+x.DValue(i) * x.DValue(j),SCAL{0.},0.5/res.Value() * x.DDValue(i,j) - 0.25 / (x.Value()*res.Value()) * x.DValue(i) * x.DValue(j));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// df(u)/dx = exp(x) * du/dx
|
||||
// d^2 f(u) / dx^2 = exp(x) * (du/dx)^2 + exp(x) * d^2u /dx^2
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> exp (AutoDiffDiff<D, SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = exp(x.Value());
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = x.DValue(k) * res.Value();
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = (x.DValue(k) * x.DValue(l)+x.DDValue(k,l)) * res.Value();
|
||||
return res;
|
||||
}
|
||||
|
||||
using std::pow;
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D,SCAL> pow (AutoDiffDiff<D,SCAL> x, AutoDiffDiff<D,SCAL> y )
|
||||
{
|
||||
return exp(log(x)*y);
|
||||
}
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> log (AutoDiffDiff<D, SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
res.Value() = log(x.Value());
|
||||
SCAL xinv = 1.0/x.Value();
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = x.DValue(k) * xinv;
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = -xinv*xinv*x.DValue(k) * x.DValue(l) + xinv * x.DDValue(k,l);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> sin (AutoDiffDiff<D, SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
SCAL s = sin(x.Value());
|
||||
SCAL c = cos(x.Value());
|
||||
|
||||
res.Value() = s;
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = x.DValue(k) * c;
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = -s * x.DValue(k) * x.DValue(l) + c * x.DDValue(k,l);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> cos (AutoDiffDiff<D, SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
SCAL s = sin(x.Value());
|
||||
SCAL c = cos(x.Value());
|
||||
|
||||
res.Value() = c;
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = -s * x.DValue(k);
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = -c * x.DValue(k) * x.DValue(l) - s * x.DDValue(k,l);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> tan (AutoDiffDiff<D, SCAL> x)
|
||||
{ return sin(x) / cos(x); }
|
||||
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> atan (AutoDiffDiff<D, SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
SCAL a = atan(x.Value());
|
||||
res.Value() = a;
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = x.DValue(k)/(1+x.Value()*x.Value()) ;
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = -2*x.Value()/((1+x.Value()*x.Value())*(1+x.Value()*x.Value())) * x.DValue(k) * x.DValue(l) + x.DDValue(k,l)/(1+x.Value()*x.Value());
|
||||
return res;
|
||||
}
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> atan2 (AutoDiffDiff<D, SCAL> x,AutoDiffDiff<D, SCAL> y)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
SCAL a = atan2(x.Value(), y.Value());
|
||||
res.Value() = a;
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = (x.Value()*y.DValue(k)-y.Value()*x.DValue(k))/(y.Value()*y.Value()+x.Value()*x.Value());
|
||||
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = (x.DValue(k)*y.DValue(l)+x.Value()*y.DDValue(l,k) - y.DValue(k)*x.DValue(l) - y.Value()*x.DDValue(l,k))/(y.Value()*y.Value()+x.Value()*x.Value()) - 2 * (x.Value()*y.DValue(k)-y.Value()*x.DValue(k)) * (x.Value()*x.DValue(k) + y.Value()*y.DValue(k))/( (y.Value()*y.Value()+x.Value()*x.Value()) * (y.Value()*y.Value()+x.Value()*x.Value()) );
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
using std::acos;
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D,SCAL> acos (AutoDiffDiff<D,SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D,SCAL> res;
|
||||
SCAL a = acos(x.Value());
|
||||
res.Value() = a;
|
||||
auto omaa = 1-x.Value()*x.Value();
|
||||
auto s = sqrt(omaa);
|
||||
SCAL da = -1 / s;
|
||||
SCAL dda = -x.Value() / (s*omaa);
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = x.DValue(k)*da;
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = dda * x.DValue(k) * x.DValue(l) + da * x.DDValue(k,l);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
using std::acos;
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D,SCAL> asin (AutoDiffDiff<D,SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D,SCAL> res;
|
||||
SCAL a = asin(x.Value());
|
||||
res.Value() = a;
|
||||
auto omaa = 1-x.Value()*x.Value();
|
||||
auto s = sqrt(omaa);
|
||||
SCAL da = 1 / s;
|
||||
SCAL dda = x.Value() / (s*omaa);
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = x.DValue(k)*da;
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = dda * x.DValue(k) * x.DValue(l) + da * x.DDValue(k,l);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> sinh (AutoDiffDiff<D, SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
SCAL sh = sinh(x.Value());
|
||||
SCAL ch = cosh(x.Value());
|
||||
|
||||
res.Value() = sh;
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = x.DValue(k) * ch;
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = sh * x.DValue(k) * x.DValue(l) + ch * x.DDValue(k,l);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> cosh (AutoDiffDiff<D, SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
SCAL sh = sinh(x.Value());
|
||||
SCAL ch = cosh(x.Value());
|
||||
|
||||
res.Value() = ch;
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = sh * x.DValue(k);
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = ch * x.DValue(k) * x.DValue(l) + sh * x.DDValue(k,l);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D, SCAL> erf (AutoDiffDiff<D, SCAL> x)
|
||||
{
|
||||
AutoDiffDiff<D, SCAL> res;
|
||||
SCAL derf = 2. / sqrt(M_PI) * exp(- x.Value() * x.Value());
|
||||
|
||||
res.Value() = erf(x.Value());
|
||||
for (int k = 0; k < D; k++)
|
||||
res.DValue(k) = - derf * x.DValue(k);
|
||||
for (int k = 0; k < D; k++)
|
||||
for (int l = 0; l < D; l++)
|
||||
res.DDValue(k,l) = derf * (x.DDValue(k, l) - 2 * x.Value() * x.DValue(k) * x.DValue(l));
|
||||
return res;
|
||||
}
|
||||
|
||||
using std::floor;
|
||||
template<int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D,SCAL> floor (const AutoDiffDiff<D,SCAL> & x)
|
||||
{
|
||||
return floor(x.Value());
|
||||
}
|
||||
|
||||
using std::ceil;
|
||||
template<int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D,SCAL> ceil (const AutoDiffDiff<D,SCAL> & x)
|
||||
{
|
||||
return ceil(x.Value());
|
||||
}
|
||||
|
||||
|
||||
template <int D, typename SCAL, typename TB, typename TC>
|
||||
auto IfPos (AutoDiffDiff<D,SCAL> a, TB b, TC c) -> decltype(IfPos (a.Value(), b, c))
|
||||
{
|
||||
return IfPos (a.Value(), b, c);
|
||||
}
|
||||
|
||||
template <int D, typename SCAL>
|
||||
NETGEN_INLINE AutoDiffDiff<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffDiff<D,SCAL> b, AutoDiffDiff<D,SCAL> c)
|
||||
{
|
||||
AutoDiffDiff<D,SCAL> res;
|
||||
res.Value() = IfPos (a, b.Value(), c.Value());
|
||||
for (int j = 0; j < D; j++)
|
||||
{
|
||||
res.DValue(j) = IfPos (a, b.DValue(j), c.DValue(j));
|
||||
res.DDValue(j) = IfPos (a, b.DDValue(j), c.DDValue(j));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
template <int D, typename SCAL, typename TC>
|
||||
NETGEN_INLINE AutoDiffDiff<D,SCAL> IfPos (SCAL /* SIMD<double> */ a, AutoDiffDiff<D,SCAL> b, TC c)
|
||||
{
|
||||
return IfPos (a, b, AutoDiffDiff<D,SCAL> (c));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//@}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace ngbla
|
||||
{
|
||||
template <typename T> struct is_scalar_type;
|
||||
template <int D, typename T>
|
||||
struct is_scalar_type<ngcore::AutoDiffDiff<D,T>> { static constexpr bool value = true; };
|
||||
|
||||
|
||||
// not meaningful for AutoDiff<D,Complex>, since this is
|
||||
// not (complex) differentiable anyway
|
||||
template<int D, typename SCAL>
|
||||
inline auto L2Norm2 (const ngcore::AutoDiffDiff<D,SCAL> & x)
|
||||
{
|
||||
return x*x;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
@ -9,6 +9,7 @@
|
||||
*/
|
||||
|
||||
#include "bitarray.hpp"
|
||||
#include "archive.hpp"
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
@ -39,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()
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <cstring>
|
||||
#include <ostream>
|
||||
|
||||
#include "archive.hpp"
|
||||
#include "array.hpp"
|
||||
#include "localheap.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
@ -50,6 +49,7 @@ public:
|
||||
{
|
||||
ba2.owns_data = false;
|
||||
ba2.data = nullptr;
|
||||
mt = std::move(ba2.mt);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -60,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
|
||||
@ -147,15 +151,15 @@ public:
|
||||
|
||||
NGCORE_API size_t NumSet () const;
|
||||
|
||||
NGCORE_API void DoArchive(Archive& archive);
|
||||
NGCORE_API void DoArchive(class Archive& archive);
|
||||
|
||||
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:
|
||||
@ -206,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
|
||||
|
@ -1,15 +1,69 @@
|
||||
#include "exception.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#ifdef EMSCRIPTEN
|
||||
#include <iostream>
|
||||
#endif // EMSCRIPTEN
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
Exception :: Exception(const std::string& s)
|
||||
: m_what(s) {}
|
||||
: m_what(s) {
|
||||
#ifdef EMSCRIPTEN
|
||||
std::cout << "THROW Exception " << s << std::endl;
|
||||
#endif
|
||||
}
|
||||
|
||||
Exception :: Exception(const char* s)
|
||||
: m_what(s) {}
|
||||
: m_what(s) {
|
||||
#ifdef EMSCRIPTEN
|
||||
std::cout << "THROW Exception " << s << std::endl;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
@ -19,11 +73,18 @@ 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
|
||||
|
||||
|
||||
// ********* STUFF FOR GETBACKTRACE ***************************
|
||||
#ifdef __GNUC__
|
||||
#if defined __GNUC__ && !defined __EMSCRIPTEN__
|
||||
|
||||
#include <execinfo.h>
|
||||
#include <string.h>
|
||||
@ -67,7 +128,7 @@ namespace ngcore
|
||||
// 1 libngcore.dylib 0x000000010ddb298c _ZL21ngcore_signal_handleri + 316
|
||||
constexpr char reset_shell[] = "\033[0m";
|
||||
constexpr char green[] = "\033[32m";
|
||||
constexpr char yellow[] = "\033[33m";
|
||||
[[maybe_unused]] constexpr char yellow[] = "\033[33m";
|
||||
|
||||
std::istringstream in(s);
|
||||
|
||||
@ -122,7 +183,7 @@ namespace ngcore
|
||||
auto libname = s.substr(0, brace_open_pos);
|
||||
auto funcname = s.substr(brace_open_pos+1, plus_pos - brace_open_pos - 1);
|
||||
auto offset = std::strtoul(s.substr(plus_pos+1, brace_close_pos - plus_pos - 1).c_str(), 0, 16);
|
||||
auto position = std::strtoul(s.substr(bracket_open_pos+1, bracket_close_pos - bracket_open_pos - 1).c_str(), 0, 16);
|
||||
// auto position = std::strtoul(s.substr(bracket_open_pos+1, bracket_close_pos - bracket_open_pos - 1).c_str(), 0, 16);
|
||||
std::stringstream out;
|
||||
|
||||
if(!funcname.empty())
|
||||
@ -181,7 +242,7 @@ namespace ngcore
|
||||
for (i = 1; i < bt_size-1; i++)
|
||||
{
|
||||
dladdr(bt[i], &info);
|
||||
size_t len = strlen(bt_syms[i]);
|
||||
// size_t len = strlen(bt_syms[i]);
|
||||
result << '#'<< i << '\t' << detail::TranslateBacktrace( bt_syms[i], info.dli_fname );
|
||||
}
|
||||
free(bt_syms);
|
||||
@ -226,7 +287,7 @@ static bool dummy = []()
|
||||
return true;
|
||||
}();
|
||||
|
||||
#else // __GNUC__
|
||||
#else // __GNUC__ and not __EMSCRIPTEN__
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
|
@ -1,16 +1,17 @@
|
||||
#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
|
||||
{
|
||||
|
||||
NGCORE_API std::string GetBackTrace();
|
||||
|
||||
// Exception for code that shouldn't be executed
|
||||
@ -33,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;
|
||||
|
||||
@ -50,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)
|
||||
{
|
||||
@ -76,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,12 +128,18 @@ namespace ngcore
|
||||
// Convenience macro to append file name and line of exception origin to the string
|
||||
#define NG_EXCEPTION(s) ngcore::Exception(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t"+std::string(s))
|
||||
|
||||
#ifdef NETGEN_ENABLE_CHECK_RANGE
|
||||
#define NETGEN_CHECK_RANGE(value, min, max_plus_one) \
|
||||
{ if ((value)<(min) || (value)>=(max_plus_one)) \
|
||||
throw ngcore::RangeException(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", (value), (min), (max_plus_one)); }
|
||||
#else // NETGEN_ENABLE_CHECK_RANGE
|
||||
#define NETGEN_CHECK_RANGE(value, min, max)
|
||||
#endif // NETGEN_ENABLE_CHECK_RANGE
|
||||
#if defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
|
||||
#define NETGEN_CHECK_RANGE(value, min, max_plus_one) ngcore::detail::CheckRange(__FILE__ ":" NETGEN_CORE_NGEXEPTION_STR(__LINE__) "\t", value, 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_NOEXCEPT noexcept
|
||||
#endif // defined(NETGEN_ENABLE_CHECK_RANGE) && !defined(__CUDA_ARCH__)
|
||||
|
||||
|
||||
|
||||
#endif // NETGEN_CORE_EXCEPTION_HPP
|
||||
|
@ -4,6 +4,7 @@
|
||||
/* Date: 10. Oct. 96 */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "archive.hpp"
|
||||
#include "flags.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
@ -15,6 +16,7 @@
|
||||
namespace ngcore
|
||||
{
|
||||
using std::string;
|
||||
using std::string_view;
|
||||
using std::endl;
|
||||
Flags :: Flags () { ; }
|
||||
|
||||
@ -208,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;
|
||||
}
|
||||
@ -238,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)]);
|
||||
}
|
||||
|
||||
|
||||
@ -295,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);
|
||||
}
|
||||
@ -605,7 +607,7 @@ namespace ngcore
|
||||
}
|
||||
else
|
||||
{
|
||||
// to be cleand up ...
|
||||
// to be cleaned up ...
|
||||
Array<char *> strs;
|
||||
|
||||
posbrack++;
|
||||
|
@ -58,7 +58,7 @@ namespace ngcore
|
||||
Flags & operator= (const Flags & f2) = default;
|
||||
Flags & operator= (Flags && f2) = default;
|
||||
|
||||
void DoArchive(Archive& ar);
|
||||
void DoArchive(class Archive& ar);
|
||||
|
||||
void Update(const Flags& other);
|
||||
|
||||
@ -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(); }
|
||||
@ -167,6 +167,7 @@ namespace ngcore
|
||||
int GetNStringListFlags () const { return strlistflags.Size(); }
|
||||
/// number of num-list flags
|
||||
int GetNNumListFlags () const { return numlistflags.Size(); }
|
||||
int GetNAnyFlags() const { return anyflags.Size(); }
|
||||
|
||||
///
|
||||
const std::string & GetStringFlag (int i, std::string & name) const
|
||||
@ -181,6 +182,8 @@ namespace ngcore
|
||||
{ name = strlistflags.GetName(i); return strlistflags[i]; }
|
||||
const Flags & GetFlagsFlag (int i, std::string & name) const
|
||||
{ name = flaglistflags.GetName(i); return flaglistflags[i]; }
|
||||
const std::any& GetAnyFlag(int i, std::string& name) const
|
||||
{ name = anyflags.GetName(i); return anyflags[i]; }
|
||||
};
|
||||
|
||||
/// Print flags
|
||||
|
174
libsrc/core/generate_mpi_sources.py
Normal file
174
libsrc/core/generate_mpi_sources.py
Normal file
@ -0,0 +1,174 @@
|
||||
functions = [
|
||||
("double", "MPI_Wtime"),
|
||||
("int", "MPI_Allgather", "void*", "int", "MPI_Datatype", "void*", "int", "MPI_Datatype", "MPI_Comm"),
|
||||
("int", "MPI_Allreduce", "void*", "void*", "int", "MPI_Datatype", "MPI_Op", "MPI_Comm"),
|
||||
("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*"),
|
||||
("int", "MPI_Comm_free", "MPI_Comm*"),
|
||||
("int", "MPI_Comm_group", "MPI_Comm", "MPI_Group*"),
|
||||
("int", "MPI_Comm_rank", "MPI_Comm", "int*"),
|
||||
("int", "MPI_Comm_size", "MPI_Comm", "int*"),
|
||||
("int", "MPI_Finalize"),
|
||||
("int", "MPI_Gather", "void*", "int", "MPI_Datatype", "void*", "int", "MPI_Datatype", "int", "MPI_Comm"),
|
||||
("int", "MPI_Gatherv", "void*", "int", "MPI_Datatype", "void*", "int*", "int*", "MPI_Datatype", "int", "MPI_Comm"),
|
||||
("int", "MPI_Get_count", "MPI_Status*", "MPI_Datatype", "int*"),
|
||||
("int", "MPI_Get_processor_name", "char*", "int*"),
|
||||
("int", "MPI_Group_incl", "MPI_Group", "int", "int*", "MPI_Group*"),
|
||||
("int", "MPI_Init", "int*", "char***"),
|
||||
("int", "MPI_Init_thread", "int*", "char***", "int", "int*"),
|
||||
("int", "MPI_Initialized", "int*"),
|
||||
("int", "MPI_Iprobe", "int", "int", "MPI_Comm", "int*", "MPI_Status*"),
|
||||
("int", "MPI_Irecv", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Request*"),
|
||||
("int", "MPI_Isend", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Request*"),
|
||||
("int", "MPI_Probe", "int", "int", "MPI_Comm", "MPI_Status*"),
|
||||
("int", "MPI_Query_thread", "int*"),
|
||||
("int", "MPI_Recv", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Status*"),
|
||||
("int", "MPI_Recv_init", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Request*"),
|
||||
("int", "MPI_Reduce", "void*", "void*", "int", "MPI_Datatype", "MPI_Op", "int", "MPI_Comm"),
|
||||
("int", "MPI_Reduce_local", "void*", "void*", "int", "MPI_Datatype", "MPI_Op"),
|
||||
("int", "MPI_Request_free", "MPI_Request*"),
|
||||
("int", "MPI_Scatter", "void*", "int", "MPI_Datatype", "void*", "int", "MPI_Datatype", "int", "MPI_Comm"),
|
||||
("int", "MPI_Send", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm"),
|
||||
("int", "MPI_Send_init", "void*", "int", "MPI_Datatype", "int", "int", "MPI_Comm", "MPI_Request*"),
|
||||
("int", "MPI_Startall", "int", "MPI_Request*:0"),
|
||||
("int", "MPI_Type_commit", "MPI_Datatype*"),
|
||||
("int", "MPI_Type_contiguous", "int", "MPI_Datatype", "MPI_Datatype*"),
|
||||
("int", "MPI_Type_create_resized", "MPI_Datatype", "MPI_Aint", "MPI_Aint", "MPI_Datatype*"),
|
||||
("int", "MPI_Type_create_struct", "int", "int*:0", "MPI_Aint*:0", "MPI_Datatype*:0", "MPI_Datatype*"),
|
||||
("int", "MPI_Type_free", "MPI_Datatype*"),
|
||||
("int", "MPI_Type_get_extent", "MPI_Datatype", "MPI_Aint*", "MPI_Aint*"),
|
||||
("int", "MPI_Type_indexed", "int", "int*:0", "int*:0", "MPI_Datatype", "MPI_Datatype*"),
|
||||
("int", "MPI_Type_size", "MPI_Datatype", "int*"),
|
||||
("int", "MPI_Wait", "MPI_Request*", "MPI_Status*"),
|
||||
("int", "MPI_Waitall", "int", "MPI_Request*:0", "MPI_Status*"),
|
||||
("int", "MPI_Waitany", "int", "MPI_Request*:0", "int*", "MPI_Status*"),
|
||||
]
|
||||
|
||||
constants = [
|
||||
("MPI_Comm", "MPI_COMM_NULL"),
|
||||
("MPI_Comm", "MPI_COMM_WORLD"),
|
||||
("MPI_Datatype", "MPI_CHAR"),
|
||||
("MPI_Datatype", "MPI_CXX_DOUBLE_COMPLEX"),
|
||||
("MPI_Datatype", "MPI_C_BOOL"),
|
||||
("MPI_Datatype", "MPI_DATATYPE_NULL"),
|
||||
("MPI_Datatype", "MPI_DOUBLE"),
|
||||
("MPI_Datatype", "MPI_FLOAT"),
|
||||
("MPI_Datatype", "MPI_INT"),
|
||||
("MPI_Datatype", "MPI_SHORT"),
|
||||
("MPI_Datatype", "MPI_UINT64_T"),
|
||||
("MPI_Op", "MPI_LOR"),
|
||||
("MPI_Op", "MPI_MAX"),
|
||||
("MPI_Op", "MPI_MIN"),
|
||||
("MPI_Op", "MPI_SUM"),
|
||||
("MPI_Request", "MPI_REQUEST_NULL"),
|
||||
("MPI_Status*", "MPI_STATUSES_IGNORE"),
|
||||
("MPI_Status*", "MPI_STATUS_IGNORE"),
|
||||
("int", "MPI_ANY_SOURCE"),
|
||||
("int", "MPI_ANY_TAG"),
|
||||
("int", "MPI_MAX_PROCESSOR_NAME"),
|
||||
("int", "MPI_PROC_NULL"),
|
||||
("int", "MPI_ROOT"),
|
||||
("int", "MPI_SUBVERSION"),
|
||||
("int", "MPI_THREAD_MULTIPLE"),
|
||||
("int", "MPI_THREAD_SINGLE"),
|
||||
("int", "MPI_VERSION"),
|
||||
("void*", "MPI_IN_PLACE"),
|
||||
]
|
||||
|
||||
def get_args(f, counts=False):
|
||||
args = []
|
||||
for arg in f[2:]:
|
||||
has_count = ':' in arg
|
||||
if has_count:
|
||||
s, count = arg.split(':')
|
||||
count = int(count)
|
||||
else:
|
||||
s = arg
|
||||
count = None
|
||||
if s.startswith("MPI_"):
|
||||
s = "NG_" + s
|
||||
if counts:
|
||||
args.append((s, count))
|
||||
else:
|
||||
args.append(s)
|
||||
return args
|
||||
|
||||
def generate_declarations():
|
||||
code = ""
|
||||
nowrapper_code = ""
|
||||
for f in functions:
|
||||
ret = f[0]
|
||||
name = f[1]
|
||||
args = ", ".join(get_args(f))
|
||||
code += f"NGCORE_API extern {ret} (*NG_{name})({args});\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"#define NG_{name} {name}\n"
|
||||
|
||||
with open("ng_mpi_generated_declarations.hpp", "w") as f:
|
||||
f.write("#ifdef NG_MPI_WRAPPER\n")
|
||||
f.write(code)
|
||||
f.write("#else // NG_MPI_WRAPPER\n")
|
||||
f.write(nowrapper_code)
|
||||
f.write("#endif // NG_MPI_WRAPPER\n")
|
||||
|
||||
def generate_dummy_init():
|
||||
code = ""
|
||||
for f in functions:
|
||||
ret = f[0]
|
||||
name = f[1]
|
||||
args = ", ".join(get_args(f))
|
||||
code += f"decltype(NG_{name}) NG_{name} = []({args})->{ret} {{ throw no_mpi(); }};\n"
|
||||
|
||||
for typ, name in constants:
|
||||
if typ.startswith("MPI_"):
|
||||
typ = "NG_" + typ
|
||||
code += f"{typ} NG_{name} = 0;\n"
|
||||
|
||||
with open("ng_mpi_generated_dummy_init.hpp", "w") as f:
|
||||
f.write(code)
|
||||
|
||||
def generate_init():
|
||||
code = ""
|
||||
for f in functions:
|
||||
ret = f[0]
|
||||
name = f[1]
|
||||
args = get_args(f, counts=True)
|
||||
in_args =''
|
||||
call_args = ''
|
||||
for i in range(len(args)):
|
||||
arg, count = args[i]
|
||||
if i > 0:
|
||||
in_args += ', '
|
||||
call_args += ', '
|
||||
in_args += arg + f" arg{i}"
|
||||
if not arg.startswith("NG_"):
|
||||
# plain type (like int, int *, etc.), just pass the argument along
|
||||
call_args += f" arg{i}"
|
||||
elif count is None:
|
||||
# MPI type (by value or pointer), but just one object, no arrays
|
||||
call_args += f" ng2mpi(arg{i})"
|
||||
else:
|
||||
# arrays of MPI types, we need to copy them due to incompatible size
|
||||
call_args += f" ng2mpi(arg{i}, arg{count})"
|
||||
code += f"NG_{name} = []({in_args})->{ret} {{ return {name}({call_args}); }};\n"
|
||||
|
||||
for _, name in constants:
|
||||
code += f"NG_{name} = mpi2ng({name});\n"
|
||||
|
||||
with open("ng_mpi_generated_init.hpp", "w") as f:
|
||||
f.write(code)
|
||||
|
||||
if __name__ == "__main__":
|
||||
generate_declarations()
|
||||
generate_dummy_init()
|
||||
generate_init()
|
@ -9,8 +9,9 @@
|
||||
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <optional>
|
||||
|
||||
#include "mpi_wrapper.hpp"
|
||||
// #include "mpi_wrapper.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
#include "table.hpp"
|
||||
#include "utils.hpp"
|
||||
@ -37,52 +38,68 @@ namespace ngcore
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
// feature check macro for transition from INT to IVec
|
||||
#define NGCORE_HAS_IVEC
|
||||
|
||||
/// N integers
|
||||
template <int N, typename T = int>
|
||||
class INT
|
||||
class IVec
|
||||
{
|
||||
/// data
|
||||
T i[(N>0)?N:1];
|
||||
// T i[(N>0)?N:1];
|
||||
|
||||
HTArray<N,T> i;
|
||||
|
||||
public:
|
||||
///
|
||||
NETGEN_INLINE INT () { }
|
||||
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 INT (T ai1)
|
||||
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]
|
||||
NETGEN_INLINE INT (T ai1, T ai2)
|
||||
{ i[0] = ai1; i[1] = ai2; }
|
||||
constexpr NETGEN_INLINE IVec (T ai1, T ai2)
|
||||
: i{ai1, ai2} { ; }
|
||||
|
||||
/// init i[0], i[1], i[2]
|
||||
NETGEN_INLINE INT (T ai1, T ai2, T ai3)
|
||||
{ i[0] = ai1; i[1] = ai2; i[2] = ai3; }
|
||||
constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3)
|
||||
: i{ai1, ai2, ai3} { ; }
|
||||
|
||||
/// init i[0], i[1], i[2]
|
||||
NETGEN_INLINE INT (T ai1, T ai2, T ai3, T ai4)
|
||||
{ i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; }
|
||||
|
||||
constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4)
|
||||
: i{ai1, ai2, ai3, ai4} { ; }
|
||||
|
||||
/// init i[0], i[1], i[2]
|
||||
NETGEN_INLINE INT (T ai1, T ai2, T ai3, T ai4, T ai5)
|
||||
{ i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; i[4] = ai5;}
|
||||
|
||||
constexpr NETGEN_INLINE IVec (T ai1, T ai2, T ai3, T ai4, T ai5)
|
||||
: i{ai1, ai2, ai3, ai4, ai5} { ; }
|
||||
|
||||
/// init i[0], i[1], i[2]
|
||||
NETGEN_INLINE INT (T ai1, T ai2, T ai3, T ai4, T ai5, T ai6, T ai7, T ai8, T ai9)
|
||||
{ i[0] = ai1; i[1] = ai2; i[2] = ai3; i[3] = ai4; i[4] = ai5; i[5] = ai6; i[6] = ai7; i[7] = ai8; i[8] = ai9; }
|
||||
|
||||
void DoArchive(Archive& ar)
|
||||
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>
|
||||
NETGEN_INLINE INT (const INT<N2,T2> & in2)
|
||||
NETGEN_INLINE IVec (const IVec<N2,T2> & in2)
|
||||
{
|
||||
if (N2 <= N)
|
||||
{
|
||||
@ -99,7 +116,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
NETGEN_INLINE INT (const BaseArrayObject<T2> & ao)
|
||||
NETGEN_INLINE IVec (const BaseArrayObject<T2> & ao)
|
||||
{
|
||||
for (int j = 0; j < N; j++)
|
||||
i[j] = ao.Spec()[j];
|
||||
@ -107,7 +124,7 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE size_t Size() const { return N; }
|
||||
/// all ints equal ?
|
||||
NETGEN_INLINE bool operator== (const INT & in2) const
|
||||
NETGEN_INLINE bool operator== (const IVec & in2) const
|
||||
{
|
||||
for (int j = 0; j < N; j++)
|
||||
if (i[j] != in2.i[j]) return 0;
|
||||
@ -115,7 +132,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// any ints unequal ?
|
||||
NETGEN_INLINE bool operator!= (const INT & in2) const
|
||||
NETGEN_INLINE bool operator!= (const IVec & in2) const
|
||||
{
|
||||
for (int j = 0; j < N; j++)
|
||||
if (i[j] != in2.i[j]) return 1;
|
||||
@ -123,7 +140,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// sort integers
|
||||
NETGEN_INLINE INT & Sort () &
|
||||
NETGEN_INLINE IVec & Sort () &
|
||||
{
|
||||
for (int k = 0; k < N; k++)
|
||||
for (int l = k+1; l < N; l++)
|
||||
@ -132,7 +149,7 @@ namespace ngcore
|
||||
return *this;
|
||||
}
|
||||
|
||||
NETGEN_INLINE INT Sort () &&
|
||||
NETGEN_INLINE IVec Sort () &&
|
||||
{
|
||||
for (int k = 0; k < N; k++)
|
||||
for (int l = k+1; l < N; l++)
|
||||
@ -146,15 +163,15 @@ namespace ngcore
|
||||
{ return i[j]; }
|
||||
|
||||
/// access
|
||||
NETGEN_INLINE const T & operator[] (int j) const
|
||||
NETGEN_INLINE constexpr const T & operator[] (int j) const
|
||||
{ return i[j]; }
|
||||
|
||||
template <size_t J>
|
||||
T get() const { return i[J]; }
|
||||
constexpr T get() const { return i[J]; }
|
||||
|
||||
operator FlatArray<T> () { return FlatArray<T> (N, &i[0]); }
|
||||
|
||||
NETGEN_INLINE INT<N,T> & operator= (T value)
|
||||
NETGEN_INLINE IVec<N,T> & operator= (T value)
|
||||
{
|
||||
for (int j = 0; j < N; j++)
|
||||
i[j] = value;
|
||||
@ -162,7 +179,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
NETGEN_INLINE INT<N,T> & operator= (INT<N,T2> v2)
|
||||
NETGEN_INLINE IVec<N,T> & operator= (IVec<N,T2> v2)
|
||||
{
|
||||
for (int j = 0; j < N; j++)
|
||||
i[j] = v2[j];
|
||||
@ -185,14 +202,14 @@ namespace ngcore
|
||||
|
||||
/// sort 2 integers
|
||||
template <>
|
||||
NETGEN_INLINE INT<2> & INT<2>::Sort () &
|
||||
NETGEN_INLINE IVec<2> & IVec<2>::Sort () &
|
||||
{
|
||||
if (i[0] > i[1]) Swap (i[0], i[1]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <>
|
||||
NETGEN_INLINE INT<2> INT<2>::Sort () &&
|
||||
NETGEN_INLINE IVec<2> IVec<2>::Sort () &&
|
||||
{
|
||||
if (i[0] > i[1]) Swap (i[0], i[1]);
|
||||
return *this;
|
||||
@ -200,7 +217,7 @@ namespace ngcore
|
||||
|
||||
/// sort 3 integers
|
||||
template <>
|
||||
NETGEN_INLINE INT<3> INT<3>::Sort () &&
|
||||
NETGEN_INLINE IVec<3> IVec<3>::Sort () &&
|
||||
{
|
||||
if (i[0] > i[1]) Swap (i[0], i[1]);
|
||||
if (i[1] > i[2]) Swap (i[1], i[2]);
|
||||
@ -210,7 +227,7 @@ namespace ngcore
|
||||
|
||||
/// Print integers
|
||||
template <int N, typename T>
|
||||
inline ostream & operator<<(ostream & s, const INT<N,T> & i2)
|
||||
inline ostream & operator<<(ostream & s, const IVec<N,T> & i2)
|
||||
{
|
||||
for (int j = 0; j < N; j++)
|
||||
s << (int) i2[j] << " ";
|
||||
@ -218,15 +235,15 @@ namespace ngcore
|
||||
}
|
||||
|
||||
template <int N, typename T>
|
||||
auto begin(const INT<N,T> & ind)
|
||||
auto begin(const IVec<N,T> & ind)
|
||||
{
|
||||
return AOWrapperIterator<INT<N,T>> (ind, 0);
|
||||
return AOWrapperIterator<IVec<N,T>> (ind, 0);
|
||||
}
|
||||
|
||||
template <int N, typename T>
|
||||
auto end(const INT<N,T> & ind)
|
||||
auto end(const IVec<N,T> & ind)
|
||||
{
|
||||
return AOWrapperIterator<INT<N,T>> (ind, N);
|
||||
return AOWrapperIterator<IVec<N,T>> (ind, N);
|
||||
}
|
||||
|
||||
|
||||
@ -235,9 +252,9 @@ namespace ngcore
|
||||
|
||||
|
||||
template <int N, typename TI>
|
||||
NETGEN_INLINE size_t HashValue (const INT<N,TI> & ind, size_t size)
|
||||
NETGEN_INLINE size_t HashValue (const IVec<N,TI> & ind, size_t size)
|
||||
{
|
||||
INT<N,size_t> lind = ind;
|
||||
IVec<N,size_t> lind = ind;
|
||||
size_t sum = 0;
|
||||
for (int i = 0; i < N; i++)
|
||||
sum += lind[i];
|
||||
@ -246,24 +263,24 @@ namespace ngcore
|
||||
|
||||
/// hash value of 1 int
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue (const INT<1,TI> & ind, size_t size)
|
||||
NETGEN_INLINE size_t HashValue (const IVec<1,TI> & ind, size_t size)
|
||||
{
|
||||
return ind[0] % size;
|
||||
}
|
||||
|
||||
/// hash value of 2 int
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue (const INT<2,TI> & ind, size_t size)
|
||||
NETGEN_INLINE size_t HashValue (const IVec<2,TI> & ind, size_t size)
|
||||
{
|
||||
INT<2,size_t> lind = ind;
|
||||
IVec<2,size_t> lind = ind;
|
||||
return (113*lind[0]+lind[1]) % size;
|
||||
}
|
||||
|
||||
/// hash value of 3 int
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue (const INT<3,TI> & ind, size_t size)
|
||||
NETGEN_INLINE size_t HashValue (const IVec<3,TI> & ind, size_t size)
|
||||
{
|
||||
INT<3,size_t> lind = ind;
|
||||
IVec<3,size_t> lind = ind;
|
||||
return (113*lind[0]+59*lind[1]+lind[2]) % size;
|
||||
}
|
||||
|
||||
@ -283,9 +300,9 @@ namespace ngcore
|
||||
|
||||
|
||||
template <int N, typename TI>
|
||||
NETGEN_INLINE size_t HashValue2 (const INT<N,TI> & ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<N,TI> & ind, size_t mask)
|
||||
{
|
||||
INT<N,size_t> lind = ind;
|
||||
IVec<N,size_t> lind = ind;
|
||||
size_t sum = 0;
|
||||
for (int i = 0; i < N; i++)
|
||||
sum += lind[i];
|
||||
@ -294,32 +311,32 @@ namespace ngcore
|
||||
|
||||
/// hash value of 1 int
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue2 (const INT<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 INT<2,TI> & ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<2,TI> & ind, size_t mask)
|
||||
{
|
||||
INT<2,size_t> lind = ind;
|
||||
IVec<2,size_t> lind = ind;
|
||||
return (113*lind[0]+lind[1]) & mask;
|
||||
}
|
||||
|
||||
/// hash value of 3 int
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue2 (const INT<3,TI> & ind, size_t mask)
|
||||
NETGEN_INLINE constexpr size_t HashValue2 (const IVec<3,TI> & ind, size_t mask)
|
||||
{
|
||||
INT<3,size_t> lind = ind;
|
||||
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;
|
||||
}
|
||||
@ -331,7 +348,7 @@ namespace ngcore
|
||||
// using ngstd::max;
|
||||
|
||||
template <int D, typename T>
|
||||
NETGEN_INLINE T Max (const INT<D,T> & i)
|
||||
NETGEN_INLINE T Max (const IVec<D,T> & i)
|
||||
{
|
||||
if (D == 0) return 0;
|
||||
T m = i[0];
|
||||
@ -341,7 +358,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
template <int D, typename T>
|
||||
NETGEN_INLINE T Min (const INT<D,T> & i)
|
||||
NETGEN_INLINE T Min (const IVec<D,T> & i)
|
||||
{
|
||||
if (D == 0) return 0;
|
||||
T m = i[0];
|
||||
@ -351,18 +368,18 @@ namespace ngcore
|
||||
}
|
||||
|
||||
template <int D, typename T>
|
||||
NETGEN_INLINE INT<D,T> Max (INT<D,T> i1, INT<D,T> i2)
|
||||
NETGEN_INLINE IVec<D,T> Max (IVec<D,T> i1, IVec<D,T> i2)
|
||||
{
|
||||
INT<D,T> tmp;
|
||||
IVec<D,T> tmp;
|
||||
for (int i = 0; i < D; i++)
|
||||
tmp[i] = std::max(i1[i], i2[i]);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <int D, typename T>
|
||||
NETGEN_INLINE INT<D,T> operator+ (INT<D,T> i1, INT<D,T> i2)
|
||||
NETGEN_INLINE IVec<D,T> operator+ (IVec<D,T> i1, IVec<D,T> i2)
|
||||
{
|
||||
INT<D,T> tmp;
|
||||
IVec<D,T> tmp;
|
||||
for (int i = 0; i < D; i++)
|
||||
tmp[i] = i1[i]+i2[i];
|
||||
return tmp;
|
||||
@ -500,7 +517,7 @@ namespace ngcore
|
||||
for (int i = 0; i < table[bnr].Size(); i++)
|
||||
if (table[bnr][i].first == ind)
|
||||
return i;
|
||||
throw Exception ("Ask for unsused hash-value");
|
||||
throw Exception ("Ask for unused hash-value");
|
||||
}
|
||||
|
||||
T & operator[] (T_HASH ahash)
|
||||
@ -574,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.
|
||||
@ -595,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;
|
||||
@ -611,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;
|
||||
@ -632,24 +674,17 @@ namespace ngcore
|
||||
size_t UsedElements () const
|
||||
{
|
||||
return used;
|
||||
/*
|
||||
size_t cnt = 0;
|
||||
for (size_t i = 0; i < size; i++)
|
||||
if (hash[i] != invalid)
|
||||
cnt++;
|
||||
return cnt;
|
||||
*/
|
||||
}
|
||||
|
||||
size_t Position (const T_HASH ind) const
|
||||
{
|
||||
size_t i = HashValue2(ind, mask);
|
||||
while (1)
|
||||
// size_t i = HashValue2(ind, mask);
|
||||
size_t i = CHT_trait<T_HASH>::HashValue(ind, mask);
|
||||
while (true)
|
||||
{
|
||||
if (hash[i] == ind) return i;
|
||||
if (hash[i] == invalid) return size_t(-1);
|
||||
i++;
|
||||
if (i >= size) i = 0;
|
||||
i = (i+1) & mask;
|
||||
}
|
||||
}
|
||||
|
||||
@ -666,9 +701,10 @@ 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 (1)
|
||||
while (true)
|
||||
{
|
||||
if (hash[i] == invalid)
|
||||
{
|
||||
@ -682,8 +718,7 @@ namespace ngcore
|
||||
apos = i;
|
||||
return false;
|
||||
}
|
||||
i++;
|
||||
if (i >= size) i = 0;
|
||||
i = (i+1) & mask;
|
||||
}
|
||||
}
|
||||
|
||||
@ -712,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 +828,21 @@ namespace ngcore
|
||||
pos = nextpos;
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteData()
|
||||
{
|
||||
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,25 +883,28 @@ namespace ngcore
|
||||
tab.GetData (i, key, val);
|
||||
ost << key << ": " << val << ", ";
|
||||
}
|
||||
*/
|
||||
for (auto [key,val] : tab)
|
||||
ost << key << ": " << val << ", ";
|
||||
return ost;
|
||||
}
|
||||
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue (const INT<3,TI> ind)
|
||||
NETGEN_INLINE size_t HashValue (const IVec<3,TI> ind)
|
||||
{
|
||||
INT<3,size_t> lind = ind;
|
||||
IVec<3,size_t> lind = ind;
|
||||
return 113*lind[0]+59*lind[1]+lind[2];
|
||||
}
|
||||
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue (const INT<2,TI> ind)
|
||||
NETGEN_INLINE size_t HashValue (const IVec<2,TI> ind)
|
||||
{
|
||||
INT<2,size_t> lind = ind;
|
||||
IVec<2,size_t> lind = ind;
|
||||
return 113*lind[0]+lind[1];
|
||||
}
|
||||
|
||||
template <typename TI>
|
||||
NETGEN_INLINE size_t HashValue (const INT<1,TI> ind)
|
||||
NETGEN_INLINE size_t HashValue (const IVec<1,TI> ind)
|
||||
{
|
||||
return ind[0];
|
||||
}
|
||||
@ -1071,22 +1131,113 @@ namespace ngcore
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <int N, typename T>
|
||||
Archive & operator & (Archive & archive, INT<N,T> & mi)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template <class T, class IndexType>
|
||||
class CompressedTable
|
||||
{
|
||||
for (int i = 0; i < N; i++)
|
||||
archive & mi[i];
|
||||
return archive;
|
||||
}
|
||||
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
|
||||
|
||||
|
||||
|
||||
/*
|
||||
#ifdef PARALLEL
|
||||
namespace ngcore {
|
||||
template<int S, typename T>
|
||||
class MPI_typetrait<ngcore::INT<S, T> >
|
||||
class MPI_typetrait<ngcore::IVec<S, T> >
|
||||
{
|
||||
public:
|
||||
/// gets the MPI datatype
|
||||
@ -1103,6 +1254,19 @@ namespace ngcore {
|
||||
};
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
template<typename T> struct MPI_typetrait;
|
||||
|
||||
template<int S, typename T>
|
||||
struct MPI_typetrait<IVec<S, T> > {
|
||||
static auto MPIType () {
|
||||
return MPI_typetrait<std::array<T,S>>::MPIType();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1110,8 +1274,8 @@ namespace std
|
||||
{
|
||||
// structured binding support
|
||||
template <auto N, typename T>
|
||||
struct tuple_size<ngcore::INT<N,T>> : std::integral_constant<std::size_t, N> {};
|
||||
template<size_t N, auto M, typename T> struct tuple_element<N,ngcore::INT<M,T>> { using type = T; };
|
||||
struct tuple_size<ngcore::IVec<N,T>> : std::integral_constant<std::size_t, N> {};
|
||||
template<size_t N, auto M, typename T> struct tuple_element<N,ngcore::IVec<M,T>> { using type = T; };
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -136,7 +136,7 @@ public:
|
||||
|
||||
|
||||
/// free memory
|
||||
NETGEN_INLINE virtual ~LocalHeap ()
|
||||
virtual ~LocalHeap ()
|
||||
{
|
||||
if (owner)
|
||||
delete [] data;
|
||||
@ -163,7 +163,7 @@ public:
|
||||
}
|
||||
|
||||
/// allocates size bytes of memory from local heap
|
||||
NETGEN_INLINE void * Alloc (size_t size) final // throw (LocalHeapOverflow)
|
||||
void * Alloc (size_t size) final // throw (LocalHeapOverflow)
|
||||
{
|
||||
char * oldp = p;
|
||||
|
||||
@ -181,7 +181,7 @@ public:
|
||||
|
||||
/// allocates size objects of type T on local heap
|
||||
template <typename T>
|
||||
NETGEN_INLINE T * Alloc (size_t size) // throw (LocalHeapOverflow)
|
||||
T * Alloc (size_t size) // throw (LocalHeapOverflow)
|
||||
{
|
||||
char * oldp = p;
|
||||
size *= sizeof (T);
|
||||
|
@ -1,15 +1,6 @@
|
||||
#include "logging.hpp"
|
||||
|
||||
#ifdef NETGEN_USE_SPDLOG
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
#include <spdlog/sinks/ansicolor_sink.h>
|
||||
#include <spdlog/sinks/basic_file_sink.h>
|
||||
|
||||
#else // NETGEN_USE_SPDLOG
|
||||
#include <iostream>
|
||||
#endif // NETGEN_USE_SPDLOG
|
||||
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
@ -19,94 +10,10 @@ namespace ngcore
|
||||
|
||||
void Logger::log(level::level_enum level, std::string && s)
|
||||
{
|
||||
#ifdef NETGEN_USE_SPDLOG
|
||||
logger->log(spdlog::level::level_enum(level), s);
|
||||
#else // NETGEN_USE_SPDLOG
|
||||
if(level>=global_level)
|
||||
std::clog << s << '\n';
|
||||
#endif // NETGEN_USE_SPDLOG
|
||||
}
|
||||
|
||||
#ifdef NETGEN_USE_SPDLOG
|
||||
namespace detail
|
||||
{
|
||||
std::vector<std::shared_ptr<spdlog::sinks::sink>>& GetDefaultSinks()
|
||||
{
|
||||
static std::vector<std::shared_ptr<spdlog::sinks::sink>> sinks =
|
||||
{ std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>() };
|
||||
return sinks;
|
||||
}
|
||||
std::shared_ptr<spdlog::logger> CreateDefaultLogger(const std::string& name)
|
||||
{
|
||||
auto& default_sinks = GetDefaultSinks();
|
||||
auto logger = std::make_shared<spdlog::logger>(name, default_sinks.begin(), default_sinks.end());
|
||||
spdlog::details::registry::instance().register_and_init(logger);
|
||||
return logger;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
std::shared_ptr<Logger> GetLogger(const std::string& name)
|
||||
{
|
||||
auto logger = spdlog::get(name);
|
||||
if(!logger)
|
||||
logger = detail::CreateDefaultLogger(name);
|
||||
return std::make_shared<Logger>(logger);
|
||||
}
|
||||
|
||||
void SetLoggingLevel(spdlog::level::level_enum level, const std::string& name)
|
||||
{
|
||||
if(!name.empty())
|
||||
spdlog::get(name)->set_level(level);
|
||||
else
|
||||
spdlog::set_level(level);
|
||||
}
|
||||
|
||||
void AddFileSink(const std::string& filename, spdlog::level::level_enum level, const std::string& logger)
|
||||
{
|
||||
auto sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename);
|
||||
sink->set_level(level);
|
||||
if(!logger.empty())
|
||||
GetLogger(logger)->logger->sinks().push_back(sink);
|
||||
else
|
||||
{
|
||||
detail::GetDefaultSinks().push_back(sink);
|
||||
spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); });
|
||||
}
|
||||
}
|
||||
|
||||
void AddConsoleSink(spdlog::level::level_enum level, const std::string& logger)
|
||||
{
|
||||
auto sink = std::make_shared<spdlog::sinks::ansicolor_stdout_sink_mt>();
|
||||
sink->set_level(level);
|
||||
if(!logger.empty())
|
||||
GetLogger(logger)->logger->sinks().push_back(sink);
|
||||
else
|
||||
{
|
||||
detail::GetDefaultSinks().push_back(sink);
|
||||
spdlog::details::registry::instance().apply_all([sink](auto logger) { logger->sinks().push_back(sink); });
|
||||
}
|
||||
}
|
||||
|
||||
void ClearLoggingSinks(const std::string& logger)
|
||||
{
|
||||
if(!logger.empty())
|
||||
GetLogger(logger)->logger->sinks().clear();
|
||||
else
|
||||
{
|
||||
detail::GetDefaultSinks().clear();
|
||||
spdlog::details::registry::instance().apply_all([](auto logger) { logger->sinks().clear(); });
|
||||
}
|
||||
}
|
||||
|
||||
void FlushOnLoggingLevel(spdlog::level::level_enum level, const std::string& logger)
|
||||
{
|
||||
if(!logger.empty())
|
||||
GetLogger(logger)->logger->flush_on(level);
|
||||
else
|
||||
spdlog::flush_on(level);
|
||||
}
|
||||
|
||||
#else // NETGEN_USE_SPDLOG
|
||||
} //namespace ngcore
|
||||
|
||||
namespace spdlog
|
||||
@ -140,5 +47,3 @@ namespace ngcore
|
||||
void ClearLoggingSinks(const std::string& /*unused*/) {}
|
||||
void FlushOnLoggingLevel(level::level_enum /*unused*/, const std::string& /*unused*/) {}
|
||||
} //namespace ngcore
|
||||
|
||||
#endif // NETGEN_USE_SPDLOG
|
||||
|
@ -1,7 +1,6 @@
|
||||
#ifndef NETGEN_CORE_LOGGING_HPP
|
||||
#define NETGEN_CORE_LOGGING_HPP
|
||||
|
||||
#undef NETGEN_USE_SPDLOG
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -11,15 +10,6 @@
|
||||
#include "ngcore_api.hpp"
|
||||
#include "utils.hpp"
|
||||
|
||||
#ifdef NETGEN_USE_SPDLOG
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
#include <spdlog/fmt/ostr.h> // to be able to parse anything to logger that implements operator << ostream
|
||||
#ifdef NETGEN_LOG_DEBUG
|
||||
#define SPDLOG_DEBUG_ON
|
||||
#define NETGEN_DEBUG_LOG(logger, ...) SPDLOG_DEBUG(logger, __VA_ARGS__)
|
||||
#endif // NETGEN_LOG_DEBUG
|
||||
#endif // NETGEN_USE_SPDLOG
|
||||
|
||||
#ifndef NETGEN_DEBUG_LOG
|
||||
#define NETGEN_DEBUG_LOG(logger, ...)
|
||||
#endif // NETGEN_DEBUG_LOG
|
||||
@ -52,7 +42,12 @@ namespace ngcore
|
||||
static NGCORE_API level::level_enum global_level;
|
||||
|
||||
public:
|
||||
static void SetGlobalLoggingLevel( level::level_enum level ) { global_level = level; }
|
||||
static auto SetGlobalLoggingLevel( level::level_enum level )
|
||||
{
|
||||
auto oldval = global_level;
|
||||
global_level = level;
|
||||
return oldval;
|
||||
}
|
||||
|
||||
std::shared_ptr<spdlog::logger> logger;
|
||||
|
||||
@ -60,13 +55,6 @@ namespace ngcore
|
||||
|
||||
void NGCORE_API log( level::level_enum level, std::string && s);
|
||||
|
||||
#ifdef NETGEN_USE_SPDLOG
|
||||
template<typename ... Args>
|
||||
void log( level::level_enum level, const char* str, Args ... args)
|
||||
{
|
||||
log(level, fmt::format(str, args...));
|
||||
}
|
||||
#else // NETGEN_USE_SPDLOG
|
||||
template<typename T>
|
||||
std::string replace(std::string s, const T & t)
|
||||
{
|
||||
@ -100,7 +88,6 @@ namespace ngcore
|
||||
{
|
||||
log(level, log_helper(std::string(str), args...));
|
||||
}
|
||||
#endif // NETGEN_USE_SPDLOG
|
||||
|
||||
template<typename ... Args>
|
||||
void trace( const char* str, Args ... args) { log(level::level_enum::trace, str, args...); }
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "array.hpp"
|
||||
@ -36,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);
|
||||
@ -49,7 +53,7 @@ namespace ngcore
|
||||
std::cerr << "Allocated " << id << " MemoryTracer objects" << std::endl;
|
||||
return id;
|
||||
}
|
||||
int id;
|
||||
mutable int id = 0;
|
||||
|
||||
public:
|
||||
|
||||
@ -58,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 )
|
||||
@ -68,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; }
|
||||
@ -149,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 */ ) {}
|
||||
@ -158,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>
|
||||
@ -167,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
|
||||
|
245
libsrc/core/mpi4py_pycapi.h
Normal file
245
libsrc/core/mpi4py_pycapi.h
Normal file
@ -0,0 +1,245 @@
|
||||
/* Author: Lisandro Dalcin */
|
||||
/* Contact: dalcinl@gmail.com */
|
||||
|
||||
#ifndef MPI4PY_PYCAPI_H
|
||||
#define MPI4PY_PYCAPI_H
|
||||
|
||||
#include <mpi.h>
|
||||
#include <Python.h>
|
||||
|
||||
#define _mpi4py_declare_pycapi(Type, star) \
|
||||
static PyTypeObject *_mpi4py_PyMPI##Type = NULL; \
|
||||
static PyObject *(*_mpi4py_PyMPI##Type##_New)(MPI_##Type star) = NULL; \
|
||||
static MPI_##Type *(*_mpi4py_PyMPI##Type##_Get)(PyObject *) = NULL;
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_DATATYPE
|
||||
_mpi4py_declare_pycapi(Datatype,)
|
||||
#define PyMPIDatatype_Type (*_mpi4py_PyMPIDatatype)
|
||||
#define PyMPIDatatype_New _mpi4py_PyMPIDatatype_New
|
||||
#define PyMPIDatatype_Get _mpi4py_PyMPIDatatype_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_STATUS
|
||||
_mpi4py_declare_pycapi(Status,*)
|
||||
#define PyMPIStatus_Type (*_mpi4py_PyMPIStatus)
|
||||
#define PyMPIStatus_New _mpi4py_PyMPIStatus_New
|
||||
#define PyMPIStatus_Get _mpi4py_PyMPIStatus_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_REQUEST
|
||||
_mpi4py_declare_pycapi(Request,)
|
||||
#define PyMPIRequest_Type (*_mpi4py_PyMPIRequest)
|
||||
#define PyMPIRequest_New _mpi4py_PyMPIRequest_New
|
||||
#define PyMPIRequest_Get _mpi4py_PyMPIRequest_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_MESSAGE
|
||||
_mpi4py_declare_pycapi(Message,)
|
||||
#define PyMPIMessage_Type (*_mpi4py_PyMPIMessage)
|
||||
#define PyMPIMessage_New _mpi4py_PyMPIMessage_New
|
||||
#define PyMPIMessage_Get _mpi4py_PyMPIMessage_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_OP
|
||||
_mpi4py_declare_pycapi(Op,)
|
||||
#define PyMPIOp_Type (*_mpi4py_PyMPIOp)
|
||||
#define PyMPIOp_New _mpi4py_PyMPIOp_New
|
||||
#define PyMPIOp_Get _mpi4py_PyMPIOp_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_GROUP
|
||||
_mpi4py_declare_pycapi(Group,)
|
||||
#define PyMPIGroup_Type (*_mpi4py_PyMPIGroup)
|
||||
#define PyMPIGroup_New _mpi4py_PyMPIGroup_New
|
||||
#define PyMPIGroup_Get _mpi4py_PyMPIGroup_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_INFO
|
||||
_mpi4py_declare_pycapi(Info,)
|
||||
#define PyMPIInfo_Type (*_mpi4py_PyMPIInfo)
|
||||
#define PyMPIInfo_New _mpi4py_PyMPIInfo_New
|
||||
#define PyMPIInfo_Get _mpi4py_PyMPIInfo_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_ERRHANDLER
|
||||
_mpi4py_declare_pycapi(Errhandler,)
|
||||
#define PyMPIErrhandler_Type (*_mpi4py_PyMPIErrhandler)
|
||||
#define PyMPIErrhandler_New _mpi4py_PyMPIErrhandler_New
|
||||
#define PyMPIErrhandler_Get _mpi4py_PyMPIErrhandler_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_SESSION
|
||||
_mpi4py_declare_pycapi(Session,)
|
||||
#define PyMPISession_Type (*_mpi4py_PyMPISession)
|
||||
#define PyMPISession_New _mpi4py_PyMPISession_New
|
||||
#define PyMPISession_Get _mpi4py_PyMPISession_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_COMM
|
||||
_mpi4py_declare_pycapi(Comm,)
|
||||
#define PyMPIComm_Type (*_mpi4py_PyMPIComm)
|
||||
#define PyMPIComm_New _mpi4py_PyMPIComm_New
|
||||
#define PyMPIComm_Get _mpi4py_PyMPIComm_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_WIN
|
||||
_mpi4py_declare_pycapi(Win,)
|
||||
#define PyMPIWin_Type (*_mpi4py_PyMPIWin)
|
||||
#define PyMPIWin_New _mpi4py_PyMPIWin_New
|
||||
#define PyMPIWin_Get _mpi4py_PyMPIWin_Get
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_FILE
|
||||
_mpi4py_declare_pycapi(File,)
|
||||
#define PyMPIFile_Type (*_mpi4py_PyMPIFile)
|
||||
#define PyMPIFile_New _mpi4py_PyMPIFile_New
|
||||
#define PyMPIFile_Get _mpi4py_PyMPIFile_Get
|
||||
#endif
|
||||
|
||||
#undef _mpi4py_define_pycapi
|
||||
|
||||
static int _mpi4py_ImportType(PyObject *module,
|
||||
const char *type_name,
|
||||
PyTypeObject **type)
|
||||
{
|
||||
PyObject *attr = NULL;
|
||||
attr = PyObject_GetAttrString(module, type_name);
|
||||
if (!attr)
|
||||
goto fn_fail;
|
||||
if (!PyType_Check(attr)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s.%.200s is not a type object",
|
||||
PyModule_GetName(module), type_name);
|
||||
goto fn_fail;
|
||||
}
|
||||
*type = (PyTypeObject *)attr;
|
||||
return 0;
|
||||
fn_fail:
|
||||
Py_DecRef(attr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _mpi4py_ImportFunc(PyObject *module,
|
||||
const char *func_name,
|
||||
const char *signature,
|
||||
void (**func)(void))
|
||||
{
|
||||
PyObject *pyxcapi = NULL;
|
||||
PyObject *capsule = NULL;
|
||||
union { void *obj; void (*fcn)(void); } ptr;
|
||||
pyxcapi = PyObject_GetAttrString(module, (char *)"__pyx_capi__");
|
||||
if (!pyxcapi)
|
||||
goto fn_fail;
|
||||
|
||||
capsule = PyDict_GetItemString(pyxcapi, func_name);
|
||||
if (!capsule) {
|
||||
PyErr_Format(PyExc_ImportError,
|
||||
"%.200s does not export expected C function %.200s",
|
||||
PyModule_GetName(module), func_name);
|
||||
goto fn_fail;
|
||||
}
|
||||
if (!PyCapsule_CheckExact(capsule)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"%.200s.%.200s is not a capsule",
|
||||
PyModule_GetName(module), func_name);
|
||||
}
|
||||
if (!signature) {
|
||||
signature = PyCapsule_GetName(capsule);
|
||||
}
|
||||
if (!PyCapsule_IsValid(capsule, signature)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"C function %.200s.%.200s has wrong signature "
|
||||
"(expected %.500s, got %.500s)",
|
||||
PyModule_GetName(module), func_name,
|
||||
signature, PyCapsule_GetName(capsule));
|
||||
goto fn_fail;
|
||||
}
|
||||
ptr.obj = PyCapsule_GetPointer(capsule, signature);
|
||||
if (!ptr.obj)
|
||||
goto fn_fail;
|
||||
*func = ptr.fcn;
|
||||
Py_DecRef(pyxcapi);
|
||||
return 0;
|
||||
fn_fail:
|
||||
Py_DecRef(pyxcapi);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int import_mpi4py_MPI(void)
|
||||
{
|
||||
PyObject *module = PyImport_ImportModule("mpi4py.MPI");
|
||||
if (!module)
|
||||
goto fn_fail;
|
||||
|
||||
#define _mpi4py_import_pycapi(Type) do { \
|
||||
if (_mpi4py_ImportType(module, #Type, &_mpi4py_PyMPI##Type) < 0) \
|
||||
goto fn_fail; \
|
||||
if (_mpi4py_ImportFunc(module, "PyMPI" #Type "_New", NULL, \
|
||||
(void (**)(void))&_mpi4py_PyMPI##Type##_New) < 0) \
|
||||
goto fn_fail; \
|
||||
if (_mpi4py_ImportFunc(module, "PyMPI" #Type "_Get", NULL, \
|
||||
(void (**)(void))&_mpi4py_PyMPI##Type##_Get) < 0) \
|
||||
goto fn_fail; \
|
||||
} while (0)
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_DATATYPE
|
||||
_mpi4py_import_pycapi(Datatype);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_STATUS
|
||||
_mpi4py_import_pycapi(Status);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_REQUEST
|
||||
_mpi4py_import_pycapi(Request);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_MESSAGE
|
||||
_mpi4py_import_pycapi(Message);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_OP
|
||||
_mpi4py_import_pycapi(Op);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_GROUP
|
||||
_mpi4py_import_pycapi(Group);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_INFO
|
||||
_mpi4py_import_pycapi(Info);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_ERRHANDLER
|
||||
_mpi4py_import_pycapi(Errhandler);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_SESSION
|
||||
_mpi4py_import_pycapi(Session);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_COMM
|
||||
_mpi4py_import_pycapi(Comm);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_WIN
|
||||
_mpi4py_import_pycapi(Win);
|
||||
#endif
|
||||
|
||||
#ifndef MPI4PY_LIMITED_API_SKIP_FILE
|
||||
_mpi4py_import_pycapi(File);
|
||||
#endif
|
||||
|
||||
#undef _mpi4py_import_pycapi
|
||||
|
||||
Py_DecRef(module);
|
||||
return 0;
|
||||
fn_fail:
|
||||
Py_DecRef(module);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define __PYX_HAVE_API__mpi4py__MPI
|
||||
#define import_mpi4py__MPI import_mpi4py_MPI
|
||||
|
||||
#endif /* MPI4PY_PYCAPI_H */
|
@ -1,14 +1,16 @@
|
||||
#ifndef NGCORE_MPIWRAPPER_HPP
|
||||
#define NGCORE_MPIWRAPPER_HPP
|
||||
|
||||
#ifdef PARALLEL
|
||||
#define OMPI_SKIP_MPICXX
|
||||
#include <mpi.h>
|
||||
#endif
|
||||
#include <array>
|
||||
|
||||
#include <complex>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "table.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "profiler.hpp"
|
||||
#include "ngstream.hpp"
|
||||
#include "ng_mpi.hpp"
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
@ -18,44 +20,133 @@ namespace ngcore
|
||||
template <class T> struct MPI_typetrait { };
|
||||
|
||||
template <> struct MPI_typetrait<int> {
|
||||
static MPI_Datatype MPIType () { return MPI_INT; } };
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_INT; } };
|
||||
|
||||
template <> struct MPI_typetrait<short> {
|
||||
static MPI_Datatype MPIType () { return MPI_SHORT; } };
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_SHORT; } };
|
||||
|
||||
template <> struct MPI_typetrait<char> {
|
||||
static MPI_Datatype MPIType () { return MPI_CHAR; } };
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };
|
||||
|
||||
template <> struct MPI_typetrait<signed char> {
|
||||
static MPI_Datatype MPIType () { return MPI_CHAR; } };
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };
|
||||
|
||||
template <> struct MPI_typetrait<unsigned char> {
|
||||
static MPI_Datatype MPIType () { return MPI_CHAR; } };
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_CHAR; } };
|
||||
|
||||
template <> struct MPI_typetrait<size_t> {
|
||||
static MPI_Datatype MPIType () { return MPI_UINT64_T; } };
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_UINT64_T; } };
|
||||
|
||||
template <> struct MPI_typetrait<double> {
|
||||
static MPI_Datatype MPIType () { return MPI_DOUBLE; } };
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_DOUBLE; } };
|
||||
|
||||
template <> struct MPI_typetrait<std::complex<double>> {
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_CXX_DOUBLE_COMPLEX; } };
|
||||
|
||||
template <> struct MPI_typetrait<bool> {
|
||||
static MPI_Datatype MPIType () { return MPI_C_BOOL; } };
|
||||
static NG_MPI_Datatype MPIType () { return NG_MPI_C_BOOL; } };
|
||||
|
||||
|
||||
template<typename T, size_t S>
|
||||
struct MPI_typetrait<std::array<T,S>>
|
||||
{
|
||||
static NG_MPI_Datatype MPIType ()
|
||||
{
|
||||
static NG_MPI_Datatype NG_MPI_T = 0;
|
||||
if (!NG_MPI_T)
|
||||
{
|
||||
NG_MPI_Type_contiguous ( S, MPI_typetrait<T>::MPIType(), &NG_MPI_T);
|
||||
NG_MPI_Type_commit ( &NG_MPI_T );
|
||||
}
|
||||
return NG_MPI_T;
|
||||
}
|
||||
};
|
||||
|
||||
template <class T, class T2 = decltype(MPI_typetrait<T>::MPIType())>
|
||||
inline MPI_Datatype GetMPIType () {
|
||||
inline NG_MPI_Datatype GetMPIType () {
|
||||
return MPI_typetrait<T>::MPIType();
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
inline MPI_Datatype GetMPIType (T &) {
|
||||
inline NG_MPI_Datatype GetMPIType (T &) {
|
||||
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;
|
||||
NG_MPI_Waitany (requests.Size(), requests.Data(), &nr, NG_MPI_STATUS_IGNORE);
|
||||
return nr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class NgMPI_Comm
|
||||
{
|
||||
protected:
|
||||
MPI_Comm comm;
|
||||
NG_MPI_Comm comm;
|
||||
bool valid_comm;
|
||||
int * refcount;
|
||||
int rank, size;
|
||||
@ -64,11 +155,11 @@ namespace ngcore
|
||||
: valid_comm(false), refcount(nullptr), rank(0), size(1)
|
||||
{ ; }
|
||||
|
||||
NgMPI_Comm (MPI_Comm _comm, bool owns = false)
|
||||
NgMPI_Comm (NG_MPI_Comm _comm, bool owns = false)
|
||||
: comm(_comm), valid_comm(true)
|
||||
{
|
||||
int flag;
|
||||
MPI_Initialized (&flag);
|
||||
NG_MPI_Initialized (&flag);
|
||||
if (!flag)
|
||||
{
|
||||
valid_comm = false;
|
||||
@ -83,8 +174,8 @@ namespace ngcore
|
||||
else
|
||||
refcount = new int{1};
|
||||
|
||||
MPI_Comm_rank(comm, &rank);
|
||||
MPI_Comm_size(comm, &size);
|
||||
NG_MPI_Comm_rank(comm, &rank);
|
||||
NG_MPI_Comm_size(comm, &size);
|
||||
}
|
||||
|
||||
NgMPI_Comm (const NgMPI_Comm & c)
|
||||
@ -105,7 +196,7 @@ namespace ngcore
|
||||
{
|
||||
if (refcount)
|
||||
if (--(*refcount) == 0)
|
||||
MPI_Comm_free(&comm);
|
||||
NG_MPI_Comm_free(&comm);
|
||||
}
|
||||
|
||||
bool ValidCommunicator() const
|
||||
@ -117,7 +208,7 @@ namespace ngcore
|
||||
{
|
||||
if (refcount)
|
||||
if (--(*refcount) == 0)
|
||||
MPI_Comm_free(&comm);
|
||||
NG_MPI_Comm_free(&comm);
|
||||
|
||||
refcount = c.refcount;
|
||||
if (refcount) (*refcount)++;
|
||||
@ -133,7 +224,7 @@ namespace ngcore
|
||||
InvalidCommException() : Exception("Do not have a valid communicator") { ; }
|
||||
};
|
||||
|
||||
operator MPI_Comm() const {
|
||||
operator NG_MPI_Comm() const {
|
||||
if (!valid_comm) throw InvalidCommException();
|
||||
return comm;
|
||||
}
|
||||
@ -142,7 +233,7 @@ namespace ngcore
|
||||
int Size() const { return size; }
|
||||
void Barrier() const {
|
||||
static Timer t("MPI - Barrier"); RegionTimer reg(t);
|
||||
if (size > 1) MPI_Barrier (comm);
|
||||
if (size > 1) NG_MPI_Barrier (comm);
|
||||
}
|
||||
|
||||
|
||||
@ -150,82 +241,82 @@ namespace ngcore
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
void Send (T & val, int dest, int tag) const {
|
||||
MPI_Send (&val, 1, GetMPIType<T>(), dest, tag, comm);
|
||||
NG_MPI_Send (&val, 1, GetMPIType<T>(), dest, tag, comm);
|
||||
}
|
||||
|
||||
void Send (const std::string & s, int dest, int tag) const {
|
||||
MPI_Send( const_cast<char*> (&s[0]), s.length(), MPI_CHAR, dest, tag, comm);
|
||||
NG_MPI_Send( const_cast<char*> (&s[0]), s.length(), NG_MPI_CHAR, dest, tag, comm);
|
||||
}
|
||||
|
||||
template<typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>
|
||||
void Send(FlatArray<T,TI> s, int dest, int tag) const {
|
||||
MPI_Send (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm);
|
||||
NG_MPI_Send (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm);
|
||||
}
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
void Recv (T & val, int src, int tag) const {
|
||||
MPI_Recv (&val, 1, GetMPIType<T>(), src, tag, comm, MPI_STATUS_IGNORE);
|
||||
NG_MPI_Recv (&val, 1, GetMPIType<T>(), src, tag, comm, NG_MPI_STATUS_IGNORE);
|
||||
}
|
||||
|
||||
void Recv (std::string & s, int src, int tag) const {
|
||||
MPI_Status status;
|
||||
NG_MPI_Status status;
|
||||
int len;
|
||||
MPI_Probe (src, tag, comm, &status);
|
||||
MPI_Get_count (&status, MPI_CHAR, &len);
|
||||
NG_MPI_Probe (src, tag, comm, &status);
|
||||
NG_MPI_Get_count (&status, NG_MPI_CHAR, &len);
|
||||
// s.assign (len, ' ');
|
||||
s.resize (len);
|
||||
MPI_Recv( &s[0], len, MPI_CHAR, src, tag, comm, MPI_STATUS_IGNORE);
|
||||
NG_MPI_Recv( &s[0], len, NG_MPI_CHAR, src, tag, comm, NG_MPI_STATUS_IGNORE);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>
|
||||
void Recv (FlatArray <T,TI> s, int src, int tag) const {
|
||||
MPI_Recv (s.Data(), s.Size(), GetMPIType<T> (), src, tag, comm, MPI_STATUS_IGNORE);
|
||||
NG_MPI_Recv (s.Data(), s.Size(), GetMPIType<T> (), src, tag, comm, NG_MPI_STATUS_IGNORE);
|
||||
}
|
||||
|
||||
template <typename T, typename TI, typename T2 = decltype(GetMPIType<T>())>
|
||||
void Recv (Array <T,TI> & s, int src, int tag) const
|
||||
{
|
||||
MPI_Status status;
|
||||
NG_MPI_Status status;
|
||||
int len;
|
||||
const MPI_Datatype MPI_T = GetMPIType<T> ();
|
||||
MPI_Probe (src, tag, comm, &status);
|
||||
MPI_Get_count (&status, MPI_T, &len);
|
||||
const NG_MPI_Datatype NG_MPI_T = GetMPIType<T> ();
|
||||
NG_MPI_Probe (src, tag, comm, &status);
|
||||
NG_MPI_Get_count (&status, NG_MPI_T, &len);
|
||||
s.SetSize (len);
|
||||
MPI_Recv (s.Data(), len, MPI_T, src, tag, comm, MPI_STATUS_IGNORE);
|
||||
NG_MPI_Recv (s.Data(), len, NG_MPI_T, src, tag, comm, NG_MPI_STATUS_IGNORE);
|
||||
}
|
||||
|
||||
/** --- non-blocking P2P --- **/
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
MPI_Request ISend (T & val, int dest, int tag) const
|
||||
{
|
||||
MPI_Request request;
|
||||
MPI_Isend (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);
|
||||
return request;
|
||||
}
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
MPI_Request ISend (FlatArray<T> s, int dest, int tag) const
|
||||
{
|
||||
MPI_Request request;
|
||||
MPI_Isend (s.Data(), s.Size(), GetMPIType<T>(), dest, tag, comm, &request);
|
||||
return request;
|
||||
}
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
MPI_Request IRecv (T & val, int dest, int tag) const
|
||||
[[nodiscard]] NG_MPI_Request ISend (T & val, int dest, int tag) const
|
||||
{
|
||||
MPI_Request request;
|
||||
MPI_Irecv (&val, 1, GetMPIType<T>(), dest, tag, comm, &request);
|
||||
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>())>
|
||||
MPI_Request IRecv (FlatArray<T> s, int src, 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>())>
|
||||
[[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);
|
||||
return request;
|
||||
}
|
||||
|
||||
template<typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
[[nodiscard]] NG_MPI_Request IRecv (FlatArray<T> s, int src, int tag) const
|
||||
{
|
||||
MPI_Request request;
|
||||
MPI_Irecv (s.Data(), s.Size(), GetMPIType<T>(), src, tag, comm, &request);
|
||||
NG_MPI_Request request;
|
||||
NG_MPI_Irecv (s.Data(), s.Size(), GetMPIType<T>(), src, tag, comm, &request);
|
||||
return request;
|
||||
}
|
||||
|
||||
@ -233,48 +324,100 @@ namespace ngcore
|
||||
/** --- collectives --- **/
|
||||
|
||||
template <typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
T Reduce (T d, const MPI_Op & op, int root = 0) const
|
||||
T Reduce (T d, const NG_MPI_Op & op, int root = 0) const
|
||||
{
|
||||
static Timer t("MPI - Reduce"); RegionTimer reg(t);
|
||||
if (size == 1) return d;
|
||||
|
||||
T global_d;
|
||||
MPI_Reduce (&d, &global_d, 1, GetMPIType<T>(), op, root, comm);
|
||||
NG_MPI_Reduce (&d, &global_d, 1, GetMPIType<T>(), op, root, comm);
|
||||
return global_d;
|
||||
}
|
||||
|
||||
template <typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
T AllReduce (T d, const MPI_Op & op) const
|
||||
T AllReduce (T d, const NG_MPI_Op & op) const
|
||||
{
|
||||
static Timer t("MPI - AllReduce"); RegionTimer reg(t);
|
||||
if (size == 1) return d;
|
||||
|
||||
T global_d;
|
||||
MPI_Allreduce ( &d, &global_d, 1, GetMPIType<T>(), op, comm);
|
||||
NG_MPI_Allreduce ( &d, &global_d, 1, GetMPIType<T>(), op, comm);
|
||||
return global_d;
|
||||
}
|
||||
|
||||
template <typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
void Bcast (T & s, int root = 0) const {
|
||||
if (size == 1) return ;
|
||||
static Timer t("MPI - Bcast"); RegionTimer reg(t);
|
||||
MPI_Bcast (&s, 1, GetMPIType<T>(), root, comm);
|
||||
void AllReduce (FlatArray<T> d, const NG_MPI_Op & op) const
|
||||
{
|
||||
static Timer t("MPI - AllReduce Array"); RegionTimer reg(t);
|
||||
if (size == 1) return;
|
||||
|
||||
NG_MPI_Allreduce (NG_MPI_IN_PLACE, d.Data(), d.Size(), GetMPIType<T>(), op, comm);
|
||||
}
|
||||
|
||||
template <typename T, typename T2 = decltype(GetMPIType<T>())>
|
||||
void Bcast (T & s, int root = 0) const {
|
||||
if (size == 1) return;
|
||||
static Timer t("MPI - Bcast"); RegionTimer reg(t);
|
||||
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) const
|
||||
{
|
||||
if (size == 1) return;
|
||||
|
||||
int ds = d.Size();
|
||||
Bcast (ds, root);
|
||||
if (Rank() != root) d.SetSize (ds);
|
||||
if (ds != 0)
|
||||
NG_MPI_Bcast (d.Data(), ds, GetMPIType<T>(), root, comm);
|
||||
}
|
||||
|
||||
|
||||
void Bcast (std::string & s, int root = 0) const
|
||||
{
|
||||
if (size == 1) return;
|
||||
int len = s.length();
|
||||
Bcast (len, root);
|
||||
if (rank != 0) s.resize (len);
|
||||
MPI_Bcast (&s[0], len, MPI_CHAR, root, comm);
|
||||
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
|
||||
{
|
||||
MPI_Alltoall (send.Data(), 1, GetMPIType<T>(),
|
||||
recv.Data(), 1, GetMPIType<T>(), comm);
|
||||
NG_MPI_Alltoall (send.Data(), 1, GetMPIType<T>(),
|
||||
recv.Data(), 1, GetMPIType<T>(), comm);
|
||||
}
|
||||
|
||||
|
||||
@ -282,18 +425,36 @@ namespace ngcore
|
||||
void ScatterRoot (FlatArray<T> send) const
|
||||
{
|
||||
if (size == 1) return;
|
||||
MPI_Scatter (send.Data(), 1, GetMPIType<T>(),
|
||||
MPI_IN_PLACE, -1, GetMPIType<T>(), 0, comm);
|
||||
NG_MPI_Scatter (send.Data(), 1, GetMPIType<T>(),
|
||||
NG_MPI_IN_PLACE, -1, GetMPIType<T>(), 0, comm);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Scatter (T & recv) const
|
||||
{
|
||||
if (size == 1) return;
|
||||
MPI_Scatter (NULL, 0, GetMPIType<T>(),
|
||||
&recv, 1, GetMPIType<T>(), 0, comm);
|
||||
NG_MPI_Scatter (NULL, 0, GetMPIType<T>(),
|
||||
&recv, 1, GetMPIType<T>(), 0, comm);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void GatherRoot (FlatArray<T> recv) const
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void Gather (T send) const
|
||||
{
|
||||
if (size == 1) return;
|
||||
NG_MPI_Gather (&send, 1, GetMPIType<T>(),
|
||||
NULL, 1, GetMPIType<T>(), 0, comm);
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
void AllGather (T val, FlatArray<T> recv) const
|
||||
{
|
||||
@ -302,66 +463,108 @@ namespace ngcore
|
||||
recv[0] = val;
|
||||
return;
|
||||
}
|
||||
MPI_Allgather (&val, 1, GetMPIType<T>(),
|
||||
NG_MPI_Allgather (&val, 1, GetMPIType<T>(),
|
||||
recv.Data(), 1, GetMPIType<T>(),
|
||||
comm);
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
void ExchangeTable (DynamicTable<T> & send_data,
|
||||
DynamicTable<T> & recv_data, int tag)
|
||||
{
|
||||
Array<int> send_sizes(size);
|
||||
Array<int> recv_sizes(size);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
send_sizes[i] = send_data[i].Size();
|
||||
|
||||
AllToAll (send_sizes, recv_sizes);
|
||||
|
||||
recv_data = DynamicTable<T> (recv_sizes, true);
|
||||
|
||||
NgMPI_Requests requests;
|
||||
for (int dest = 0; dest < size; dest++)
|
||||
if (dest != rank && send_data[dest].Size())
|
||||
requests += ISend (FlatArray<T>(send_data[dest]), dest, tag);
|
||||
|
||||
for (int dest = 0; dest < size; dest++)
|
||||
if (dest != rank && recv_data[dest].Size())
|
||||
requests += IRecv (FlatArray<T>(recv_data[dest]), dest, tag);
|
||||
|
||||
requests.WaitAll();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
NgMPI_Comm SubCommunicator (FlatArray<int> procs) const
|
||||
{
|
||||
MPI_Comm subcomm;
|
||||
MPI_Group gcomm, gsubcomm;
|
||||
MPI_Comm_group(comm, &gcomm);
|
||||
MPI_Group_incl(gcomm, procs.Size(), procs.Data(), &gsubcomm);
|
||||
MPI_Comm_create_group(comm, gsubcomm, 4242, &subcomm);
|
||||
NG_MPI_Comm subcomm;
|
||||
NG_MPI_Group gcomm, gsubcomm;
|
||||
NG_MPI_Comm_group(comm, &gcomm);
|
||||
NG_MPI_Group_incl(gcomm, procs.Size(), procs.Data(), &gsubcomm);
|
||||
NG_MPI_Comm_create_group(comm, gsubcomm, 4242, &subcomm);
|
||||
return NgMPI_Comm(subcomm, true);
|
||||
}
|
||||
|
||||
}; // class NgMPI_Comm
|
||||
|
||||
NETGEN_INLINE void MyMPI_WaitAll (FlatArray<MPI_Request> requests)
|
||||
{
|
||||
static Timer t("MPI - WaitAll"); RegionTimer reg(t);
|
||||
if (!requests.Size()) return;
|
||||
MPI_Waitall (requests.Size(), requests.Data(), MPI_STATUSES_IGNORE);
|
||||
}
|
||||
|
||||
NETGEN_INLINE int MyMPI_WaitAny (FlatArray<MPI_Request> requests)
|
||||
{
|
||||
int nr;
|
||||
MPI_Waitany (requests.Size(), requests.Data(), &nr, MPI_STATUS_IGNORE);
|
||||
return nr;
|
||||
}
|
||||
|
||||
#else // PARALLEL
|
||||
class MPI_Comm {
|
||||
class NG_MPI_Comm {
|
||||
int nr;
|
||||
public:
|
||||
MPI_Comm (int _nr = 0) : nr(_nr) { ; }
|
||||
NG_MPI_Comm (int _nr = 0) : nr(_nr) { ; }
|
||||
operator int() const { return nr; }
|
||||
bool operator== (MPI_Comm c2) const { return nr == c2.nr; }
|
||||
bool operator== (NG_MPI_Comm c2) const { return nr == c2.nr; }
|
||||
};
|
||||
static MPI_Comm MPI_COMM_WORLD = 12345, MPI_COMM_NULL = 10000;
|
||||
static NG_MPI_Comm NG_MPI_COMM_WORLD = 12345, NG_MPI_COMM_NULL = 10000;
|
||||
|
||||
typedef int MPI_Op;
|
||||
typedef int MPI_Datatype;
|
||||
typedef int MPI_Request;
|
||||
typedef int NG_MPI_Op;
|
||||
typedef int NG_MPI_Datatype;
|
||||
typedef int NG_MPI_Request;
|
||||
|
||||
enum { MPI_SUM = 0, MPI_MIN = 1, MPI_MAX = 2, MPI_LOR = 4711 };
|
||||
enum { NG_MPI_SUM = 0, NG_MPI_MIN = 1, NG_MPI_MAX = 2, NG_MPI_LOR = 4711 };
|
||||
|
||||
inline void NG_MPI_Type_contiguous ( int, NG_MPI_Datatype, NG_MPI_Datatype*) { ; }
|
||||
inline void NG_MPI_Type_commit ( NG_MPI_Datatype * ) { ; }
|
||||
|
||||
template <class T> struct MPI_typetrait {
|
||||
static NG_MPI_Datatype MPIType () { return -1; }
|
||||
};
|
||||
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
|
||||
{
|
||||
|
||||
public:
|
||||
NgMPI_Comm () { ; }
|
||||
NgMPI_Comm (MPI_Comm _comm, bool owns = false) { ; }
|
||||
NgMPI_Comm (NG_MPI_Comm _comm, bool owns = false) { ; }
|
||||
|
||||
size_t Rank() const { return 0; }
|
||||
size_t Size() const { return 1; }
|
||||
bool ValidCommunicator() const { return false; }
|
||||
void Barrier() const { ; }
|
||||
operator MPI_Comm() const { return MPI_Comm(); }
|
||||
operator NG_MPI_Comm() const { return NG_MPI_Comm(); }
|
||||
|
||||
template<typename T>
|
||||
void Send( T & val, int dest, int tag) const { ; }
|
||||
@ -379,31 +582,58 @@ namespace ngcore
|
||||
void Recv (Array <T> & s, int src, int tag) const { ; }
|
||||
|
||||
template<typename T>
|
||||
MPI_Request ISend (T & val, int dest, int tag) const { return 0; }
|
||||
NG_MPI_Request ISend (T & val, int dest, int tag) const { return 0; }
|
||||
|
||||
template<typename T>
|
||||
MPI_Request ISend (FlatArray<T> s, int dest, int tag) const { return 0; }
|
||||
NG_MPI_Request ISend (FlatArray<T> s, int dest, int tag) const { return 0; }
|
||||
|
||||
template<typename T>
|
||||
MPI_Request IRecv (T & val, int dest, int tag) const { return 0; }
|
||||
NG_MPI_Request IRecv (T & val, int dest, int tag) const { return 0; }
|
||||
|
||||
template<typename T>
|
||||
MPI_Request IRecv (FlatArray<T> s, int src, int tag) const { return 0; }
|
||||
NG_MPI_Request IRecv (FlatArray<T> s, int src, int tag) const { return 0; }
|
||||
|
||||
template <typename T>
|
||||
T Reduce (T d, const MPI_Op & op, int root = 0) const { return d; }
|
||||
T Reduce (T d, const NG_MPI_Op & op, int root = 0) const { return d; }
|
||||
|
||||
template <typename T>
|
||||
T AllReduce (T d, const MPI_Op & op) const { return d; }
|
||||
T AllReduce (T d, const NG_MPI_Op & op) const { return d; }
|
||||
|
||||
template <typename T>
|
||||
void AllReduce (FlatArray<T> d, const NG_MPI_Op & op) const { ; }
|
||||
|
||||
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) 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
|
||||
{
|
||||
recv[0] = val;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void ExchangeTable (DynamicTable<T> & send_data,
|
||||
DynamicTable<T> & recv_data, int tag) { ; }
|
||||
|
||||
|
||||
NgMPI_Comm SubCommunicator (FlatArray<int> procs) const
|
||||
{ return *this; }
|
||||
};
|
||||
|
||||
NETGEN_INLINE void MyMPI_WaitAll (FlatArray<MPI_Request> requests) { ; }
|
||||
inline void MyMPI_WaitAll (FlatArray<NG_MPI_Request> requests) { ; }
|
||||
inline int MyMPI_WaitAny (FlatArray<NG_MPI_Request> requests) { return 0; }
|
||||
|
||||
#endif // PARALLEL
|
||||
|
||||
|
184
libsrc/core/ng_mpi.cpp
Normal file
184
libsrc/core/ng_mpi.cpp
Normal file
@ -0,0 +1,184 @@
|
||||
#define OMPI_SKIP_MPICXX
|
||||
#include <mpi.h>
|
||||
|
||||
#include "ng_mpi.hpp"
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
|
||||
#ifdef NG_PYTHON
|
||||
#include "pybind11/pytypes.h"
|
||||
#include "python_ngcore.hpp"
|
||||
|
||||
#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,
|
||||
MPI_Comm* arg3) {
|
||||
throw std::runtime_error(
|
||||
"MPI_Comm_create_group not supported on Microsoft MPI");
|
||||
}
|
||||
static MPI_Datatype MPI_CXX_DOUBLE_COMPLEX;
|
||||
#endif // MSMPI_VER
|
||||
|
||||
namespace ngcore {
|
||||
|
||||
static_assert(sizeof(MPI_Status) <= sizeof(NG_MPI_Status), "Size mismatch");
|
||||
static_assert(alignof(MPI_Status) <= alignof(NG_MPI_Status), "Size mismatch");
|
||||
|
||||
int mpi2ng(int value) { return value; }
|
||||
void* mpi2ng(void* ptr) { return ptr; }
|
||||
|
||||
NG_MPI_Status* mpi2ng(MPI_Status* status) {
|
||||
return reinterpret_cast<NG_MPI_Status*>(status);
|
||||
}
|
||||
|
||||
#if !defined(MPICH) && !defined(MSMPI_VER)
|
||||
NG_MPI_Comm mpi2ng(MPI_Comm comm) { return reinterpret_cast<uintptr_t>(comm); }
|
||||
#endif
|
||||
|
||||
template <size_t size, size_t stride>
|
||||
void gather_strided_array(size_t count, char* data) {
|
||||
static_assert(size <= stride, "Size must be less than or equal to stride");
|
||||
if constexpr (size < stride) {
|
||||
char* dst = data;
|
||||
char* src = data;
|
||||
for ( [[maybe_unused]] auto i : Range(count)) {
|
||||
memcpy(dst, src, size);
|
||||
dst += size;
|
||||
src += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T cast_ng2mpi(uintptr_t obj) {
|
||||
if constexpr (std::is_pointer_v<T>)
|
||||
return reinterpret_cast<T>(obj);
|
||||
else
|
||||
return static_cast<T>(obj);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T cast_ng2mpi(uintptr_t* ptr) {
|
||||
if constexpr (std::is_pointer_v<T>)
|
||||
return reinterpret_cast<T>(ptr);
|
||||
else
|
||||
return static_cast<T>(ptr);
|
||||
}
|
||||
|
||||
template <typename T, typename TSrc>
|
||||
T* cast_ng2mpi(TSrc* ptr, int count) {
|
||||
gather_strided_array<sizeof(T), sizeof(TSrc)>(count,
|
||||
reinterpret_cast<char*>(ptr));
|
||||
return reinterpret_cast<T*>(ptr);
|
||||
}
|
||||
|
||||
MPI_Comm ng2mpi(NG_MPI_Comm comm) {
|
||||
static_assert(sizeof(MPI_Comm) <= sizeof(comm.value), "Size mismatch");
|
||||
static_assert(alignof(MPI_Comm) <= alignof(NG_MPI_Comm), "Size mismatch");
|
||||
return cast_ng2mpi<MPI_Comm>(comm.value);
|
||||
}
|
||||
|
||||
MPI_Group ng2mpi(NG_MPI_Group group) {
|
||||
static_assert(sizeof(MPI_Group) <= sizeof(group.value), "Size mismatch");
|
||||
static_assert(alignof(MPI_Group) <= alignof(NG_MPI_Group), "Size mismatch");
|
||||
return cast_ng2mpi<MPI_Group>(group.value);
|
||||
}
|
||||
|
||||
MPI_Comm* ng2mpi(NG_MPI_Comm* comm) {
|
||||
return cast_ng2mpi<MPI_Comm*>(&comm->value);
|
||||
}
|
||||
MPI_Group* ng2mpi(NG_MPI_Group* group) {
|
||||
return cast_ng2mpi<MPI_Group*>(&group->value);
|
||||
}
|
||||
MPI_Datatype* ng2mpi(NG_MPI_Datatype* type) {
|
||||
return cast_ng2mpi<MPI_Datatype*>(&type->value);
|
||||
}
|
||||
MPI_Datatype* ng2mpi(NG_MPI_Datatype* type, int count) {
|
||||
return cast_ng2mpi<MPI_Datatype>(&type->value, count);
|
||||
}
|
||||
MPI_Request* ng2mpi(NG_MPI_Request* request) {
|
||||
return cast_ng2mpi<MPI_Request*>(&request->value);
|
||||
}
|
||||
MPI_Request* ng2mpi(NG_MPI_Request* request, int count) {
|
||||
return cast_ng2mpi<MPI_Request>(&request->value, count);
|
||||
}
|
||||
MPI_Status* ng2mpi(NG_MPI_Status* status) {
|
||||
return reinterpret_cast<MPI_Status*>(status);
|
||||
}
|
||||
MPI_Aint* ng2mpi(NG_MPI_Aint* aint) {
|
||||
return reinterpret_cast<MPI_Aint*>(aint);
|
||||
}
|
||||
MPI_Aint* ng2mpi(NG_MPI_Aint* aint, int count) {
|
||||
return cast_ng2mpi<MPI_Aint>(aint, count);
|
||||
}
|
||||
|
||||
MPI_Datatype ng2mpi(NG_MPI_Datatype type) {
|
||||
static_assert(sizeof(MPI_Datatype) <= sizeof(type.value), "Size mismatch");
|
||||
return cast_ng2mpi<MPI_Datatype>(type.value);
|
||||
}
|
||||
|
||||
MPI_Request ng2mpi(NG_MPI_Request request) {
|
||||
static_assert(sizeof(MPI_Request) <= sizeof(request.value), "Size mismatch");
|
||||
return cast_ng2mpi<MPI_Request>(request.value);
|
||||
}
|
||||
|
||||
MPI_Op ng2mpi(NG_MPI_Op op) {
|
||||
static_assert(sizeof(MPI_Op) <= sizeof(op.value), "Size mismatch");
|
||||
return cast_ng2mpi<MPI_Op>(op.value);
|
||||
}
|
||||
|
||||
MPI_Aint ng2mpi(NG_MPI_Aint aint) {
|
||||
static_assert(sizeof(MPI_Aint) <= sizeof(aint.value), "Size mismatch");
|
||||
return cast_ng2mpi<MPI_Aint>(aint.value);
|
||||
}
|
||||
|
||||
void* ng2mpi(void* ptr) { return ptr; }
|
||||
char* ng2mpi(char* ptr) { return ptr; }
|
||||
char*** ng2mpi(char*** ptr) { return ptr; }
|
||||
int* ng2mpi(int* ptr) { return ptr; }
|
||||
int ng2mpi(int value) { return value; }
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
using namespace ngcore;
|
||||
|
||||
extern "C" {
|
||||
NGCORE_API_EXPORT void ng_init_mpi();
|
||||
}
|
||||
|
||||
static bool imported_mpi4py = false;
|
||||
|
||||
void ng_init_mpi() {
|
||||
#ifdef NG_PYTHON
|
||||
NG_MPI_CommFromMPI4Py = [](py::handle src, NG_MPI_Comm& dst) -> bool {
|
||||
if (!imported_mpi4py) {
|
||||
import_mpi4py__MPI();
|
||||
imported_mpi4py = true;
|
||||
}
|
||||
PyObject* py_src = src.ptr();
|
||||
[[maybe_unused]] auto type = Py_TYPE(py_src);
|
||||
if (PyObject_TypeCheck(py_src, &PyMPIComm_Type)) {
|
||||
dst = mpi2ng(*PyMPIComm_Get(py_src));
|
||||
return !PyErr_Occurred();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
NG_MPI_CommToMPI4Py = [](NG_MPI_Comm src) -> py::handle {
|
||||
if (!imported_mpi4py) {
|
||||
import_mpi4py__MPI();
|
||||
imported_mpi4py = true;
|
||||
}
|
||||
return py::handle(PyMPIComm_New(ng2mpi(src)));
|
||||
};
|
||||
#endif // NG_PYTHON
|
||||
|
||||
#include "ng_mpi_generated_init.hpp"
|
||||
}
|
94
libsrc/core/ng_mpi.hpp
Normal file
94
libsrc/core/ng_mpi.hpp
Normal file
@ -0,0 +1,94 @@
|
||||
#ifndef NG_MPI_HPP_INCLUDED
|
||||
#define NG_MPI_HPP_INCLUDED
|
||||
|
||||
#ifdef PARALLEL
|
||||
|
||||
#include <cstdint>
|
||||
#include <filesystem>
|
||||
#include <optional>
|
||||
|
||||
#include "ngcore_api.hpp"
|
||||
|
||||
#ifndef NG_MPI_WRAPPER
|
||||
#define OMPI_SKIP_MPICXX
|
||||
#include <mpi.h>
|
||||
#endif // NG_MPI_WRAPPER
|
||||
|
||||
namespace ngcore {
|
||||
|
||||
NGCORE_API bool MPI_Loaded();
|
||||
NGCORE_API void InitMPI(
|
||||
std::optional<std::filesystem::path> mpi_lib_path = std::nullopt);
|
||||
|
||||
#ifdef NG_MPI_WRAPPER
|
||||
inline void not_implemented() { throw std::runtime_error("Not implemented"); }
|
||||
|
||||
struct NG_MPI_Status {
|
||||
uintptr_t data[4];
|
||||
};
|
||||
|
||||
struct NG_MPI_Comm {
|
||||
uintptr_t value;
|
||||
NG_MPI_Comm() { value = 0; }
|
||||
NG_MPI_Comm(uintptr_t value_) : value(value_) {}
|
||||
NG_MPI_Comm(const NG_MPI_Comm &comm) : value(comm.value) {}
|
||||
|
||||
void operator=(int value_) { value = value_; }
|
||||
void operator=(uintptr_t value_) { value = value_; }
|
||||
bool operator==(const NG_MPI_Comm &comm) const { return value == comm.value; }
|
||||
bool operator!=(const NG_MPI_Comm &comm) const { return value != comm.value; }
|
||||
};
|
||||
|
||||
struct NG_MPI_Datatype {
|
||||
uintptr_t value = 0;
|
||||
NG_MPI_Datatype() = default;
|
||||
NG_MPI_Datatype(uintptr_t value_) : value(value_) {}
|
||||
operator bool() const { return value != 0; }
|
||||
void operator=(NG_MPI_Datatype type) { value = type.value; }
|
||||
void operator=(uintptr_t value_) { value = value_; }
|
||||
void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }
|
||||
};
|
||||
|
||||
struct NG_MPI_Request {
|
||||
uintptr_t value = 0;
|
||||
NG_MPI_Request() = default;
|
||||
NG_MPI_Request(uintptr_t value_) : value(value_) {}
|
||||
void operator=(uintptr_t value_) { value = value_; }
|
||||
void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }
|
||||
};
|
||||
|
||||
struct NG_MPI_Op {
|
||||
uintptr_t value;
|
||||
NG_MPI_Op(uintptr_t value_) : value(value_) {}
|
||||
void operator=(uintptr_t value_) { value = value_; }
|
||||
void operator=(void *value_) { value = reinterpret_cast<uintptr_t>(value_); }
|
||||
};
|
||||
|
||||
struct NG_MPI_Group {
|
||||
uintptr_t value = 0;
|
||||
NG_MPI_Group(uintptr_t value_) : value(value_) {}
|
||||
NG_MPI_Group() = default;
|
||||
};
|
||||
|
||||
struct NG_MPI_Aint {
|
||||
intptr_t value = 0;
|
||||
NG_MPI_Aint(intptr_t value_) : value(value_) {}
|
||||
NG_MPI_Aint() = default;
|
||||
};
|
||||
|
||||
#else // NG_MPI_WRAPPER
|
||||
using NG_MPI_Comm = MPI_Comm;
|
||||
using NG_MPI_Status = MPI_Status;
|
||||
using NG_MPI_Datatype = MPI_Datatype;
|
||||
using NG_MPI_Request = MPI_Request;
|
||||
using NG_MPI_Op = MPI_Op;
|
||||
using NG_MPI_Group = MPI_Group;
|
||||
using NG_MPI_Aint = MPI_Aint;
|
||||
#endif // NG_MPI_WRAPPER
|
||||
|
||||
#include "ng_mpi_generated_declarations.hpp"
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
#endif // PARALLEL
|
||||
#endif // NG_MPI_HPP_INCLUDED
|
155
libsrc/core/ng_mpi_generated_declarations.hpp
Normal file
155
libsrc/core/ng_mpi_generated_declarations.hpp
Normal file
@ -0,0 +1,155 @@
|
||||
#ifdef NG_MPI_WRAPPER
|
||||
NGCORE_API extern double (*NG_MPI_Wtime)();
|
||||
NGCORE_API extern int (*NG_MPI_Allgather)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Allreduce)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, NG_MPI_Comm);
|
||||
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*);
|
||||
NGCORE_API extern int (*NG_MPI_Comm_free)(NG_MPI_Comm*);
|
||||
NGCORE_API extern int (*NG_MPI_Comm_group)(NG_MPI_Comm, NG_MPI_Group*);
|
||||
NGCORE_API extern int (*NG_MPI_Comm_rank)(NG_MPI_Comm, int*);
|
||||
NGCORE_API extern int (*NG_MPI_Comm_size)(NG_MPI_Comm, int*);
|
||||
NGCORE_API extern int (*NG_MPI_Finalize)();
|
||||
NGCORE_API extern int (*NG_MPI_Gather)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Gatherv)(void*, int, NG_MPI_Datatype, void*, int*, int*, NG_MPI_Datatype, int, NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Get_count)(NG_MPI_Status*, NG_MPI_Datatype, int*);
|
||||
NGCORE_API extern int (*NG_MPI_Get_processor_name)(char*, int*);
|
||||
NGCORE_API extern int (*NG_MPI_Group_incl)(NG_MPI_Group, int, int*, NG_MPI_Group*);
|
||||
NGCORE_API extern int (*NG_MPI_Init)(int*, char***);
|
||||
NGCORE_API extern int (*NG_MPI_Init_thread)(int*, char***, int, int*);
|
||||
NGCORE_API extern int (*NG_MPI_Initialized)(int*);
|
||||
NGCORE_API extern int (*NG_MPI_Iprobe)(int, int, NG_MPI_Comm, int*, NG_MPI_Status*);
|
||||
NGCORE_API extern int (*NG_MPI_Irecv)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);
|
||||
NGCORE_API extern int (*NG_MPI_Isend)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);
|
||||
NGCORE_API extern int (*NG_MPI_Probe)(int, int, NG_MPI_Comm, NG_MPI_Status*);
|
||||
NGCORE_API extern int (*NG_MPI_Query_thread)(int*);
|
||||
NGCORE_API extern int (*NG_MPI_Recv)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Status*);
|
||||
NGCORE_API extern int (*NG_MPI_Recv_init)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);
|
||||
NGCORE_API extern int (*NG_MPI_Reduce)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, int, NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Reduce_local)(void*, void*, int, NG_MPI_Datatype, NG_MPI_Op);
|
||||
NGCORE_API extern int (*NG_MPI_Request_free)(NG_MPI_Request*);
|
||||
NGCORE_API extern int (*NG_MPI_Scatter)(void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Send)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm);
|
||||
NGCORE_API extern int (*NG_MPI_Send_init)(void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*);
|
||||
NGCORE_API extern int (*NG_MPI_Startall)(int, NG_MPI_Request*);
|
||||
NGCORE_API extern int (*NG_MPI_Type_commit)(NG_MPI_Datatype*);
|
||||
NGCORE_API extern int (*NG_MPI_Type_contiguous)(int, NG_MPI_Datatype, NG_MPI_Datatype*);
|
||||
NGCORE_API extern int (*NG_MPI_Type_create_resized)(NG_MPI_Datatype, NG_MPI_Aint, NG_MPI_Aint, NG_MPI_Datatype*);
|
||||
NGCORE_API extern int (*NG_MPI_Type_create_struct)(int, int*, NG_MPI_Aint*, NG_MPI_Datatype*, NG_MPI_Datatype*);
|
||||
NGCORE_API extern int (*NG_MPI_Type_free)(NG_MPI_Datatype*);
|
||||
NGCORE_API extern int (*NG_MPI_Type_get_extent)(NG_MPI_Datatype, NG_MPI_Aint*, NG_MPI_Aint*);
|
||||
NGCORE_API extern int (*NG_MPI_Type_indexed)(int, int*, int*, NG_MPI_Datatype, NG_MPI_Datatype*);
|
||||
NGCORE_API extern int (*NG_MPI_Type_size)(NG_MPI_Datatype, int*);
|
||||
NGCORE_API extern int (*NG_MPI_Wait)(NG_MPI_Request*, NG_MPI_Status*);
|
||||
NGCORE_API extern int (*NG_MPI_Waitall)(int, NG_MPI_Request*, NG_MPI_Status*);
|
||||
NGCORE_API extern int (*NG_MPI_Waitany)(int, NG_MPI_Request*, int*, NG_MPI_Status*);
|
||||
NGCORE_API extern NG_MPI_Comm NG_MPI_COMM_NULL;
|
||||
NGCORE_API extern NG_MPI_Comm NG_MPI_COMM_WORLD;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_CHAR;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_CXX_DOUBLE_COMPLEX;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_C_BOOL;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_DATATYPE_NULL;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_DOUBLE;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_FLOAT;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_INT;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_SHORT;
|
||||
NGCORE_API extern NG_MPI_Datatype NG_MPI_UINT64_T;
|
||||
NGCORE_API extern NG_MPI_Op NG_MPI_LOR;
|
||||
NGCORE_API extern NG_MPI_Op NG_MPI_MAX;
|
||||
NGCORE_API extern NG_MPI_Op NG_MPI_MIN;
|
||||
NGCORE_API extern NG_MPI_Op NG_MPI_SUM;
|
||||
NGCORE_API extern NG_MPI_Request NG_MPI_REQUEST_NULL;
|
||||
NGCORE_API extern NG_MPI_Status* NG_MPI_STATUSES_IGNORE;
|
||||
NGCORE_API extern NG_MPI_Status* NG_MPI_STATUS_IGNORE;
|
||||
NGCORE_API extern int NG_MPI_ANY_SOURCE;
|
||||
NGCORE_API extern int NG_MPI_ANY_TAG;
|
||||
NGCORE_API extern int NG_MPI_MAX_PROCESSOR_NAME;
|
||||
NGCORE_API extern int NG_MPI_PROC_NULL;
|
||||
NGCORE_API extern int NG_MPI_ROOT;
|
||||
NGCORE_API extern int NG_MPI_SUBVERSION;
|
||||
NGCORE_API extern int NG_MPI_THREAD_MULTIPLE;
|
||||
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
|
||||
#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
|
76
libsrc/core/ng_mpi_generated_dummy_init.hpp
Normal file
76
libsrc/core/ng_mpi_generated_dummy_init.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
decltype(NG_MPI_Wtime) NG_MPI_Wtime = []()->double { throw no_mpi(); };
|
||||
decltype(NG_MPI_Allgather) NG_MPI_Allgather = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Allreduce) NG_MPI_Allreduce = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
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(); };
|
||||
decltype(NG_MPI_Comm_free) NG_MPI_Comm_free = [](NG_MPI_Comm*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Comm_group) NG_MPI_Comm_group = [](NG_MPI_Comm, NG_MPI_Group*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Comm_rank) NG_MPI_Comm_rank = [](NG_MPI_Comm, int*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Comm_size) NG_MPI_Comm_size = [](NG_MPI_Comm, int*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Finalize) NG_MPI_Finalize = []()->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Gather) NG_MPI_Gather = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Gatherv) NG_MPI_Gatherv = [](void*, int, NG_MPI_Datatype, void*, int*, int*, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Get_count) NG_MPI_Get_count = [](NG_MPI_Status*, NG_MPI_Datatype, int*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Get_processor_name) NG_MPI_Get_processor_name = [](char*, int*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Group_incl) NG_MPI_Group_incl = [](NG_MPI_Group, int, int*, NG_MPI_Group*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Init) NG_MPI_Init = [](int*, char***)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Init_thread) NG_MPI_Init_thread = [](int*, char***, int, int*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Initialized) NG_MPI_Initialized = [](int*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Iprobe) NG_MPI_Iprobe = [](int, int, NG_MPI_Comm, int*, NG_MPI_Status*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Irecv) NG_MPI_Irecv = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Isend) NG_MPI_Isend = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Probe) NG_MPI_Probe = [](int, int, NG_MPI_Comm, NG_MPI_Status*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Query_thread) NG_MPI_Query_thread = [](int*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Recv) NG_MPI_Recv = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Status*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Recv_init) NG_MPI_Recv_init = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Reduce) NG_MPI_Reduce = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op, int, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Reduce_local) NG_MPI_Reduce_local = [](void*, void*, int, NG_MPI_Datatype, NG_MPI_Op)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Request_free) NG_MPI_Request_free = [](NG_MPI_Request*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Scatter) NG_MPI_Scatter = [](void*, int, NG_MPI_Datatype, void*, int, NG_MPI_Datatype, int, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Send) NG_MPI_Send = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Send_init) NG_MPI_Send_init = [](void*, int, NG_MPI_Datatype, int, int, NG_MPI_Comm, NG_MPI_Request*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Startall) NG_MPI_Startall = [](int, NG_MPI_Request*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Type_commit) NG_MPI_Type_commit = [](NG_MPI_Datatype*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Type_contiguous) NG_MPI_Type_contiguous = [](int, NG_MPI_Datatype, NG_MPI_Datatype*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Type_create_resized) NG_MPI_Type_create_resized = [](NG_MPI_Datatype, NG_MPI_Aint, NG_MPI_Aint, NG_MPI_Datatype*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Type_create_struct) NG_MPI_Type_create_struct = [](int, int*, NG_MPI_Aint*, NG_MPI_Datatype*, NG_MPI_Datatype*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Type_free) NG_MPI_Type_free = [](NG_MPI_Datatype*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Type_get_extent) NG_MPI_Type_get_extent = [](NG_MPI_Datatype, NG_MPI_Aint*, NG_MPI_Aint*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Type_indexed) NG_MPI_Type_indexed = [](int, int*, int*, NG_MPI_Datatype, NG_MPI_Datatype*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Type_size) NG_MPI_Type_size = [](NG_MPI_Datatype, int*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Wait) NG_MPI_Wait = [](NG_MPI_Request*, NG_MPI_Status*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Waitall) NG_MPI_Waitall = [](int, NG_MPI_Request*, NG_MPI_Status*)->int { throw no_mpi(); };
|
||||
decltype(NG_MPI_Waitany) NG_MPI_Waitany = [](int, NG_MPI_Request*, int*, NG_MPI_Status*)->int { throw no_mpi(); };
|
||||
NG_MPI_Comm NG_MPI_COMM_NULL = 0;
|
||||
NG_MPI_Comm NG_MPI_COMM_WORLD = 0;
|
||||
NG_MPI_Datatype NG_MPI_CHAR = 0;
|
||||
NG_MPI_Datatype NG_MPI_CXX_DOUBLE_COMPLEX = 0;
|
||||
NG_MPI_Datatype NG_MPI_C_BOOL = 0;
|
||||
NG_MPI_Datatype NG_MPI_DATATYPE_NULL = 0;
|
||||
NG_MPI_Datatype NG_MPI_DOUBLE = 0;
|
||||
NG_MPI_Datatype NG_MPI_FLOAT = 0;
|
||||
NG_MPI_Datatype NG_MPI_INT = 0;
|
||||
NG_MPI_Datatype NG_MPI_SHORT = 0;
|
||||
NG_MPI_Datatype NG_MPI_UINT64_T = 0;
|
||||
NG_MPI_Op NG_MPI_LOR = 0;
|
||||
NG_MPI_Op NG_MPI_MAX = 0;
|
||||
NG_MPI_Op NG_MPI_MIN = 0;
|
||||
NG_MPI_Op NG_MPI_SUM = 0;
|
||||
NG_MPI_Request NG_MPI_REQUEST_NULL = 0;
|
||||
NG_MPI_Status* NG_MPI_STATUSES_IGNORE = 0;
|
||||
NG_MPI_Status* NG_MPI_STATUS_IGNORE = 0;
|
||||
int NG_MPI_ANY_SOURCE = 0;
|
||||
int NG_MPI_ANY_TAG = 0;
|
||||
int NG_MPI_MAX_PROCESSOR_NAME = 0;
|
||||
int NG_MPI_PROC_NULL = 0;
|
||||
int NG_MPI_ROOT = 0;
|
||||
int NG_MPI_SUBVERSION = 0;
|
||||
int NG_MPI_THREAD_MULTIPLE = 0;
|
||||
int NG_MPI_THREAD_SINGLE = 0;
|
||||
int NG_MPI_VERSION = 0;
|
||||
void* NG_MPI_IN_PLACE = 0;
|
76
libsrc/core/ng_mpi_generated_init.hpp
Normal file
76
libsrc/core/ng_mpi_generated_init.hpp
Normal file
@ -0,0 +1,76 @@
|
||||
NG_MPI_Wtime = []()->double { return MPI_Wtime(); };
|
||||
NG_MPI_Allgather = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, NG_MPI_Comm arg6)->int { return MPI_Allgather( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
|
||||
NG_MPI_Allreduce = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4, NG_MPI_Comm arg5)->int { return MPI_Allreduce( arg0, arg1, arg2, ng2mpi(arg3), ng2mpi(arg4), ng2mpi(arg5)); };
|
||||
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)); };
|
||||
NG_MPI_Comm_free = [](NG_MPI_Comm* arg0)->int { return MPI_Comm_free( ng2mpi(arg0)); };
|
||||
NG_MPI_Comm_group = [](NG_MPI_Comm arg0, NG_MPI_Group* arg1)->int { return MPI_Comm_group( ng2mpi(arg0), ng2mpi(arg1)); };
|
||||
NG_MPI_Comm_rank = [](NG_MPI_Comm arg0, int* arg1)->int { return MPI_Comm_rank( ng2mpi(arg0), arg1); };
|
||||
NG_MPI_Comm_size = [](NG_MPI_Comm arg0, int* arg1)->int { return MPI_Comm_size( ng2mpi(arg0), arg1); };
|
||||
NG_MPI_Finalize = []()->int { return MPI_Finalize(); };
|
||||
NG_MPI_Gather = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, int arg6, NG_MPI_Comm arg7)->int { return MPI_Gather( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), arg6, ng2mpi(arg7)); };
|
||||
NG_MPI_Gatherv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int* arg4, int* arg5, NG_MPI_Datatype arg6, int arg7, NG_MPI_Comm arg8)->int { return MPI_Gatherv( arg0, arg1, ng2mpi(arg2), arg3, arg4, arg5, ng2mpi(arg6), arg7, ng2mpi(arg8)); };
|
||||
NG_MPI_Get_count = [](NG_MPI_Status* arg0, NG_MPI_Datatype arg1, int* arg2)->int { return MPI_Get_count( ng2mpi(arg0), ng2mpi(arg1), arg2); };
|
||||
NG_MPI_Get_processor_name = [](char* arg0, int* arg1)->int { return MPI_Get_processor_name( arg0, arg1); };
|
||||
NG_MPI_Group_incl = [](NG_MPI_Group arg0, int arg1, int* arg2, NG_MPI_Group* arg3)->int { return MPI_Group_incl( ng2mpi(arg0), arg1, arg2, ng2mpi(arg3)); };
|
||||
NG_MPI_Init = [](int* arg0, char*** arg1)->int { return MPI_Init( arg0, arg1); };
|
||||
NG_MPI_Init_thread = [](int* arg0, char*** arg1, int arg2, int* arg3)->int { return MPI_Init_thread( arg0, arg1, arg2, arg3); };
|
||||
NG_MPI_Initialized = [](int* arg0)->int { return MPI_Initialized( arg0); };
|
||||
NG_MPI_Iprobe = [](int arg0, int arg1, NG_MPI_Comm arg2, int* arg3, NG_MPI_Status* arg4)->int { return MPI_Iprobe( arg0, arg1, ng2mpi(arg2), arg3, ng2mpi(arg4)); };
|
||||
NG_MPI_Irecv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Irecv( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
|
||||
NG_MPI_Isend = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Isend( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
|
||||
NG_MPI_Probe = [](int arg0, int arg1, NG_MPI_Comm arg2, NG_MPI_Status* arg3)->int { return MPI_Probe( arg0, arg1, ng2mpi(arg2), ng2mpi(arg3)); };
|
||||
NG_MPI_Query_thread = [](int* arg0)->int { return MPI_Query_thread( arg0); };
|
||||
NG_MPI_Recv = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Status* arg6)->int { return MPI_Recv( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
|
||||
NG_MPI_Recv_init = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Recv_init( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
|
||||
NG_MPI_Reduce = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4, int arg5, NG_MPI_Comm arg6)->int { return MPI_Reduce( arg0, arg1, arg2, ng2mpi(arg3), ng2mpi(arg4), arg5, ng2mpi(arg6)); };
|
||||
NG_MPI_Reduce_local = [](void* arg0, void* arg1, int arg2, NG_MPI_Datatype arg3, NG_MPI_Op arg4)->int { return MPI_Reduce_local( arg0, arg1, arg2, ng2mpi(arg3), ng2mpi(arg4)); };
|
||||
NG_MPI_Request_free = [](NG_MPI_Request* arg0)->int { return MPI_Request_free( ng2mpi(arg0)); };
|
||||
NG_MPI_Scatter = [](void* arg0, int arg1, NG_MPI_Datatype arg2, void* arg3, int arg4, NG_MPI_Datatype arg5, int arg6, NG_MPI_Comm arg7)->int { return MPI_Scatter( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), arg6, ng2mpi(arg7)); };
|
||||
NG_MPI_Send = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5)->int { return MPI_Send( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5)); };
|
||||
NG_MPI_Send_init = [](void* arg0, int arg1, NG_MPI_Datatype arg2, int arg3, int arg4, NG_MPI_Comm arg5, NG_MPI_Request* arg6)->int { return MPI_Send_init( arg0, arg1, ng2mpi(arg2), arg3, arg4, ng2mpi(arg5), ng2mpi(arg6)); };
|
||||
NG_MPI_Startall = [](int arg0, NG_MPI_Request* arg1)->int { return MPI_Startall( arg0, ng2mpi(arg1, arg0)); };
|
||||
NG_MPI_Type_commit = [](NG_MPI_Datatype* arg0)->int { return MPI_Type_commit( ng2mpi(arg0)); };
|
||||
NG_MPI_Type_contiguous = [](int arg0, NG_MPI_Datatype arg1, NG_MPI_Datatype* arg2)->int { return MPI_Type_contiguous( arg0, ng2mpi(arg1), ng2mpi(arg2)); };
|
||||
NG_MPI_Type_create_resized = [](NG_MPI_Datatype arg0, NG_MPI_Aint arg1, NG_MPI_Aint arg2, NG_MPI_Datatype* arg3)->int { return MPI_Type_create_resized( ng2mpi(arg0), ng2mpi(arg1), ng2mpi(arg2), ng2mpi(arg3)); };
|
||||
NG_MPI_Type_create_struct = [](int arg0, int* arg1, NG_MPI_Aint* arg2, NG_MPI_Datatype* arg3, NG_MPI_Datatype* arg4)->int { return MPI_Type_create_struct( arg0, arg1, ng2mpi(arg2, arg0), ng2mpi(arg3, arg0), ng2mpi(arg4)); };
|
||||
NG_MPI_Type_free = [](NG_MPI_Datatype* arg0)->int { return MPI_Type_free( ng2mpi(arg0)); };
|
||||
NG_MPI_Type_get_extent = [](NG_MPI_Datatype arg0, NG_MPI_Aint* arg1, NG_MPI_Aint* arg2)->int { return MPI_Type_get_extent( ng2mpi(arg0), ng2mpi(arg1), ng2mpi(arg2)); };
|
||||
NG_MPI_Type_indexed = [](int arg0, int* arg1, int* arg2, NG_MPI_Datatype arg3, NG_MPI_Datatype* arg4)->int { return MPI_Type_indexed( arg0, arg1, arg2, ng2mpi(arg3), ng2mpi(arg4)); };
|
||||
NG_MPI_Type_size = [](NG_MPI_Datatype arg0, int* arg1)->int { return MPI_Type_size( ng2mpi(arg0), arg1); };
|
||||
NG_MPI_Wait = [](NG_MPI_Request* arg0, NG_MPI_Status* arg1)->int { return MPI_Wait( ng2mpi(arg0), ng2mpi(arg1)); };
|
||||
NG_MPI_Waitall = [](int arg0, NG_MPI_Request* arg1, NG_MPI_Status* arg2)->int { return MPI_Waitall( arg0, ng2mpi(arg1, arg0), ng2mpi(arg2)); };
|
||||
NG_MPI_Waitany = [](int arg0, NG_MPI_Request* arg1, int* arg2, NG_MPI_Status* arg3)->int { return MPI_Waitany( arg0, ng2mpi(arg1, arg0), arg2, ng2mpi(arg3)); };
|
||||
NG_MPI_COMM_NULL = mpi2ng(MPI_COMM_NULL);
|
||||
NG_MPI_COMM_WORLD = mpi2ng(MPI_COMM_WORLD);
|
||||
NG_MPI_CHAR = mpi2ng(MPI_CHAR);
|
||||
NG_MPI_CXX_DOUBLE_COMPLEX = mpi2ng(MPI_CXX_DOUBLE_COMPLEX);
|
||||
NG_MPI_C_BOOL = mpi2ng(MPI_C_BOOL);
|
||||
NG_MPI_DATATYPE_NULL = mpi2ng(MPI_DATATYPE_NULL);
|
||||
NG_MPI_DOUBLE = mpi2ng(MPI_DOUBLE);
|
||||
NG_MPI_FLOAT = mpi2ng(MPI_FLOAT);
|
||||
NG_MPI_INT = mpi2ng(MPI_INT);
|
||||
NG_MPI_SHORT = mpi2ng(MPI_SHORT);
|
||||
NG_MPI_UINT64_T = mpi2ng(MPI_UINT64_T);
|
||||
NG_MPI_LOR = mpi2ng(MPI_LOR);
|
||||
NG_MPI_MAX = mpi2ng(MPI_MAX);
|
||||
NG_MPI_MIN = mpi2ng(MPI_MIN);
|
||||
NG_MPI_SUM = mpi2ng(MPI_SUM);
|
||||
NG_MPI_REQUEST_NULL = mpi2ng(MPI_REQUEST_NULL);
|
||||
NG_MPI_STATUSES_IGNORE = mpi2ng(MPI_STATUSES_IGNORE);
|
||||
NG_MPI_STATUS_IGNORE = mpi2ng(MPI_STATUS_IGNORE);
|
||||
NG_MPI_ANY_SOURCE = mpi2ng(MPI_ANY_SOURCE);
|
||||
NG_MPI_ANY_TAG = mpi2ng(MPI_ANY_TAG);
|
||||
NG_MPI_MAX_PROCESSOR_NAME = mpi2ng(MPI_MAX_PROCESSOR_NAME);
|
||||
NG_MPI_PROC_NULL = mpi2ng(MPI_PROC_NULL);
|
||||
NG_MPI_ROOT = mpi2ng(MPI_ROOT);
|
||||
NG_MPI_SUBVERSION = mpi2ng(MPI_SUBVERSION);
|
||||
NG_MPI_THREAD_MULTIPLE = mpi2ng(MPI_THREAD_MULTIPLE);
|
||||
NG_MPI_THREAD_SINGLE = mpi2ng(MPI_THREAD_SINGLE);
|
||||
NG_MPI_VERSION = mpi2ng(MPI_VERSION);
|
||||
NG_MPI_IN_PLACE = mpi2ng(MPI_IN_PLACE);
|
21
libsrc/core/ng_mpi_native.hpp
Normal file
21
libsrc/core/ng_mpi_native.hpp
Normal file
@ -0,0 +1,21 @@
|
||||
#ifndef NG_MPI_NATIVE_HPP
|
||||
#define NG_MPI_NATIVE_HPP
|
||||
|
||||
#include <mpi.h>
|
||||
|
||||
#include "mpi_wrapper.hpp"
|
||||
#include "ng_mpi.hpp"
|
||||
|
||||
namespace ngcore {
|
||||
|
||||
MPI_Comm NG_MPI_Native(NG_MPI_Comm comm) {
|
||||
return reinterpret_cast<MPI_Comm>(comm.value);
|
||||
}
|
||||
|
||||
MPI_Comm NG_MPI_Native(NgMPI_Comm comm) {
|
||||
return reinterpret_cast<MPI_Comm>(static_cast<NG_MPI_Comm>(comm).value);
|
||||
}
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
#endif // NG_MPI_NATIVE_HPP
|
206
libsrc/core/ng_mpi_wrapper.cpp
Normal file
206
libsrc/core/ng_mpi_wrapper.cpp
Normal file
@ -0,0 +1,206 @@
|
||||
#ifdef PARALLEL
|
||||
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "ng_mpi.hpp"
|
||||
#include "ngstream.hpp"
|
||||
#ifdef NG_PYTHON
|
||||
#include "python_ngcore.hpp"
|
||||
#endif // NG_PYTHON
|
||||
#include "utils.hpp"
|
||||
|
||||
using std::cerr;
|
||||
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 {
|
||||
|
||||
#ifdef NG_MPI_WRAPPER
|
||||
static std::unique_ptr<SharedLibrary> mpi_lib, ng_mpi_lib;
|
||||
static bool need_mpi_finalize = false;
|
||||
|
||||
struct MPIFinalizer {
|
||||
~MPIFinalizer() {
|
||||
if (need_mpi_finalize) {
|
||||
cout << IM(5) << "Calling MPI_Finalize" << endl;
|
||||
NG_MPI_Finalize();
|
||||
}
|
||||
}
|
||||
} mpi_finalizer;
|
||||
|
||||
bool MPI_Loaded() { return ng_mpi_lib != nullptr; }
|
||||
|
||||
void InitMPI(std::optional<std::filesystem::path> mpi_lib_path) {
|
||||
if (ng_mpi_lib) return;
|
||||
|
||||
cout << IM(3) << "InitMPI" << endl;
|
||||
|
||||
std::string vendor = "";
|
||||
std::string mpi4py_lib_file = "";
|
||||
|
||||
if (mpi_lib_path) {
|
||||
// Dynamic load of given shared MPI library
|
||||
// Then call MPI_Init, read the library version and set the vender name
|
||||
try {
|
||||
typedef int (*init_handle)(int *, char ***);
|
||||
typedef int (*mpi_initialized_handle)(int *);
|
||||
mpi_lib =
|
||||
std::make_unique<SharedLibrary>(*mpi_lib_path, std::nullopt, true);
|
||||
auto mpi_init = mpi_lib->GetSymbol<init_handle>("MPI_Init");
|
||||
auto mpi_initialized =
|
||||
mpi_lib->GetSymbol<mpi_initialized_handle>("MPI_Initialized");
|
||||
|
||||
int flag = 0;
|
||||
mpi_initialized(&flag);
|
||||
if (!flag) {
|
||||
typedef const char *pchar;
|
||||
int argc = 1;
|
||||
pchar args[] = {"netgen", nullptr};
|
||||
pchar *argv = &args[0];
|
||||
cout << IM(5) << "Calling MPI_Init" << endl;
|
||||
mpi_init(&argc, (char ***)argv);
|
||||
need_mpi_finalize = true;
|
||||
}
|
||||
|
||||
char c_version_string[65536];
|
||||
c_version_string[0] = '\0';
|
||||
int result_len = 0;
|
||||
typedef void (*get_version_handle)(char *, int *);
|
||||
auto get_version =
|
||||
mpi_lib->GetSymbol<get_version_handle>("MPI_Get_library_version");
|
||||
get_version(c_version_string, &result_len);
|
||||
std::string version = c_version_string;
|
||||
|
||||
if (version.substr(0, 8) == "Open MPI")
|
||||
vendor = "Open MPI";
|
||||
else if (version.substr(0, 5) == "MPICH")
|
||||
vendor = "MPICH";
|
||||
else if (version.substr(0, 13) == "Microsoft MPI")
|
||||
vendor = "Microsoft MPI";
|
||||
else if (version.substr(0, 12) == "Intel(R) MPI")
|
||||
vendor = "Intel MPI";
|
||||
else
|
||||
throw std::runtime_error(
|
||||
std::string("Unknown MPI version: " + version));
|
||||
} catch (std::runtime_error &e) {
|
||||
cerr << "Could not load MPI: " << e.what() << endl;
|
||||
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>();
|
||||
|
||||
#ifndef WIN32
|
||||
// Load mpi4py library (it exports all MPI symbols) to have all MPI symbols
|
||||
// available before the ng_mpi wrapper is loaded This is not necessary on
|
||||
// windows as the matching mpi dll is linked to the ng_mpi wrapper directly
|
||||
mpi4py_lib_file = mpi4py.attr("__file__").cast<std::string>();
|
||||
mpi_lib =
|
||||
std::make_unique<SharedLibrary>(mpi4py_lib_file, std::nullopt, true);
|
||||
#endif // WIN32
|
||||
#endif // NG_PYTHON
|
||||
}
|
||||
|
||||
std::string ng_lib_name = "";
|
||||
if (vendor == "Open MPI")
|
||||
ng_lib_name = "ng_openmpi";
|
||||
else if (vendor == "MPICH")
|
||||
ng_lib_name = "ng_mpich";
|
||||
else if (vendor == "Microsoft MPI")
|
||||
ng_lib_name = "ng_microsoft_mpi";
|
||||
else if (vendor == "Intel MPI")
|
||||
ng_lib_name = "ng_intel_mpi";
|
||||
else
|
||||
throw std::runtime_error("Unknown MPI vendor: " + vendor);
|
||||
|
||||
ng_lib_name += NETGEN_SHARED_LIBRARY_SUFFIX;
|
||||
|
||||
// Load the ng_mpi wrapper and call ng_init_mpi to set all function pointers
|
||||
typedef void (*ng_init_handle)();
|
||||
ng_mpi_lib = std::make_unique<SharedLibrary>(ng_lib_name);
|
||||
ng_mpi_lib->GetSymbol<ng_init_handle>("ng_init_mpi")();
|
||||
std::cout << IM(3) << "MPI wrapper loaded, vendor: " << vendor << endl;
|
||||
}
|
||||
|
||||
static std::runtime_error no_mpi() {
|
||||
return std::runtime_error("MPI not enabled");
|
||||
}
|
||||
|
||||
#ifdef NG_PYTHON
|
||||
decltype(NG_MPI_CommFromMPI4Py) NG_MPI_CommFromMPI4Py =
|
||||
[](py::handle py_obj, NG_MPI_Comm &ng_comm) -> bool {
|
||||
// If this gets called, it means that we want to convert an mpi4py
|
||||
// communicator to a Netgen MPI communicator, but the Netgen MPI wrapper
|
||||
// runtime was not yet initialized.
|
||||
|
||||
// store the current address of this function
|
||||
auto old_converter_address = NG_MPI_CommFromMPI4Py;
|
||||
|
||||
// initialize the MPI wrapper runtime, this sets all the function pointers
|
||||
InitMPI();
|
||||
|
||||
// if the initialization was successful, the function pointer should have
|
||||
// changed
|
||||
// -> call the actual conversion function
|
||||
if (NG_MPI_CommFromMPI4Py != old_converter_address)
|
||||
return NG_MPI_CommFromMPI4Py(py_obj, ng_comm);
|
||||
|
||||
// otherwise, something strange happened
|
||||
throw no_mpi();
|
||||
};
|
||||
decltype(NG_MPI_CommToMPI4Py) NG_MPI_CommToMPI4Py =
|
||||
[](NG_MPI_Comm) -> py::handle { throw no_mpi(); };
|
||||
#endif // NG_PYTHON
|
||||
|
||||
#include "ng_mpi_generated_dummy_init.hpp"
|
||||
#else // NG_MPI_WRAPPER
|
||||
|
||||
static bool imported_mpi4py = false;
|
||||
#ifdef NG_PYTHON
|
||||
decltype(NG_MPI_CommFromMPI4Py) NG_MPI_CommFromMPI4Py =
|
||||
[](py::handle src, NG_MPI_Comm &dst) -> bool {
|
||||
if (!imported_mpi4py) {
|
||||
import_mpi4py__MPI();
|
||||
imported_mpi4py = true;
|
||||
}
|
||||
PyObject *py_src = src.ptr();
|
||||
auto type = Py_TYPE(py_src);
|
||||
if (PyObject_TypeCheck(py_src, &PyMPIComm_Type)) {
|
||||
dst = *PyMPIComm_Get(py_src);
|
||||
return !PyErr_Occurred();
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
decltype(NG_MPI_CommToMPI4Py) NG_MPI_CommToMPI4Py =
|
||||
[](NG_MPI_Comm src) -> py::handle {
|
||||
if (!imported_mpi4py) {
|
||||
import_mpi4py__MPI();
|
||||
imported_mpi4py = true;
|
||||
}
|
||||
return py::handle(PyMPIComm_New(src));
|
||||
};
|
||||
|
||||
#endif // NG_PYTHON
|
||||
|
||||
bool MPI_Loaded() { return true; }
|
||||
void InitMPI(std::optional<std::filesystem::path>) {}
|
||||
|
||||
#endif // NG_MPI_WRAPPER
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
#endif // PARALLEL
|
@ -10,13 +10,18 @@
|
||||
#include "hashtable.hpp"
|
||||
#include "localheap.hpp"
|
||||
#include "logging.hpp"
|
||||
#include "mpi_wrapper.hpp"
|
||||
// #include "mpi_wrapper.hpp"
|
||||
#include "profiler.hpp"
|
||||
#include "signal.hpp"
|
||||
#include "simd.hpp"
|
||||
#include "autodiff.hpp"
|
||||
#include "autodiffdiff.hpp"
|
||||
#include "symboltable.hpp"
|
||||
#include "taskmanager.hpp"
|
||||
#include "version.hpp"
|
||||
#include "xbool.hpp"
|
||||
#include "ngstream.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "ranges.hpp"
|
||||
|
||||
#endif // NETGEN_CORE_NGCORE_HPP
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef NETGEN_CORE_NGCORE_API_HPP
|
||||
#define NETGEN_CORE_NGCORE_API_HPP
|
||||
|
||||
#include "netgen_config.hpp"
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
// This function or variable may be unsafe. Consider using _ftime64_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
|
||||
@ -48,20 +50,29 @@
|
||||
#define NGCORE_API NGCORE_API_IMPORT
|
||||
#endif
|
||||
|
||||
// Set __host__ __device__ for all inline functions
|
||||
#ifdef __CUDACC__
|
||||
#define NETGEN_HD __host__ __device__
|
||||
#else // __CUDACC__
|
||||
#define NETGEN_HD
|
||||
#endif // __CUDACC__
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
#define NETGEN_ALWAYS_INLINE __forceinline
|
||||
#define NETGEN_INLINE __forceinline inline
|
||||
#ifdef WIN32
|
||||
#define NETGEN_INLINE __forceinline inline
|
||||
#define NETGEN_LAMBDA_INLINE
|
||||
#else
|
||||
#define NETGEN_INLINE __forceinline inline
|
||||
#define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__))
|
||||
#endif
|
||||
#else
|
||||
#ifdef __GNUC__
|
||||
#define NETGEN_INLINE __attribute__ ((__always_inline__)) inline
|
||||
#define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__))
|
||||
#define NETGEN_ALWAYS_INLINE __attribute__ ((__always_inline__))
|
||||
#define NETGEN_INLINE __attribute__ ((__always_inline__)) inline NETGEN_HD
|
||||
#define NETGEN_LAMBDA_INLINE __attribute__ ((__always_inline__)) NETGEN_HD
|
||||
#define NETGEN_VLA
|
||||
#else
|
||||
#define NETGEN_ALWAYS_INLINE
|
||||
#define NETGEN_INLINE inline
|
||||
#define NETGEN_LAMBDA_INLINE
|
||||
#endif
|
||||
|
115
libsrc/core/ngstream.hpp
Normal file
115
libsrc/core/ngstream.hpp
Normal file
@ -0,0 +1,115 @@
|
||||
#ifndef FILE_NGSTREAM
|
||||
#define FILE_NGSTREAM
|
||||
|
||||
/**************************************************************************/
|
||||
/* File: ng(s)stream.hpp */
|
||||
/* Author: Joachim Schoeberl */
|
||||
/* Date: 20. Jul. 2011 */
|
||||
/**************************************************************************/
|
||||
|
||||
// #include <ios>
|
||||
// #include <iostream>
|
||||
namespace ngcore
|
||||
{
|
||||
|
||||
NGCORE_API extern int printmessage_importance;
|
||||
|
||||
// important message
|
||||
class IM
|
||||
{
|
||||
int value;
|
||||
public:
|
||||
IM (int val) : value(val) { ; }
|
||||
int Value () const { return value; }
|
||||
};
|
||||
|
||||
class trunc
|
||||
{
|
||||
double eps;
|
||||
public:
|
||||
trunc (double aeps) : eps(aeps) { ; }
|
||||
double Eps() const { return eps; }
|
||||
};
|
||||
|
||||
class NGSOStream
|
||||
{
|
||||
std::ostream & ost;
|
||||
bool active;
|
||||
NGCORE_API static bool glob_active;
|
||||
double trunc;
|
||||
public:
|
||||
NGSOStream (std::ostream & aost, bool aactive)
|
||||
: ost(aost), active(aactive), trunc(-1) { ; }
|
||||
NGSOStream & SetTrunc (double atrunc) { trunc = atrunc; return *this; }
|
||||
double GetTrunc () const { return trunc; }
|
||||
bool Active () const { return active && glob_active; }
|
||||
std::ostream & GetStream () { return ost; }
|
||||
static void SetGlobalActive (bool b) { glob_active = b; }
|
||||
};
|
||||
|
||||
inline NGSOStream operator<< (std::ostream & ost, const IM & im)
|
||||
{
|
||||
return NGSOStream (ost,
|
||||
(im.Value() <= printmessage_importance));
|
||||
}
|
||||
|
||||
/*
|
||||
// doesn't work for matrices
|
||||
inline NGSOStream operator<< (ostream & ost, trunc tr)
|
||||
{
|
||||
cout << "set trunc modifier" << endl;
|
||||
return NGSOStream (ost, true).SetTrunc (tr.Eps());
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline NGSOStream operator<< (NGSOStream ngsost, const T & data)
|
||||
{
|
||||
if (ngsost.Active())
|
||||
ngsost.GetStream() << data;
|
||||
return ngsost;
|
||||
}
|
||||
|
||||
/*
|
||||
inline NGSOStream operator<< (NGSOStream ngsost, const double & data)
|
||||
{
|
||||
cout << "double out" << endl;
|
||||
if (ngsost.Active())
|
||||
{
|
||||
double hdata = data;
|
||||
if (fabs (hdata) < ngsost.GetTrunc()) hdata = 0.0;
|
||||
ngsost.GetStream() << hdata;
|
||||
}
|
||||
return ngsost;
|
||||
}
|
||||
*/
|
||||
|
||||
inline NGSOStream operator<< (NGSOStream ngsost, std::ostream& ( *pf )(std::ostream&))
|
||||
{
|
||||
if ( ngsost.Active() )
|
||||
ngsost.GetStream() << (*pf);
|
||||
|
||||
return ngsost;
|
||||
}
|
||||
|
||||
inline NGSOStream operator<< (NGSOStream ngsost, std::ios& ( *pf )(std::ios&))
|
||||
{
|
||||
if ( ngsost.Active() )
|
||||
ngsost.GetStream() << (*pf);
|
||||
|
||||
return ngsost;
|
||||
}
|
||||
|
||||
inline NGSOStream operator<< (NGSOStream ngsost, std::ios_base& ( *pf )(std::ios_base&))
|
||||
{
|
||||
if ( ngsost.Active() )
|
||||
ngsost.GetStream() << (*pf);
|
||||
|
||||
return ngsost;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -7,12 +7,14 @@
|
||||
|
||||
#include "archive.hpp" // for Demangle
|
||||
#include "paje_trace.hpp"
|
||||
#include "ng_mpi.hpp"
|
||||
#include "profiler.hpp"
|
||||
#include "mpi_wrapper.hpp"
|
||||
|
||||
extern const char *header;
|
||||
|
||||
constexpr int MPI_PAJE_WRITER = 1;
|
||||
constexpr int ASSUMED_MPI_MAX_PROCESSOR_NAME = 256;
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
@ -24,7 +26,7 @@ namespace ngcore
|
||||
if(id<NgProfiler::SIZE)
|
||||
return NgProfiler::GetName(id);
|
||||
|
||||
NgMPI_Comm comm(MPI_COMM_WORLD);
|
||||
NgMPI_Comm comm(NG_MPI_COMM_WORLD);
|
||||
return NgProfiler::GetName(id-NgProfiler::SIZE*comm.Rank());
|
||||
#endif // PARALLEL
|
||||
}
|
||||
@ -39,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)
|
||||
{
|
||||
@ -65,13 +68,17 @@ namespace ngcore
|
||||
|
||||
jobs.reserve(reserve_size);
|
||||
timer_events.reserve(reserve_size);
|
||||
gpu_events.reserve(reserve_size);
|
||||
memory_events.reserve(1024*1024);
|
||||
|
||||
// sync start time when running in parallel
|
||||
#ifdef PARALLEL
|
||||
NgMPI_Comm comm(MPI_COMM_WORLD);
|
||||
for(auto i : Range(5))
|
||||
comm.Barrier();
|
||||
if(MPI_Loaded())
|
||||
{
|
||||
NgMPI_Comm comm(NG_MPI_COMM_WORLD);
|
||||
for([[maybe_unused]] auto i : Range(5))
|
||||
comm.Barrier();
|
||||
}
|
||||
#endif // PARALLEL
|
||||
|
||||
start_time = GetTimeCounter();
|
||||
@ -95,6 +102,15 @@ namespace ngcore
|
||||
for(auto & event : timer_events)
|
||||
event.time -= start_time;
|
||||
|
||||
for(auto & event : user_events)
|
||||
{
|
||||
event.t_start -= start_time;
|
||||
event.t_end -= start_time;
|
||||
}
|
||||
|
||||
for(auto & event : gpu_events)
|
||||
event.time -= start_time;
|
||||
|
||||
for(auto & llink : links)
|
||||
for(auto & link : llink)
|
||||
link.time -= start_time;
|
||||
@ -102,11 +118,14 @@ namespace ngcore
|
||||
for(auto i : IntRange(n_memory_events_at_start, memory_events.size()))
|
||||
memory_events[i].time -= start_time;
|
||||
|
||||
NgMPI_Comm comm(MPI_COMM_WORLD);
|
||||
|
||||
NgMPI_Comm comm;
|
||||
#ifdef PARALLEL
|
||||
if(MPI_Loaded())
|
||||
comm = NgMPI_Comm(NG_MPI_COMM_WORLD);
|
||||
#endif
|
||||
if(comm.Size()==1)
|
||||
{
|
||||
Write(tracefile_name);
|
||||
Write();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -114,8 +133,11 @@ namespace ngcore
|
||||
for(auto & event : timer_events)
|
||||
event.timer_id += NgProfiler::SIZE*comm.Rank();
|
||||
|
||||
for(auto & event : gpu_events)
|
||||
event.timer_id += NgProfiler::SIZE*comm.Rank();
|
||||
|
||||
if(comm.Rank() == MPI_PAJE_WRITER)
|
||||
Write(tracefile_name);
|
||||
Write();
|
||||
else
|
||||
SendData();
|
||||
}
|
||||
@ -148,7 +170,7 @@ namespace ngcore
|
||||
else if (x<5*d)
|
||||
r=6*(x-4*d), g=0,b=1;
|
||||
else
|
||||
r=1, g=0,b=1-5*(x-d);
|
||||
r=1, g=0,b=1-6*(x-5*d);
|
||||
};
|
||||
|
||||
int alias_counter;
|
||||
@ -185,6 +207,10 @@ namespace ngcore
|
||||
: time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), id(aid), value_is_alias(avalue_is_alias)
|
||||
{ }
|
||||
|
||||
PajeEvent( int aevent_type, double atime, int atype, int acontainer, std::string as_value, int aid = 0 )
|
||||
: time(atime), event_type(aevent_type), type(atype), container(acontainer), s_value(as_value), id(aid), value_is_alias(false), value_is_int(false)
|
||||
{ }
|
||||
|
||||
PajeEvent( int aevent_type, double atime, int atype, int acontainer, int avalue, int astart_container, int akey )
|
||||
: time(atime), event_type(aevent_type), type(atype), container(acontainer), value(avalue), start_container(astart_container), id(akey)
|
||||
{ }
|
||||
@ -194,10 +220,12 @@ namespace ngcore
|
||||
int event_type;
|
||||
int type;
|
||||
int container;
|
||||
std::string s_value = "";
|
||||
int value = 0;
|
||||
int start_container = 0;
|
||||
int id = 0;
|
||||
bool value_is_alias = true;
|
||||
bool value_is_int = true;
|
||||
|
||||
bool operator < (const PajeEvent & other) const {
|
||||
// Same start and stop times can occur for very small tasks -> take "starting" events first (eg. PajePushState before PajePopState)
|
||||
@ -221,8 +249,10 @@ namespace ngcore
|
||||
case PajePushState:
|
||||
if(value_is_alias)
|
||||
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\ta%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT
|
||||
else
|
||||
else if(value_is_int)
|
||||
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t%d\t%d\n", PajePushState, time, type, container, value, id); // NOLINT
|
||||
else
|
||||
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\t\"%s\"\t%d\n", PajePushState, time, type, container, s_value.c_str(), id); // NOLINT
|
||||
case PajePopState:
|
||||
return fprintf( stream, "%d\t%.15g\ta%d\ta%d\n", PajePopState, time, type, container ); // NOLINT
|
||||
case PajeStartLink:
|
||||
@ -347,6 +377,11 @@ namespace ngcore
|
||||
events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id, value_is_alias) );
|
||||
}
|
||||
|
||||
void PushState ( TTimePoint time, int type, int container, std::string value, int id = 0)
|
||||
{
|
||||
events.emplace_back( PajeEvent( PajePushState, ConvertTime(time), type, container, value, id) );
|
||||
}
|
||||
|
||||
void PopState ( TTimePoint time, int type, int container )
|
||||
{
|
||||
events.emplace_back( PajeEvent( PajePopState, ConvertTime(time), type, container ) );
|
||||
@ -409,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)
|
||||
@ -460,25 +504,25 @@ namespace ngcore
|
||||
std::vector <int> thread_aliases;
|
||||
std::vector<int> container_nodes;
|
||||
|
||||
#ifdef PARALLEL
|
||||
// Hostnames
|
||||
NgMPI_Comm comm(MPI_COMM_WORLD);
|
||||
auto rank = comm.Rank();
|
||||
auto nranks = comm.Size();
|
||||
if(nranks>1)
|
||||
NgMPI_Comm comm;
|
||||
#ifdef PARALLEL
|
||||
if(MPI_Loaded())
|
||||
comm = NgMPI_Comm(NG_MPI_COMM_WORLD);
|
||||
if(comm.Size()>1)
|
||||
{
|
||||
nthreads = nranks;
|
||||
auto comm = NgMPI_Comm(NG_MPI_COMM_WORLD);
|
||||
nthreads = comm.Size();
|
||||
thread_aliases.reserve(nthreads);
|
||||
|
||||
std::array<char, MPI_MAX_PROCESSOR_NAME+1> ahostname;
|
||||
std::array<char, ASSUMED_MPI_MAX_PROCESSOR_NAME+1> ahostname;
|
||||
int len;
|
||||
MPI_Get_processor_name(ahostname.data(), &len);
|
||||
NG_MPI_Get_processor_name(ahostname.data(), &len);
|
||||
std::string hostname = ahostname.data();
|
||||
|
||||
std::map<std::string, int> host_map;
|
||||
|
||||
std::string name;
|
||||
for(auto i : IntRange(0, nranks))
|
||||
for(auto i : IntRange(0, comm.Size()))
|
||||
{
|
||||
if(i!=MPI_PAJE_WRITER)
|
||||
comm.Recv(name, i, 0);
|
||||
@ -493,7 +537,7 @@ namespace ngcore
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // PARALLEL
|
||||
#endif
|
||||
{
|
||||
container_nodes.reserve(num_nodes);
|
||||
for(int i=0; i<num_nodes; i++)
|
||||
@ -504,7 +548,8 @@ namespace ngcore
|
||||
for (int i=0; i<nthreads; i++)
|
||||
{
|
||||
auto name = "Thread " + ToString(i);
|
||||
thread_aliases.emplace_back( paje.CreateContainer( container_type_thread, container_nodes[i*num_nodes/nthreads], name ) );
|
||||
if(tasks[i].size())
|
||||
thread_aliases.emplace_back( paje.CreateContainer( container_type_thread, container_nodes[i*num_nodes/nthreads], name ) );
|
||||
}
|
||||
}
|
||||
|
||||
@ -556,6 +601,8 @@ namespace ngcore
|
||||
for(auto & event : timer_events)
|
||||
timer_ids.insert(event.timer_id);
|
||||
|
||||
for(auto & event : gpu_events)
|
||||
timer_ids.insert(event.timer_id);
|
||||
|
||||
// Timer names
|
||||
for(auto & vtasks : tasks)
|
||||
@ -566,10 +613,9 @@ namespace ngcore
|
||||
for(auto id : timer_ids)
|
||||
timer_names[id] = GetTimerName(id);
|
||||
|
||||
#ifdef PARALLEL
|
||||
if(nranks>1)
|
||||
if(comm.Size()>1)
|
||||
{
|
||||
for(auto src : IntRange(0, nranks))
|
||||
for(auto src : IntRange(0, comm.Size()))
|
||||
{
|
||||
if(src==MPI_PAJE_WRITER)
|
||||
continue;
|
||||
@ -579,7 +625,7 @@ namespace ngcore
|
||||
|
||||
int id;
|
||||
std::string name;
|
||||
for(auto i : IntRange(n_timers))
|
||||
for([[maybe_unused]]auto i : IntRange(n_timers))
|
||||
{
|
||||
comm.Recv (id, src, 0);
|
||||
comm.Recv (name, src, 0);
|
||||
@ -588,7 +634,6 @@ namespace ngcore
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // PARALLEL
|
||||
|
||||
for(auto id : timer_ids)
|
||||
timer_aliases[id] = paje.DefineEntityValue( state_type_timer, timer_names[id], -1 );
|
||||
@ -623,6 +668,54 @@ namespace ngcore
|
||||
paje.PopState( event.time, state_type_timer, timer_container_aliases[--timerdepth] );
|
||||
}
|
||||
|
||||
if(gpu_events.size())
|
||||
{
|
||||
auto gpu_container = paje.CreateContainer( container_type_timer, container_task_manager, "GPU" );
|
||||
for(auto & event : gpu_events)
|
||||
{
|
||||
if(event.is_start)
|
||||
paje.PushState( event.time, state_type_timer, gpu_container, timer_aliases[event.timer_id] );
|
||||
else
|
||||
paje.PopState( event.time, state_type_timer, gpu_container);
|
||||
}
|
||||
}
|
||||
|
||||
if(user_events.size())
|
||||
{
|
||||
std::sort (user_events.begin(), user_events.end());
|
||||
|
||||
std::map<int, int> containers;
|
||||
|
||||
for(auto i : Range(user_containers.size()))
|
||||
{
|
||||
auto & [name, parent] = user_containers[i];
|
||||
int a_parent = parent == -1 ? container_task_manager : containers[parent];
|
||||
containers[i] = paje.CreateContainer( container_type_timer, a_parent, name );
|
||||
}
|
||||
|
||||
for(auto ev : user_events)
|
||||
{
|
||||
if(containers[ev.container]==0)
|
||||
{
|
||||
std::string name = "User " + ToString(ev.container);
|
||||
containers[ev.container] = paje.CreateContainer( container_type_timer, container_task_manager, name );
|
||||
}
|
||||
}
|
||||
|
||||
int i_start = 0;
|
||||
for(auto i : Range(user_events.size()))
|
||||
{
|
||||
auto & event = user_events[i];
|
||||
while(i_start < user_events.size() && user_events[i_start].t_start < event.t_end)
|
||||
{
|
||||
auto & ev = user_events[i_start];
|
||||
paje.PushState( ev.t_start, state_type_timer, containers[ev.container], ev.data, ev.id );
|
||||
i_start++;
|
||||
}
|
||||
paje.PopState( event.t_end, state_type_timer, containers[event.container]);
|
||||
}
|
||||
}
|
||||
|
||||
for(auto & vtasks : tasks)
|
||||
{
|
||||
for (Task & t : vtasks) {
|
||||
@ -665,7 +758,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
#ifdef PARALLEL
|
||||
if(nranks>1)
|
||||
if(comm.Size()>1)
|
||||
{
|
||||
for(auto & event : timer_events)
|
||||
{
|
||||
@ -681,7 +774,7 @@ namespace ngcore
|
||||
Array<bool> is_start;
|
||||
Array<int> thread_id;
|
||||
|
||||
for(auto src : IntRange(0, nranks))
|
||||
for(auto src : IntRange(0, comm.Size()))
|
||||
{
|
||||
if(src==MPI_PAJE_WRITER)
|
||||
continue;
|
||||
@ -766,10 +859,6 @@ namespace ngcore
|
||||
}
|
||||
}
|
||||
}
|
||||
WriteTimingChart();
|
||||
#ifdef NETGEN_TRACE_MEMORY
|
||||
WriteMemoryChart("");
|
||||
#endif // NETGEN_TRACE_MEMORY
|
||||
paje.WriteEvents();
|
||||
}
|
||||
|
||||
@ -777,15 +866,15 @@ namespace ngcore
|
||||
{
|
||||
#ifdef PARALLEL
|
||||
// Hostname
|
||||
NgMPI_Comm comm(MPI_COMM_WORLD);
|
||||
auto rank = comm.Rank();
|
||||
auto nranks = comm.Size();
|
||||
NgMPI_Comm comm(NG_MPI_COMM_WORLD);
|
||||
// auto rank = comm.Rank();
|
||||
// auto nranks = comm.Size();
|
||||
|
||||
std::string hostname;
|
||||
{
|
||||
std::array<char, MPI_MAX_PROCESSOR_NAME+1> ahostname;
|
||||
std::array<char, ASSUMED_MPI_MAX_PROCESSOR_NAME+1> ahostname;
|
||||
int len;
|
||||
MPI_Get_processor_name(ahostname.data(), &len);
|
||||
NG_MPI_Get_processor_name(ahostname.data(), &len);
|
||||
hostname = ahostname.data();
|
||||
}
|
||||
|
||||
@ -878,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";
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef NETGEN_CORE_PAJE_TRACE_HPP
|
||||
#define NETGEN_CORE_PAJE_TRACE_HPP
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
@ -24,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;
|
||||
@ -31,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 );
|
||||
@ -60,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
|
||||
@ -97,6 +106,16 @@ namespace ngcore
|
||||
bool operator < (const TimerEvent & other) const { return time < other.time; }
|
||||
};
|
||||
|
||||
struct UserEvent
|
||||
{
|
||||
TTimePoint t_start = 0, t_end = 0;
|
||||
std::string data = "";
|
||||
int container = 0;
|
||||
int id = 0;
|
||||
|
||||
bool operator < (const UserEvent & other) const { return t_start < other.t_start; }
|
||||
};
|
||||
|
||||
struct ThreadLink
|
||||
{
|
||||
int thread_id;
|
||||
@ -119,6 +138,9 @@ namespace ngcore
|
||||
std::vector<std::vector<Task> > tasks;
|
||||
std::vector<Job> jobs;
|
||||
std::vector<TimerEvent> timer_events;
|
||||
std::vector<UserEvent> user_events;
|
||||
std::vector<std::tuple<std::string, int>> user_containers;
|
||||
std::vector<TimerEvent> gpu_events;
|
||||
std::vector<std::vector<ThreadLink> > links;
|
||||
NGCORE_API static std::vector<MemoryEvent> memory_events;
|
||||
|
||||
@ -134,6 +156,36 @@ namespace ngcore
|
||||
void operator=(const PajeTrace &) = delete;
|
||||
void operator=(PajeTrace &&) = delete;
|
||||
|
||||
int AddUserContainer(std::string name, int parent=-1)
|
||||
{
|
||||
if(auto pos = std::find(user_containers.begin(), user_containers.end(), std::tuple{name,parent}); pos != user_containers.end())
|
||||
return pos - user_containers.begin();
|
||||
int id = user_containers.size();
|
||||
user_containers.push_back({name, parent});
|
||||
return id;
|
||||
}
|
||||
|
||||
void AddUserEvent(UserEvent ue)
|
||||
{
|
||||
if(!tracing_enabled) return;
|
||||
user_events.push_back(ue);
|
||||
}
|
||||
void StartGPU(int timer_id = 0)
|
||||
{
|
||||
if(!tracing_enabled) return;
|
||||
if(unlikely(gpu_events.size() == max_num_events_per_thread))
|
||||
StopTracing();
|
||||
gpu_events.push_back(TimerEvent{timer_id, GetTimeCounter(), true});
|
||||
}
|
||||
|
||||
void StopGPU(int timer_id)
|
||||
{
|
||||
if(!tracing_enabled) return;
|
||||
if(unlikely(gpu_events.size() == max_num_events_per_thread))
|
||||
StopTracing();
|
||||
gpu_events.push_back(TimerEvent{timer_id, GetTimeCounter(), false});
|
||||
}
|
||||
|
||||
void StartTimer(int timer_id)
|
||||
{
|
||||
if(!tracing_enabled) return;
|
||||
@ -171,7 +223,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
|
||||
NETGEN_INLINE int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1)
|
||||
int StartTask(int thread_id, int id, int id_type = Task::ID_NONE, int additional_value = -1)
|
||||
{
|
||||
if(!tracing_enabled) return -1;
|
||||
if(!trace_threads && !trace_thread_counter) return -1;
|
||||
@ -218,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
|
||||
|
||||
};
|
||||
|
@ -94,7 +94,7 @@ namespace ngcore
|
||||
if (first_overflow)
|
||||
{
|
||||
first_overflow = false;
|
||||
NgProfiler::logger->warn("no more timer available, reusing last one");
|
||||
NgProfiler::logger->warn( ("no more timer available ("+name+"), reusing last one").c_str());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -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
|
||||
|
@ -147,7 +147,7 @@ namespace ngcore
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct TNoTracing{ static constexpr bool do_tracing=false; };
|
||||
struct TTracing{ static constexpr bool do_tracing=true; };
|
||||
|
||||
@ -163,8 +163,8 @@ namespace ngcore
|
||||
constexpr bool is_timing_type_v = std::is_same_v<T, TNoTiming> || std::is_same_v<T, TTiming>;
|
||||
}
|
||||
|
||||
static TNoTracing NoTracing;
|
||||
static TNoTiming NoTiming;
|
||||
[[maybe_unused]] static TNoTracing NoTracing;
|
||||
[[maybe_unused]] static TNoTiming NoTiming;
|
||||
|
||||
template<typename TTracing=TTracing, typename TTiming=TTiming>
|
||||
class Timer
|
||||
@ -247,7 +247,7 @@ namespace ngcore
|
||||
double GetMFlops ()
|
||||
{ return NgProfiler::GetFlops(timernr)
|
||||
/ NgProfiler::GetTime(timernr) * 1e-6; }
|
||||
operator int () { return timernr; }
|
||||
operator int () const { return timernr; }
|
||||
};
|
||||
|
||||
|
||||
|
@ -14,13 +14,11 @@ namespace ngcore
|
||||
{
|
||||
if (py::isinstance<py::dict>(value))
|
||||
{
|
||||
py::dict vdd(value);
|
||||
// call recursively to set dictionary
|
||||
for (auto item : vdd) {
|
||||
string name = item.first.cast<string>();
|
||||
py::object val = py::reinterpret_borrow<py::object>(item.second);
|
||||
SetFlag(flags, name, val);
|
||||
}
|
||||
Flags nested_flags;
|
||||
for(auto item : value.cast<py::dict>())
|
||||
SetFlag(nested_flags, item.first.cast<string>(),
|
||||
item.second.cast<py::object>());
|
||||
flags.SetFlag(s, nested_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -103,7 +101,9 @@ namespace ngcore
|
||||
}
|
||||
}
|
||||
|
||||
auto flags = py::cast<Flags>(flags_dict);
|
||||
Flags flags;
|
||||
for(auto item : flags_dict)
|
||||
SetFlag(flags, item.first.cast<string>(), item.second.cast<py::object>());
|
||||
|
||||
for (auto item : kwargs)
|
||||
{
|
||||
@ -157,6 +157,11 @@ namespace ngcore
|
||||
auto val = flags.GetDefineFlag(i, key);
|
||||
d[key.c_str()] = val;
|
||||
}
|
||||
for(auto i : Range(flags.GetNAnyFlags()))
|
||||
{
|
||||
auto& a = flags.GetAnyFlag(i, key);
|
||||
d[key.c_str()] = CastAnyToPy(a);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
@ -6,20 +6,76 @@
|
||||
#include <pybind11/operators.h>
|
||||
#include <pybind11/numpy.h>
|
||||
#include <pybind11/stl.h>
|
||||
#include <pybind11/stl/filesystem.h>
|
||||
|
||||
#include "array.hpp"
|
||||
#include "table.hpp"
|
||||
#include "archive.hpp"
|
||||
#include "flags.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
#include "profiler.hpp"
|
||||
#include "ng_mpi.hpp"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
#ifdef PARALLEL
|
||||
NGCORE_API extern bool (*NG_MPI_CommFromMPI4Py)(py::handle, NG_MPI_Comm &);
|
||||
NGCORE_API extern py::handle (*NG_MPI_CommToMPI4Py)(NG_MPI_Comm);
|
||||
#endif // PARALLEL
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
struct HasPyFormat
|
||||
{
|
||||
private:
|
||||
template<typename T2>
|
||||
static auto check(T2*) -> std::enable_if_t<std::is_same_v<decltype(std::declval<py::format_descriptor<T2>>().format()), std::string>, std::true_type>;
|
||||
static auto check(...) -> std::false_type;
|
||||
public:
|
||||
static constexpr bool value = decltype(check((T*) nullptr))::value;
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
#ifdef PARALLEL
|
||||
struct mpi4py_comm {
|
||||
mpi4py_comm() = default;
|
||||
mpi4py_comm(NG_MPI_Comm value) : value(value) {}
|
||||
operator NG_MPI_Comm () { return value; }
|
||||
|
||||
NG_MPI_Comm value;
|
||||
};
|
||||
#endif // PARALLEL
|
||||
} // namespace ngcore
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// automatic conversion of python list to Array<>
|
||||
namespace pybind11 {
|
||||
namespace detail {
|
||||
|
||||
#ifdef PARALLEL
|
||||
template <> struct type_caster<ngcore::mpi4py_comm> {
|
||||
public:
|
||||
PYBIND11_TYPE_CASTER(ngcore::mpi4py_comm, _("mpi4py_comm"));
|
||||
|
||||
// Python -> C++
|
||||
bool load(handle src, bool) {
|
||||
return ngcore::NG_MPI_CommFromMPI4Py(src, value.value);
|
||||
}
|
||||
|
||||
// C++ -> Python
|
||||
static handle cast(ngcore::mpi4py_comm src,
|
||||
return_value_policy /* policy */,
|
||||
handle /* parent */)
|
||||
{
|
||||
// Create an mpi4py handle
|
||||
return ngcore::NG_MPI_CommToMPI4Py(src.value);
|
||||
}
|
||||
};
|
||||
#endif // PARALLEL
|
||||
|
||||
template <typename Type, typename Value> struct ngcore_list_caster {
|
||||
using value_conv = make_caster<Value>;
|
||||
|
||||
@ -57,7 +113,8 @@ public:
|
||||
PYBIND11_TYPE_CASTER(Type, _("Array[") + value_conv::name + _("]"));
|
||||
};
|
||||
|
||||
template <typename Type> struct type_caster<ngcore::Array<Type>>
|
||||
|
||||
template <typename Type> struct type_caster<ngcore::Array<Type>, enable_if_t<!ngcore::detail::HasPyFormat<Type>::value>>
|
||||
: ngcore_list_caster<ngcore::Array<Type>, Type> { };
|
||||
|
||||
|
||||
@ -136,6 +193,93 @@ namespace ngcore
|
||||
{ return std::string("sp_")+GetPyName<T>(); }
|
||||
};
|
||||
|
||||
template<typename ARCHIVE>
|
||||
class NGCORE_API_EXPORT PyArchive : public ARCHIVE
|
||||
{
|
||||
private:
|
||||
pybind11::list lst;
|
||||
size_t index = 0;
|
||||
std::map<std::string, VersionInfo> version_needed;
|
||||
protected:
|
||||
using ARCHIVE::stream;
|
||||
using ARCHIVE::version_map;
|
||||
public:
|
||||
PyArchive(const pybind11::object& alst = pybind11::none()) :
|
||||
ARCHIVE(std::make_shared<std::stringstream>()),
|
||||
lst(alst.is_none() ? pybind11::list() : pybind11::cast<pybind11::list>(alst))
|
||||
{
|
||||
ARCHIVE::shallow_to_python = true;
|
||||
if(Input())
|
||||
{
|
||||
stream = std::make_shared<std::stringstream>
|
||||
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-1]));
|
||||
*this & version_needed;
|
||||
for(auto& libversion : version_needed)
|
||||
if(libversion.second > GetLibraryVersion(libversion.first))
|
||||
throw Exception("Error in unpickling data:\nLibrary " + libversion.first +
|
||||
" must be at least " + libversion.second.to_string());
|
||||
stream = std::make_shared<std::stringstream>
|
||||
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-2]));
|
||||
*this & version_map;
|
||||
stream = std::make_shared<std::stringstream>
|
||||
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-3]));
|
||||
}
|
||||
}
|
||||
|
||||
void NeedsVersion(const std::string& library, const std::string& version) override
|
||||
{
|
||||
if(Output())
|
||||
{
|
||||
version_needed[library] = version_needed[library] > version ? version_needed[library] : version;
|
||||
}
|
||||
}
|
||||
|
||||
using ARCHIVE::Output;
|
||||
using ARCHIVE::Input;
|
||||
using ARCHIVE::FlushBuffer;
|
||||
using ARCHIVE::operator&;
|
||||
using ARCHIVE::operator<<;
|
||||
using ARCHIVE::GetVersion;
|
||||
void ShallowOutPython(const pybind11::object& val) override { lst.append(val); }
|
||||
void ShallowInPython(pybind11::object& val) override { val = lst[index++]; }
|
||||
|
||||
pybind11::list WriteOut()
|
||||
{
|
||||
auto version_runtime = GetLibraryVersions();
|
||||
FlushBuffer();
|
||||
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
||||
stream = std::make_shared<std::stringstream>();
|
||||
*this & version_runtime;
|
||||
FlushBuffer();
|
||||
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
||||
stream = std::make_shared<std::stringstream>();
|
||||
*this & version_needed;
|
||||
FlushBuffer();
|
||||
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
||||
return lst;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename T_ARCHIVE_OUT=BinaryOutArchive, typename T_ARCHIVE_IN=BinaryInArchive>
|
||||
auto NGSPickle()
|
||||
{
|
||||
return pybind11::pickle([](T* self)
|
||||
{
|
||||
PyArchive<T_ARCHIVE_OUT> ar;
|
||||
ar.SetParallel(parallel_pickling);
|
||||
ar & self;
|
||||
auto output = pybind11::make_tuple(ar.WriteOut());
|
||||
return output;
|
||||
},
|
||||
[](const pybind11::tuple & state)
|
||||
{
|
||||
T* val = nullptr;
|
||||
PyArchive<T_ARCHIVE_IN> ar(state[0]);
|
||||
ar & val;
|
||||
return val;
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Array<T> makeCArray(const py::object& obj)
|
||||
{
|
||||
@ -151,19 +295,15 @@ namespace ngcore
|
||||
return arr;
|
||||
}
|
||||
|
||||
namespace detail
|
||||
template <typename T>
|
||||
// py::object makePyTuple (FlatArray<T> ar)
|
||||
py::object makePyTuple (const BaseArrayObject<T> & ar)
|
||||
{
|
||||
template<typename T>
|
||||
struct HasPyFormat
|
||||
{
|
||||
private:
|
||||
template<typename T2>
|
||||
static auto check(T2*) -> std::enable_if_t<std::is_same_v<decltype(std::declval<py::format_descriptor<T2>>().format()), std::string>, std::true_type>;
|
||||
static auto check(...) -> std::false_type;
|
||||
public:
|
||||
static constexpr bool value = decltype(check((T*) nullptr))::value;
|
||||
};
|
||||
} // namespace detail
|
||||
py::tuple res(ar.Size());
|
||||
for (auto i : Range(ar))
|
||||
res[i] = py::cast(ar[i]);
|
||||
return res;
|
||||
}
|
||||
|
||||
template <typename T, typename TIND=typename FlatArray<T>::index_type>
|
||||
void ExportArray (py::module &m)
|
||||
@ -179,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];
|
||||
},
|
||||
@ -188,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];
|
||||
@ -244,7 +386,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
std::string aname = std::string("Array_") + suffix;
|
||||
py::class_<TArray, TFlat>(m, aname.c_str())
|
||||
auto arr = py::class_<TArray, TFlat> (m, aname.c_str())
|
||||
.def(py::init([] (size_t n) { return new TArray(n); }),py::arg("n"), "Makes array of given length")
|
||||
.def(py::init([] (std::vector<T> const & x)
|
||||
{
|
||||
@ -254,8 +396,10 @@ namespace ngcore
|
||||
tmp[TIND(i)] = x[i];
|
||||
return tmp;
|
||||
}), py::arg("vec"), "Makes array with given list of elements")
|
||||
|
||||
;
|
||||
;
|
||||
if constexpr(is_archivable<TArray>)
|
||||
arr.def(NGSPickle<TArray>());
|
||||
py::implicitly_convertible<std::vector<T>, TArray>();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@ -307,121 +451,6 @@ namespace ngcore
|
||||
// Create python dict from kwargs
|
||||
py::dict NGCORE_API CreateDictFromFlags(const Flags& flags);
|
||||
|
||||
// *************** Archiving functionality **************
|
||||
|
||||
template<typename T>
|
||||
Archive& Archive :: Shallow(T& val)
|
||||
{
|
||||
static_assert(detail::is_any_pointer<T>, "ShallowArchive must be given pointer type!");
|
||||
#ifdef NETGEN_PYTHON
|
||||
if(shallow_to_python)
|
||||
{
|
||||
if(is_output)
|
||||
ShallowOutPython(pybind11::cast(val));
|
||||
else
|
||||
{
|
||||
pybind11::object obj;
|
||||
ShallowInPython(obj);
|
||||
val = pybind11::cast<T>(obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif // NETGEN_PYTHON
|
||||
*this & val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ARCHIVE>
|
||||
class NGCORE_API_EXPORT PyArchive : public ARCHIVE
|
||||
{
|
||||
private:
|
||||
pybind11::list lst;
|
||||
size_t index = 0;
|
||||
std::map<std::string, VersionInfo> version_needed;
|
||||
protected:
|
||||
using ARCHIVE::stream;
|
||||
using ARCHIVE::version_map;
|
||||
using ARCHIVE::logger;
|
||||
public:
|
||||
PyArchive(const pybind11::object& alst = pybind11::none()) :
|
||||
ARCHIVE(std::make_shared<std::stringstream>()),
|
||||
lst(alst.is_none() ? pybind11::list() : pybind11::cast<pybind11::list>(alst))
|
||||
{
|
||||
ARCHIVE::shallow_to_python = true;
|
||||
if(Input())
|
||||
{
|
||||
stream = std::make_shared<std::stringstream>
|
||||
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-1]));
|
||||
*this & version_needed;
|
||||
logger->debug("versions needed for unpickling = {}", version_needed);
|
||||
for(auto& libversion : version_needed)
|
||||
if(libversion.second > GetLibraryVersion(libversion.first))
|
||||
throw Exception("Error in unpickling data:\nLibrary " + libversion.first +
|
||||
" must be at least " + libversion.second.to_string());
|
||||
stream = std::make_shared<std::stringstream>
|
||||
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-2]));
|
||||
*this & version_map;
|
||||
stream = std::make_shared<std::stringstream>
|
||||
(pybind11::cast<pybind11::bytes>(lst[pybind11::len(lst)-3]));
|
||||
}
|
||||
}
|
||||
|
||||
void NeedsVersion(const std::string& library, const std::string& version) override
|
||||
{
|
||||
if(Output())
|
||||
{
|
||||
logger->debug("Need version {} of library {}.", version, library);
|
||||
version_needed[library] = version_needed[library] > version ? version_needed[library] : version;
|
||||
}
|
||||
}
|
||||
|
||||
using ARCHIVE::Output;
|
||||
using ARCHIVE::Input;
|
||||
using ARCHIVE::FlushBuffer;
|
||||
using ARCHIVE::operator&;
|
||||
using ARCHIVE::operator<<;
|
||||
using ARCHIVE::GetVersion;
|
||||
void ShallowOutPython(const pybind11::object& val) override { lst.append(val); }
|
||||
void ShallowInPython(pybind11::object& val) override { val = lst[index++]; }
|
||||
|
||||
pybind11::list WriteOut()
|
||||
{
|
||||
auto version_runtime = GetLibraryVersions();
|
||||
FlushBuffer();
|
||||
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
||||
stream = std::make_shared<std::stringstream>();
|
||||
*this & version_runtime;
|
||||
FlushBuffer();
|
||||
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
||||
stream = std::make_shared<std::stringstream>();
|
||||
logger->debug("Writeout version needed = {}", version_needed);
|
||||
*this & version_needed;
|
||||
FlushBuffer();
|
||||
lst.append(pybind11::bytes(std::static_pointer_cast<std::stringstream>(stream)->str()));
|
||||
return lst;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, typename T_ARCHIVE_OUT=BinaryOutArchive, typename T_ARCHIVE_IN=BinaryInArchive>
|
||||
auto NGSPickle()
|
||||
{
|
||||
return pybind11::pickle([](T* self)
|
||||
{
|
||||
PyArchive<T_ARCHIVE_OUT> ar;
|
||||
ar.SetParallel(parallel_pickling);
|
||||
ar & self;
|
||||
auto output = pybind11::make_tuple(ar.WriteOut());
|
||||
return output;
|
||||
},
|
||||
[](const pybind11::tuple & state)
|
||||
{
|
||||
T* val = nullptr;
|
||||
PyArchive<T_ARCHIVE_IN> ar(state[0]);
|
||||
ar & val;
|
||||
return val;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
|
@ -1,11 +1,18 @@
|
||||
#include "python_ngcore.hpp"
|
||||
#include "bitarray.hpp"
|
||||
#include "taskmanager.hpp"
|
||||
#include "mpi_wrapper.hpp"
|
||||
|
||||
using namespace ngcore;
|
||||
using namespace std;
|
||||
using namespace pybind11::literals;
|
||||
|
||||
namespace pybind11 { namespace detail {
|
||||
}} // namespace pybind11::detail
|
||||
|
||||
|
||||
|
||||
|
||||
PYBIND11_MODULE(pyngcore, m) // NOLINT
|
||||
{
|
||||
try
|
||||
@ -18,9 +25,24 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
|
||||
ExportArray<unsigned>(m);
|
||||
ExportArray<size_t>(m);
|
||||
ExportArray<double>(m);
|
||||
ExportArray<float>(m);
|
||||
ExportArray<signed short>(m);
|
||||
ExportArray<signed char>(m);
|
||||
ExportArray<unsigned short>(m);
|
||||
ExportArray<unsigned char>(m);
|
||||
|
||||
// Compiler dependent implementation of size_t
|
||||
if constexpr(!is_same_v<size_t, uint64_t>)
|
||||
ExportArray<uint64_t>(m);
|
||||
|
||||
ExportTable<int>(m);
|
||||
|
||||
|
||||
#ifdef PARALLEL
|
||||
py::class_<NG_MPI_Comm> (m, "_NG_MPI_Comm")
|
||||
;
|
||||
m.def("InitMPI", &InitMPI, py::arg("mpi_library_path")=nullopt);
|
||||
#endif // PARALLEL
|
||||
|
||||
py::class_<BitArray, shared_ptr<BitArray>> (m, "BitArray")
|
||||
.def(py::init([] (size_t n) { return make_shared<BitArray>(n); }),py::arg("n"))
|
||||
.def(py::init([] (const BitArray& a) { return make_shared<BitArray>(a); } ), py::arg("ba"))
|
||||
@ -37,12 +59,14 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
|
||||
.def("__len__", &BitArray::Size)
|
||||
.def("__getitem__", [] (BitArray & self, int i)
|
||||
{
|
||||
if (i < 0) i+=self.Size();
|
||||
if (i < 0 || i >= self.Size())
|
||||
throw py::index_error();
|
||||
return self.Test(i);
|
||||
}, py::arg("pos"), "Returns bit from given position")
|
||||
.def("__setitem__", [] (BitArray & self, int i, bool b)
|
||||
{
|
||||
if (i < 0) i+=self.Size();
|
||||
if (i < 0 || i >= self.Size())
|
||||
throw py::index_error();
|
||||
if (b) self.SetBit(i); else self.Clear(i);
|
||||
@ -117,20 +141,34 @@ 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)
|
||||
;
|
||||
|
||||
py::class_<Flags>(m, "Flags")
|
||||
.def(py::init<>())
|
||||
.def("__str__", &ToString<Flags>)
|
||||
.def(py::init([](py::object & obj) {
|
||||
.def(py::init([](py::dict kwargs) {
|
||||
Flags flags;
|
||||
py::dict d(obj);
|
||||
SetFlag (flags, "", d);
|
||||
for (auto d : kwargs)
|
||||
SetFlag(flags, d.first.cast<string>(), d.second.cast<py::object>());
|
||||
return flags;
|
||||
}), py::arg("obj"), "Create Flags by given object")
|
||||
}), "Create flags from dict")
|
||||
.def(py::init([](py::kwargs kwargs) {
|
||||
Flags flags;
|
||||
for (auto d : kwargs)
|
||||
SetFlag(flags, d.first.cast<string>(), d.second.cast<py::object>());
|
||||
return flags;
|
||||
}), "Create flags from kwargs")
|
||||
.def(py::pickle([] (const Flags& self)
|
||||
{
|
||||
std::stringstream str;
|
||||
@ -158,6 +196,9 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
|
||||
return self;
|
||||
}, py::arg("akey"), py::arg("value"), "Set flag by given value.")
|
||||
|
||||
.def("keys", [](Flags & self) -> py::list {
|
||||
return CreateDictFromFlags(self).attr("keys")();
|
||||
})
|
||||
.def("__getitem__", [](Flags & self, const string& name) -> py::object {
|
||||
|
||||
if(self.NumListFlagDefined(name))
|
||||
@ -177,6 +218,14 @@ PYBIND11_MODULE(pyngcore, m) // NOLINT
|
||||
|
||||
return py::cast(self.GetDefineFlag(name));
|
||||
}, py::arg("name"), "Return flag by given name")
|
||||
.def("ToDict", [](const Flags& flags)
|
||||
{
|
||||
return CreateDictFromFlags(flags);
|
||||
})
|
||||
.def("items", [](const Flags& flags)
|
||||
{
|
||||
return CreateDictFromFlags(flags).attr("items")();
|
||||
})
|
||||
;
|
||||
py::implicitly_convertible<py::dict, Flags>();
|
||||
|
||||
@ -229,7 +278,10 @@ threads : int
|
||||
class ParallelContextManager {
|
||||
int num_threads;
|
||||
public:
|
||||
ParallelContextManager() : num_threads(0) {};
|
||||
ParallelContextManager() : num_threads(0) {
|
||||
TaskManager::SetPajeTrace(0);
|
||||
PajeTrace::SetMaxTracefileSize(0);
|
||||
};
|
||||
ParallelContextManager(size_t pajesize) : num_threads(0) {
|
||||
TaskManager::SetPajeTrace(pajesize > 0);
|
||||
PajeTrace::SetMaxTracefileSize(pajesize);
|
||||
@ -263,8 +315,7 @@ threads : int
|
||||
"size in Megabytes"
|
||||
)
|
||||
.def("__enter__", [](PajeTrace & self) { })
|
||||
.def("__exit__", [](PajeTrace & self, py::args) { self.StopTracing(); })
|
||||
.def("__del__", [](PajeTrace & self) { trace = nullptr; })
|
||||
.def("__exit__", [](PajeTrace & self, py::args) { trace = nullptr; })
|
||||
.def_static("SetTraceThreads", &PajeTrace::SetTraceThreads)
|
||||
.def_static("SetTraceThreadCounter", &PajeTrace::SetTraceThreadCounter)
|
||||
.def_static("SetMaxTracefileSize", &PajeTrace::SetMaxTracefileSize)
|
||||
@ -273,5 +324,70 @@ 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")
|
||||
.def("Stop", static_cast<void (Timer<>::*)()const>(&Timer<>::Stop), "stop timer")
|
||||
.def_property_readonly("time", &Timer<>::GetTime, "returns time")
|
||||
.def("__enter__", static_cast<void (Timer<>::*)()const>(&Timer<>::Start))
|
||||
.def("__exit__", [](Timer<>& t, py::object, py::object, py::object)
|
||||
{
|
||||
t.Stop();
|
||||
})
|
||||
;
|
||||
|
||||
m.def("Timers",
|
||||
[]()
|
||||
{
|
||||
py::list timers;
|
||||
for (int i = 0; i < NgProfiler::SIZE; i++)
|
||||
if (!NgProfiler::timers[i].name.empty())
|
||||
{
|
||||
py::dict timer;
|
||||
timer["name"] = py::str(NgProfiler::timers[i].name);
|
||||
timer["time"] = py::float_(NgProfiler::GetTime(i));
|
||||
timer["counts"] = py::int_(NgProfiler::GetCounts(i));
|
||||
timer["flops"] = py::float_(NgProfiler::GetFlops(i));
|
||||
timer["Gflop/s"] = py::float_(NgProfiler::GetFlops(i)/NgProfiler::GetTime(i)*1e-9);
|
||||
timers.append(timer);
|
||||
}
|
||||
return timers;
|
||||
}, "Returns list of timers"
|
||||
);
|
||||
m.def("ResetTimers", &NgProfiler::Reset);
|
||||
|
||||
py::class_<NgMPI_Comm> (m, "MPI_Comm")
|
||||
#ifdef PARALLEL
|
||||
.def(py::init([] (mpi4py_comm comm) { return NgMPI_Comm(comm); }))
|
||||
.def("WTime", [](NgMPI_Comm & c) { return NG_MPI_Wtime(); })
|
||||
.def_property_readonly ("mpi4py", [](NgMPI_Comm & self) { return NG_MPI_CommToMPI4Py(self); })
|
||||
#endif // PARALLEL
|
||||
.def_property_readonly ("rank", &NgMPI_Comm::Rank)
|
||||
.def_property_readonly ("size", &NgMPI_Comm::Size)
|
||||
.def("Barrier", &NgMPI_Comm::Barrier)
|
||||
.def("Sum", [](NgMPI_Comm & c, double x) { return c.AllReduce(x, NG_MPI_SUM); })
|
||||
.def("Min", [](NgMPI_Comm & c, double x) { return c.AllReduce(x, NG_MPI_MIN); })
|
||||
.def("Max", [](NgMPI_Comm & c, double x) { return c.AllReduce(x, NG_MPI_MAX); })
|
||||
.def("Sum", [](NgMPI_Comm & c, int x) { return c.AllReduce(x, NG_MPI_SUM); })
|
||||
.def("Min", [](NgMPI_Comm & c, int x) { return c.AllReduce(x, NG_MPI_MIN); })
|
||||
.def("Max", [](NgMPI_Comm & c, int x) { return c.AllReduce(x, NG_MPI_MAX); })
|
||||
.def("Sum", [](NgMPI_Comm & c, size_t x) { return c.AllReduce(x, NG_MPI_SUM); })
|
||||
.def("Min", [](NgMPI_Comm & c, size_t x) { return c.AllReduce(x, NG_MPI_MIN); })
|
||||
.def("Max", [](NgMPI_Comm & c, size_t x) { return c.AllReduce(x, NG_MPI_MAX); })
|
||||
.def("SubComm", [](NgMPI_Comm & c, std::vector<int> proc_list) {
|
||||
Array<int> procs(proc_list.size());
|
||||
for (int i = 0; i < procs.Size(); i++)
|
||||
{ procs[i] = proc_list[i]; }
|
||||
if (!procs.Contains(c.Rank()))
|
||||
{ throw Exception("rank "+ToString(c.Rank())+" not in subcomm"); }
|
||||
return c.SubCommunicator(procs);
|
||||
}, py::arg("procs"));
|
||||
;
|
||||
|
||||
|
||||
#ifdef PARALLEL
|
||||
py::implicitly_convertible<mpi4py_comm, NgMPI_Comm>();
|
||||
#endif // PARALLEL
|
||||
}
|
||||
|
92
libsrc/core/register_archive.hpp
Normal file
92
libsrc/core/register_archive.hpp
Normal file
@ -0,0 +1,92 @@
|
||||
#ifndef NETGEN_REGISTER_ARCHIVE_HPP
|
||||
#define NETGEN_REGISTER_ARCHIVE_HPP
|
||||
|
||||
#ifdef NETGEN_PYTHON
|
||||
#include <memory>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/cast.h>
|
||||
#endif // NETGEN_PYTHON
|
||||
#include <tuple>
|
||||
|
||||
#include "archive.hpp"
|
||||
|
||||
namespace ngcore {
|
||||
// *************** Archiving functionality **************
|
||||
|
||||
#ifdef NETGEN_PYTHON
|
||||
template<typename T>
|
||||
Archive& Archive :: Shallow(T& val)
|
||||
{
|
||||
static_assert(detail::is_any_pointer<T>, "ShallowArchive must be given pointer type!");
|
||||
if(shallow_to_python)
|
||||
{
|
||||
if(is_output)
|
||||
ShallowOutPython(pybind11::cast(val));
|
||||
else
|
||||
{
|
||||
pybind11::object obj;
|
||||
ShallowInPython(obj);
|
||||
val = pybind11::cast<T>(obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
*this & val;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
// now using has_shared_from_this2 in archive.hpp
|
||||
template <typename T>
|
||||
struct has_shared_from_this
|
||||
{
|
||||
template <typename C> static std::true_type check( decltype( sizeof(&C::shared_from_this )) ) { return std::true_type(); }
|
||||
template <typename> static std::false_type check(...) { return std::false_type(); }
|
||||
typedef decltype( check<T>(sizeof(char)) ) type;
|
||||
static constexpr type value = type();
|
||||
};
|
||||
*/
|
||||
#endif // NETGEN_PYTHON
|
||||
|
||||
|
||||
template<typename T, typename Bases=std::tuple<>>
|
||||
class RegisterClassForArchive
|
||||
{
|
||||
public:
|
||||
RegisterClassForArchive()
|
||||
{
|
||||
static_assert(std::is_base_of<Bases, T>::value ||
|
||||
detail::is_base_of_tuple<T, Bases>,
|
||||
"Second argument must be base class or tuple of base classes of T");
|
||||
detail::ClassArchiveInfo info {};
|
||||
info.creator = [](const std::type_info& ti, Archive& ar) -> void*
|
||||
{
|
||||
detail::TCargs<T> args;
|
||||
ar &args;
|
||||
auto nT = detail::constructIfPossible<T>(std::move(args));
|
||||
return typeid(T) == ti ? nT
|
||||
: Archive::Caster<T, Bases>::tryUpcast(ti, nT);
|
||||
};
|
||||
info.upcaster = [](const std::type_info& ti, void* p) -> void*
|
||||
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases>::tryUpcast(ti, static_cast<T*>(p)); };
|
||||
info.downcaster = [](const std::type_info& ti, void* p) -> void*
|
||||
{ return typeid(T) == ti ? p : Archive::Caster<T, Bases>::tryDowncast(ti, p); };
|
||||
info.cargs_archiver = [](Archive &ar, void* p) {
|
||||
if constexpr(detail::has_GetCArgs_v<T>)
|
||||
ar << static_cast<T*>(p)->GetCArgs();
|
||||
};
|
||||
#ifdef NETGEN_PYTHON
|
||||
info.anyToPyCaster = [](const std::any &a) {
|
||||
if constexpr(has_shared_from_this2<T>::value) {
|
||||
std::shared_ptr<T> val = std::any_cast<std::shared_ptr<T>>(a);
|
||||
return pybind11::cast(val);
|
||||
} else {
|
||||
const T* val = std::any_cast<T>(&a);
|
||||
return pybind11::cast(val);
|
||||
}
|
||||
};
|
||||
#endif // NETGEN_PYTHON
|
||||
Archive::SetArchiveRegister(std::string(Demangle(typeid(T).name())),info);
|
||||
}
|
||||
};
|
||||
} // namespace ngcore
|
||||
#endif // NETGEN_REGISTER_ARCHIVE_HPP
|
@ -2,6 +2,7 @@
|
||||
#define NGCORE_SIGNALS_HPP
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
namespace ngcore
|
||||
@ -43,6 +44,39 @@ namespace ngcore
|
||||
}
|
||||
inline bool GetEmitting() const { return is_emitting; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class SimpleSignal
|
||||
{
|
||||
private:
|
||||
// std::map<void*,std::function<void()>> funcs;
|
||||
std::list<std::pair<void*,std::function<void()>>> funcs;
|
||||
public:
|
||||
SimpleSignal() = default;
|
||||
|
||||
template<typename FUNC>
|
||||
void Connect(void* var, FUNC f)
|
||||
{
|
||||
// funcs[var] = f;
|
||||
funcs.push_back ( { var, f } );
|
||||
}
|
||||
|
||||
void Remove(void* var)
|
||||
{
|
||||
// funcs.erase(var);
|
||||
funcs.remove_if([&] (auto var_f) { return var_f.first==var; });
|
||||
}
|
||||
|
||||
inline void Emit()
|
||||
{
|
||||
for (auto [key,f] : funcs)
|
||||
f();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
#endif // NGCORE_SIGNALS_HPP
|
||||
|
@ -11,6 +11,8 @@
|
||||
|
||||
#include "simd_generic.hpp"
|
||||
|
||||
#ifndef __CUDA_ARCH__
|
||||
|
||||
#ifdef NETGEN_ARCH_AMD64
|
||||
#ifndef __SSE__
|
||||
#define __SSE__
|
||||
@ -30,35 +32,49 @@
|
||||
#include "simd_arm64.hpp"
|
||||
#endif
|
||||
|
||||
#endif // __CUDA_ARCH__
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
#ifndef __CUDA_ARCH__
|
||||
#ifdef NETGEN_ARCH_AMD64
|
||||
/*
|
||||
NETGEN_INLINE auto HSum (SIMD<double,2> v1, SIMD<double,2> v2, SIMD<double,2> v3, SIMD<double,2> v4)
|
||||
{
|
||||
SIMD<double,2> hsum1 = my_mm_hadd_pd (v1.Data(), v2.Data());
|
||||
SIMD<double,2> hsum2 = my_mm_hadd_pd (v3.Data(), v4.Data());
|
||||
return SIMD<double,4> (hsum1, hsum2);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
NETGEN_INLINE auto GetMaskFromBits( unsigned int i )
|
||||
{
|
||||
return SIMD<mask64>::GetMaskFromBits(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif // __CUDA_ARCH__
|
||||
|
||||
NETGEN_INLINE void SIMDTranspose (SIMD<double,4> a1, SIMD<double,4> a2, SIMD <double,4> a3, SIMD<double,4> a4,
|
||||
SIMD<double,4> & b1, SIMD<double,4> & b2, SIMD<double,4> & b3, SIMD<double,4> & b4)
|
||||
SIMD<double,4> & b1, SIMD<double,4> & b2, SIMD<double,4> & b3, SIMD<double,4> & b4)
|
||||
{
|
||||
SIMD<double,4> h1,h2,h3,h4;
|
||||
std::tie(h1,h2) = Unpack(a1,a2);
|
||||
std::tie(h3,h4) = Unpack(a3,a4);
|
||||
b1 = SIMD<double,4> (h1.Lo(), h3.Lo());
|
||||
b2 = SIMD<double,4> (h2.Lo(), h4.Lo());
|
||||
b3 = SIMD<double,4> (h1.Hi(), h3.Hi());
|
||||
b4 = SIMD<double,4> (h2.Hi(), h4.Hi());
|
||||
if constexpr (sizeof(a1.Lo()) == 16)
|
||||
{
|
||||
auto [h1,h2] = Unpack(a1,a2);
|
||||
auto [h3,h4] = Unpack(a3,a4);
|
||||
b1 = SIMD<double,4> (h1.Lo(), h3.Lo());
|
||||
b2 = SIMD<double,4> (h2.Lo(), h4.Lo());
|
||||
b3 = SIMD<double,4> (h1.Hi(), h3.Hi());
|
||||
b4 = SIMD<double,4> (h2.Hi(), h4.Hi());
|
||||
}
|
||||
else
|
||||
{
|
||||
b1 = SIMD<double,4> (a1[0], a2[0], a3[0], a4[0]);
|
||||
b2 = SIMD<double,4> (a1[1], a2[1], a3[1], a4[1]);
|
||||
b3 = SIMD<double,4> (a1[2], a2[2], a3[2], a4[2]);
|
||||
b4 = SIMD<double,4> (a1[3], a2[3], a3[3], a4[3]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<int N>
|
||||
NETGEN_INLINE auto HSum (SIMD<double,N> s1, SIMD<double,N> s2)
|
||||
{
|
||||
@ -68,7 +84,8 @@ namespace ngcore
|
||||
template<int N>
|
||||
NETGEN_INLINE auto HSum (SIMD<double,N> s1, SIMD<double,N> s2, SIMD<double,N> s3, SIMD<double,N> s4 )
|
||||
{
|
||||
return SIMD<double,4>(HSum(s1), HSum(s2), HSum(s3), HSum(s4));
|
||||
// return SIMD<double,4>(HSum(s1), HSum(s2), HSum(s3), HSum(s4));
|
||||
return SIMD<double,4>(HSum(s1, s2), HSum(s3,s4));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,9 +14,10 @@ namespace ngcore
|
||||
mask[1] = i > 1 ? -1 : 0;
|
||||
}
|
||||
|
||||
SIMD (bool i0, bool i1) { mask[0] = i0 ? -1:0; mask[1] = i1 ? -1 : 0; }
|
||||
SIMD (bool i0, bool i1) { mask[0] = i0 ? -1 : 0; mask[1] = i1 ? -1 : 0; }
|
||||
SIMD (SIMD<mask64,1> i0, SIMD<mask64,1> i1) { mask[0] = i0[0]; mask[1] = i1[0]; }
|
||||
SIMD (float64x2_t _data) : mask{_data} { }
|
||||
// SIMD (float64x2_t _data) : mask{_data} { }
|
||||
SIMD (int64x2_t _data) : mask{_data} { }
|
||||
auto Data() const { return mask; }
|
||||
static constexpr int Size() { return 2; }
|
||||
// static NETGEN_INLINE SIMD<mask64, 2> GetMaskFromBits (unsigned int i);
|
||||
@ -41,6 +42,7 @@ namespace ngcore
|
||||
SIMD (const SIMD &) = default;
|
||||
// SIMD (double v0, double v1) : data{v0,v1} { }
|
||||
SIMD (double v0, double v1) : data{vcombine_f64(float64x1_t{v0}, float64x1_t{v1})} { }
|
||||
SIMD (SIMD<double,1> v0, SIMD<double,1> v1) : data{vcombine_f64(float64x1_t{v0.Data()}, float64x1_t{v1.Data()})} { }
|
||||
SIMD (std::array<double, 2> arr) : data{arr[0], arr[1]} { }
|
||||
|
||||
SIMD & operator= (const SIMD &) = default;
|
||||
@ -117,9 +119,21 @@ namespace ngcore
|
||||
{
|
||||
// return SIMD<double,2> (a[0]+a[1], b[0]+b[1]);
|
||||
return vpaddq_f64(a.Data(), b.Data());
|
||||
|
||||
}
|
||||
|
||||
NETGEN_INLINE SIMD<double,4> HSum(SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> c, SIMD<double,2> d)
|
||||
{
|
||||
return SIMD<double,4> (HSum(a,b), HSum(c,d));
|
||||
}
|
||||
|
||||
|
||||
NETGEN_INLINE SIMD<double,2> SwapPairs (SIMD<double,2> a)
|
||||
{
|
||||
return __builtin_shufflevector(a.Data(), a.Data(), 1, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// a*b+c
|
||||
NETGEN_INLINE SIMD<double,2> FMA (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> c)
|
||||
{
|
||||
@ -140,6 +154,16 @@ namespace ngcore
|
||||
return FNMA(SIMD<double,2> (a), b, c);
|
||||
}
|
||||
|
||||
// ARM complex mult:
|
||||
// https://arxiv.org/pdf/1901.07294.pdf
|
||||
// c += a*b (a0re, a0im, a1re, a1im, ...),
|
||||
NETGEN_INLINE void FMAComplex (SIMD<double,2> a, SIMD<double,2> b, SIMD<double,2> & c)
|
||||
{
|
||||
auto tmp = vcmlaq_f64(c.Data(), a.Data(), b.Data()); // are * b
|
||||
c = vcmlaq_rot90_f64(tmp, a.Data(), b.Data()); // += i*aim * b
|
||||
}
|
||||
|
||||
|
||||
NETGEN_INLINE SIMD<double,2> operator+ (SIMD<double,2> a, SIMD<double,2> b)
|
||||
{ return a.Data()+b.Data(); }
|
||||
|
||||
@ -159,7 +183,8 @@ namespace ngcore
|
||||
NETGEN_INLINE SIMD<double,2> If (SIMD<mask64,2> a, SIMD<double,2> b, SIMD<double,2> c)
|
||||
{
|
||||
// return { a[0] ? b[0] : c[0], a[1] ? b[1] : c[1] };
|
||||
return vbslq_f64(a.Data(), b.Data(), c.Data());
|
||||
uint64x2_t mask = vreinterpretq_u64_s64(a.Data());
|
||||
return vbslq_f64(mask, b.Data(), c.Data());
|
||||
}
|
||||
NETGEN_INLINE SIMD<int64_t,2> If (SIMD<mask64,2> a, SIMD<int64_t,2> b, SIMD<int64_t,2> c)
|
||||
{
|
||||
@ -168,7 +193,10 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE SIMD<mask64,2> operator&& (SIMD<mask64,2> a, SIMD<mask64,2> b)
|
||||
{
|
||||
return vandq_u64 (a.Data(), b.Data());
|
||||
uint64x2_t m1 = vreinterpretq_u64_s64(a.Data());
|
||||
uint64x2_t m2 = vreinterpretq_u64_s64(b.Data());
|
||||
uint64x2_t res = vandq_u64 (m1, m2);
|
||||
return vreinterpretq_s64_u64(res);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -141,10 +141,8 @@ namespace ngcore
|
||||
|
||||
NETGEN_INLINE double operator[] (int i) const { return ((double*)(&data))[i]; }
|
||||
NETGEN_INLINE double & operator[] (int i) { return ((double*)(&data))[i]; }
|
||||
// [[deprecated("don't write to individual elments of SIMD")]]
|
||||
// [[deprecated("don't write to individual elements of SIMD")]]
|
||||
// NETGEN_INLINE double & operator[] (int i) { return ((double*)(&data))[i]; }
|
||||
template <int I>
|
||||
double Get() const { return ((double*)(&data))[I]; }
|
||||
NETGEN_INLINE __m256d Data() const { return data; }
|
||||
NETGEN_INLINE __m256d & Data() { return data; }
|
||||
|
||||
@ -153,6 +151,13 @@ namespace ngcore
|
||||
|
||||
operator std::tuple<double&,double&,double&,double&> ()
|
||||
{ return std::tuple<double&,double&,double&,double&>((*this)[0], (*this)[1], (*this)[2], (*this)[3]); }
|
||||
|
||||
template <int I>
|
||||
double Get() const
|
||||
{
|
||||
static_assert(I>=0 && I<4, "Index out of range");
|
||||
return (*this)[I];
|
||||
}
|
||||
};
|
||||
|
||||
NETGEN_INLINE auto Unpack (SIMD<double,4> a, SIMD<double,4> b)
|
||||
@ -214,8 +219,18 @@ namespace ngcore
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__FMA__)
|
||||
NETGEN_INLINE SIMD<double,4> FMAddSub (SIMD<double,4> a, SIMD<double,4> b, SIMD<double,4> c)
|
||||
{
|
||||
return _mm256_fmaddsub_pd(a.Data(), b.Data(), c.Data());
|
||||
}
|
||||
#endif
|
||||
|
||||
NETGEN_INLINE SIMD<double,4> SwapPairs (SIMD<double,4> a)
|
||||
{
|
||||
return _mm256_shuffle_pd (a.Data(), a.Data(), 0b0101);
|
||||
}
|
||||
|
||||
|
||||
NETGEN_INLINE SIMD<mask64,4> operator<= (SIMD<double,4> a , SIMD<double,4> b)
|
||||
@ -303,6 +318,8 @@ namespace ngcore
|
||||
{ return _mm256_castpd_si256(_mm256_blendv_pd(_mm256_castsi256_pd(c.Data()), _mm256_castsi256_pd(b.Data()),
|
||||
_mm256_castsi256_pd(a.Data()))); }
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // NETGEN_CORE_SIMD_AVX_HPP
|
||||
|
@ -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 }; }
|
||||
@ -92,6 +93,12 @@ namespace ngcore
|
||||
SIMD (double const * p, SIMD<mask64,8> mask)
|
||||
{ data = _mm512_mask_loadu_pd(_mm512_setzero_pd(), mask.Data(), p); }
|
||||
SIMD (__m512d _data) { data = _data; }
|
||||
SIMD (SIMD<double,4> v0, SIMD<double,4> v1)
|
||||
: data(_mm512_set_pd(v1[3], v1[2], v1[1], v1[0], v0[3], v0[2], v0[1], v0[0]))
|
||||
{}
|
||||
SIMD (SIMD<double,6> v0, SIMD<double,2> v1)
|
||||
: data(_mm512_set_pd(v1[1], v1[0], v0[5], v0[4], v0[3], v0[2], v0[1], v0[0]))
|
||||
{}
|
||||
|
||||
template<typename T, typename std::enable_if<std::is_convertible<T, std::function<double(int)>>::value, int>::type = 0>
|
||||
SIMD (const T & func)
|
||||
@ -105,7 +112,7 @@ namespace ngcore
|
||||
template <typename Function>
|
||||
void SIMD_function (const Function & func, std::true_type)
|
||||
{
|
||||
data = (__m512){ func(7), func(6), func(5), func(4),
|
||||
data = (__m512d){ func(7), func(6), func(5), func(4),
|
||||
func(3), func(2), func(1), func(0) };
|
||||
}
|
||||
|
||||
@ -126,12 +133,22 @@ 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; }
|
||||
|
||||
SIMD<double,4> Lo() const { return _mm512_extractf64x4_pd(data, 0); }
|
||||
SIMD<double,4> Hi() const { return _mm512_extractf64x4_pd(data, 1); }
|
||||
|
||||
template <int I>
|
||||
double Get() const
|
||||
{
|
||||
static_assert(I>=0 && I<8, "Index out of range");
|
||||
return (*this)[I];
|
||||
}
|
||||
};
|
||||
|
||||
NETGEN_INLINE SIMD<double,8> operator- (SIMD<double,8> a) { return -a.Data(); }
|
||||
NETGEN_INLINE SIMD<double,8> operator- (SIMD<double,8> a) { return _mm512_xor_pd(a.Data(), _mm512_set1_pd(-0.0)); } //{ return -a.Data(); }
|
||||
NETGEN_INLINE SIMD<double,8> operator+ (SIMD<double,8> a, SIMD<double,8> b) { return _mm512_add_pd(a.Data(),b.Data()); }
|
||||
NETGEN_INLINE SIMD<double,8> operator- (SIMD<double,8> a, SIMD<double,8> b) { return _mm512_sub_pd(a.Data(),b.Data()); }
|
||||
NETGEN_INLINE SIMD<double,8> operator* (SIMD<double,8> a, SIMD<double,8> b) { return _mm512_mul_pd(a.Data(),b.Data()); }
|
||||
@ -142,7 +159,7 @@ namespace ngcore
|
||||
NETGEN_INLINE SIMD<double,8> sqrt (SIMD<double,8> a) { return _mm512_sqrt_pd(a.Data()); }
|
||||
NETGEN_INLINE SIMD<double,8> floor (SIMD<double,8> a) { return _mm512_floor_pd(a.Data()); }
|
||||
NETGEN_INLINE SIMD<double,8> ceil (SIMD<double,8> a) { return _mm512_ceil_pd(a.Data()); }
|
||||
NETGEN_INLINE SIMD<double,8> fabs (SIMD<double,8> a) { return _mm512_max_pd(a.Data(), -a.Data()); }
|
||||
NETGEN_INLINE SIMD<double,8> fabs (SIMD<double,8> a) { return _mm512_max_pd(a.Data(), ( - a).Data()); }
|
||||
|
||||
NETGEN_INLINE SIMD<mask64,8> operator<= (SIMD<double,8> a , SIMD<double,8> b)
|
||||
{ return _mm512_cmp_pd_mask (a.Data(), b.Data(), _CMP_LE_OQ); }
|
||||
@ -221,9 +238,9 @@ namespace ngcore
|
||||
// sum01 b a b a b a b a
|
||||
// sum23 d c d c d c d c
|
||||
// __m512 perm = _mm512_permutex2var_pd (sum01.Data(), _mm512_set_epi64(1,2,3,4,5,6,7,8), sum23.Data());
|
||||
__m256d ab = _mm512_extractf64x4_pd(sum01.Data(),0) + _mm512_extractf64x4_pd(sum01.Data(),1);
|
||||
__m256d cd = _mm512_extractf64x4_pd(sum23.Data(),0) + _mm512_extractf64x4_pd(sum23.Data(),1);
|
||||
return _mm256_add_pd (_mm256_permute2f128_pd (ab, cd, 1+2*16), _mm256_blend_pd (ab, cd, 12));
|
||||
SIMD<double,4> ab = _mm512_extractf64x4_pd(sum01.Data(),0) + _mm512_extractf64x4_pd(sum01.Data(),1);
|
||||
SIMD<double,4> cd = _mm512_extractf64x4_pd(sum23.Data(),0) + _mm512_extractf64x4_pd(sum23.Data(),1);
|
||||
return _mm256_add_pd (_mm256_permute2f128_pd (ab.Data(), cd.Data(), 1 + 2 * 16), _mm256_blend_pd(ab.Data(), cd.Data(), 12));
|
||||
}
|
||||
|
||||
NETGEN_INLINE SIMD<double,8> FMA (SIMD<double,8> a, SIMD<double,8> b, SIMD<double,8> c)
|
||||
@ -244,6 +261,16 @@ namespace ngcore
|
||||
return _mm512_fnmadd_pd (_mm512_set1_pd(a), b.Data(), c.Data());
|
||||
}
|
||||
|
||||
NETGEN_INLINE SIMD<double,8> FMAddSub (SIMD<double,8> a, SIMD<double,8> b, SIMD<double,8> c)
|
||||
{
|
||||
return _mm512_fmaddsub_pd(a.Data(), b.Data(), c.Data());
|
||||
}
|
||||
|
||||
NETGEN_INLINE SIMD<double,8> SwapPairs (SIMD<double,8> a)
|
||||
{
|
||||
return _mm512_shuffle_pd (a.Data(), a.Data(), 0b01010101);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // NETGEN_CORE_SIMD_AVX512_HPP
|
||||
|
@ -10,22 +10,42 @@
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <cmath>
|
||||
|
||||
#include "array.hpp"
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
#if defined __AVX512F__
|
||||
#define NETGEN_DEFAULT_SIMD_SIZE 8
|
||||
#elif defined __AVX__
|
||||
#define NETGEN_DEFAULT_SIMD_SIZE 4
|
||||
#else
|
||||
#define NETGEN_DEFAULT_SIMD_SIZE 2
|
||||
#endif
|
||||
|
||||
constexpr int GetDefaultSIMDSize() {
|
||||
#if defined __AVX512F__
|
||||
return 8;
|
||||
#elif defined __AVX__
|
||||
return 4;
|
||||
#elif defined NETGEN_ARCH_AMD64
|
||||
return 2;
|
||||
#else
|
||||
return 2;
|
||||
return NETGEN_DEFAULT_SIMD_SIZE;
|
||||
}
|
||||
|
||||
constexpr bool IsNativeSIMDSize(int n) {
|
||||
if(n==1) return true;
|
||||
if(n==2) return true;
|
||||
#if defined __AVX__
|
||||
if(n==4) return true;
|
||||
#endif
|
||||
#if defined __AVX512F__
|
||||
if(n==8) return true;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
// split n = k+l such that k is the largest natively supported simd size < n
|
||||
constexpr int GetLargestNativeSIMDPart(int n) {
|
||||
int k = n-1;
|
||||
while(!IsNativeSIMDSize(k))
|
||||
k--;
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
@ -67,9 +87,9 @@ namespace ngcore
|
||||
|
||||
|
||||
template <int N>
|
||||
class alignas(GetDefaultSIMDSize()*sizeof(int64_t)) SIMD<mask64,N>
|
||||
class alignas(GetLargestNativeSIMDPart(N)*sizeof(int64_t)) SIMD<mask64,N>
|
||||
{
|
||||
static constexpr int N1 = std::min(GetDefaultSIMDSize(), N/2);
|
||||
static constexpr int N1 = GetLargestNativeSIMDPart(N);
|
||||
static constexpr int N2 = N-N1;
|
||||
|
||||
SIMD<mask64,N1> lo;
|
||||
@ -123,9 +143,9 @@ namespace ngcore
|
||||
};
|
||||
|
||||
template<int N>
|
||||
class alignas(GetDefaultSIMDSize()*sizeof(int64_t)) SIMD<int64_t,N>
|
||||
class alignas(GetLargestNativeSIMDPart(N)*sizeof(int64_t)) SIMD<int64_t,N>
|
||||
{
|
||||
static constexpr int N1 = std::min(GetDefaultSIMDSize(), N/2);
|
||||
static constexpr int N1 = GetLargestNativeSIMDPart(N);
|
||||
static constexpr int N2 = N-N1;
|
||||
|
||||
SIMD<int64_t,N1> lo;
|
||||
@ -240,9 +260,9 @@ namespace ngcore
|
||||
|
||||
|
||||
template<int N>
|
||||
class alignas(GetDefaultSIMDSize()*sizeof(double)) SIMD<double, N>
|
||||
class alignas(GetLargestNativeSIMDPart(N)*sizeof(double)) SIMD<double, N>
|
||||
{
|
||||
static constexpr int N1 = std::min(GetDefaultSIMDSize(), N/2);
|
||||
static constexpr int N1 = GetLargestNativeSIMDPart(N);
|
||||
static constexpr int N2 = N-N1;
|
||||
|
||||
SIMD<double, N1> lo;
|
||||
@ -486,8 +506,6 @@ namespace ngcore
|
||||
return HSum(a.Lo()) + HSum(a.Hi());
|
||||
}
|
||||
|
||||
NETGEN_INLINE double IfPos (double a, double b, double c) { return a>0 ? b : c; }
|
||||
NETGEN_INLINE double IfZero (double a, double b, double c) { return a==0. ? b : c; }
|
||||
|
||||
template<typename T, int N>
|
||||
NETGEN_INLINE SIMD<T,N> IfPos (SIMD<T,N> a, SIMD<T,N> b, SIMD<T,N> c)
|
||||
@ -541,9 +559,18 @@ namespace ngcore
|
||||
sum = FNMA(a,b,sum);
|
||||
}
|
||||
|
||||
// c += a*b (a0re, a0im, a1re, a1im, ...),
|
||||
template <int N>
|
||||
void FMAComplex (SIMD<double,N> a, SIMD<double,N> b, SIMD<double,N> & c)
|
||||
{
|
||||
auto [are, aim] = Unpack(a, a);
|
||||
SIMD<double,N> bswap = SwapPairs(b);
|
||||
SIMD<double,N> aim_bswap = aim*bswap;
|
||||
c += FMAddSub (are, b, aim_bswap);
|
||||
}
|
||||
|
||||
template <int i, typename T, int N>
|
||||
T get(SIMD<T,N> a) { return a[i]; }
|
||||
T get(SIMD<T,N> a) { return a.template Get<i>(); }
|
||||
|
||||
template <int NUM, typename FUNC>
|
||||
NETGEN_INLINE void Iterate2 (FUNC f)
|
||||
@ -571,31 +598,31 @@ namespace ngcore
|
||||
using std::sqrt;
|
||||
template <int N>
|
||||
NETGEN_INLINE ngcore::SIMD<double,N> sqrt (ngcore::SIMD<double,N> a) {
|
||||
return ngcore::SIMD<double>([a](int i)->double { return sqrt(a[i]); } );
|
||||
return ngcore::SIMD<double,N>([a](int i)->double { return sqrt(a[i]); } );
|
||||
}
|
||||
|
||||
using std::fabs;
|
||||
template <int N>
|
||||
NETGEN_INLINE ngcore::SIMD<double,N> fabs (ngcore::SIMD<double,N> a) {
|
||||
return ngcore::SIMD<double>([a](int i)->double { return fabs(a[i]); } );
|
||||
return ngcore::SIMD<double,N>([a](int i)->double { return fabs(a[i]); } );
|
||||
}
|
||||
|
||||
using std::floor;
|
||||
template <int N>
|
||||
NETGEN_INLINE ngcore::SIMD<double,N> floor (ngcore::SIMD<double,N> a) {
|
||||
return ngcore::SIMD<double>([a](int i)->double { return floor(a[i]); } );
|
||||
return ngcore::SIMD<double,N>([a](int i)->double { return floor(a[i]); } );
|
||||
}
|
||||
|
||||
using std::ceil;
|
||||
template <int N>
|
||||
NETGEN_INLINE ngcore::SIMD<double,N> ceil (ngcore::SIMD<double,N> a) {
|
||||
return ngcore::SIMD<double>([a](int i)->double { return ceil(a[i]); } );
|
||||
return ngcore::SIMD<double,N>([a](int i)->double { return ceil(a[i]); } );
|
||||
}
|
||||
|
||||
using std::exp;
|
||||
template <int N>
|
||||
NETGEN_INLINE ngcore::SIMD<double,N> exp (ngcore::SIMD<double,N> a) {
|
||||
return ngcore::SIMD<double>([a](int i)->double { return exp(a[i]); } );
|
||||
return ngcore::SIMD<double,N>([a](int i)->double { return exp(a[i]); } );
|
||||
}
|
||||
|
||||
using std::log;
|
||||
@ -604,6 +631,12 @@ namespace ngcore
|
||||
return ngcore::SIMD<double,N>([a](int i)->double { return log(a[i]); } );
|
||||
}
|
||||
|
||||
using std::erf;
|
||||
template <int N>
|
||||
NETGEN_INLINE ngcore::SIMD<double,N> erf (ngcore::SIMD<double,N> a) {
|
||||
return ngcore::SIMD<double,N>([a](int i)->double { return erf(a[i]); } );
|
||||
}
|
||||
|
||||
using std::pow;
|
||||
template <int N>
|
||||
NETGEN_INLINE ngcore::SIMD<double,N> pow (ngcore::SIMD<double,N> a, double x) {
|
||||
@ -693,6 +726,57 @@ namespace ngcore
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: specialize for AVX, ...
|
||||
template<int N>
|
||||
NETGEN_INLINE auto SwapPairs (SIMD<double,N> a)
|
||||
{
|
||||
if constexpr(N==1) {
|
||||
// static_assert(false);
|
||||
return a;
|
||||
}
|
||||
else if constexpr(N==2) {
|
||||
return SIMD<double,N> (a.Hi(), a.Lo());
|
||||
}
|
||||
else {
|
||||
return SIMD<double,N> (SwapPairs(a.Lo()), SwapPairs(a.Hi()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<int N>
|
||||
NETGEN_INLINE auto HSum128 (SIMD<double,N> a)
|
||||
{
|
||||
if constexpr(N==1) {
|
||||
// static_assert(false);
|
||||
return a;
|
||||
}
|
||||
else if constexpr(N==2) {
|
||||
return a;
|
||||
}
|
||||
else {
|
||||
return HSum128(a.Lo()) + HSum128(a.Hi());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO: specialize for AVX, ...
|
||||
// a*b+-c (even: -, odd: +)
|
||||
template<int N>
|
||||
NETGEN_INLINE auto FMAddSub (SIMD<double,N> a, SIMD<double,N> b, SIMD<double,N> c)
|
||||
{
|
||||
if constexpr(N==1) {
|
||||
// static_assert(false);
|
||||
return a*b-c;
|
||||
}
|
||||
else if constexpr(N==2) {
|
||||
return SIMD<double,N> (a.Lo()*b.Lo()-c.Lo(),
|
||||
a.Hi()*b.Hi()+c.Hi());
|
||||
}
|
||||
else {
|
||||
return SIMD<double,N> (FMAddSub(a.Lo(), b.Lo(), c.Lo()),
|
||||
FMAddSub(a.Hi(), b.Hi(), c.Hi()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -86,6 +86,9 @@ NETGEN_INLINE SIMD<int64_t,2> operator- (SIMD<int64_t,2> a, SIMD<int64_t,2> b) {
|
||||
SIMD () {}
|
||||
SIMD (const SIMD &) = default;
|
||||
SIMD (double v0, double v1) { data = _mm_set_pd(v1,v0); }
|
||||
SIMD (SIMD<double,1> v0, SIMD<double,1> v1)
|
||||
: data{_mm_set_pd(v0.Data(), v1.Data())}
|
||||
{ }
|
||||
SIMD (std::array<double, 2> arr)
|
||||
: data{_mm_set_pd(arr[1], arr[0])}
|
||||
{}
|
||||
@ -137,6 +140,16 @@ NETGEN_INLINE SIMD<int64_t,2> operator- (SIMD<int64_t,2> a, SIMD<int64_t,2> b) {
|
||||
NETGEN_INLINE __m128d Data() const { return data; }
|
||||
NETGEN_INLINE __m128d & Data() { return data; }
|
||||
|
||||
template <int I>
|
||||
double Get() const
|
||||
{
|
||||
static_assert(I>=0 && I<2, "Index out of range");
|
||||
return (*this)[I];
|
||||
}
|
||||
|
||||
double Lo() const { return Get<0>(); }
|
||||
double Hi() const { return Get<1>(); }
|
||||
|
||||
operator std::tuple<double&,double&> ()
|
||||
{
|
||||
auto pdata = (double*)&data;
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "archive.hpp"
|
||||
#include "exception.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
|
||||
@ -38,14 +37,15 @@ namespace ngcore
|
||||
SymbolTable& operator=(const SymbolTable<T>&) = default;
|
||||
SymbolTable& operator=(SymbolTable<T>&&) = default;
|
||||
|
||||
template<typename T2=T>
|
||||
auto DoArchive(Archive& ar) -> typename std::enable_if_t<is_archivable<T2>>
|
||||
template<typename ARCHIVE>
|
||||
auto DoArchive(ARCHIVE& ar)
|
||||
-> typename std::enable_if_t<ARCHIVE::template is_archivable<T>, void>
|
||||
{
|
||||
ar & names & data;
|
||||
}
|
||||
|
||||
/// INDEX of symbol name, throws exception if unused
|
||||
size_t Index (const std::string & name) const
|
||||
size_t Index (std::string_view name) const
|
||||
{
|
||||
for (size_t i = 0; i < names.size(); i++)
|
||||
if (names[i] == name) return i;
|
||||
@ -53,7 +53,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// Index of symbol name, returns -1 if unused
|
||||
int CheckIndex (const std::string & name) const
|
||||
int CheckIndex (std::string_view name) const
|
||||
{
|
||||
for (int i = 0; i < names.size(); i++)
|
||||
if (names[i] == name) return i;
|
||||
@ -67,12 +67,12 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// Returns reference to element. exception for unused identifier
|
||||
reference operator[] (const std::string & name)
|
||||
reference operator[] (std::string_view name)
|
||||
{
|
||||
return data[Index (name)];
|
||||
}
|
||||
|
||||
const_reference operator[] (const std::string & name) const
|
||||
const_reference operator[] (std::string_view name) const
|
||||
{
|
||||
return data[Index (name)];
|
||||
}
|
||||
@ -99,7 +99,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// Associates el to the string name, overrides if name is used
|
||||
void Set (const std::string & name, const T & el)
|
||||
void Set (std::string_view name, const T & el)
|
||||
{
|
||||
int i = CheckIndex (name);
|
||||
if (i >= 0)
|
||||
@ -107,15 +107,24 @@ namespace ngcore
|
||||
else
|
||||
{
|
||||
data.push_back(el);
|
||||
names.push_back(name);
|
||||
names.push_back(std::string(name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
bool Used (const std::string & name) const
|
||||
{
|
||||
return CheckIndex(name) >= 0;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
bool Used (std::string_view name) const
|
||||
{
|
||||
return CheckIndex(name) >= 0;
|
||||
}
|
||||
|
||||
/// Deletes symboltable
|
||||
inline void DeleteAll ()
|
||||
{
|
||||
|
@ -62,9 +62,9 @@ namespace ngcore
|
||||
return index;
|
||||
}
|
||||
|
||||
NGCORE_API size_t * TablePrefixSum32 (FlatArray<unsigned int> entrysize)
|
||||
NGCORE_API size_t * TablePrefixSum32 (FlatArray<uint32_t> entrysize)
|
||||
{ return TablePrefixSum2 (entrysize); }
|
||||
NGCORE_API size_t * TablePrefixSum64 (FlatArray<size_t> entrysize)
|
||||
NGCORE_API size_t * TablePrefixSum64 (FlatArray<uint64_t> entrysize)
|
||||
{ return TablePrefixSum2 (entrysize); }
|
||||
|
||||
/*
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "memtracer.hpp"
|
||||
#include "ngcore_api.hpp"
|
||||
#include "profiler.hpp"
|
||||
#include "taskmanager.hpp"
|
||||
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
@ -36,7 +36,8 @@ namespace ngcore
|
||||
|
||||
public:
|
||||
FlatTable() = delete;
|
||||
|
||||
FlatTable (const FlatTable &) = default;
|
||||
|
||||
NETGEN_INLINE FlatTable(size_t as, size_t * aindex, T * adata)
|
||||
: size(as), index(aindex), data(adata) { ; }
|
||||
|
||||
@ -46,8 +47,7 @@ namespace ngcore
|
||||
/// Access entry
|
||||
NETGEN_INLINE const FlatArray<T> operator[] (IndexType i) const
|
||||
{
|
||||
i = i-BASE;
|
||||
return FlatArray<T> (index[i+1]-index[i], data+index[i]);
|
||||
return FlatArray<T> (index[i-BASE+1]-index[i-BASE], data+index[i-BASE]);
|
||||
}
|
||||
|
||||
NETGEN_INLINE T * Data() const { return data; }
|
||||
@ -94,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);
|
||||
|
||||
@ -106,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.
|
||||
@ -131,6 +145,7 @@ namespace ngcore
|
||||
{
|
||||
for (size_t i : IntRange(size+1))
|
||||
index[i] = i*entrysize;
|
||||
mt.Alloc(GetMemUsage());
|
||||
}
|
||||
|
||||
/// Construct table of variable entrysize
|
||||
@ -142,13 +157,36 @@ 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)
|
||||
: FlatTable<T,IndexType>(0, nullptr, nullptr)
|
||||
{
|
||||
size = tab2.Size();
|
||||
if (size == 0) return;
|
||||
|
||||
index = new size_t[size+1];
|
||||
this->IndexArray() = tab2.IndexArray();
|
||||
// for (size_t i = 0; i <= size; i++)
|
||||
// index[i] = tab2.index[i];
|
||||
|
||||
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];
|
||||
*/
|
||||
}
|
||||
|
||||
explicit NETGEN_INLINE Table (const Table & tab2)
|
||||
: FlatTable<T,IndexType>(0, nullptr, nullptr)
|
||||
{
|
||||
size = tab2.Size();
|
||||
|
||||
if (size == 0) return;
|
||||
|
||||
index = new size_t[size+1];
|
||||
for (size_t i = 0; i <= size; i++)
|
||||
index[i] = tab2.index[i];
|
||||
@ -157,20 +195,42 @@ 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);
|
||||
}
|
||||
|
||||
template<typename ARCHIVE>
|
||||
auto DoArchive(ARCHIVE& ar)
|
||||
{
|
||||
ar & size;
|
||||
if(size == 0)
|
||||
return;
|
||||
if(ar.Input())
|
||||
{
|
||||
index = new IndexType[size+1];
|
||||
mt.Alloc(sizeof(IndexType) * (size+1));
|
||||
}
|
||||
ar.Do(index, size+1);
|
||||
if(ar.Input())
|
||||
{
|
||||
data = new T[index[size]];
|
||||
mt.Alloc(sizeof(T) * index[size]);
|
||||
}
|
||||
ar.Do(data, index[size]);
|
||||
}
|
||||
|
||||
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);
|
||||
@ -284,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;
|
||||
@ -361,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++)
|
||||
@ -407,7 +467,9 @@ namespace ngcore
|
||||
void Add (size_t blocknr, FlatArray<int> dofs);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
A dynamic table class.
|
||||
@ -446,7 +508,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
/// Creates table with a priori fixed entry sizes.
|
||||
DynamicTable (const Array<int, IndexType> & entrysizes)
|
||||
DynamicTable (const Array<int, IndexType> & entrysizes, bool setentrysize=false)
|
||||
: data(entrysizes.Size())
|
||||
{
|
||||
size_t cnt = 0;
|
||||
@ -460,7 +522,10 @@ namespace ngcore
|
||||
for (auto i : data.Range())
|
||||
{
|
||||
data[i].maxsize = entrysizes[i];
|
||||
data[i].size = 0;
|
||||
if (setentrysize)
|
||||
data[i].size = entrysizes[i];
|
||||
else
|
||||
data[i].size = 0;
|
||||
data[i].col = &oneblock[cnt];
|
||||
cnt += entrysizes[i];
|
||||
}
|
||||
|
@ -76,14 +76,14 @@ namespace ngcore
|
||||
numa_run_on_node (0);
|
||||
#endif
|
||||
|
||||
#ifndef WIN32
|
||||
#if !defined(WIN32) && !defined(EMSCRIPTEN)
|
||||
// master has maximal priority !
|
||||
int policy;
|
||||
struct sched_param param;
|
||||
pthread_getschedparam(pthread_self(), &policy, ¶m);
|
||||
param.sched_priority = sched_get_priority_max(policy);
|
||||
pthread_setschedparam(pthread_self(), policy, ¶m);
|
||||
#endif // WIN32
|
||||
#endif // !defined(WIN32) && !defined(EMSCRIPTEN)
|
||||
|
||||
|
||||
task_manager->StartWorkers();
|
||||
@ -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
|
||||
@ -235,13 +241,14 @@ namespace ngcore
|
||||
const function<void(TaskInfo&)> * func;
|
||||
int mynr;
|
||||
int total;
|
||||
int producing_thread;
|
||||
atomic<int> * endcnt;
|
||||
|
||||
TNestedTask () { ; }
|
||||
TNestedTask (const function<void(TaskInfo&)> & _func,
|
||||
int _mynr, int _total,
|
||||
atomic<int> & _endcnt)
|
||||
: func(&_func), mynr(_mynr), total(_total), endcnt(&_endcnt)
|
||||
atomic<int> & _endcnt, int prod_tid)
|
||||
: func(&_func), mynr(_mynr), total(_total), producing_thread(prod_tid), endcnt(&_endcnt)
|
||||
{
|
||||
;
|
||||
}
|
||||
@ -260,12 +267,14 @@ namespace ngcore
|
||||
TPToken ptoken(taskqueue);
|
||||
|
||||
int num = endcnt;
|
||||
auto tid = TaskManager::GetThreadId();
|
||||
for (int i = 0; i < num; i++)
|
||||
taskqueue.enqueue (ptoken, { afunc, i, num, endcnt });
|
||||
taskqueue.enqueue (ptoken, { afunc, i, num, endcnt, tid });
|
||||
}
|
||||
|
||||
bool TaskManager :: ProcessTask()
|
||||
{
|
||||
// static Timer t("process task");
|
||||
TNestedTask task;
|
||||
TCToken ctoken(taskqueue);
|
||||
|
||||
@ -282,8 +291,14 @@ namespace ngcore
|
||||
cout << "process nested, nr = " << ti.task_nr << "/" << ti.ntasks << endl;
|
||||
}
|
||||
*/
|
||||
// if(trace && task.producing_thread != ti.thread_nr)
|
||||
// trace->StartTask (ti.thread_nr, t, PajeTrace::Task::ID_TIMER, task.producing_thread);
|
||||
|
||||
(*task.func)(ti);
|
||||
--*task.endcnt;
|
||||
|
||||
// if(trace && task.producing_thread != ti.thread_nr)
|
||||
// trace->StopTask (ti.thread_nr, t);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -403,7 +418,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception & e)
|
||||
{
|
||||
{
|
||||
lock_guard<mutex> guard(copyex_mutex);
|
||||
@ -476,6 +491,7 @@ namespace ngcore
|
||||
#endif
|
||||
|
||||
|
||||
size_t no_job_counter = 0;
|
||||
while (!done)
|
||||
{
|
||||
if (complete[mynode] > jobdone)
|
||||
@ -483,11 +499,12 @@ namespace ngcore
|
||||
|
||||
if (jobnr == jobdone)
|
||||
{
|
||||
no_job_counter++;
|
||||
// RegionTracer t(ti.thread_nr, tCASyield, ti.task_nr);
|
||||
while (ProcessTask()); // do the nested tasks
|
||||
while (ProcessTask()) no_job_counter = 0; // do the nested tasks
|
||||
|
||||
if(sleep)
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(sleep_usecs));
|
||||
if(sleep || no_job_counter > 10000)
|
||||
std::this_thread::sleep_for(std::chrono::microseconds(10));
|
||||
else
|
||||
{
|
||||
#ifdef WIN32
|
||||
@ -528,6 +545,7 @@ namespace ngcore
|
||||
|
||||
ti.task_nr = mytasks.First()+mytask;
|
||||
ti.ntasks = ntasks;
|
||||
no_job_counter = 0;
|
||||
|
||||
{
|
||||
RegionTracer t(ti.thread_nr, jobnr, RegionTracer::ID_JOB, ti.task_nr);
|
||||
@ -536,7 +554,7 @@ namespace ngcore
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (Exception & e)
|
||||
{
|
||||
{
|
||||
// cout << "got exception in TM" << endl;
|
||||
|
@ -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); }
|
||||
};
|
||||
@ -462,25 +464,32 @@ public:
|
||||
// return IntRange(begin, end);
|
||||
// }
|
||||
|
||||
bool PopFirst (size_t & first)
|
||||
bool PopFirst (size_t & hfirst)
|
||||
{
|
||||
first = begin++;
|
||||
return first < end;
|
||||
/*
|
||||
// int oldbegin = begin;
|
||||
size_t oldbegin = begin.load(std::memory_order_acquire);
|
||||
if (oldbegin >= end) return false;
|
||||
while (!begin.compare_exchange_weak (oldbegin, oldbegin+1,
|
||||
std::memory_order_relaxed, std::memory_order_relaxed))
|
||||
if (oldbegin >= end) return false;
|
||||
// first = begin++;
|
||||
// return first < end;
|
||||
|
||||
first = oldbegin;
|
||||
return true;
|
||||
*/
|
||||
size_t first = begin.load(std::memory_order_relaxed);
|
||||
|
||||
size_t nextfirst = first+1;
|
||||
if (first >= end) nextfirst = std::numeric_limits<size_t>::max()-1;
|
||||
|
||||
// while (!begin.compare_exchange_weak (first, nextfirst))
|
||||
while (!begin.compare_exchange_weak (first, nextfirst,
|
||||
std::memory_order_relaxed,
|
||||
std::memory_order_relaxed))
|
||||
{
|
||||
first = begin;
|
||||
nextfirst = first+1;
|
||||
if (nextfirst >= end) nextfirst = std::numeric_limits<size_t>::max()-1;
|
||||
}
|
||||
hfirst = first;
|
||||
return first < end;
|
||||
}
|
||||
|
||||
bool PopHalf (IntRange & r)
|
||||
{
|
||||
/*
|
||||
// int oldbegin = begin;
|
||||
size_t oldbegin = begin.load(std::memory_order_acquire);
|
||||
size_t oldend = end.load(std::memory_order_acquire);
|
||||
@ -496,6 +505,28 @@ public:
|
||||
|
||||
r = IntRange(oldbegin, (oldbegin+oldend+1)/2);
|
||||
return true;
|
||||
*/
|
||||
|
||||
|
||||
size_t oldbegin = begin; // .load(std::memory_order_acquire);
|
||||
size_t oldend = end; // .load(std::memory_order_acquire);
|
||||
if (oldbegin >= oldend) return false;
|
||||
|
||||
size_t nextbegin = (oldbegin+oldend+1)/2;
|
||||
if (nextbegin >= oldend) nextbegin = std::numeric_limits<size_t>::max()-1;
|
||||
|
||||
while (!begin.compare_exchange_weak (oldbegin, nextbegin))
|
||||
// std::memory_order_relaxed, std::memory_order_relaxed))
|
||||
{
|
||||
oldend = end; // .load(std::memory_order_acquire);
|
||||
if (oldbegin >= oldend) return false;
|
||||
|
||||
nextbegin = (oldbegin+oldend+1)/2;
|
||||
if (nextbegin >= oldend) nextbegin = std::numeric_limits<size_t>::max()-1;
|
||||
}
|
||||
|
||||
r = IntRange(oldbegin, (oldbegin+oldend+1)/2);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
@ -593,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++)
|
||||
@ -602,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()
|
||||
{
|
||||
@ -856,6 +892,30 @@ public:
|
||||
auto GetNum() const { return num; }
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
// some idea, not yet supported
|
||||
|
||||
using namespace std;
|
||||
template <typename T>
|
||||
class ParallelValue
|
||||
{
|
||||
T val;
|
||||
public:
|
||||
ParallelValue (const T & _val) : val(_val) { ; }
|
||||
operator T () const { return val; }
|
||||
};
|
||||
|
||||
template <typename FUNC> class ParallelFunction
|
||||
{
|
||||
FUNC f;
|
||||
public:
|
||||
ParallelFunction (const FUNC & _f) : f(_f) { ; }
|
||||
operator FUNC () const { return f; }
|
||||
auto operator() (size_t i) const { return f(i); }
|
||||
};
|
||||
*/
|
||||
|
||||
/* currently not used, plus causing problems on MSVC 2017
|
||||
template <typename T, typename std::enable_if<ngstd::has_call_operator<T>::value, int>::type = 0>
|
||||
inline ParallelFunction<T> operator| (const T & func, Tasks tasks)
|
||||
@ -957,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;
|
||||
|
@ -16,6 +16,15 @@ namespace ngcore
|
||||
template<typename T>
|
||||
struct is_any_pointer_impl : std::false_type {};
|
||||
|
||||
// check if second template argument is tuple of base classes to first
|
||||
// template argument, return constexpr bool
|
||||
template<typename T, typename Tuple>
|
||||
constexpr bool is_base_of_tuple = false;
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
constexpr bool is_base_of_tuple<T, std::tuple<Ts...>> =
|
||||
all_of_tmpl<std::is_base_of<Ts, T>::value...>;
|
||||
|
||||
template<typename T>
|
||||
struct is_any_pointer_impl<T*> : std::true_type {};
|
||||
|
||||
|
@ -1,13 +1,70 @@
|
||||
#include "ngcore_api.hpp"
|
||||
#include "utils.hpp"
|
||||
#include "logging.hpp"
|
||||
#include "simd_generic.hpp"
|
||||
|
||||
#ifndef WIN32
|
||||
#ifdef WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#undef WIN32_LEAN_AND_MEAN
|
||||
#else // WIN32
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
#include <dlfcn.h>
|
||||
#endif //WIN32
|
||||
//
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
#include "ngstream.hpp"
|
||||
|
||||
|
||||
namespace ngcore
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
// see https://github.com/RobotLocomotion/drake/blob/master/common/nice_type_name.cc
|
||||
static const auto demangle_regexes =
|
||||
std::array<std::pair<std::regex, std::string>, 8>{
|
||||
// Remove unwanted keywords and following space. (\b is word boundary.)
|
||||
std::make_pair(std::regex("\\b(class|struct|enum|union) "), ""),
|
||||
// Tidy up anonymous namespace.
|
||||
{std::regex("[`(]anonymous namespace[')]"), "(anonymous)"},
|
||||
// Replace Microsoft __int64 with long long.
|
||||
{std::regex("\\b__int64\\b"), "long long"},
|
||||
// Temporarily replace spaces we want to keep with "!". (\w is
|
||||
// alphanumeric or underscore.)
|
||||
{std::regex("(\\w) (\\w)"), "$1!$2"},
|
||||
{std::regex(" "), ""}, // Delete unwanted spaces.
|
||||
// Some compilers throw in extra namespaces like "__1" or "__cxx11".
|
||||
// Delete them.
|
||||
{std::regex("\\b__[[:alnum:]_]+::"), ""},
|
||||
{std::regex("!"), " "}, // Restore wanted spaces.
|
||||
|
||||
// Recognize std::string's full name and abbreviate.
|
||||
{std::regex("\\bstd::basic_string<char,std::char_traits<char>,"
|
||||
"std::allocator<char>>"), "std::string"}
|
||||
};
|
||||
std::string CleanupDemangledName( std::string s )
|
||||
{
|
||||
for(const auto & [r, sub] : demangle_regexes)
|
||||
s = std::regex_replace (s,r,sub);
|
||||
#ifdef EMSCRIPTEN
|
||||
// for some reason regex_replace is not working at all
|
||||
std::string temp = s;
|
||||
s = "";
|
||||
for(auto c : temp)
|
||||
if(c!=' ')
|
||||
s+=c;
|
||||
#endif // EMSCRIPTEN
|
||||
|
||||
return s;
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
// parallel netgen
|
||||
int id = 0, ntasks = 1;
|
||||
|
||||
@ -15,12 +72,7 @@ namespace ngcore
|
||||
// windows does demangling in typeid(T).name()
|
||||
NGCORE_API std::string Demangle(const char* typeinfo) {
|
||||
std::string name = typeinfo;
|
||||
// remove "class " and "struct " at beginning of type names to be consistent with demangled names of gcc/clang
|
||||
if(name.find("class ") == 0)
|
||||
name.erase(0,6);
|
||||
if(name.find("struct ") == 0)
|
||||
name.erase(0,7);
|
||||
return name;
|
||||
return detail::CleanupDemangledName(name);
|
||||
}
|
||||
#else
|
||||
NGCORE_API std::string Demangle(const char* typeinfo)
|
||||
@ -29,15 +81,23 @@ namespace ngcore
|
||||
try
|
||||
{
|
||||
char *s = abi::__cxa_demangle(typeinfo, nullptr, nullptr, &status);
|
||||
std::string result{s};
|
||||
free(s);
|
||||
std::string result;
|
||||
if (s == nullptr)
|
||||
result = typeinfo;
|
||||
else
|
||||
{
|
||||
result = s;
|
||||
free(s);
|
||||
}
|
||||
result = detail::CleanupDemangledName(result);
|
||||
return result;
|
||||
}
|
||||
catch( const std::exception & e )
|
||||
{
|
||||
GetLogger("utils")->warn("{}:{} cannot demangle {}, status: {}, error:{}", __FILE__, __LINE__, typeinfo, status, e.what());
|
||||
}
|
||||
return typeinfo;
|
||||
std::string name = typeinfo;
|
||||
return detail::CleanupDemangledName(name);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -58,5 +118,116 @@ namespace ngcore
|
||||
|
||||
const std::chrono::time_point<TClock> wall_time_start = TClock::now();
|
||||
|
||||
int printmessage_importance = getenv("NG_MESSAGE_LEVEL") ? atoi(getenv("NG_MESSAGE_LEVEL")) : 0;
|
||||
bool NGSOStream :: glob_active = true;
|
||||
|
||||
NGCORE_API int GetCompiledSIMDSize()
|
||||
{
|
||||
return GetDefaultSIMDSize();
|
||||
}
|
||||
|
||||
NGCORE_API bool IsRangeCheckEnabled()
|
||||
{
|
||||
#ifdef NETGEN_ENABLE_CHECK_RANGE
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
NGCORE_API std::filesystem::path GetTempFilename()
|
||||
{
|
||||
static int counter = 0;
|
||||
auto path = std::filesystem::temp_directory_path();
|
||||
path += ".temp_netgen_file_"+ToString(counter++)+"_"+ToString(GetTimeCounter());
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
SharedLibrary :: SharedLibrary(const std::filesystem::path & lib_name_, std::optional<std::filesystem::path> directory_to_delete_, bool global )
|
||||
: lib_name(lib_name_),directory_to_delete(directory_to_delete_)
|
||||
{
|
||||
Load(lib_name, global);
|
||||
}
|
||||
|
||||
SharedLibrary :: ~SharedLibrary()
|
||||
{
|
||||
Unload();
|
||||
if(directory_to_delete)
|
||||
for([[maybe_unused]] auto i : Range(5))
|
||||
{
|
||||
// on Windows, a (detached?) child process of the compiler/linker might still block the directory
|
||||
// wait for it to finish (up to a second)
|
||||
try
|
||||
{
|
||||
std::filesystem::remove_all(*directory_to_delete);
|
||||
directory_to_delete = std::nullopt;
|
||||
break;
|
||||
}
|
||||
catch(const std::exception &e)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(200));
|
||||
}
|
||||
}
|
||||
if(directory_to_delete)
|
||||
std::cerr << "Could not delete " << directory_to_delete->string() << std::endl;
|
||||
}
|
||||
|
||||
void SharedLibrary :: Load( const std::filesystem::path & lib_name_, bool global )
|
||||
{
|
||||
Unload();
|
||||
lib_name = lib_name_;
|
||||
#ifdef WIN32
|
||||
lib = LoadLibraryW(lib_name.wstring().c_str());
|
||||
if (!lib) throw std::runtime_error(std::string("Could not load library ") + lib_name.string());
|
||||
#else // WIN32
|
||||
auto flags = RTLD_NOW;
|
||||
if (global) flags |= RTLD_GLOBAL;
|
||||
lib = dlopen(lib_name.c_str(), flags);
|
||||
if(lib == nullptr) throw std::runtime_error(dlerror());
|
||||
#endif // WIN32
|
||||
}
|
||||
|
||||
void SharedLibrary :: Unload() {
|
||||
if(lib)
|
||||
{
|
||||
#ifdef WIN32
|
||||
FreeLibrary((HMODULE)lib);
|
||||
#else // WIN32
|
||||
int rc = dlclose(lib);
|
||||
if(rc != 0) std::cerr << "Failed to close library " << lib_name << std::endl;
|
||||
#endif // WIN32
|
||||
}
|
||||
}
|
||||
|
||||
void* SharedLibrary :: GetRawSymbol( std::string func_name )
|
||||
{
|
||||
#ifdef WIN32
|
||||
void* func = GetProcAddress((HMODULE)lib, func_name.c_str());
|
||||
if(func == nullptr)
|
||||
throw std::runtime_error(std::string("Could not find function ") + func_name + " in library " + lib_name.string());
|
||||
#else // WIN32
|
||||
void* func = dlsym(lib, func_name.c_str());
|
||||
if(func == nullptr)
|
||||
throw std::runtime_error(dlerror());
|
||||
#endif // WIN32
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
void* GetRawSymbol( std::string func_name )
|
||||
{
|
||||
void * func = nullptr;
|
||||
#ifdef WIN32
|
||||
throw std::runtime_error("GetRawSymbol not implemented on WIN32");
|
||||
#else // WIN32
|
||||
func = dlsym(RTLD_DEFAULT, func_name.c_str());
|
||||
if(func == nullptr)
|
||||
throw std::runtime_error(dlerror());
|
||||
#endif // WIN32
|
||||
return func;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
|
@ -3,8 +3,10 @@
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <ostream>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
@ -25,7 +27,10 @@
|
||||
namespace ngcore
|
||||
{
|
||||
// MPI rank, nranks TODO: Rename
|
||||
extern NGCORE_API int id, ntasks;
|
||||
// [[deprecated("don't use global id/ntasks")]]
|
||||
extern NGCORE_API int id;
|
||||
// [[deprecated("don't use global id/ntasks")]]
|
||||
extern NGCORE_API int ntasks;
|
||||
|
||||
NGCORE_API std::string Demangle(const char* typeinfo);
|
||||
|
||||
@ -67,6 +72,8 @@ namespace ngcore
|
||||
unsigned long long tics;
|
||||
__asm __volatile("mrs %0, CNTVCT_EL0" : "=&r" (tics));
|
||||
return tics;
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
return std::chrono::high_resolution_clock::now().time_since_epoch().count();
|
||||
#else
|
||||
#warning "Unsupported CPU architecture"
|
||||
return 0;
|
||||
@ -81,6 +88,42 @@ namespace ngcore
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
inline std::string ToLower( const std::string & s )
|
||||
{
|
||||
std::string res;
|
||||
res.reserve(s.size());
|
||||
|
||||
for(auto & c : s)
|
||||
res.push_back(tolower(c));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
inline std::string ToLower( const std::filesystem::path & p )
|
||||
{
|
||||
return ToLower(p.string());
|
||||
}
|
||||
|
||||
|
||||
|
||||
template <class T>
|
||||
void SaveBin (std::ostream & ost, const T & val)
|
||||
{
|
||||
const char * cp = reinterpret_cast<const char*> (&val);
|
||||
for (unsigned j = 0; j < sizeof(T); j++)
|
||||
ost.put(cp[j]);
|
||||
}
|
||||
|
||||
|
||||
template <class T>
|
||||
void LoadBin (std::istream & ist, T & val)
|
||||
{
|
||||
char * cp = reinterpret_cast<char*> (&val);
|
||||
for (unsigned j = 0; j < sizeof(T); j++)
|
||||
ist.get(cp[j]);
|
||||
}
|
||||
|
||||
|
||||
template<typename T1, typename T2>
|
||||
std::ostream& operator << (std::ostream& ost, const std::map<T1,T2>& map)
|
||||
{
|
||||
@ -97,6 +140,65 @@ namespace ngcore
|
||||
b = std::move(temp);
|
||||
}
|
||||
|
||||
|
||||
/// min of 2 values
|
||||
template <class T>
|
||||
NETGEN_INLINE T min2 (T a, T b)
|
||||
{
|
||||
return (a < b) ? a : b;
|
||||
}
|
||||
|
||||
/// max of 2 values
|
||||
template <class T>
|
||||
NETGEN_INLINE T max2 (T a, T b)
|
||||
{
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
|
||||
/// min of 3 values
|
||||
template <class T>
|
||||
NETGEN_INLINE T min3 (T a, T b, T c)
|
||||
{
|
||||
return (a < b) ? (a < c) ? a : c
|
||||
: (b < c) ? b : c;
|
||||
}
|
||||
|
||||
/// max of 3 values
|
||||
template <class T>
|
||||
NETGEN_INLINE T max3 (T a, T b, T c)
|
||||
{
|
||||
///
|
||||
return (a > b) ? ((a > c) ? a : c)
|
||||
: ((b > c) ? b : c);
|
||||
}
|
||||
|
||||
|
||||
/// sign of value (+1, 0, -1)
|
||||
template <class T>
|
||||
NETGEN_INLINE int sgn (T a)
|
||||
{
|
||||
return (a > 0) ? 1 : ( ( a < 0) ? -1 : 0 );
|
||||
}
|
||||
|
||||
/// square element
|
||||
template <class T>
|
||||
NETGEN_INLINE constexpr T sqr (const T a)
|
||||
{
|
||||
return a * a;
|
||||
}
|
||||
|
||||
/// element to the third power
|
||||
template <class T>
|
||||
NETGEN_INLINE T pow3 (const T a)
|
||||
{
|
||||
return a * a * a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NETGEN_INLINE double IfPos (double a, double b, double c) { return a>0 ? b : c; }
|
||||
NETGEN_INLINE double IfZero (double a, double b, double c) { return a==0. ? b : c; }
|
||||
|
||||
// checks if string starts with sequence
|
||||
inline bool StartsWith(const std::string& str, const std::string& start)
|
||||
{
|
||||
@ -148,6 +250,49 @@ namespace ngcore
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <int N> using IC = std::integral_constant<int,N>; // needed for Iterate
|
||||
|
||||
|
||||
namespace detail {
|
||||
template <typename T, typename Enable = int>
|
||||
struct IsIC_trait {
|
||||
static constexpr auto check() { return false; }
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct IsIC_trait<T, std::enable_if_t<std::is_same_v<T, IC<T::value>> == true, int> > {
|
||||
static constexpr auto check() { return true; }
|
||||
};
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr bool is_IC() {
|
||||
return detail::IsIC_trait<T>::check();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
template <int NUM, typename FUNC>
|
||||
NETGEN_INLINE void Iterate (FUNC f)
|
||||
{
|
||||
if constexpr (NUM > 1) Iterate<NUM-1> (f);
|
||||
if constexpr (NUM >= 1) f(IC<NUM-1>());
|
||||
}
|
||||
|
||||
|
||||
template <int NUM, typename FUNC>
|
||||
NETGEN_INLINE void Switch (size_t nr, FUNC f)
|
||||
{
|
||||
if (NUM-1 == nr) f(IC<NUM-1>());
|
||||
if constexpr (NUM > 1) Switch<NUM-1> (nr, f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template<typename T>
|
||||
@ -198,6 +343,45 @@ namespace ngcore
|
||||
~MyLock () { mutex.unlock(); }
|
||||
};
|
||||
|
||||
NGCORE_API int GetCompiledSIMDSize();
|
||||
NGCORE_API bool IsRangeCheckEnabled();
|
||||
|
||||
NGCORE_API std::filesystem::path GetTempFilename();
|
||||
|
||||
NGCORE_API void* GetRawSymbol( std::string func_name );
|
||||
|
||||
template <typename TFunc>
|
||||
TFunc GetSymbol( std::string func_name )
|
||||
{
|
||||
return reinterpret_cast<TFunc>(GetRawSymbol(func_name));
|
||||
}
|
||||
|
||||
// Class to handle/load shared libraries
|
||||
class NGCORE_API SharedLibrary
|
||||
{
|
||||
std::filesystem::path lib_name;
|
||||
std::optional<std::filesystem::path> directory_to_delete = std::nullopt;
|
||||
void *lib = nullptr;
|
||||
|
||||
public:
|
||||
SharedLibrary() = default;
|
||||
SharedLibrary(const std::filesystem::path & lib_name_, std::optional<std::filesystem::path> directory_to_delete_ = std::nullopt, bool global = false );
|
||||
|
||||
SharedLibrary(const SharedLibrary &) = delete;
|
||||
SharedLibrary & operator =(const SharedLibrary &) = delete;
|
||||
|
||||
~SharedLibrary();
|
||||
|
||||
template <typename TFunc>
|
||||
TFunc GetSymbol( std::string func_name )
|
||||
{
|
||||
return reinterpret_cast<TFunc>(GetRawSymbol(func_name));
|
||||
}
|
||||
|
||||
void Load( const std::filesystem::path & lib_name_, bool global = true);
|
||||
void Unload();
|
||||
void* GetRawSymbol( std::string func_name );
|
||||
};
|
||||
|
||||
} // namespace ngcore
|
||||
|
||||
|
@ -1,33 +1,14 @@
|
||||
add_definitions(-DNGINTERFACE_EXPORTS)
|
||||
add_library(csg ${NG_LIB_TYPE}
|
||||
target_sources(nglib PRIVATE
|
||||
algprim.cpp brick.cpp
|
||||
bspline2d.cpp csgeom.cpp csgparser.cpp curve2d.cpp edgeflw.cpp
|
||||
explicitcurve2d.cpp extrusion.cpp gencyl.cpp genmesh.cpp identify.cpp
|
||||
manifold.cpp meshsurf.cpp polyhedra.cpp revolution.cpp singularref.cpp
|
||||
solid.cpp specpoin.cpp spline3d.cpp surface.cpp triapprox.cpp zrefine.cpp
|
||||
python_csg.cpp splinesurface.cpp
|
||||
)
|
||||
if(APPLE)
|
||||
set_target_properties( csg PROPERTIES SUFFIX ".so")
|
||||
endif(APPLE)
|
||||
|
||||
target_link_libraries(csg PUBLIC mesh PRIVATE "$<BUILD_INTERFACE:netgen_python>")
|
||||
if(NOT WIN32)
|
||||
install( TARGETS csg ${NG_INSTALL_DIR})
|
||||
endif(NOT WIN32)
|
||||
|
||||
target_link_libraries(csg PUBLIC ngcore)
|
||||
)
|
||||
|
||||
if(USE_GUI)
|
||||
add_library(csgvis ${NG_LIB_TYPE} vscsg.cpp )
|
||||
target_link_libraries(csgvis PRIVATE "$<BUILD_INTERFACE:netgen_python>" PUBLIC ngcore)
|
||||
if(NOT WIN32)
|
||||
target_link_libraries(csgvis PUBLIC csg visual)
|
||||
if(APPLE)
|
||||
set_target_properties( csgvis PROPERTIES SUFFIX ".so")
|
||||
endif(APPLE)
|
||||
install( TARGETS csgvis ${NG_INSTALL_DIR})
|
||||
endif(NOT WIN32)
|
||||
target_sources(nggui PRIVATE vscsg.cpp csgpkg.cpp)
|
||||
endif(USE_GUI)
|
||||
|
||||
install(FILES
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <mystdlib.h>
|
||||
#include <core/register_archive.hpp>
|
||||
|
||||
|
||||
#include <linalg.hpp>
|
||||
@ -877,9 +878,11 @@ namespace netgen
|
||||
Vec<3> v1 = b - a;
|
||||
Vec<3> v2 = cyl2->a - a;
|
||||
|
||||
if ( fabs (v1 * v2) < (1-eps) * v1.Length() * v2.Length()) return 0;
|
||||
// if ( fabs (v1 * v2) < (1-1e-12) * v1.Length() * v2.Length()) return 0;
|
||||
if ( Cross(v1,v2).Length2() > 1e-20 * v1.Length2() * v2.Length2()) return 0;
|
||||
v2 = cyl2->b - a;
|
||||
if ( fabs (v1 * v2) < (1-eps) * v1.Length() * v2.Length()) return 0;
|
||||
// if ( fabs (v1 * v2) < (1-eps) * v1.Length() * v2.Length()) return 0;
|
||||
if ( Cross(v1,v2).Length2() > 1e-20 * v1.Length2() * v2.Length2()) return 0;
|
||||
|
||||
inv = 0;
|
||||
return 1;
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <mystdlib.h>
|
||||
#include <core/register_archive.hpp>
|
||||
|
||||
#include <linalg.hpp>
|
||||
#include <csg.hpp>
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <mystdlib.h>
|
||||
#include <myadt.hpp>
|
||||
#include <core/register_archive.hpp>
|
||||
|
||||
#include <linalg.hpp>
|
||||
#include <csg.hpp>
|
||||
@ -220,7 +221,16 @@ namespace netgen
|
||||
|
||||
int CSGeometry :: GenerateMesh (shared_ptr<Mesh> & mesh, MeshingParameters & mparam)
|
||||
{
|
||||
return CSGGenerateMesh (*this, mesh, mparam);
|
||||
if(restricted_h.Size())
|
||||
{
|
||||
// copy so that we don't change mparam outside
|
||||
MeshingParameters mp = mparam;
|
||||
for(const auto& [pnt, maxh] : restricted_h)
|
||||
mp.meshsize_points.Append({pnt, maxh});
|
||||
return CSGGenerateMesh (*this, mesh, mp);
|
||||
}
|
||||
else
|
||||
return CSGGenerateMesh (*this, mesh, mparam);
|
||||
}
|
||||
|
||||
class WritePrimitivesIt : public SolidIterator
|
||||
@ -254,7 +264,7 @@ namespace netgen
|
||||
}
|
||||
|
||||
|
||||
void CSGeometry :: Save (string filename) const
|
||||
void CSGeometry :: Save (const filesystem::path & filename) const
|
||||
{
|
||||
ofstream ost (filename.c_str());
|
||||
Save (ost);
|
||||
@ -312,7 +322,7 @@ namespace netgen
|
||||
{
|
||||
// CSGeometry * geo = new CSGeometry;
|
||||
|
||||
char key[100], name[100], classname[100], sname[100];
|
||||
char key[100], name[100], classname[100], sname[150];
|
||||
int ncoeff, i, j;
|
||||
NgArray<double> coeff;
|
||||
|
||||
@ -339,7 +349,7 @@ namespace netgen
|
||||
|
||||
for (j = 0; j < nprim->GetNSurfaces(); j++)
|
||||
{
|
||||
sprintf (sname, "%s,%d", name, j);
|
||||
snprintf (sname, size(sname), "%s,%d", name, j);
|
||||
AddSurface (sname, &nprim->GetSurface(j));
|
||||
nprim -> SetSurfaceId (j, GetNSurf());
|
||||
}
|
||||
@ -407,7 +417,7 @@ namespace netgen
|
||||
& identpoints & boundingbox & isidenticto & ideps
|
||||
& filename & spline_surfaces & splinecurves2d & splinecurves3d & surf2prim;
|
||||
if(archive.Input())
|
||||
FindIdenticSurfaces(1e-6);
|
||||
FindIdenticSurfaces(1e-8 * MaxSize());
|
||||
}
|
||||
|
||||
void CSGeometry :: SaveSurfaces (ostream & out) const
|
||||
@ -622,8 +632,8 @@ namespace netgen
|
||||
{
|
||||
static int cntsurfs = 0;
|
||||
cntsurfs++;
|
||||
char name[15];
|
||||
sprintf (name, "nnsurf%d", cntsurfs);
|
||||
char name[20];
|
||||
snprintf (name, size(name), "nnsurf%d", cntsurfs);
|
||||
AddSurface (name, surf);
|
||||
}
|
||||
|
||||
@ -939,6 +949,7 @@ namespace netgen
|
||||
{
|
||||
int inv;
|
||||
int nsurf = GetNSurf();
|
||||
identicsurfaces.DeleteData();
|
||||
|
||||
|
||||
isidenticto.SetSize(nsurf);
|
||||
@ -1200,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
|
||||
@ -1609,21 +1620,21 @@ namespace netgen
|
||||
class CSGeometryRegister : public GeometryRegister
|
||||
{
|
||||
public:
|
||||
virtual NetgenGeometry * Load (string filename) const;
|
||||
virtual NetgenGeometry * LoadFromMeshFile (istream & ist) const;
|
||||
virtual NetgenGeometry * Load (const filesystem::path & filename) const;
|
||||
virtual NetgenGeometry * LoadFromMeshFile (istream & ist, string token) const;
|
||||
// virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;
|
||||
};
|
||||
|
||||
extern CSGeometry * ParseCSG (istream & istr, CSGeometry *instance=nullptr);
|
||||
|
||||
NetgenGeometry * CSGeometryRegister :: Load (string filename) const
|
||||
NetgenGeometry * CSGeometryRegister :: Load (const filesystem::path & filename) const
|
||||
{
|
||||
const char * cfilename = filename.c_str();
|
||||
if (strcmp (&cfilename[strlen(cfilename)-3], "geo") == 0)
|
||||
string extension = filename.extension().string();
|
||||
if (extension == ".geo")
|
||||
{
|
||||
PrintMessage (1, "Load CSG geometry file ", cfilename);
|
||||
PrintMessage (1, "Load CSG geometry file ", filename);
|
||||
|
||||
ifstream infile(cfilename);
|
||||
ifstream infile(filename);
|
||||
|
||||
CSGeometry * hgeom = ParseCSG (infile);
|
||||
if (!hgeom)
|
||||
@ -1633,38 +1644,28 @@ namespace netgen
|
||||
return hgeom;
|
||||
}
|
||||
|
||||
if (strcmp (&cfilename[strlen(cfilename)-3], "ngg") == 0)
|
||||
if (extension == ".ngg")
|
||||
{
|
||||
PrintMessage (1, "Load new CSG geometry file ", cfilename);
|
||||
PrintMessage (1, "Load new CSG geometry file ", filename);
|
||||
|
||||
ifstream infile(cfilename);
|
||||
ifstream infile(filename);
|
||||
CSGeometry * hgeom = new CSGeometry("");
|
||||
hgeom -> Load (infile);
|
||||
|
||||
return hgeom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist) const
|
||||
NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist, string token) const
|
||||
{
|
||||
string auxstring;
|
||||
if (ist.good())
|
||||
{
|
||||
ist >> auxstring;
|
||||
if (auxstring == "csgsurfaces")
|
||||
{
|
||||
CSGeometry * geometry = new CSGeometry ("");
|
||||
geometry -> LoadSurfaces(ist);
|
||||
return geometry;
|
||||
}
|
||||
// else
|
||||
// ist.putback (auxstring);
|
||||
}
|
||||
return NULL;
|
||||
if (token != "csgsurfaces")
|
||||
return nullptr;
|
||||
|
||||
CSGeometry * geometry = new CSGeometry ("");
|
||||
geometry -> LoadSurfaces(ist);
|
||||
return geometry;
|
||||
}
|
||||
|
||||
|
||||
|
@ -18,7 +18,6 @@ namespace netgen
|
||||
class TriangleApproximation;
|
||||
class TATriangle;
|
||||
|
||||
|
||||
/**
|
||||
A top level object is an entity to be meshed.
|
||||
I can be either a solid, or one surface patch of a solid.
|
||||
@ -131,7 +130,7 @@ namespace netgen
|
||||
public:
|
||||
UserPoint() = default;
|
||||
UserPoint (Point<3> p, int _index) : Point<3>(p), index(_index) { ; }
|
||||
UserPoint (Point<3> p, const string & _name) : Point<3>(p), name(_name), index(-1) { ; }
|
||||
UserPoint (Point<3> p, const string & _name) : Point<3>(p), index(-1), name(_name) { ; }
|
||||
int GetIndex() const { return index; }
|
||||
const string & GetName() const { return name; }
|
||||
void DoArchive(Archive& archive)
|
||||
@ -182,7 +181,7 @@ namespace netgen
|
||||
|
||||
void Clean ();
|
||||
|
||||
virtual void Save (string filename) const override;
|
||||
virtual void Save (const filesystem::path & filename) const override;
|
||||
void Save (ostream & ost) const;
|
||||
void Load (istream & ist);
|
||||
|
||||
|
@ -17,7 +17,6 @@ extern "C" int Ng_CSG_Init (Tcl_Interp * interp);
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
// extern DLL_HEADER NetgenGeometry * ng_geometry;
|
||||
extern DLL_HEADER shared_ptr<NetgenGeometry> ng_geometry;
|
||||
extern DLL_HEADER shared_ptr<Mesh> mesh;
|
||||
|
||||
@ -66,18 +65,18 @@ namespace netgen
|
||||
Point3d pmin = geometry->BoundingBox ().PMin();
|
||||
Point3d pmax = geometry->BoundingBox ().PMax();
|
||||
|
||||
sprintf (buf, "%5.1lf", pmin.X());
|
||||
snprintf (buf, size(buf), "%5.1lf", pmin.X());
|
||||
Tcl_SetVar (interp, "::geooptions.minx", buf, 0);
|
||||
sprintf (buf, "%5.1lf", pmin.Y());
|
||||
snprintf (buf, size(buf), "%5.1lf", pmin.Y());
|
||||
Tcl_SetVar (interp, "::geooptions.miny", buf, 0);
|
||||
sprintf (buf, "%5.1lf", pmin.Z());
|
||||
snprintf (buf, size(buf), "%5.1lf", pmin.Z());
|
||||
Tcl_SetVar (interp, "::geooptions.minz", buf, 0);
|
||||
|
||||
sprintf (buf, "%5.1lf", pmax.X());
|
||||
snprintf (buf, size(buf), "%5.1lf", pmax.X());
|
||||
Tcl_SetVar (interp, "::geooptions.maxx", buf, 0);
|
||||
sprintf (buf, "%5.1lf", pmax.Y());
|
||||
snprintf (buf, size(buf), "%5.1lf", pmax.Y());
|
||||
Tcl_SetVar (interp, "::geooptions.maxy", buf, 0);
|
||||
sprintf (buf, "%5.1lf", pmax.Z());
|
||||
snprintf (buf, size(buf), "%5.1lf", pmax.Z());
|
||||
Tcl_SetVar (interp, "::geooptions.maxz", buf, 0);
|
||||
}
|
||||
}
|
||||
@ -433,17 +432,17 @@ namespace netgen
|
||||
if (!tlo) return TCL_OK;
|
||||
|
||||
char varname[50];
|
||||
sprintf (varname, "%s(red)", propvar);
|
||||
snprintf (varname, size(varname), "%s(red)", propvar);
|
||||
double red = atof (Tcl_GetVar (interp, varname, 0));
|
||||
sprintf (varname, "%s(blue)", propvar);
|
||||
snprintf (varname, size(varname), "%s(blue)", propvar);
|
||||
double blue = atof (Tcl_GetVar (interp, varname, 0));
|
||||
sprintf (varname, "%s(green)", propvar);
|
||||
snprintf (varname, size(varname), "%s(green)", propvar);
|
||||
double green = atof (Tcl_GetVar (interp, varname, 0));
|
||||
tlo -> SetRGB (red, green, blue);
|
||||
|
||||
sprintf (varname, "%s(visible)", propvar);
|
||||
snprintf (varname, size(varname), "%s(visible)", propvar);
|
||||
tlo -> SetVisible (bool(atoi (Tcl_GetVar (interp, varname, 0))));
|
||||
sprintf (varname, "%s(transp)", propvar);
|
||||
snprintf (varname, size(varname), "%s(transp)", propvar);
|
||||
tlo -> SetTransparent (bool(atoi (Tcl_GetVar (interp, varname, 0))));
|
||||
}
|
||||
|
||||
@ -461,24 +460,24 @@ namespace netgen
|
||||
|
||||
char varname[50], varval[10];
|
||||
|
||||
sprintf (varname, "%s(red)", propvar);
|
||||
sprintf (varval, "%lf", tlo->GetRed());
|
||||
snprintf (varname, size(varname), "%s(red)", propvar);
|
||||
snprintf (varval, size(varval), "%lf", tlo->GetRed());
|
||||
Tcl_SetVar (interp, varname, varval, 0);
|
||||
|
||||
sprintf (varname, "%s(green)", propvar);
|
||||
sprintf (varval, "%lf", tlo->GetGreen());
|
||||
snprintf (varname, size(varname), "%s(green)", propvar);
|
||||
snprintf (varval, size(varval), "%lf", tlo->GetGreen());
|
||||
Tcl_SetVar (interp, varname, varval, 0);
|
||||
|
||||
sprintf (varname, "%s(blue)", propvar);
|
||||
sprintf (varval, "%lf", tlo->GetBlue());
|
||||
snprintf (varname, size(varname), "%s(blue)", propvar);
|
||||
snprintf (varval, size(varval), "%lf", tlo->GetBlue());
|
||||
Tcl_SetVar (interp, varname, varval, 0);
|
||||
|
||||
sprintf (varname, "%s(visible)", propvar);
|
||||
sprintf (varval, "%d", tlo->GetVisible());
|
||||
snprintf (varname, size(varname), "%s(visible)", propvar);
|
||||
snprintf (varval, size(varval), "%d", tlo->GetVisible());
|
||||
Tcl_SetVar (interp, varname, varval, 0);
|
||||
|
||||
sprintf (varname, "%s(transp)", propvar);
|
||||
sprintf (varval, "%d", tlo->GetTransparent());
|
||||
snprintf (varname, size(varname), "%s(transp)", propvar);
|
||||
snprintf (varval, size(varval), "%d", tlo->GetTransparent());
|
||||
Tcl_SetVar (interp, varname, varval, 0);
|
||||
}
|
||||
|
||||
@ -547,86 +546,10 @@ namespace netgen
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
class CSGeometryRegister : public GeometryRegister
|
||||
{
|
||||
public:
|
||||
virtual NetgenGeometry * Load (string filename) const;
|
||||
virtual NetgenGeometry * LoadFromMeshFile (istream & ist) const;
|
||||
virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;
|
||||
};
|
||||
|
||||
extern CSGeometry * ParseCSG (istream & istr);
|
||||
|
||||
NetgenGeometry * CSGeometryRegister :: Load (string filename) const
|
||||
{
|
||||
const char * cfilename = filename.c_str();
|
||||
if (strcmp (&cfilename[strlen(cfilename)-3], "geo") == 0)
|
||||
{
|
||||
PrintMessage (1, "Load CSG geometry file ", cfilename);
|
||||
|
||||
ifstream infile(cfilename);
|
||||
|
||||
CSGeometry * hgeom = ParseCSG (infile);
|
||||
if (!hgeom)
|
||||
throw NgException ("geo-file should start with 'algebraic3d'");
|
||||
|
||||
hgeom -> FindIdenticSurfaces(1e-8 * hgeom->MaxSize());
|
||||
return hgeom;
|
||||
}
|
||||
|
||||
if (strcmp (&cfilename[strlen(cfilename)-3], "ngg") == 0)
|
||||
{
|
||||
PrintMessage (1, "Load new CSG geometry file ", cfilename);
|
||||
|
||||
ifstream infile(cfilename);
|
||||
CSGeometry * hgeom = new CSGeometry("");
|
||||
hgeom -> Load (infile);
|
||||
|
||||
return hgeom;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NetgenGeometry * CSGeometryRegister :: LoadFromMeshFile (istream & ist) const
|
||||
{
|
||||
string auxstring;
|
||||
if (ist.good())
|
||||
{
|
||||
ist >> auxstring;
|
||||
if (auxstring == "csgsurfaces")
|
||||
{
|
||||
CSGeometry * geometry = new CSGeometry ("");
|
||||
geometry -> LoadSurfaces(ist);
|
||||
return geometry;
|
||||
}
|
||||
// else
|
||||
// ist.putback (auxstring);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VisualScene * CSGeometryRegister :: GetVisualScene (const NetgenGeometry * geom) const
|
||||
{
|
||||
CSGeometry * geometry = dynamic_cast<CSGeometry*> (ng_geometry.get());
|
||||
if (geometry)
|
||||
{
|
||||
vsgeom.SetGeometry (geometry);
|
||||
return &vsgeom;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
class CSGeometryVisRegister : public GeometryRegister
|
||||
{
|
||||
public:
|
||||
virtual NetgenGeometry * Load (string filename) const { return NULL; }
|
||||
virtual NetgenGeometry * Load (const filesystem::path & filename) const { return NULL; }
|
||||
virtual VisualScene * GetVisualScene (const NetgenGeometry * geom) const;
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,7 @@ namespace netgen
|
||||
|
||||
/*
|
||||
|
||||
2D Curve repesentation
|
||||
2D Curve representation
|
||||
|
||||
*/
|
||||
|
||||
|
@ -180,7 +180,7 @@ namespace netgen
|
||||
|
||||
pi1 = 0;
|
||||
copyedge = 0;
|
||||
// identifyable point available ?
|
||||
// identifiable point available ?
|
||||
|
||||
|
||||
for (int i = 0; i < geometry.identifications.Size() && !pi1; i++)
|
||||
@ -191,8 +191,8 @@ namespace netgen
|
||||
<< ", v = " << specpoints[startpoints[j]].v
|
||||
<< " for copying (i,j = " << i << ", " << j << ")" << endl;
|
||||
#endif
|
||||
if (geometry.identifications[i]->IdentifyableCandidate (specpoints[startpoints[j]]) &&
|
||||
geometry.identifications[i]->IdentifyableCandidate (specpoints[endpoints[j]]))
|
||||
if (geometry.identifications[i]->IdentifiableCandidate (specpoints[startpoints[j]]) &&
|
||||
geometry.identifications[i]->IdentifiableCandidate (specpoints[endpoints[j]]))
|
||||
|
||||
|
||||
{
|
||||
@ -201,7 +201,7 @@ namespace netgen
|
||||
|
||||
for (int k = 0; k < hsp.Size() && !pi1; k++)
|
||||
{
|
||||
//(*testout) << " ? identifyable with " << specpoints[hsp[k]].p
|
||||
//(*testout) << " ? identifiable with " << specpoints[hsp[k]].p
|
||||
//<< ", v = " << specpoints[hsp[k]].v
|
||||
// << endl;
|
||||
if (identification_used.Used (INDEX_2(i, startpoints[j])) ||
|
||||
@ -212,12 +212,12 @@ namespace netgen
|
||||
}
|
||||
|
||||
if (geometry.identifications[i]
|
||||
->Identifyable(specpoints[startpoints[j]], specpoints[hsp[k]], specpoint2tlo, specpoint2surface) ||
|
||||
->Identifiable(specpoints[startpoints[j]], specpoints[hsp[k]], specpoint2tlo, specpoint2surface) ||
|
||||
geometry.identifications[i]
|
||||
->Identifyable(specpoints[hsp[k]], specpoints[startpoints[j]], specpoint2tlo, specpoint2surface))
|
||||
->Identifiable(specpoints[hsp[k]], specpoints[startpoints[j]], specpoint2tlo, specpoint2surface))
|
||||
{
|
||||
#ifdef DEVELOP
|
||||
(*testout) << "identifyable: " << specpoints[hsp[k]].p << ", v = " << specpoints[hsp[k]].v
|
||||
(*testout) << "identifiable: " << specpoints[hsp[k]].p << ", v = " << specpoints[hsp[k]].v
|
||||
<< " and " << specpoints[startpoints[j]].p << ", v = " << specpoints[startpoints[j]].v
|
||||
<< " (identification " << i+1 << ")" << endl;
|
||||
#endif
|
||||
@ -245,7 +245,7 @@ namespace netgen
|
||||
}
|
||||
|
||||
|
||||
// cannot copy from other ege ?
|
||||
// cannot copy from other edge ?
|
||||
if (!pi1)
|
||||
checkedcopy = startpoints.Size();
|
||||
|
||||
@ -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;
|
||||
@ -1680,9 +1680,9 @@ namespace netgen
|
||||
(*geometry.identifications.Get(copyedgeidentification));
|
||||
|
||||
|
||||
if (csi.Identifyable (mesh[frompi], mesh[topi]))
|
||||
if (csi.Identifiable (mesh[frompi], mesh[topi]))
|
||||
mesh.GetIdentifications().Add(frompi, topi, copyedgeidentification);
|
||||
else if (csi.Identifyable (mesh[topi], mesh[frompi]))
|
||||
else if (csi.Identifiable (mesh[topi], mesh[frompi]))
|
||||
mesh.GetIdentifications().Add(topi, frompi, copyedgeidentification);
|
||||
else
|
||||
{
|
||||
@ -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;
|
||||
|
@ -13,7 +13,7 @@ namespace netgen
|
||||
|
||||
/*
|
||||
|
||||
Explicit 2D Curve repesentation
|
||||
Explicit 2D Curve representation
|
||||
|
||||
*/
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <mystdlib.h>
|
||||
#include <core/register_archive.hpp>
|
||||
|
||||
#include <linalg.hpp>
|
||||
#include <csg.hpp>
|
||||
@ -140,16 +141,21 @@ namespace netgen
|
||||
void ExtrusionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d,
|
||||
int & seg, double & t) const
|
||||
{
|
||||
if (Dist2 (point3d, latest_point3d) <
|
||||
1e-25 * Dist2(path->GetSpline(0).StartPI(), path->GetSpline(0).EndPI()))
|
||||
static mutex set_latest_point;
|
||||
|
||||
auto eps = 1e-25 * Dist2(path->GetSpline(0).StartPI(), path->GetSpline(0).EndPI());
|
||||
if (Dist2 (point3d, latest_point3d) < eps)
|
||||
{
|
||||
point2d = latest_point2d;
|
||||
seg = latest_seg;
|
||||
t = latest_t;
|
||||
return;
|
||||
std::lock_guard<std::mutex> guard(set_latest_point);
|
||||
if (Dist2 (point3d, latest_point3d) < eps)
|
||||
{
|
||||
point2d = latest_point2d;
|
||||
seg = latest_seg;
|
||||
t = latest_t;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
latest_point3d = point3d;
|
||||
|
||||
double cutdist = -1;
|
||||
|
||||
@ -213,11 +219,13 @@ namespace netgen
|
||||
point2d = testpoint2d;
|
||||
t = thist;
|
||||
seg = i;
|
||||
latest_seg = i;
|
||||
latest_t = t;
|
||||
latest_point2d = point2d;
|
||||
}
|
||||
}
|
||||
std::lock_guard<std::mutex> guard(set_latest_point);
|
||||
latest_seg = seg;
|
||||
latest_t = t;
|
||||
latest_point2d = point2d;
|
||||
latest_point3d = point3d;
|
||||
}
|
||||
|
||||
double ExtrusionFace :: CalcProj(const Point<3> & point3d, Point<2> & point2d,
|
||||
|
@ -11,7 +11,7 @@
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
NgArray<SpecialPoint> global_specpoints; // for visualization
|
||||
DLL_HEADER NgArray<SpecialPoint> global_specpoints; // for visualization
|
||||
//static NgArray<MeshPoint> spoints;
|
||||
|
||||
#define TCL_OK 0
|
||||
@ -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
|
||||
|
@ -36,24 +36,24 @@ void Identification :: IdentifySpecialPoints (NgArray<class SpecialPoint> & poin
|
||||
|
||||
|
||||
int Identification ::
|
||||
Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
const TABLE<int> & specpoint2solid,
|
||||
const TABLE<int> & specpoint2surface) const
|
||||
{
|
||||
cout << "Identification::Identifyable called for base-class" << endl;
|
||||
cout << "Identification::Identifiable called for base-class" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int Identification ::
|
||||
Identifyable (const Point<3> & p1, const Point<3> & sp2) const
|
||||
Identifiable (const Point<3> & p1, const Point<3> & sp2) const
|
||||
{
|
||||
cout << "Identification::Identifyable called for base-class" << endl;
|
||||
cout << "Identification::Identifiable called for base-class" << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int Identification ::
|
||||
IdentifyableCandidate (const SpecialPoint & sp1) const
|
||||
IdentifiableCandidate (const SpecialPoint & sp1) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@ -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)
|
||||
@ -196,7 +196,7 @@ void PeriodicIdentification :: IdentifySpecialPoints
|
||||
*/
|
||||
|
||||
int PeriodicIdentification ::
|
||||
Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
const TABLE<int> & specpoint2solid,
|
||||
const TABLE<int> & specpoint2surface) const
|
||||
{
|
||||
@ -252,7 +252,7 @@ Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
}
|
||||
|
||||
int PeriodicIdentification ::
|
||||
Identifyable (const Point<3> & p1, const Point<3> & p2) const
|
||||
Identifiable (const Point<3> & p1, const Point<3> & p2) const
|
||||
{
|
||||
return (s1->PointOnSurface (p1) &&
|
||||
s2->PointOnSurface (p2));
|
||||
@ -261,8 +261,8 @@ Identifyable (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;
|
||||
@ -672,7 +684,7 @@ void CloseSurfaceIdentification :: IdentifySpecialPoints
|
||||
*/
|
||||
|
||||
int CloseSurfaceIdentification ::
|
||||
Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
const TABLE<int> & specpoint2solid,
|
||||
const TABLE<int> & specpoint2surface) const
|
||||
{
|
||||
@ -830,7 +842,7 @@ Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
}
|
||||
|
||||
int CloseSurfaceIdentification ::
|
||||
Identifyable (const Point<3> & p1, const Point<3> & p2) const
|
||||
Identifiable (const Point<3> & p1, const Point<3> & p2) const
|
||||
{
|
||||
// if (domain)
|
||||
// if (!domain->GetSolid()->IsIn (p1) || !domain->GetSolid()->IsIn (p2))
|
||||
@ -842,7 +854,7 @@ Identifyable (const Point<3> & p1, const Point<3> & p2) const
|
||||
|
||||
|
||||
int CloseSurfaceIdentification ::
|
||||
IdentifyableCandidate (const SpecialPoint & sp1) const
|
||||
IdentifiableCandidate (const SpecialPoint & sp1) const
|
||||
{
|
||||
if (domain)
|
||||
if (!domain->GetSolid()->IsIn (sp1.p))
|
||||
@ -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);
|
||||
@ -1544,7 +1560,7 @@ void CloseEdgesIdentification :: IdentifySpecialPoints
|
||||
*/
|
||||
|
||||
int CloseEdgesIdentification ::
|
||||
Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
const TABLE<int> & specpoint2solid,
|
||||
const TABLE<int> & specpoint2surface) const
|
||||
{
|
||||
@ -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];
|
||||
|
@ -38,13 +38,13 @@ namespace netgen
|
||||
|
||||
/// can identify both special points (fixed direction)
|
||||
/// (identified points, same tangent)
|
||||
virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
virtual int Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
const TABLE<int> & specpoint2solid,
|
||||
const TABLE<int> & specpoint2surface) const;
|
||||
///
|
||||
virtual int Identifyable (const Point<3> & p1, const Point<3> & sp2) const;
|
||||
virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const;
|
||||
/// is it possible to identify sp1 with some other ?
|
||||
virtual int IdentifyableCandidate (const SpecialPoint & sp1) const;
|
||||
virtual int IdentifiableCandidate (const SpecialPoint & sp1) const;
|
||||
|
||||
/// are points (if connected) by a short edge (direction anyhow) ?
|
||||
virtual int ShortEdge (const SpecialPoint & sp1, const SpecialPoint & sp2) const;
|
||||
@ -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,
|
||||
@ -92,12 +92,12 @@ namespace netgen
|
||||
|
||||
|
||||
// virtual void IdentifySpecialPoints (NgArray<class SpecialPoint> & points);
|
||||
virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
virtual int Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
const TABLE<int> & specpoint2solid,
|
||||
const TABLE<int> & specpoint2surface) const override;
|
||||
|
||||
virtual int Identifyable (const Point<3> & p1, const Point<3> & sp2) const override;
|
||||
virtual int GetIdentifiedPoint (class Mesh & mesh, int pi1) override;
|
||||
virtual int Identifiable (const Point<3> & p1, const Point<3> & sp2) const 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,
|
||||
@ -147,13 +147,13 @@ namespace netgen
|
||||
|
||||
|
||||
// virtual void IdentifySpecialPoints (NgArray<class SpecialPoint> & points);
|
||||
virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
virtual int Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
const TABLE<int> & specpoint2solid,
|
||||
const TABLE<int> & specpoint2surface) const;
|
||||
virtual int Identifyable (const Point<3> & p1, const Point<3> & sp2) const;
|
||||
virtual int IdentifyableCandidate (const SpecialPoint & sp1) const;
|
||||
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);
|
||||
@ -197,7 +197,7 @@ namespace netgen
|
||||
virtual void GetData (ostream & ost) const;
|
||||
|
||||
// virtual void IdentifySpecialPoints (NgArray<class SpecialPoint> & points);
|
||||
virtual int Identifyable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
virtual int Identifiable (const SpecialPoint & sp1, const SpecialPoint & sp2,
|
||||
const TABLE<int> & specpoint2solid,
|
||||
const TABLE<int> & specpoint2surface) const;
|
||||
|
||||
|
@ -272,7 +272,7 @@ namespace netgen
|
||||
if (printing)
|
||||
*testout << "lam = " << lam1 << " " << lam2 << " " << lam3 << endl;
|
||||
if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam3 >= -eps_base1)
|
||||
{ // point is close to trianlge, perturbe by alpha*v
|
||||
{ // point is close to triangle, perturbed by alpha*v
|
||||
double dlamn = face.nn*v;
|
||||
|
||||
if (fabs(dlamn) < 1e-8) // vec also in plane
|
||||
@ -540,7 +540,7 @@ namespace netgen
|
||||
double lam3 = 1-lam1-lam2;
|
||||
|
||||
if (lam1 >= -eps_base1 && lam2 >= -eps_base1 && lam3 >= -eps_base1)
|
||||
{ // point is close to trianlge, perturbe by alpha*v
|
||||
{ // point is close to triangle, perturbed by alpha*v
|
||||
double dlamn = face.nn*v;
|
||||
|
||||
if (fabs(dlamn) < 1e-8) // vec also in plane
|
||||
|
@ -1,9 +1,10 @@
|
||||
#ifdef NG_PYTHON
|
||||
|
||||
#include <../general/ngpython.hpp>
|
||||
#include <core/python_ngcore.hpp>
|
||||
#include <csg.hpp>
|
||||
#include "../general/ngpython.hpp"
|
||||
#include "../core/python_ngcore.hpp"
|
||||
#include "csg.hpp"
|
||||
#include "../meshing/python_mesh.hpp"
|
||||
#include "../general/gzstream.h"
|
||||
|
||||
|
||||
using namespace netgen;
|
||||
@ -582,8 +583,8 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
|
||||
NgArray<int> si1, si2;
|
||||
s1->GetSolid()->GetSurfaceIndices (si1);
|
||||
s2->GetSolid()->GetSurfaceIndices (si2);
|
||||
cout << "surface ids1 = " << si1 << endl;
|
||||
cout << "surface ids2 = " << si2 << endl;
|
||||
cout << IM(3) << "surface ids1 = " << si1 << endl;
|
||||
cout << IM(3) << "surface ids2 = " << si2 << endl;
|
||||
|
||||
Flags flags;
|
||||
const TopLevelObject * domain = nullptr;
|
||||
@ -675,7 +676,7 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
|
||||
.def("Draw", FunctionPointer
|
||||
([] (shared_ptr<CSGeometry> self)
|
||||
{
|
||||
self->FindIdenticSurfaces(1e-6);
|
||||
self->FindIdenticSurfaces(1e-8 * self->MaxSize());
|
||||
self->CalcTriangleApproximation(0.01, 20);
|
||||
ng_geometry = self;
|
||||
})
|
||||
@ -705,8 +706,8 @@ However, when r = 0, the top part becomes a point(tip) and meshing fails!
|
||||
auto surf = csg_geo->GetSurface(i);
|
||||
surfnames.push_back(surf->GetBCName());
|
||||
}
|
||||
csg_geo->FindIdenticSurfaces(1e-6);
|
||||
csg_geo->CalcTriangleApproximation(0.01,100);
|
||||
csg_geo->FindIdenticSurfaces(1e-8 * csg_geo->MaxSize());
|
||||
csg_geo->CalcTriangleApproximation(0.01,20);
|
||||
auto nto = csg_geo->GetNTopLevelObjects();
|
||||
size_t np = 0;
|
||||
size_t ntrig = 0;
|
||||
@ -755,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);
|
||||
@ -769,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
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <mystdlib.h>
|
||||
#include <core/register_archive.hpp>
|
||||
|
||||
#include <linalg.hpp>
|
||||
#include <csg.hpp>
|
||||
@ -780,7 +781,7 @@ namespace netgen
|
||||
Point<2> p2d;
|
||||
faces[0]->CalcProj(p,p2d);
|
||||
|
||||
int intersections_before(0), intersections_after(0);
|
||||
[[maybe_unused]] int intersections_before(0), intersections_after(0);
|
||||
double randomx = 7.42357;
|
||||
double randomy = 1.814756;
|
||||
double randomlen = sqrt(randomx*randomx+randomy*randomy);
|
||||
|
@ -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];
|
||||
|
@ -19,7 +19,7 @@ namespace netgen
|
||||
|
||||
/**
|
||||
Singular Face.
|
||||
Causes a bounday layer mesh refinement.
|
||||
Causes a boundary layer mesh refinement.
|
||||
All elements in subdomain domnr will get a boundary layer
|
||||
on faces sharing the solid sol
|
||||
*/
|
||||
|
@ -194,6 +194,7 @@ namespace netgen
|
||||
case ROOT:
|
||||
return s1->PointInSolid (p, eps);
|
||||
}
|
||||
throw Exception("PointInSolid: invalid op");
|
||||
}
|
||||
|
||||
|
||||
@ -213,6 +214,7 @@ namespace netgen
|
||||
case ROOT:
|
||||
return s1->VecInSolid (p, v, eps);
|
||||
}
|
||||
throw Exception("VecInSolid: invalid op");
|
||||
}
|
||||
|
||||
// checks if lim s->0 lim t->0 p + t(v1 + s v2) in solid
|
||||
@ -233,6 +235,7 @@ namespace netgen
|
||||
case ROOT:
|
||||
return s1->VecInSolid2 (p, v1, v2, eps);
|
||||
}
|
||||
throw Exception("VecInSolid2: invalid op");
|
||||
}
|
||||
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
NgArray<Box<3> > boxes; // for visualizaton
|
||||
DLL_HEADER NgArray<Box<3> > boxes; // for visualization
|
||||
|
||||
|
||||
void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp);
|
||||
|
@ -86,7 +86,7 @@ namespace netgen
|
||||
///
|
||||
double size;
|
||||
///
|
||||
double relydegtest; // maximal dimension of bisection intervall for
|
||||
double relydegtest; // maximal dimension of bisection interval for
|
||||
/// test of degeneration parameters
|
||||
double cpeps1, epeps1, epeps2, epspointdist2;
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
|
||||
#include <csg.hpp>
|
||||
#include <core/register_archive.hpp>
|
||||
|
||||
namespace netgen
|
||||
{
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <mystdlib.h>
|
||||
#include <core/register_archive.hpp>
|
||||
|
||||
#include <myadt.hpp>
|
||||
#include <csg.hpp>
|
||||
@ -257,7 +258,7 @@ Primitive * Primitive :: CreatePrimitive (const char * classname)
|
||||
|
||||
|
||||
stringstream ost;
|
||||
ost << "Primitve::CreatePrimitive not implemented for " << classname << endl;
|
||||
ost << "Primitive::CreatePrimitive not implemented for " << classname << endl;
|
||||
throw NgException (ost.str());
|
||||
}
|
||||
|
||||
@ -265,7 +266,7 @@ Primitive * Primitive :: CreatePrimitive (const char * classname)
|
||||
Primitive * Primitive :: Copy () const
|
||||
{
|
||||
stringstream ost;
|
||||
ost << "Primitve::Copy not implemented for " << typeid(*this).name() << endl;
|
||||
ost << "Primitive::Copy not implemented for " << typeid(*this).name() << endl;
|
||||
throw NgException (ost.str());
|
||||
}
|
||||
|
||||
@ -273,7 +274,7 @@ Primitive * Primitive :: Copy () const
|
||||
void Primitive :: Transform (Transformation<3> & trans)
|
||||
{
|
||||
stringstream ost;
|
||||
ost << "Primitve::Transform not implemented for " << typeid(*this).name() << endl;
|
||||
ost << "Primitive::Transform not implemented for " << typeid(*this).name() << endl;
|
||||
throw NgException (ost.str());
|
||||
}
|
||||
|
||||
@ -579,5 +580,5 @@ void ProjectToEdge (const Surface * f1, const Surface * f2, Point<3> & hp)
|
||||
|
||||
RegisterClassForArchive<Surface> regsurf;
|
||||
RegisterClassForArchive<Primitive> regprim;
|
||||
RegisterClassForArchive<OneSurfacePrimitive, Surface, Primitive> regosf;
|
||||
RegisterClassForArchive<OneSurfacePrimitive, tuple<Surface, Primitive>> regosf;
|
||||
}
|
||||
|
@ -17,11 +17,11 @@ namespace netgen
|
||||
|
||||
/* *********************** Draw Geometry **************** */
|
||||
|
||||
extern shared_ptr<Mesh> mesh;
|
||||
extern NgArray<SpecialPoint> global_specpoints;
|
||||
DLL_HEADER extern shared_ptr<Mesh> mesh;
|
||||
DLL_HEADER extern NgArray<SpecialPoint> global_specpoints;
|
||||
NgArray<SpecialPoint> & specpoints = global_specpoints;
|
||||
|
||||
extern NgArray<Box<3> > boxes;
|
||||
DLL_HEADER extern NgArray<Box<3> > boxes;
|
||||
|
||||
|
||||
|
||||
@ -343,7 +343,7 @@ namespace netgen
|
||||
const Point3d p = Center (p1, p2);
|
||||
glRasterPos3d (p.X(), p.Y(), p.Z());
|
||||
|
||||
sprintf (buf, "%d", seg.edgenr);
|
||||
snprintf (buf, sizeof(buf), "%d", seg.edgenr);
|
||||
// glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);
|
||||
MyOpenGLText (buf);
|
||||
}
|
||||
@ -393,9 +393,9 @@ namespace netgen
|
||||
glBitmap (7, 7, 3, 3, 0, 0, &knoedel[0]);
|
||||
}
|
||||
*/
|
||||
for (const Point3d & p : mesh->Points())
|
||||
for (Point<3> p : mesh->Points())
|
||||
{
|
||||
glRasterPos3d (p.X(), p.Y(), p.Z());
|
||||
glRasterPos3d (p(0), p(1), p(2));
|
||||
glBitmap (7, 7, 3, 3, 0, 0, &knoedel[0]);
|
||||
}
|
||||
}
|
||||
@ -418,7 +418,7 @@ namespace netgen
|
||||
const Point3d & p = mesh->Point(i);
|
||||
glRasterPos3d (p.X(), p.Y(), p.Z());
|
||||
|
||||
sprintf (buf, "%d", int(i));
|
||||
snprintf (buf, sizeof(buf), "%d", int(i));
|
||||
// glCallLists (GLsizei(strlen (buf)), GL_UNSIGNED_BYTE, buf);
|
||||
MyOpenGLText (buf);
|
||||
}
|
||||
@ -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)
|
||||
@ -500,7 +501,7 @@ namespace netgen
|
||||
#ifdef NG_PYTHON
|
||||
#include <../general/ngpython.hpp>
|
||||
|
||||
DLL_HEADER void ExportCSGVis(py::module &m)
|
||||
NGGUI_API void ExportCSGVis(py::module &m)
|
||||
{
|
||||
using namespace netgen;
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
namespace netgen
|
||||
{
|
||||
|
||||
class DLL_HEADER VisualSceneGeometry : public VisualScene
|
||||
class NGGUI_API VisualSceneGeometry : public VisualScene
|
||||
{
|
||||
class CSGeometry * geometry;
|
||||
NgArray<int> trilists;
|
||||
|
@ -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))
|
||||
|
@ -1,19 +1,25 @@
|
||||
add_definitions(-DNGINTERFACE_EXPORTS)
|
||||
add_library(gen INTERFACE)
|
||||
set(sdir ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_sources(gen INTERFACE
|
||||
${sdir}/ngarray.cpp ${sdir}/ngbitarray.cpp ${sdir}/dynamicmem.cpp
|
||||
${sdir}/hashtabl.cpp ${sdir}/mystring.cpp ${sdir}/optmem.cpp ${sdir}/parthreads.cpp
|
||||
${sdir}/seti.cpp ${sdir}/sort.cpp ${sdir}/spbita2d.cpp ${sdir}/table.cpp
|
||||
${sdir}/mpi_interface.cpp ${sdir}/gzstream.cpp
|
||||
)
|
||||
target_sources(nglib PRIVATE
|
||||
gzstream.cpp
|
||||
hashtabl.cpp
|
||||
mystring.cpp
|
||||
ngbitarray.cpp
|
||||
optmem.cpp
|
||||
parthreads.cpp
|
||||
seti.cpp
|
||||
sort.cpp
|
||||
spbita2d.cpp
|
||||
table.cpp
|
||||
)
|
||||
|
||||
# dynamicmem.cpp
|
||||
|
||||
install(FILES
|
||||
ngarray.hpp autodiff.hpp autoptr.hpp ngbitarray.hpp
|
||||
dynamicmem.hpp hashtabl.hpp mpi_interface.hpp myadt.hpp
|
||||
hashtabl.hpp myadt.hpp
|
||||
mystring.hpp netgenout.hpp ngpython.hpp
|
||||
optmem.hpp parthreads.hpp seti.hpp sort.hpp
|
||||
spbita2d.hpp stack.hpp table.hpp template.hpp
|
||||
gzstream.h
|
||||
DESTINATION ${NG_INSTALL_DIR_INCLUDE}/general COMPONENT netgen_devel
|
||||
)
|
||||
# dynamicmem.hpp
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user