Compare commits
544
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
088ef1b667 | ||
|
|
ad21b3e8fc | ||
|
|
82f75c3a05 | ||
|
|
4fba9c2575 | ||
|
|
916ed1b2c3 | ||
|
|
acaf6ad484 | ||
|
|
e20e323ea5 | ||
|
|
3e9a86cecf | ||
|
|
da7b500db5 | ||
|
|
7cfb879a17 | ||
|
|
9e4e3b2e10 | ||
|
|
3b4a080565 | ||
|
|
83de2dfd76 | ||
|
|
58b708713f | ||
|
|
3a977fb925 | ||
|
|
b1e2aaf09d | ||
|
|
004e664f18 | ||
|
|
2ad5a65e02 | ||
|
|
f9e7fb2bd7 | ||
|
|
4987e1132a | ||
|
|
1bb9998b13 | ||
|
|
41205ed92f | ||
|
|
31ff80a137 | ||
|
|
e17a73fa8b | ||
|
|
338a4767c2 | ||
|
|
7fe4b57a62 | ||
|
|
f2b71d807f | ||
|
|
5b8ae39c88 | ||
|
|
da43f83a1d | ||
|
|
d2f4e745e2 | ||
|
|
634d9431d8 | ||
|
|
79cddce644 | ||
|
|
5e6dabb3c8 | ||
|
|
903d51e78f | ||
|
|
83cef85c1d | ||
|
|
ffaa2ed259 | ||
|
|
6a2d288ece | ||
|
|
7bf1c95e26 | ||
|
|
62182060e9 | ||
|
|
d44aa186d2 | ||
|
|
3fd08ddc67 | ||
|
|
1a0976dc17 | ||
|
|
fde408ec95 | ||
|
|
9776ebe890 | ||
|
|
63c03920b3 | ||
|
|
56059b4672 | ||
|
|
2b14832192 | ||
|
|
8d6669b83f | ||
|
|
91e47a804f | ||
|
|
4e22e0f772 | ||
|
|
605a535c0f | ||
|
|
884abe71b5 | ||
|
|
9807f9dba6 | ||
|
|
61cce4d4bc | ||
|
|
ced7c47558 | ||
|
|
bb55232c49 | ||
|
|
87f86d45c9 | ||
|
|
144635c3d8 | ||
|
|
3c674d72fd | ||
|
|
1dd1300812 | ||
|
|
fba0fd6187 | ||
|
|
f8fdf24246 | ||
|
|
f015b94c89 | ||
|
|
ede020977c | ||
|
|
b92d1d37ba | ||
|
|
9dd9189563 | ||
|
|
6beb052e86 | ||
|
|
25f8e3f3f4 | ||
|
|
92ab0429f2 | ||
|
|
9a9c29e03f | ||
|
|
7c9bf81d17 | ||
|
|
f94b099e40 | ||
|
|
777c6d98f7 | ||
|
|
367503651e | ||
|
|
03f2898985 | ||
|
|
6ca447ec36 | ||
|
|
493c8b1e63 | ||
|
|
7724bdf9c4 | ||
|
|
7e72e7f559 | ||
|
|
ddba68f2be | ||
|
|
8f601776cd | ||
|
|
9457962d33 | ||
|
|
560697884d | ||
|
|
eb578c55a0 | ||
|
|
9fa65e6412 | ||
|
|
f3c2fae804 | ||
|
|
ea81393011 | ||
|
|
7b6ddb6227 | ||
|
|
72bd63a556 | ||
|
|
7f40802a83 | ||
|
|
04983d747e | ||
|
|
795c758dd4 | ||
|
|
94f7568165 | ||
|
|
c8e0a5ae00 | ||
|
|
f1eb664f58 | ||
|
|
7934db1a9c | ||
|
|
34cc491b19 | ||
|
|
6d2680cde6 | ||
|
|
ff6bfe3808 | ||
|
|
9be3b415aa | ||
|
|
b7557d4664 | ||
|
|
6d9f041bc7 | ||
|
|
562434aabb | ||
|
|
e8d7299091 | ||
|
|
8499dee89d | ||
|
|
4155b591a4 | ||
|
|
e8c31c884d | ||
|
|
e69f787149 | ||
|
|
ab7b1609a9 | ||
|
|
bc9f74fddd | ||
|
|
492133825a | ||
|
|
588548b13d | ||
|
|
3d0ffe65e4 | ||
|
|
721ee611c4 | ||
|
|
4cb8d2cbc1 | ||
|
|
7ca6676475 | ||
|
|
35cd561675 | ||
|
|
190c605bc1 | ||
|
|
a2ace42dc4 | ||
|
|
668a7cc3b9 | ||
|
|
bc3189d560 | ||
|
|
d13ea5fe0d | ||
|
|
beb5994616 | ||
|
|
7eea20baef | ||
|
|
572d447033 | ||
|
|
ae1a01df4b | ||
|
|
e3ad48d930 | ||
|
|
8eb9de562d | ||
|
|
1d66080c77 | ||
|
|
ccc5883cca | ||
|
|
bd9f831a0b | ||
|
|
93c8be74d3 | ||
|
|
7b39339fab | ||
|
|
14e3a3d2d7 | ||
|
|
0b6783959a | ||
|
|
c7118efe7e | ||
|
|
ea33141aae | ||
|
|
80fa382b53 | ||
|
|
125bafebc8 | ||
|
|
b270dc8323 | ||
|
|
ff43f75b5b | ||
|
|
a922078a11 | ||
|
|
797370ec97 | ||
|
|
46cc41c0c9 | ||
|
|
9306ffc841 | ||
|
|
2ae23b17d2 | ||
|
|
f90f1ac989 | ||
|
|
58ca57f0f3 | ||
|
|
0c31381de8 | ||
|
|
7277e0ad01 | ||
|
|
73a4ddfb61 | ||
|
|
c55788c526 | ||
|
|
ab4f2b0ffc | ||
|
|
3665a96d52 | ||
|
|
6262ac25b8 | ||
|
|
d5d51cee9b | ||
|
|
d2c885fd1d | ||
|
|
da3ad902f4 | ||
|
|
95fce28de1 | ||
|
|
d4c7a4bf0b | ||
|
|
367929f415 | ||
|
|
b560030f32 | ||
|
|
dd22e6bbf3 | ||
|
|
21fa41f0f6 | ||
|
|
0aa13c973b | ||
|
|
d4ce263c08 | ||
|
|
ec07fc2dbe | ||
|
|
ce7b66f5be | ||
|
|
fc3c0743ae | ||
|
|
684fbcb2e6 | ||
|
|
dec82f7046 | ||
|
|
195a77e959 | ||
|
|
81a359dc6d | ||
|
|
c20960c50a | ||
|
|
265006d59f | ||
|
|
26bfd8b757 | ||
|
|
e8fc6fcdb2 | ||
|
|
48469e8e10 | ||
|
|
2019606947 | ||
|
|
8bfa269825 | ||
|
|
d19ec0aad0 | ||
|
|
00227e56ad | ||
|
|
cfdc9322b3 | ||
|
|
cf694b4492 | ||
|
|
43cf4fb2f5 | ||
|
|
3b69137064 | ||
|
|
9032dd3c9a | ||
|
|
abe79bb2f3 | ||
|
|
264770d21f | ||
|
|
24cebb3b13 | ||
|
|
54bb55bc32 | ||
|
|
18994df30a | ||
|
|
daad02cbe3 | ||
|
|
559acc05fc | ||
|
|
36cd32306f | ||
|
|
c819aa09ad | ||
|
|
ba60c07379 | ||
|
|
f7ab960d24 | ||
|
|
0d6e920cc7 | ||
|
|
665d58bab6 | ||
|
|
52a3e70765 | ||
|
|
895b935807 | ||
|
|
6f9a5585c8 | ||
|
|
c95b1de846 | ||
|
|
4307149838 | ||
|
|
f065090fa7 | ||
|
|
10ce20447b | ||
|
|
6c6ac7ea6b | ||
|
|
2a1a3a33b4 | ||
|
|
877bae7623 | ||
|
|
a11f53ce43 | ||
|
|
eeb60aff40 | ||
|
|
6e9fb6abb0 | ||
|
|
251021cbe1 | ||
|
|
b74e81edc3 | ||
|
|
4f25a377b4 | ||
|
|
72003a06b1 | ||
|
|
eb5dd736f7 | ||
|
|
6c54949cb7 | ||
|
|
7095d4b7e0 | ||
|
|
556e55fc37 | ||
|
|
32793336bd | ||
|
|
40534e4f48 | ||
|
|
14808f8cab | ||
|
|
d1fb866651 | ||
|
|
e79074c938 | ||
|
|
7053c05338 | ||
|
|
a14ff8d866 | ||
|
|
4f3c122233 | ||
|
|
c3ea170328 | ||
|
|
cc9df02fe5 | ||
|
|
46c7a80c65 | ||
|
|
6b4f41f626 | ||
|
|
c8b9e434a5 | ||
|
|
c52ce95c6b | ||
|
|
481174fd4c | ||
|
|
5d5b483b6a | ||
|
|
696694f124 | ||
|
|
7b0c974fe8 | ||
|
|
b8ffb74c52 | ||
|
|
9b657d5303 | ||
|
|
9bd8f77f10 | ||
|
|
ba983bd37e | ||
|
|
203fe01f87 | ||
|
|
bdc5415de9 | ||
|
|
b1537b5648 | ||
|
|
357b925738 | ||
|
|
f168dfe1c7 | ||
|
|
030544c2d9 | ||
|
|
88c8b70b45 | ||
|
|
3af6c5bfb4 | ||
|
|
f049206f6c | ||
|
|
54125a350d | ||
|
|
38feeb08a4 | ||
|
|
aa2a8eb687 | ||
|
|
102f7833c7 | ||
|
|
65cf48ccc2 | ||
|
|
f4b7cc883c | ||
|
|
3b5986bcd4 | ||
|
|
da2fb88a17 | ||
|
|
110998255b | ||
|
|
e8382c0b75 | ||
|
|
ed6ea98bb8 | ||
|
|
4c96ac94ef | ||
|
|
9dc443e3d3 | ||
|
|
1218f51995 | ||
|
|
851d075a14 | ||
|
|
46d92466fa | ||
|
|
debea3cff7 | ||
|
|
15bc58dd2a | ||
|
|
200c906e3c | ||
|
|
d74316144e | ||
|
|
1ddbc1e719 | ||
|
|
0f828353da | ||
|
|
2b24600f82 | ||
|
|
fd809f84f8 | ||
|
|
b995f44a41 | ||
|
|
d791e2bf26 | ||
|
|
419aa43306 | ||
|
|
20086252cf | ||
|
|
fef3d1c3a3 | ||
|
|
e47d652a88 | ||
|
|
f9694c3c2b | ||
|
|
26a77da393 | ||
|
|
f1601bd24f | ||
|
|
3506544b42 | ||
|
|
132cd5d316 | ||
|
|
2bec165a83 | ||
|
|
3bc5c3f1f3 | ||
|
|
93349a068d | ||
|
|
f1cde22573 | ||
|
|
d372d76336 | ||
|
|
b11335c3ab | ||
|
|
b4d3473dab | ||
|
|
766d90c942 | ||
|
|
1fd822cfb5 | ||
|
|
2ecebf912f | ||
|
|
d144057b23 | ||
|
|
400e6fc422 | ||
|
|
d80c92ec54 | ||
|
|
4f059c1898 | ||
|
|
e9176049bf | ||
|
|
5cce8731af | ||
|
|
bed70d3ca9 | ||
|
|
7c0b8c3147 | ||
|
|
3dae180160 | ||
|
|
74813abf09 | ||
|
|
e3c83134f1 | ||
|
|
9f854aa078 | ||
|
|
bbac26bffe | ||
|
|
0d6d850e09 | ||
|
|
cb6fcfd39d | ||
|
|
a8589359d1 | ||
|
|
816985fe8e | ||
|
|
bd02a23e70 | ||
|
|
e59f42b926 | ||
|
|
b40d28ffc6 | ||
|
|
40a9f507e0 | ||
|
|
472ec2906c | ||
|
|
d78ee29349 | ||
|
|
b78036c2c4 | ||
|
|
f0dcf0bee0 | ||
|
|
c3a5b8e18f | ||
|
|
2c9d06fcff | ||
|
|
d7162db2aa | ||
|
|
06cc992b88 | ||
|
|
ea1e1dcec1 | ||
|
|
0c201f9ee3 | ||
|
|
c992559c18 | ||
|
|
91b97b617c | ||
|
|
1f3214d7c5 | ||
|
|
dc113bd29d | ||
|
|
1f67431608 | ||
|
|
a8880d7a57 | ||
|
|
db90716187 | ||
|
|
97ba008e3d | ||
|
|
b9626e8f2b | ||
|
|
6d815143b9 | ||
|
|
bd5007e868 | ||
|
|
25e9030b08 | ||
|
|
fbf6a27447 | ||
|
|
94b4f23664 | ||
|
|
aa5c29e7bd | ||
|
|
f948c724bc | ||
|
|
7b09c91564 | ||
|
|
bd52c083e6 | ||
|
|
9ff454b959 | ||
|
|
c0cbe38b48 | ||
|
|
6331f5c43d | ||
|
|
de88f554fd | ||
|
|
b4c143c40d | ||
|
|
57557479c6 | ||
|
|
2e0c5b927c | ||
|
|
9ff338c6e4 | ||
|
|
3ed45b3665 | ||
|
|
e79afa5508 | ||
|
|
c19c1284a5 | ||
|
|
e694c796f9 | ||
|
|
96a7752e86 | ||
|
|
5b334276a1 | ||
|
|
1e9c62eb8d | ||
|
|
723e2c2bbe | ||
|
|
ce8a0cd527 | ||
|
|
bba10888d1 | ||
|
|
341064508e | ||
|
|
e269582dbe | ||
|
|
b3c6177292 | ||
|
|
75849bf3ea | ||
|
|
108eaa46f4 | ||
|
|
1259e95425 | ||
|
|
20b07c3ca2 | ||
|
|
450dc4cd8b | ||
|
|
b6df5d2805 | ||
|
|
c6f0d84b31 | ||
|
|
3a8c0ddc5e | ||
|
|
5ebcda8f08 | ||
|
|
79fd394f71 | ||
|
|
960ba8a8c2 | ||
|
|
3309520ed6 | ||
|
|
ddda86a6d0 | ||
|
|
057b688116 | ||
|
|
4bfdd59ac5 | ||
|
|
d7f0640204 | ||
|
|
a47d70cfba | ||
|
|
1e100b3f26 | ||
|
|
7e8ac2f1d1 | ||
|
|
72c52af4c3 | ||
|
|
196a193224 | ||
|
|
8e21f7f5d0 | ||
|
|
cb2166b786 | ||
|
|
82815d2cf4 | ||
|
|
2fc7eb39ab | ||
|
|
1faf3f3073 | ||
|
|
3bf8a815b5 | ||
|
|
3b55f92b78 | ||
|
|
6d8f70ba57 | ||
|
|
0f0883c8c0 | ||
|
|
b924ac4518 | ||
|
|
0249dcf7d5 | ||
|
|
639a30c5fd | ||
|
|
370552b3e2 | ||
|
|
7442982ac5 | ||
|
|
e068bd6883 | ||
|
|
4dd0799db8 | ||
|
|
9d7b9e47fb | ||
|
|
aa98b92e8c | ||
|
|
8d4948dc74 | ||
|
|
bf0b2be104 | ||
|
|
959cd13211 | ||
|
|
3466f991ca | ||
|
|
0c111ee4e1 | ||
|
|
e4f26fa252 | ||
|
|
3583cd8a83 | ||
|
|
0c087abe42 | ||
|
|
396969db0d | ||
|
|
dd3991a0fc | ||
|
|
ff7ed2efc6 | ||
|
|
d525f0a730 | ||
|
|
cd7e2dcb4c | ||
|
|
51ba4a9e13 | ||
|
|
ecfc2b1360 | ||
|
|
7658cbb6d4 | ||
|
|
90968146bb | ||
|
|
7d1b1c51d3 | ||
|
|
c3e023deed | ||
|
|
b7952fb8ed | ||
|
|
6db10d2147 | ||
|
|
887788da68 | ||
|
|
54c5582fbd | ||
|
|
0792af6c3e | ||
|
|
8aacc088ea | ||
|
|
76aeca77bd | ||
|
|
14143faa88 | ||
|
|
612c828cf3 | ||
|
|
8c4a3a7bf5 | ||
|
|
e472854dd0 | ||
|
|
f291244bc1 | ||
|
|
1a41951843 | ||
|
|
2767704cc6 | ||
|
|
0958ac8644 | ||
|
|
253e1dc320 | ||
|
|
761854a143 | ||
|
|
cfe0e0063f | ||
|
|
d0cecfba52 | ||
|
|
0545862005 | ||
|
|
ef17fa07e9 | ||
|
|
8bf859381b | ||
|
|
dcebaab1ab | ||
|
|
132dd9724d | ||
|
|
e7f24c66f9 | ||
|
|
53f4b0423e | ||
|
|
f19fafe71b | ||
|
|
8adf1bf29c | ||
|
|
a0b21e9ec0 | ||
|
|
bae718680d | ||
|
|
f0b59a7371 | ||
|
|
75c6486cdc | ||
|
|
590c0d7f6a | ||
|
|
7eaf351332 | ||
|
|
0edcb4a6d6 | ||
|
|
cbb2b2b272 | ||
|
|
35fc235ace | ||
|
|
d1a87f25d9 | ||
|
|
7518b5ce9d | ||
|
|
07158b29f6 | ||
|
|
6cfc1081d8 | ||
|
|
6079f4674a | ||
|
|
20d6e495ac | ||
|
|
8a5a250204 | ||
|
|
3e20045b56 | ||
|
|
fb9921fac2 | ||
|
|
dd94a5ce4a | ||
|
|
77d0d01dd0 | ||
|
|
ca56e2e6b5 | ||
|
|
9793b393c5 | ||
|
|
1f58383468 | ||
|
|
c72ecf9a9c | ||
|
|
a3f7b4ab02 | ||
|
|
9dbde39b0c | ||
|
|
e5e80bb3a3 | ||
|
|
3e7da90620 | ||
|
|
2b296192ff | ||
|
|
032176f5c4 | ||
|
|
1cc14aa4d8 | ||
|
|
40c658b74f | ||
|
|
6df61f337e | ||
|
|
487975f952 | ||
|
|
90c123811e | ||
|
|
e8ecc20a2f | ||
|
|
92d334277e | ||
|
|
3ff130cd91 | ||
|
|
c911b598e4 | ||
|
|
6a236ada82 | ||
|
|
d6ebac09c6 | ||
|
|
6e443353df | ||
|
|
aa754254f1 | ||
|
|
c9c6db3ef8 | ||
|
|
fd356bcce7 | ||
|
|
916f400575 | ||
|
|
787607a273 | ||
|
|
c989798981 | ||
|
|
523a7cb9e2 | ||
|
|
25b828001d | ||
|
|
e234a6da94 | ||
|
|
191a1fa470 | ||
|
|
ccb36621f7 | ||
|
|
c8cee31d33 | ||
|
|
5956e157c1 | ||
|
|
00069e5914 | ||
|
|
be198061ce | ||
|
|
f5558d5054 | ||
|
|
981629fac6 | ||
|
|
cb7e52fcba | ||
|
|
e9f0bd9489 | ||
|
|
0e53b4ba9b | ||
|
|
70dab69198 | ||
|
|
55a3f13bfd | ||
|
|
10ac646d18 | ||
|
|
4e768e68e2 | ||
|
|
29c3baaea4 | ||
|
|
201c51b7d1 | ||
|
|
81b041567b | ||
|
|
d7385c0db4 | ||
|
|
ef7fcf7576 | ||
|
|
344ee2f115 | ||
|
|
ec36b397b0 | ||
|
|
bec7973784 | ||
|
|
b0aa25c996 | ||
|
|
8aa2941b55 | ||
|
|
bb80432cd1 | ||
|
|
7a8deac838 | ||
|
|
56ac6ec435 | ||
|
|
bf37988ec6 | ||
|
|
16bacad76b | ||
|
|
a92e32e388 | ||
|
|
d9791934f8 | ||
|
|
118e2fd469 | ||
|
|
82f591d2df | ||
|
|
a881380de7 | ||
|
|
3893845102 | ||
|
|
ca1e273afc | ||
|
|
7694a8e18f | ||
|
|
f158b615c0 | ||
|
|
b69699c133 |
+17
@@ -45,6 +45,8 @@ examples/ex[1-9]
|
||||
examples/ex[1-9]p
|
||||
examples/ex1[04-9]
|
||||
examples/ex1[0-9]p
|
||||
examples/ex2[0-9]
|
||||
examples/ex2[0-9]p
|
||||
|
||||
examples/refined.mesh
|
||||
examples/displaced.mesh
|
||||
@@ -76,6 +78,13 @@ examples/vortex-?-init.*
|
||||
examples/vortex-?-final.*
|
||||
examples/deformation.*
|
||||
examples/pressure.*
|
||||
examples/ex20.dat
|
||||
examples/ex20p_?????.dat
|
||||
examples/gnuplot_ex20.inp
|
||||
examples/gnuplot_ex20p.inp
|
||||
examples/ex22*.mesh
|
||||
examples/ex22*.sol
|
||||
examples/ex22p_*.*
|
||||
|
||||
examples/sundials/ex9
|
||||
examples/sundials/ex1[06]
|
||||
@@ -133,16 +142,20 @@ miniapps/electromagnetics/Joule_*
|
||||
|
||||
miniapps/meshing/mobius-strip
|
||||
miniapps/meshing/klein-bottle
|
||||
miniapps/meshing/toroid
|
||||
miniapps/meshing/mesh-explorer
|
||||
miniapps/meshing/shaper
|
||||
miniapps/meshing/extruder
|
||||
miniapps/meshing/mesh-optimizer
|
||||
miniapps/meshing/pmesh-optimizer
|
||||
|
||||
miniapps/meshing/mobius-strip.mesh
|
||||
miniapps/meshing/klein-bottle.mesh
|
||||
miniapps/meshing/toroid-*.mesh
|
||||
miniapps/meshing/mesh-explorer.mesh
|
||||
miniapps/meshing/partitioning.txt
|
||||
miniapps/meshing/shaper.mesh
|
||||
miniapps/meshing/extruder.mesh
|
||||
miniapps/meshing/optimized*
|
||||
miniapps/meshing/perturbed*
|
||||
|
||||
@@ -165,3 +178,7 @@ miniapps/nurbs/mesh.*
|
||||
miniapps/nurbs/sol.*
|
||||
miniapps/nurbs/mode_*
|
||||
miniapps/nurbs/Example1*
|
||||
|
||||
# Unit test binary and outputs
|
||||
tests/unit/output_meshes
|
||||
tests/unit/unit_tests
|
||||
|
||||
@@ -10,15 +10,111 @@
|
||||
|
||||
Version 3.4.1 (development)
|
||||
===========================
|
||||
|
||||
Support for wedge elements and meshes with mixed element types
|
||||
--------------------------------------------------------------
|
||||
- Added support for wedge shaped mesh elements of arbitrary order (with Geometry
|
||||
type PRISM) which have two triangular faces and three quadrilateral faces.
|
||||
Several examples of such meshes can be found in the data/ directory.
|
||||
|
||||
- Added H1 and L2 finite elements of arbitrary order for Wedge elements.
|
||||
|
||||
- Added support for mixed meshes containing triangles and quadrilaterals in 2D
|
||||
or tetrahedra, wedges, and hexahedra in 3D. This includes support for uniform
|
||||
refinement of such meshes. Several examples of such meshes can be found in the
|
||||
data/ directory.
|
||||
|
||||
- Added support for reading and writing linear and quadratic meshes containing
|
||||
wedge elements in VTK mesh format. Several examples of such meshes can be
|
||||
found in the data/ directory.
|
||||
|
||||
Other meshing improvements
|
||||
--------------------------
|
||||
- Improved the uniform refinement of tetrahedral meshes (also part of the
|
||||
uniform refinement of mixed 3D meshes). The previous refinement algorithm is
|
||||
still available as an option in Mesh::UniformRefinement. Both can be used in
|
||||
the updated Mesh Explorer miniapp.
|
||||
|
||||
- The local tetrahedral mesh refinement algorithm in serial and in parallel now
|
||||
follows precisely the paper:
|
||||
|
||||
D. Arnold, A. Mukherjee, and L. Pouly, "Locally Adapted Tetrahedral Meshes
|
||||
Using Bisection", SIAM J. Sci. Comput., 22(2), 431–448.
|
||||
|
||||
This guarantees that the shape regularity of the elements will be preserved
|
||||
under refinement.
|
||||
|
||||
- Added support for parallel communication groups on non-conforming meshes.
|
||||
|
||||
- A boundary in a NURBS mesh can now be connected with another boundary. Such a
|
||||
periodic NURBS mesh is a simple way to impose periodic boundary conditions.
|
||||
|
||||
- Added support for reading linear and quadratic 2D quadrilateral and triangular
|
||||
Cubit meshes.
|
||||
|
||||
- The tetrahedral mesh refinement algorithm in serial and in parallel now
|
||||
follows precisely the paper:
|
||||
D. Arnold, A. Mukherjee, and L. Pouly, "Locally Adapted Tetrahedral Meshes
|
||||
Using Bisection", SIAM J. Sci. Comput., 22(2), 431–448.
|
||||
This guarantees that the shape regularity of the elements will be preserved
|
||||
under refinement.
|
||||
- The TMOP mesh optimization algorithms were extended to support user-defined
|
||||
space-dependent limiting terms. Improved the TMOP objective functions by
|
||||
more accurate normalization of the different terms.
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- Added support for derefinement of vector (RT + ND) spaces.
|
||||
|
||||
- Added element flux, and flux energy computation in class ElasticityIntegrator,
|
||||
allowing for the use of Zienkiewicz-Zhu type error estimators with the
|
||||
integrator. For an illustration of this addition, see the new Example 22.
|
||||
|
||||
- Added a variety of coefficients which are sums or products of existing
|
||||
coefficients as well as grid function coefficients which return the
|
||||
divergence, gradient, or curl of their GridFunctions.
|
||||
|
||||
New and improved solvers and preconditioners
|
||||
--------------------------------------------
|
||||
- Added support for parallel ILU preconditioning via hypre's Euclid solver.
|
||||
|
||||
New and updated examples and miniapps
|
||||
-------------------------------------
|
||||
- Added a new meshing miniapp, Toroid, which can produce a variety of torus
|
||||
shaped meshes by twisting a stack of wedges or hexahedra.
|
||||
|
||||
- Added a new meshing miniapp, Extruder, that demonstrates the capability to
|
||||
produce 3D meshes by extruding 2D meshes.
|
||||
|
||||
- Added a new example, Example 20/20p, that solves a system of 1D ODEs derived
|
||||
from a Hamiltonian. The example demonstrates the use of the variable order,
|
||||
symplectic integration algorithm implemented in class SIAVSolver.
|
||||
|
||||
- Added a new example, Example 22/22p, that illustrates the use of AMR to solve
|
||||
a linear elasticity problem. This is an extension of Example 2/2p.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
- Added unit tests based on the Catch++ library.
|
||||
|
||||
- Altered the way FGMRES counts its iterations so that it matches GMRES.
|
||||
|
||||
- Various other simplifications, extensions, and bugfixes in the code.
|
||||
|
||||
API changes
|
||||
-----------
|
||||
- In multiple places, use Geometry::Type instead of int, where appropriate.
|
||||
- In multiple places, use Element::Type instead of int, where appropriate.
|
||||
- The Mesh methods GetElementBaseGeometry and GetBdrElementBaseGeometry no
|
||||
longer have a default value for their parameter, they only work with an
|
||||
explicitly given index.
|
||||
- In class Mesh, added methods useful for queries regarding the types of
|
||||
elements present in the mesh: HasGeometry, GetNumGeometries, GetGeometries,
|
||||
and class Mesh::GeometryList.
|
||||
- The struct CoarseFineTransformations (returned by the Mesh method
|
||||
GetRefinementTransforms) now stores the embedding matrices separately for each
|
||||
Geometry::Type.
|
||||
- In class ParMesh, replaced the method GroupNFaces with two new methods:
|
||||
GroupNTriangles and GroupNQuadrilaterals. Also, replaced GroupFace with two
|
||||
methods: GroupTriangle and GroupQuadrilateral.
|
||||
- In class ParMesh, made the two RefineGroups methods protected.
|
||||
- Removed the virtual method Element::GetRefinementFlag, it is only used by the
|
||||
derived class Tetrahedron.
|
||||
- Added new methods: Array::CopyTo, Tetrahedron::Init.
|
||||
|
||||
|
||||
Version 3.4, released on May 29, 2018
|
||||
|
||||
+13
-4
@@ -312,9 +312,6 @@ message(STATUS "MFEM build type: CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
|
||||
message(STATUS "MFEM version: v${MFEM_VERSION_STRING}")
|
||||
message(STATUS "MFEM git string: ${MFEM_GIT_STRING}")
|
||||
|
||||
# Windows specific
|
||||
set(_USE_MATH_DEFINES ${WIN32})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Define and configure the MFEM library
|
||||
#-------------------------------------------------------------------------------
|
||||
@@ -388,6 +385,9 @@ endif()
|
||||
# Enable testing if required
|
||||
if (MFEM_ENABLE_TESTING)
|
||||
enable_testing()
|
||||
set(MFEM_ALL_TESTS_TARGET_NAME tests)
|
||||
add_mfem_target(${MFEM_ALL_TESTS_TARGET_NAME} OFF)
|
||||
add_subdirectory(tests EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
# Define a target that all examples and miniapps will depend on.
|
||||
@@ -407,7 +407,9 @@ add_subdirectory(miniapps EXCLUDE_FROM_ALL)
|
||||
# Target to build all executables, i.e. everything.
|
||||
add_custom_target(exec)
|
||||
add_dependencies(exec
|
||||
${MFEM_ALL_EXAMPLES_TARGET_NAME} ${MFEM_ALL_MINIAPPS_TARGET_NAME})
|
||||
${MFEM_ALL_EXAMPLES_TARGET_NAME}
|
||||
${MFEM_ALL_MINIAPPS_TARGET_NAME}
|
||||
${MFEM_ALL_TESTS_TARGET_NAME})
|
||||
# Here, we want to "add_dependencies(test exec)". However, dependencies for
|
||||
# 'test' (and other built-in targets) can not be added with add_dependencies():
|
||||
# - https://gitlab.kitware.com/cmake/cmake/issues/8438
|
||||
@@ -543,3 +545,10 @@ install(FILES
|
||||
# Install the export set for use with the install-tree
|
||||
install(EXPORT ${PROJECT_NAME_UC}Targets
|
||||
DESTINATION ${INSTALL_CMAKE_DIR})
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Create 'config.mk' from 'config.mk.in' for the build and install locations and
|
||||
# define install rules for 'config.mk' and 'test.mk'
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
mfem_export_mk_files()
|
||||
|
||||
+18
-11
@@ -90,13 +90,18 @@ Origin](#developers-certificate-of-origin-11) at the end of this file.*
|
||||
├── general
|
||||
├── linalg
|
||||
├── mesh
|
||||
└── miniapps
|
||||
├── common
|
||||
├── electromagnetics
|
||||
├── meshing
|
||||
├── nurbs
|
||||
├── performance
|
||||
└── tools
|
||||
├── miniapps
|
||||
│ ├── common
|
||||
│ ├── electromagnetics
|
||||
│ ├── meshing
|
||||
│ ├── nurbs
|
||||
│ ├── performance
|
||||
│ └── tools
|
||||
└── tests
|
||||
├── unit
|
||||
│ ├── ...
|
||||
└── ...
|
||||
|
||||
```
|
||||
|
||||
- The main directories are `fem/`, `mesh/` and `linalg/` containing the C++
|
||||
@@ -151,6 +156,9 @@ Origin](#developers-certificate-of-origin-11) at the end of this file.*
|
||||
in the simple example codes and more fully-featured mini applications in the
|
||||
`examples/` and `miniapps/` directories.
|
||||
|
||||
- The `tests/` directory contains a unit test suite and will later contain more
|
||||
tests that run example codes.
|
||||
|
||||
- See also the [code overview](http://mfem.org/code-overview/) section on the
|
||||
MFEM website.
|
||||
|
||||
@@ -316,9 +324,9 @@ Before a PR can be merged, it should satisfy the following:
|
||||
- [ ] Is this a new feature users need to be aware of? New or updated example or miniapp?
|
||||
- [ ] Does it make sense to create a new section in the `CHANGELOG` to group with other related features?
|
||||
- [ ] Update `INSTALL`:
|
||||
- [ ] Has a new optional library been added? (*Make sure the external library is licensed under LGPL, not GPL!*)
|
||||
- [ ] Had a new optional library been added? (*Make sure the external library is licensed under LGPL, not GPL!*)
|
||||
- [ ] Does `make` or `cmake` have a new target?
|
||||
- [ ] Did the requirements or the installation process change? *(rare)*.
|
||||
- [ ] Did the requirements or the installation process change? *(rare)*
|
||||
- [ ] Update `.gitignore`:
|
||||
- [ ] Check if `make distclean; git status` shows any files that are generated from the source but we don't want to track in the repository.
|
||||
- [ ] Add new patterns (just for the new files above) and re-run the above test.
|
||||
@@ -358,10 +366,10 @@ Before a PR can be merged, it should satisfy the following:
|
||||
- [ ] If this is a major new feature, consider mentioning in the short summary inside `README` *(rare)*.
|
||||
- [ ] List major new classes in `doc/CodeDocumentation.dox` *(rare)*.
|
||||
- [ ] Update this checklist, if the new pull request affects it.
|
||||
- [ ] Run the unit tests and make sure they all pass `make unittest`.
|
||||
- [ ] (LLNL only) Clone the `tests` repository and run the following tests, see `mfem/tests/README.md`:
|
||||
- [ ] `compilers`
|
||||
- [ ] `memcheck`
|
||||
- [ ] `unit-test`
|
||||
- [ ] `documentation`
|
||||
- [ ] (LLNL only) After merging:
|
||||
- [ ] Regenerate `README.html` files from companion documentation pull requests.
|
||||
@@ -472,7 +480,6 @@ MFEM uses a `master`/`next`-branch workflow as described below:
|
||||
- `mfem:gh-next` -- Bleeding-edge development version, may be broken, use at
|
||||
your own risk.
|
||||
|
||||
|
||||
## Automated Testing
|
||||
|
||||
MFEM has several levels of automated testing running on GitHub, as well as on
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
@@ -10,7 +10,7 @@
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -112,7 +112,7 @@ modification follow. Pay close attention to the difference between a
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
@@ -146,7 +146,7 @@ such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
@@ -432,7 +432,7 @@ decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
@@ -455,7 +455,7 @@ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
@@ -485,7 +485,8 @@ convey the exclusion of warranty; and each file should have at least the
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
||||
USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -494,11 +495,10 @@ school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
library `Frob' (a library for tweaking knobs) written by James Random
|
||||
Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
|
||||
@@ -180,3 +180,75 @@ IF (USE_XSDK_DEFAULTS)
|
||||
ENDIF()
|
||||
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_MPI)
|
||||
SET(MFEM_USE_MPI ${TPL_ENABLE_MPI} CACHE BOOL "Enable MPI parallel build" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_METIS)
|
||||
SET(MFEM_USE_METIS ${TPL_ENABLE_METIS} CACHE BOOL "Enable METIS usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_GZSTREAM)
|
||||
SET(MFEM_USE_GZSTREAM ${TPL_ENABLE_GZSTREAM} CACHE BOOL "Enable gzstream for compressed data streams." FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_LIBUNWIND)
|
||||
SET(MFEM_USE_LIBUNWIND ${TPL_ENABLE_LIBUNWIND} CACHE BOOL "Enable backtrace for errors." FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_LAPACK)
|
||||
SET(MFEM_USE_LAPACK ${TPL_ENABLE_LAPACK} CACHE BOOL "Enable LAPACK usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_SUNDIALS)
|
||||
SET(MFEM_USE_SUNDIALS ${TPL_ENABLE_SUNDIALS} CACHE BOOL "Enable SUNDIALS usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_MESQUITE)
|
||||
SET(MFEM_USE_MESQUITE ${TPL_ENABLE_MESQUITE} CACHE BOOL "Enable MESQUITE usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_SUITESPARSE)
|
||||
SET(MFEM_USE_SUITESPARSE ${TPL_ENABLE_SUITESPARSE} CACHE BOOL "Enable SuiteSparse usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_SUPERLU)
|
||||
SET(MFEM_USE_SUPERLU ${TPL_ENABLE_SUPERLU} CACHE BOOL "Enable SuperLU_DIST usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_STRUMPACK)
|
||||
SET(MFEM_USE_STRUMPACK ${TPL_ENABLE_STRUMPACK} CACHE BOOL "Enable STRUMPACK usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_GECKO)
|
||||
SET(MFEM_USE_GECKO ${TPL_ENABLE_GECKO} CACHE BOOL "Enable GECKO usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_GNUTLS)
|
||||
SET(MFEM_USE_GNUTLS ${TPL_ENABLE_GNUTLS} CACHE BOOL "Enable GNUTLS usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_NETCDF)
|
||||
SET(MFEM_USE_NETCDF ${TPL_ENABLE_NETCDF} CACHE BOOL "Enable NETCDF usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_PETSC)
|
||||
SET(MFEM_USE_PETSC ${TPL_ENABLE_PETSC} CACHE BOOL "Enable PETSc support." FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_MPFR)
|
||||
SET(MFEM_USE_MPFR ${TPL_ENABLE_MPFR} CACHE BOOL "Enable MPFR usage." FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_SIDRE)
|
||||
SET(MFEM_USE_SIDRE ${TPL_ENABLE_SIDRE} CACHE BOOL "Enable Axom/Sidre usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_CONDUIT)
|
||||
SET(MFEM_USE_CONDUIT ${TPL_ENABLE_CONDUIT} CACHE BOOL "Enable Conduit usage" FORCE)
|
||||
ENDIF()
|
||||
|
||||
IF (DEFINED TPL_ENABLE_PUMI)
|
||||
SET(MFEM_USE_PUMI ${TPL_ENABLE_PUMI} CACHE BOOL "Enable PUMI" FORCE)
|
||||
ENDIF()
|
||||
|
||||
@@ -109,10 +109,6 @@
|
||||
// Enable MFEM functionality based on the SUNDIALS libraries.
|
||||
#cmakedefine MFEM_USE_SUNDIALS
|
||||
|
||||
// Windows specific options
|
||||
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
|
||||
#cmakedefine _USE_MATH_DEFINES
|
||||
|
||||
// Version of HYPRE used for building MFEM.
|
||||
#cmakedefine MFEM_HYPRE_VERSION @MFEM_HYPRE_VERSION@
|
||||
|
||||
|
||||
@@ -229,6 +229,15 @@ endfunction(mfem_find_component)
|
||||
function(mfem_find_package Name Prefix DirVar IncSuffixes Header LibSuffixes
|
||||
Lib IncDoc LibDoc)
|
||||
|
||||
# If we have the TPL_ versions of _INCLUDE_DIRS and _LIBRARIES then set the
|
||||
# standard ${Prefix} versions
|
||||
if (TPL_${Prefix}_INCLUDE_DIRS)
|
||||
set(${Prefix}_INCLUDE_DIRS ${TPL_${Prefix}_INCLUDE_DIRS} CACHE STRING "TPL_${Prefix}_INCLUDE_DIRS was found." FORCE)
|
||||
endif()
|
||||
if (TPL_${Prefix}_LIBRARIES)
|
||||
set(${Prefix}_LIBRARIES ${TPL_${Prefix}_LIBRARIES} CACHE STRING "TPL_${Prefix}_LIBRARIES was found." FORCE)
|
||||
endif()
|
||||
|
||||
# Quick return
|
||||
if (${Prefix}_FOUND)
|
||||
return()
|
||||
@@ -685,3 +694,162 @@ function(mfem_find_library Name Prefix Lib LibDoc CheckVar CheckSrc)
|
||||
endif()
|
||||
|
||||
endfunction(mfem_find_library)
|
||||
|
||||
|
||||
#
|
||||
# Function that creates 'config.mk' from 'config.mk.in' for the both the
|
||||
# build- and the install-locations and define install rules for 'config.mk'
|
||||
# and 'test.mk'.
|
||||
#
|
||||
function(mfem_export_mk_files)
|
||||
|
||||
# Define a few auxiliary variables (not written to 'config.mk')
|
||||
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
|
||||
# CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG -> '-Wl,-rpath,'
|
||||
set(shared_link_flag ${CMAKE_SHARED_LIBRARY_RUNTIME_C_FLAG})
|
||||
if (NOT shared_link_flag)
|
||||
set(shared_link_flag "-Wl,-rpath,")
|
||||
endif()
|
||||
|
||||
# Convert Boolean vars to YES/NO without writting the values to cache
|
||||
set(CONFIG_MK_BOOL_VARS MFEM_USE_MPI MFEM_USE_METIS MFEM_USE_METIS_5
|
||||
MFEM_DEBUG MFEM_USE_EXCEPTIONS MFEM_USE_GZSTREAM MFEM_USE_LIBUNWIND
|
||||
MFEM_USE_LAPACK MFEM_THREAD_SAFE MFEM_USE_OPENMP MFEM_USE_MEMALLOC
|
||||
MFEM_USE_SUNDIALS MFEM_USE_MESQUITE MFEM_USE_SUITESPARSE MFEM_USE_SUPERLU
|
||||
MFEM_USE_STRUMPACK MFEM_USE_GECKO MFEM_USE_GNUTLS MFEM_USE_NETCDF
|
||||
MFEM_USE_PETSC MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_CONDUIT
|
||||
MFEM_USE_PUMI)
|
||||
foreach(var ${CONFIG_MK_BOOL_VARS})
|
||||
if (${var})
|
||||
set(${var} YES)
|
||||
else()
|
||||
set(${var} NO)
|
||||
endif()
|
||||
endforeach()
|
||||
set(MFEM_CXX ${CMAKE_CXX_COMPILER})
|
||||
set(MFEM_CPPFLAGS "")
|
||||
string(STRIP "${CMAKE_CXX_FLAGS_${BUILD_TYPE}} ${CMAKE_CXX_FLAGS}"
|
||||
MFEM_CXXFLAGS)
|
||||
set(MFEM_TPLFLAGS "")
|
||||
foreach(dir ${MFEM_TPL_INCLUDE_DIRS})
|
||||
set(MFEM_TPLFLAGS "${MFEM_TPLFLAGS} -I${dir}")
|
||||
endforeach()
|
||||
# TODO: MFEM_TPLFLAGS: add other TPL flags, in addition to the -I flags.
|
||||
set(MFEM_INCFLAGS "-I\$(MFEM_INC_DIR) \$(MFEM_TPLFLAGS)")
|
||||
set(MFEM_PICFLAG "")
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set(MFEM_PICFLAG "${CMAKE_SHARED_LIBRARY_CXX_FLAGS}")
|
||||
endif()
|
||||
set(MFEM_FLAGS "\$(MFEM_CPPFLAGS) \$(MFEM_CXXFLAGS) \$(MFEM_INCFLAGS)")
|
||||
# TPL link flags: set below
|
||||
set(MFEM_EXT_LIBS "")
|
||||
if (BUILD_SHARED_LIBS)
|
||||
set(MFEM_LIBS "${shared_link_flag}\$(MFEM_LIB_DIR) -L\$(MFEM_LIB_DIR)")
|
||||
set(MFEM_LIBS "${MFEM_LIBS} -lmfem \$(MFEM_EXT_LIBS)")
|
||||
if (APPLE)
|
||||
set(SO_VER ".${mfem_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
else()
|
||||
set(SO_VER "${CMAKE_SHARED_LIBRARY_SUFFIX}.${mfem_VERSION}")
|
||||
endif()
|
||||
set(MFEM_LIB_FILE "\$(MFEM_LIB_DIR)/libmfem${SO_VER}")
|
||||
set(MFEM_SHARED YES)
|
||||
set(MFEM_STATIC NO)
|
||||
else()
|
||||
set(MFEM_LIBS "-L\$(MFEM_LIB_DIR) -lmfem \$(MFEM_EXT_LIBS)")
|
||||
set(MFEM_LIB_FILE "\$(MFEM_LIB_DIR)/libmfem.a")
|
||||
set(MFEM_SHARED NO)
|
||||
set(MFEM_STATIC YES)
|
||||
endif()
|
||||
set(MFEM_BUILD_TAG "${CMAKE_SYSTEM}")
|
||||
set(MFEM_PREFIX "${CMAKE_INSTALL_PREFIX}")
|
||||
# For the next 4 variable, these are the values for the build-tree version of
|
||||
# 'config.mk'
|
||||
set(MFEM_INC_DIR "${PROJECT_BINARY_DIR}")
|
||||
set(MFEM_LIB_DIR "${PROJECT_BINARY_DIR}")
|
||||
set(MFEM_TEST_MK "${PROJECT_SOURCE_DIR}/config/test.mk")
|
||||
set(MFEM_CONFIG_EXTRA "MFEM_BUILD_DIR ?= ${PROJECT_BINARY_DIR}")
|
||||
set(MFEM_MPIEXEC ${MPIEXEC})
|
||||
if (NOT MFEM_MPIEXEC)
|
||||
set(MFEM_MPIEXEC "mpirun")
|
||||
endif()
|
||||
set(MFEM_MPIEXEC_NP ${MPIEXEC_NUMPROC_FLAG})
|
||||
if (NOT MFEM_MPIEXEC_NP)
|
||||
set(MFEM_MPIEXEC_NP "-np")
|
||||
endif()
|
||||
# MFEM_MPI_NP is already set
|
||||
# Define the variable 'MFEM_EXT_LIBS': handle PUMI libs
|
||||
if ("${MFEM_USE_PUMI}" STREQUAL "YES")
|
||||
message(STATUS "simmodsuite_dir = '${SIMMODSUITE_DIR}'")
|
||||
get_target_property(liblist ${PUMI_LIBRARIES} INTERFACE_LINK_LIBRARIES)
|
||||
set(pumi_dep_libs "${liblist}")
|
||||
foreach(pumilib ${liblist})
|
||||
get_target_property(libdeps ${pumilib} INTERFACE_LINK_LIBRARIES)
|
||||
if (NOT "${libdeps}" MATCHES "libdeps-NOTFOUND")
|
||||
list(APPEND pumi_dep_libs ${libdeps})
|
||||
endif()
|
||||
endforeach()
|
||||
list(REMOVE_DUPLICATES pumi_dep_libs)
|
||||
foreach(pumilib ${pumi_dep_libs})
|
||||
unset(lib CACHE)
|
||||
string(REGEX REPLACE "^SCOREC::" "" libname ${pumilib})
|
||||
string(FIND "${pumilib}" ".a" staticlib)
|
||||
string(FIND "${pumilib}" ".so" sharedlib)
|
||||
find_library(lib ${libname} PATHS ${PUMI_DIR}/lib NO_DEFUALT_PATH)
|
||||
if (NOT "${sharedlib}" MATCHES "-1" OR
|
||||
NOT "${staticlib}" MATCHES "-1" )
|
||||
set(MFEM_EXT_LIBS "${pumilib} ${MFEM_EXT_LIBS}")
|
||||
elseif (NOT "${lib}" MATCHES "lib-NOTFOUND")
|
||||
set(MFEM_EXT_LIBS "${lib} ${MFEM_EXT_LIBS}")
|
||||
elseif ("${lib}" MATCHES "lib-NOTFOUND" AND
|
||||
NOT "${libname}" MATCHES "can" AND
|
||||
NOT "${libname}" MATCHES "pthread")
|
||||
message(FATAL_ERROR "SCOREC lib ${libname} not found")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
# Define the variable 'MFEM_EXT_LIBS': handle other (not PUMI) libs
|
||||
foreach(lib ${TPL_LIBRARIES})
|
||||
get_filename_component(suffix ${lib} EXT)
|
||||
# handle interfaces (e.g., SCOREC::apf)
|
||||
if ("${lib}" MATCHES "SCOREC::.*")
|
||||
elseif (NOT "${lib}" MATCHES "SCOREC::.*" AND "${lib}" MATCHES ".*::.*")
|
||||
message(FATAL_ERROR "***** interface lib found ... exiting *****")
|
||||
# handle static and shared libs
|
||||
elseif ("${suffix}" STREQUAL "${CMAKE_SHARED_LIBRARY_SUFFIX}")
|
||||
get_filename_component(dir ${lib} DIRECTORY)
|
||||
get_filename_component(fullLibName ${lib} NAME_WE)
|
||||
string(REGEX REPLACE "^lib" "" libname ${fullLibName})
|
||||
set(MFEM_EXT_LIBS
|
||||
"${MFEM_EXT_LIBS} ${shared_link_flag}${dir} -L${dir} -l${libname}")
|
||||
else()
|
||||
set(MFEM_EXT_LIBS "${MFEM_EXT_LIBS} ${lib}")
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Create the build-tree version of 'config.mk'
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/config/config.mk.in"
|
||||
"${PROJECT_BINARY_DIR}/config/config.mk")
|
||||
# Copy 'test.mk' from the source-tree to the build-tree
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/config/test.mk"
|
||||
"${PROJECT_BINARY_DIR}/config/test.mk" COPYONLY)
|
||||
|
||||
# Update variables for the install-tree version of 'config.mk'
|
||||
set(MFEM_INC_DIR "${CMAKE_INSTALL_PREFIX}/include")
|
||||
set(MFEM_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
|
||||
set(MFEM_TEST_MK "${CMAKE_INSTALL_PREFIX}/share/mfem/test.mk")
|
||||
set(MFEM_CONFIG_EXTRA "")
|
||||
|
||||
# Create the install-tree version of 'config.mk'
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/config/config.mk.in"
|
||||
"${PROJECT_BINARY_DIR}/config/config-install.mk")
|
||||
|
||||
# Install rules for 'config.mk' and 'test.mk'
|
||||
install(FILES ${PROJECT_SOURCE_DIR}/config/test.mk
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mfem/)
|
||||
install(FILES ${PROJECT_BINARY_DIR}/config/config-install.mk
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mfem/ RENAME config.mk)
|
||||
|
||||
endfunction()
|
||||
|
||||
@@ -23,6 +23,18 @@
|
||||
#include "_config.hpp"
|
||||
#endif
|
||||
|
||||
// Common configuration macros
|
||||
|
||||
#if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__)
|
||||
#define MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
|
||||
#endif
|
||||
|
||||
// Windows specific options
|
||||
#ifdef _WIN32
|
||||
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
// Check dependencies:
|
||||
|
||||
// Options that require MPI
|
||||
|
||||
@@ -112,12 +112,6 @@
|
||||
// Enable MFEM functionality based on the PUMI library
|
||||
// #define MFEM_USE_PUMI
|
||||
|
||||
// Windows specific options
|
||||
#ifdef _WIN32
|
||||
// Macro needed to get defines like M_PI from <cmath>. (Visual Studio C++ only?)
|
||||
#define _USE_MATH_DEFINES
|
||||
#endif
|
||||
|
||||
// Version of HYPRE used for building MFEM.
|
||||
// #define MFEM_HYPRE_VERSION @MFEM_HYPRE_VERSION@
|
||||
|
||||
|
||||
@@ -42,6 +42,8 @@ option(MFEM_USE_SIDRE "Enable Axom/Sidre usage" OFF)
|
||||
option(MFEM_USE_CONDUIT "Enable Conduit usage" OFF)
|
||||
option(MFEM_USE_PUMI "Enable PUMI" OFF)
|
||||
|
||||
set(MFEM_MPI_NP 4 CACHE STRING "Number of processes used for MPI tests")
|
||||
|
||||
# Allow a user to disable testing, examples, and/or miniapps at CONFIGURE TIME
|
||||
# if they don't want/need them (e.g. if MFEM is "just a dependency" and all they
|
||||
# need is the library, building all that stuff adds unnecessary overhead). Note
|
||||
|
||||
+16
-7
@@ -30,7 +30,7 @@ groups_serial=(
|
||||
'"examples"
|
||||
"Examples:"
|
||||
"examples"
|
||||
"ex{,1}[0-9].cpp"'
|
||||
"ex{,1,2}[0-9].cpp"'
|
||||
# "ex1.cpp"'
|
||||
'"sundials"
|
||||
"SUNDIALS examples:"
|
||||
@@ -44,14 +44,15 @@ groups_serial=(
|
||||
'"meshing"
|
||||
"Meshing miniapps:"
|
||||
"miniapps/meshing"
|
||||
"mobius-strip.cpp klein-bottle.cpp mesh-optimizer.cpp"'
|
||||
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp
|
||||
mesh-optimizer.cpp"'
|
||||
)
|
||||
# Parallel groups
|
||||
groups_parallel=(
|
||||
'"examples"
|
||||
"Examples:"
|
||||
"examples"
|
||||
"ex{,1}[0-9]p.cpp"'
|
||||
"ex{,1,2}[0-9]p.cpp"'
|
||||
# "ex1p.cpp"'
|
||||
'"sundials"
|
||||
"SUNDIALS examples:"
|
||||
@@ -81,7 +82,7 @@ groups_all=(
|
||||
'"examples"
|
||||
"Examples:"
|
||||
"examples"
|
||||
"ex\"{,1}[0-9]\"{,p}.cpp"'
|
||||
"ex\"{,1,2}[0-9]\"{,p}.cpp"'
|
||||
'"sundials"
|
||||
"SUNDIALS examples:"
|
||||
"examples/sundials"
|
||||
@@ -97,7 +98,8 @@ groups_all=(
|
||||
'"meshing"
|
||||
"Meshing miniapps:"
|
||||
"miniapps/meshing"
|
||||
"mobius-strip.cpp klein-bottle.cpp {,p}mesh-optimizer.cpp"'
|
||||
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp
|
||||
{,p}mesh-optimizer.cpp"'
|
||||
'"electromagnetics"
|
||||
"Electromagnetics miniapps:"
|
||||
"miniapps/electromagnetics"
|
||||
@@ -170,6 +172,9 @@ function help_message()
|
||||
-v Enable valgrind
|
||||
-o <dir> [${output_dir:-"<empty>: output goes to stdout"}]
|
||||
If not empty, save output to files inside <dir>
|
||||
-d <dir> [${mfem_build_dir}]
|
||||
If <dir> is different from <mfem_dir> then use an
|
||||
out-of-source build in <dir>
|
||||
-j <np> [${make_j}] Specify the number of jobs to use for building
|
||||
-c|-color Always use colors for the status messages: OK, FAILED, etc
|
||||
-b|-built Do NOT rebuild the library and the executables
|
||||
@@ -196,8 +201,8 @@ function help_message()
|
||||
Their values can also set using the respective uppercase environment
|
||||
variable
|
||||
mfem_build_dir [${mfem_build_dir}]
|
||||
Set this variable to something different from <mfem_dir> to use an
|
||||
out-of-source build
|
||||
Same as '-d': set this variable to something different from <mfem_dir>
|
||||
to use an out-of-source build
|
||||
|
||||
For other valid variables, see the script source.
|
||||
|
||||
@@ -266,6 +271,10 @@ case "$1" in
|
||||
shift
|
||||
output_dir="$1"
|
||||
;;
|
||||
-d)
|
||||
shift
|
||||
mfem_build_dir="$1"
|
||||
;;
|
||||
-j)
|
||||
shift
|
||||
make_j="-j $1"
|
||||
|
||||
+3
-2
@@ -38,7 +38,7 @@ export TIME='%es %MkB %x'; \
|
||||
set -- $$($(1) $(SHELL) -c "$(2)" 2>&1); while [ "$$#" -gt 3 ]; do shift; done
|
||||
endef
|
||||
define TIMECMD.NOTGNU
|
||||
set -- $$($(1) -l $(SHELL) -c "$(2)" 2>&1; echo $$?); \
|
||||
set -- $$($(1) -l $(SHELL) -c "{ $(2); } > /dev/null 2>&1" 2>&1; echo $$?); \
|
||||
set -- "$$1"s "$$(($$7/1024))"kB "$${60}"
|
||||
endef
|
||||
define TIMECMD.BASH
|
||||
@@ -60,7 +60,8 @@ endif
|
||||
# Test runs of the examples/miniapps with parameters - check exit code
|
||||
mfem-test = \
|
||||
printf " $(3) [$(2) $(1) ... ]: "; \
|
||||
$(call $(TIMEFUN),$(TIMECMD),$(2) ./$(1) -no-vis $(4) > $(1).stderr 2>&1); \
|
||||
$(call $(TIMEFUN),$(TIMECMD),$(2) ./$(1) $(if $(5),,-no-vis )$(4) \
|
||||
> $(1).stderr 2>&1); \
|
||||
if [ "$$3" = 0 ]; \
|
||||
then $(PRINT_OK); else $(PRINT_FAILED); cat $(1).stderr; fi; \
|
||||
rm -f $(1).stderr; exit $$3
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
#
|
||||
|
||||
dimension
|
||||
3
|
||||
|
||||
elements
|
||||
8
|
||||
1 6 0 9 18 1 10 19
|
||||
1 6 1 10 19 2 11 20
|
||||
1 6 2 11 20 3 12 21
|
||||
1 6 3 12 21 4 13 22
|
||||
2 6 4 13 22 5 14 23
|
||||
2 6 5 14 23 6 15 24
|
||||
2 6 6 15 24 7 16 25
|
||||
2 6 7 16 25 8 17 26
|
||||
|
||||
boundary
|
||||
26
|
||||
1 2 0 18 9
|
||||
2 2 8 17 26
|
||||
3 3 0 9 10 1
|
||||
3 3 1 10 11 2
|
||||
3 3 2 11 12 3
|
||||
3 3 3 12 13 4
|
||||
3 3 4 13 14 5
|
||||
3 3 5 14 15 6
|
||||
3 3 6 15 16 7
|
||||
3 3 7 16 17 8
|
||||
3 3 18 0 1 19
|
||||
3 3 19 1 2 20
|
||||
3 3 20 2 3 21
|
||||
3 3 21 3 4 22
|
||||
3 3 22 4 5 23
|
||||
3 3 23 5 6 24
|
||||
3 3 24 6 7 25
|
||||
3 3 25 7 8 26
|
||||
3 3 9 18 19 10
|
||||
3 3 10 19 20 11
|
||||
3 3 11 20 21 12
|
||||
3 3 12 21 22 13
|
||||
3 3 13 22 23 14
|
||||
3 3 14 23 24 15
|
||||
3 3 15 24 25 16
|
||||
3 3 16 25 26 17
|
||||
|
||||
vertices
|
||||
27
|
||||
3
|
||||
0 0 0
|
||||
1 0 0
|
||||
2 0 0
|
||||
3 0 0
|
||||
4 0 0
|
||||
5 0 0
|
||||
6 0 0
|
||||
7 0 0
|
||||
8 0 0
|
||||
0 1 0
|
||||
1 1 0
|
||||
2 1 0
|
||||
3 1 0
|
||||
4 1 0
|
||||
5 1 0
|
||||
6 1 0
|
||||
7 1 0
|
||||
8 1 0
|
||||
0 0.5 1
|
||||
1 0.5 1
|
||||
2 0.5 1
|
||||
3 0.5 1
|
||||
4 0.5 1
|
||||
5 0.5 1
|
||||
6 0.5 1
|
||||
7 0.5 1
|
||||
8 0.5 1
|
||||
@@ -0,0 +1,61 @@
|
||||
# vtk DataFile Version 3.0
|
||||
Generated by MFEM
|
||||
ASCII
|
||||
DATASET UNSTRUCTURED_GRID
|
||||
POINTS 27 double
|
||||
0 0 0
|
||||
1 0 0
|
||||
2 0 0
|
||||
3 0 0
|
||||
4 0 0
|
||||
5 0 0
|
||||
6 0 0
|
||||
7 0 0
|
||||
8 0 0
|
||||
0 1 0
|
||||
1 1 0
|
||||
2 1 0
|
||||
3 1 0
|
||||
4 1 0
|
||||
5 1 0
|
||||
6 1 0
|
||||
7 1 0
|
||||
8 1 0
|
||||
0 0.5 1
|
||||
1 0.5 1
|
||||
2 0.5 1
|
||||
3 0.5 1
|
||||
4 0.5 1
|
||||
5 0.5 1
|
||||
6 0.5 1
|
||||
7 0.5 1
|
||||
8 0.5 1
|
||||
CELLS 8 56
|
||||
6 0 9 18 1 10 19
|
||||
6 1 10 19 2 11 20
|
||||
6 2 11 20 3 12 21
|
||||
6 3 12 21 4 13 22
|
||||
6 4 13 22 5 14 23
|
||||
6 5 14 23 6 15 24
|
||||
6 6 15 24 7 16 25
|
||||
6 7 16 25 8 17 26
|
||||
CELL_TYPES 8
|
||||
13
|
||||
13
|
||||
13
|
||||
13
|
||||
13
|
||||
13
|
||||
13
|
||||
13
|
||||
CELL_DATA 8
|
||||
SCALARS material int
|
||||
LOOKUP_TABLE default
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
2
|
||||
2
|
||||
2
|
||||
2
|
||||
@@ -0,0 +1,192 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
#
|
||||
|
||||
dimension
|
||||
3
|
||||
|
||||
elements
|
||||
14
|
||||
1 4 13 15 21 25
|
||||
1 4 15 13 21 12
|
||||
1 4 21 13 25 22
|
||||
1 4 15 21 25 24
|
||||
1 4 13 15 25 16
|
||||
1 5 0 1 4 3 9 10 13 12
|
||||
1 5 8 9 12 11 17 18 21 20
|
||||
1 5 2 3 6 5 11 12 15 14
|
||||
1 6 3 4 6 12 13 15
|
||||
1 6 4 7 6 13 16 15
|
||||
1 6 12 13 21 9 10 18
|
||||
1 6 13 22 21 10 19 18
|
||||
1 6 11 14 20 12 15 21
|
||||
1 6 15 21 24 14 20 23
|
||||
|
||||
boundary
|
||||
30
|
||||
1 3 5 6 3 2
|
||||
2 2 6 4 3
|
||||
2 2 4 6 7
|
||||
3 3 3 4 1 0
|
||||
4 3 11 12 9 8
|
||||
5 3 2 3 12 11
|
||||
6 3 0 1 10 9
|
||||
7 2 10 18 9
|
||||
7 2 18 10 19
|
||||
8 3 8 9 18 17
|
||||
9 3 1 4 13 10
|
||||
10 3 4 7 16 13
|
||||
11 2 25 13 16
|
||||
11 2 13 25 22
|
||||
12 3 10 13 22 19
|
||||
13 3 7 6 15 16
|
||||
14 3 6 5 14 15
|
||||
15 3 15 14 23 24
|
||||
16 2 15 25 16
|
||||
16 2 25 15 24
|
||||
17 3 5 2 11 14
|
||||
18 3 3 0 9 12
|
||||
19 3 11 8 17 20
|
||||
20 2 20 14 11
|
||||
20 2 14 20 23
|
||||
21 3 17 18 21 20
|
||||
22 3 18 19 22 21
|
||||
23 2 25 21 22
|
||||
23 2 21 25 24
|
||||
24 3 20 21 24 23
|
||||
|
||||
vertices
|
||||
26
|
||||
|
||||
nodes
|
||||
FiniteElementSpace
|
||||
FiniteElementCollection: H1_3D_P2
|
||||
VDim: 3
|
||||
Ordering: 1
|
||||
|
||||
0.028213666146621 -1.0129124616273 -1.0197422793601
|
||||
0.99151103207842 -0.97408353323117 -1.0219424221199
|
||||
-0.98628834960982 -0.048291393648833 -1.0334530425724
|
||||
-0.045286384224892 -0.028259630873799 -0.95961592583917
|
||||
1.0351351283956 0.016103611653671 -1.0465984194074
|
||||
-0.97963495329022 0.975340601895 -0.95050375238061
|
||||
-0.016565482225269 0.98394050155766 -1.0119900547434
|
||||
0.98232264800655 1.0061312792241 -0.97468885016611
|
||||
-1.0111163694877 -1.0328216757625 -0.033904406474903
|
||||
-0.031359497737139 -0.95907832225785 -0.02936147605069
|
||||
1.0216721775476 -0.95571139678359 -0.041445003869012
|
||||
-0.96617995956913 0.013420177670196 -0.047073400672525
|
||||
0.03735491973348 0.024136644229293 -0.035419858060777
|
||||
0.99844568660483 -0.023344853520393 0.043047091318294
|
||||
-1.0075354852248 0.95110015915707 0.040374961402267
|
||||
-0.018023004801944 0.98735854397528 0.035048884851858
|
||||
0.96496833880778 0.98624407089765 0.029059857856424
|
||||
-0.95618249163963 -0.95913625303656 0.99699592567049
|
||||
0.010523111699149 -1.0380611987319 1.0054330066312
|
||||
1.0131589291349 -0.99133288586241 1.0510169859154
|
||||
-0.9992929702159 -0.016950021823868 1.0209834648762
|
||||
-0.030905270343646 -0.024878516234457 0.96677784407511
|
||||
1.0369556044533 0.036727200814101 0.97476146325791
|
||||
-1.0268666699025 0.99100244478387 0.95557046163574
|
||||
0.032850918109418 0.9761234538078 0.99340013005027
|
||||
0.96517252528448 1.018590816239 0.96241486393546
|
||||
0.52641251369336 0.53453492783232 -0.046831832639522
|
||||
0.54842095679127 0.012466884090474 0.52264325135947
|
||||
1.0546647359835 0.51503200008771 0.47661895657821
|
||||
0.008193729444779 0.46320342579585 0.51330736048101
|
||||
0.48446121998846 1.0366433051979 0.46910527980021
|
||||
0.50338134740858 0.53372671722279 1.0016026703109
|
||||
-0.0026805294677615 0.54834160562605 -0.022633473388851
|
||||
0.4992129677441 -0.027650739811361 -0.025983834639192
|
||||
-0.010308592952788 0.043478553090245 0.54404251929373
|
||||
0.52373361142037 0.017260625417003 1.0190168930687
|
||||
0.95156254112601 0.024917951411289 0.48927665714905
|
||||
1.0114961385777 0.53988309084877 0.98077339629239
|
||||
0.01429600397056 1.0255897320394 0.44945099394948
|
||||
-0.0037663174125072 0.46114195337251 0.98693741812483
|
||||
0.53955416269275 0.95254191223583 0.99345054396648
|
||||
1.0344137934711 0.51549308419917 0.0019079259000746
|
||||
0.4635900873147 1.0074141174823 -0.025796540646941
|
||||
1.0393698821347 0.99823230649269 0.53561992818844
|
||||
0.54910938213579 -1.0186136680655 -1.0399189315271
|
||||
0.98251790353097 -0.52159510049969 -1.0488538759761
|
||||
0.51290647936985 0.019199261348695 -1.0180139709264
|
||||
0.039190890220925 -0.51870735888369 -1.0145805133507
|
||||
0.54531239252537 -1.0346180800814 -0.026071808021516
|
||||
1.0111227696296 -0.45961035727523 0.028725982550532
|
||||
-0.0024106570985168 -0.51591348233633 0.042102640075609
|
||||
0.019072471559048 -1.0489699664991 -0.53822694290429
|
||||
1.0197706996463 -1.0138504981995 -0.48532295548357
|
||||
0.97708769380115 0.012869927892461 -0.49512141938321
|
||||
-0.0056951441802084 -0.018287890031934 -0.46456751856022
|
||||
-0.48628377295099 -0.97137148869224 -0.040609835088253
|
||||
-0.52949825478718 0.022831952339038 0.036623532185331
|
||||
-0.9682938832324 -0.51529484749772 0.039498377451673
|
||||
-0.45076946932822 -0.98247022288851 1.0229644412175
|
||||
-0.036635886738077 -0.53934830226935 0.97308384231292
|
||||
-0.47986206617206 -0.041745604947209 0.98161771683954
|
||||
-0.95103283049539 -0.5087813614402 1.0116585971788
|
||||
-0.95395673410967 -0.95082942959853 0.50977751370519
|
||||
0.030673310998827 -0.97366141136736 0.47265974627808
|
||||
-1.0076441270299 0.025157339498401 0.51940553779714
|
||||
-0.45112570035271 0.030354945734143 -1.0244264173787
|
||||
-0.034796683816239 0.47213521944359 -1.0233666383661
|
||||
-0.52309081116691 1.0127369282767 -1.030445962213
|
||||
-1.0052867605351 0.54541603662074 -0.99267176855355
|
||||
-0.53441363093443 1.0101050069556 0.034852372528985
|
||||
-1.0361742412671 0.51952713127248 -0.0075041593052447
|
||||
-1.0224051106721 0.037305149668828 -0.51234883274883
|
||||
-0.0468317149207 0.99936735257506 -0.53290488454513
|
||||
-1.0323944162577 1.0470460939221 -0.49629869163036
|
||||
0.50827771586097 0.51091354087276 -0.96143114171132
|
||||
0.97860428203942 0.53881222049291 -1.0227558970328
|
||||
0.54899092558423 1.0449853148062 -1.0290394971016
|
||||
0.98149990118493 1.0265442789565 -0.45402792714566
|
||||
0.47938502309767 -0.95321110021154 0.46438798044786
|
||||
0.98893120098231 -1.0252040218394 0.52866776747387
|
||||
0.46061993861414 -0.973998097143 0.95264651015888
|
||||
0.98858339184873 -0.49578777734639 0.97955980177082
|
||||
-0.95322811676761 0.49312524158842 0.46350421594559
|
||||
-0.9670648949319 0.52720408663568 1.0147400701319
|
||||
-0.95970724064157 0.9966338243727 0.47198853459547
|
||||
-0.55076990539437 0.95548113087191 1.0002298586837
|
||||
0.48237521727569 -0.51972299404442 -0.98436066769063
|
||||
0.45025863721967 -1.0030842470471 -0.53693975312635
|
||||
0.95356930759735 -0.4606471833773 -0.49721032292582
|
||||
0.48610299886204 0.033102156873792 -0.45204877182841
|
||||
0.016292646434158 -0.4694908623118 -0.53292224425822
|
||||
0.47584088565782 -0.54223454683088 -0.036028525792062
|
||||
-0.53143287785351 -0.4923779387027 0.0039846746250987
|
||||
-0.52957315347157 -1.0359902368858 0.51208876920864
|
||||
-0.024055424472317 -0.49951890320517 0.48579422575422
|
||||
-0.45644746879116 -0.012607240816578 0.51010388839059
|
||||
-0.98394734906033 -0.50309513998218 0.47998268660158
|
||||
-0.53098605261184 -0.48258609846234 0.97544367099181
|
||||
-0.51822144156322 0.45223189569078 -1.0385291075334
|
||||
-0.45871022404172 -0.042734754644334 -0.54302125046961
|
||||
0.041843411838636 0.46222349074669 -0.5097909247037
|
||||
-0.45607118047774 1.0116704457439 -0.45481789885089
|
||||
-1.0244252419565 0.4849586374592 -0.50017994958907
|
||||
-0.52441235366277 0.50157218999229 0.023797604069114
|
||||
0.46467856940869 0.54693057615002 -0.46251054922067
|
||||
0.98669286111723 0.51824862516758 -0.45168929326637
|
||||
0.54790127868275 0.98589193659248 -0.51421705686245
|
||||
0.54233705943277 -0.4508773840935 0.45025142266283
|
||||
1.0203662623874 -0.5304726794563 0.52365051237419
|
||||
0.48446453821555 -0.47976663671026 1.043945324572
|
||||
-0.48793381256969 0.50247088679532 0.48323828733422
|
||||
-0.52670996575095 0.50194146344506 1.0026980744777
|
||||
-0.47523256142428 0.97748358070477 0.48234451559035
|
||||
0.45616661459208 -0.50770850274712 -0.4568053398747
|
||||
-0.52734654471278 -0.51337681044824 0.47594708297402
|
||||
-0.45737625267357 0.47732204026543 -0.54846904515289
|
||||
@@ -0,0 +1,168 @@
|
||||
# vtk DataFile Version 3.0
|
||||
Generated by MFEM
|
||||
ASCII
|
||||
DATASET UNSTRUCTURED_GRID
|
||||
POINTS 116 double
|
||||
0.028213666146621 -1.0129124616273 -1.0197422793601
|
||||
0.99151103207842 -0.97408353323117 -1.0219424221199
|
||||
-0.98628834960982 -0.048291393648833 -1.0334530425724
|
||||
-0.045286384224892 -0.028259630873799 -0.95961592583917
|
||||
1.0351351283956 0.016103611653671 -1.0465984194074
|
||||
-0.97963495329022 0.975340601895 -0.95050375238061
|
||||
-0.016565482225269 0.98394050155766 -1.0119900547434
|
||||
0.98232264800655 1.0061312792241 -0.97468885016611
|
||||
-1.0111163694877 -1.0328216757625 -0.033904406474903
|
||||
-0.031359497737139 -0.95907832225785 -0.02936147605069
|
||||
1.0216721775476 -0.95571139678359 -0.041445003869012
|
||||
-0.96617995956913 0.013420177670196 -0.047073400672525
|
||||
0.03735491973348 0.024136644229293 -0.035419858060777
|
||||
0.99844568660483 -0.023344853520393 0.043047091318294
|
||||
-1.0075354852248 0.95110015915707 0.040374961402267
|
||||
-0.018023004801944 0.98735854397528 0.035048884851858
|
||||
0.96496833880778 0.98624407089765 0.029059857856424
|
||||
-0.95618249163963 -0.95913625303656 0.99699592567049
|
||||
0.010523111699149 -1.0380611987319 1.0054330066312
|
||||
1.0131589291349 -0.99133288586241 1.0510169859154
|
||||
-0.9992929702159 -0.016950021823868 1.0209834648762
|
||||
-0.030905270343646 -0.024878516234457 0.96677784407511
|
||||
1.0369556044533 0.036727200814101 0.97476146325791
|
||||
-1.0268666699025 0.99100244478387 0.95557046163574
|
||||
0.032850918109418 0.9761234538078 0.99340013005027
|
||||
0.96517252528448 1.018590816239 0.96241486393546
|
||||
0.50338134740858 0.53372671722279 1.0016026703109
|
||||
0.54842095679127 0.012466884090474 0.52264325135947
|
||||
0.008193729444779 0.46320342579585 0.51330736048101
|
||||
1.0546647359835 0.51503200008771 0.47661895657821
|
||||
0.48446121998846 1.0366433051979 0.46910527980021
|
||||
0.52641251369336 0.53453492783232 -0.046831832639522
|
||||
-0.0026805294677615 0.54834160562605 -0.022633473388851
|
||||
0.4992129677441 -0.027650739811361 -0.025983834639192
|
||||
-0.010308592952788 0.043478553090245 0.54404251929373
|
||||
1.0114961385777 0.53988309084877 0.98077339629239
|
||||
0.52373361142037 0.017260625417003 1.0190168930687
|
||||
0.95156254112601 0.024917951411289 0.48927665714905
|
||||
-0.0037663174125072 0.46114195337251 0.98693741812483
|
||||
0.53955416269275 0.95254191223583 0.99345054396648
|
||||
0.01429600397056 1.0255897320394 0.44945099394948
|
||||
1.0344137934711 0.51549308419917 0.0019079259000746
|
||||
0.4635900873147 1.0074141174823 -0.025796540646941
|
||||
1.0393698821347 0.99823230649269 0.53561992818844
|
||||
0.54910938213579 -1.0186136680655 -1.0399189315271
|
||||
0.98251790353097 -0.52159510049969 -1.0488538759761
|
||||
0.51290647936985 0.019199261348695 -1.0180139709264
|
||||
0.039190890220925 -0.51870735888369 -1.0145805133507
|
||||
0.54531239252537 -1.0346180800814 -0.026071808021516
|
||||
1.0111227696296 -0.45961035727523 0.028725982550532
|
||||
-0.0024106570985168 -0.51591348233633 0.042102640075609
|
||||
0.019072471559048 -1.0489699664991 -0.53822694290429
|
||||
1.0197706996463 -1.0138504981995 -0.48532295548357
|
||||
0.97708769380115 0.012869927892461 -0.49512141938321
|
||||
-0.0056951441802084 -0.018287890031934 -0.46456751856022
|
||||
-0.48628377295099 -0.97137148869224 -0.040609835088253
|
||||
-0.52949825478718 0.022831952339038 0.036623532185331
|
||||
-0.9682938832324 -0.51529484749772 0.039498377451673
|
||||
-0.45076946932822 -0.98247022288851 1.0229644412175
|
||||
-0.036635886738077 -0.53934830226935 0.97308384231292
|
||||
-0.47986206617206 -0.041745604947209 0.98161771683954
|
||||
-0.95103283049539 -0.5087813614402 1.0116585971788
|
||||
-0.95395673410967 -0.95082942959853 0.50977751370519
|
||||
0.030673310998827 -0.97366141136736 0.47265974627808
|
||||
-1.0076441270299 0.025157339498401 0.51940553779714
|
||||
-0.45112570035271 0.030354945734143 -1.0244264173787
|
||||
-0.034796683816239 0.47213521944359 -1.0233666383661
|
||||
-0.52309081116691 1.0127369282767 -1.030445962213
|
||||
-1.0052867605351 0.54541603662074 -0.99267176855355
|
||||
-0.53441363093443 1.0101050069556 0.034852372528985
|
||||
-1.0361742412671 0.51952713127248 -0.0075041593052447
|
||||
-1.0224051106721 0.037305149668828 -0.51234883274883
|
||||
-0.0468317149207 0.99936735257506 -0.53290488454513
|
||||
-1.0323944162577 1.0470460939221 -0.49629869163036
|
||||
0.50827771586097 0.51091354087276 -0.96143114171132
|
||||
0.97860428203942 0.53881222049291 -1.0227558970328
|
||||
0.54899092558423 1.0449853148062 -1.0290394971016
|
||||
0.98149990118493 1.0265442789565 -0.45402792714566
|
||||
0.47938502309767 -0.95321110021154 0.46438798044786
|
||||
0.98893120098231 -1.0252040218394 0.52866776747387
|
||||
0.46061993861414 -0.973998097143 0.95264651015888
|
||||
0.98858339184873 -0.49578777734639 0.97955980177082
|
||||
-0.95322811676761 0.49312524158842 0.46350421594559
|
||||
-0.9670648949319 0.52720408663568 1.0147400701319
|
||||
-0.95970724064157 0.9966338243727 0.47198853459547
|
||||
-0.55076990539437 0.95548113087191 1.0002298586837
|
||||
0.48237521727569 -0.51972299404442 -0.98436066769063
|
||||
0.45025863721967 -1.0030842470471 -0.53693975312635
|
||||
0.95356930759735 -0.4606471833773 -0.49721032292582
|
||||
0.48610299886204 0.033102156873792 -0.45204877182841
|
||||
0.016292646434158 -0.4694908623118 -0.53292224425822
|
||||
0.47584088565782 -0.54223454683088 -0.036028525792062
|
||||
-0.53143287785351 -0.4923779387027 0.0039846746250987
|
||||
-0.52957315347157 -1.0359902368858 0.51208876920864
|
||||
-0.024055424472317 -0.49951890320517 0.48579422575422
|
||||
-0.45644746879116 -0.012607240816578 0.51010388839059
|
||||
-0.98394734906033 -0.50309513998218 0.47998268660158
|
||||
-0.53098605261184 -0.48258609846234 0.97544367099181
|
||||
-0.51822144156322 0.45223189569078 -1.0385291075334
|
||||
-0.45871022404172 -0.042734754644334 -0.54302125046961
|
||||
0.041843411838636 0.46222349074669 -0.5097909247037
|
||||
-0.45607118047774 1.0116704457439 -0.45481789885089
|
||||
-1.0244252419565 0.4849586374592 -0.50017994958907
|
||||
-0.52441235366277 0.50157218999229 0.023797604069114
|
||||
0.46467856940869 0.54693057615002 -0.46251054922067
|
||||
0.98669286111723 0.51824862516758 -0.45168929326637
|
||||
0.54790127868275 0.98589193659248 -0.51421705686245
|
||||
0.54233705943277 -0.4508773840935 0.45025142266283
|
||||
1.0203662623874 -0.5304726794563 0.52365051237419
|
||||
0.48446453821555 -0.47976663671026 1.043945324572
|
||||
-0.48793381256969 0.50247088679532 0.48323828733422
|
||||
-0.52670996575095 0.50194146344506 1.0026980744777
|
||||
-0.47523256142428 0.97748358070477 0.48234451559035
|
||||
0.45616661459208 -0.50770850274712 -0.4568053398747
|
||||
-0.52734654471278 -0.51337681044824 0.47594708297402
|
||||
-0.45737625267357 0.47732204026543 -0.54846904515289
|
||||
CELLS 14 253
|
||||
10 21 25 13 15 26 29 27 28 30 31
|
||||
10 15 13 21 12 31 27 28 32 33 34
|
||||
10 25 21 13 22 26 27 29 35 36 37
|
||||
10 21 25 15 24 26 30 28 38 39 40
|
||||
10 13 15 25 16 31 30 29 41 42 43
|
||||
27 0 1 4 3 9 10 13 12 44 45 46 47 48 49 33 50 51 52 53 54 90 88 87 89 86 91 113
|
||||
27 8 9 12 11 17 18 21 20 55 50 56 57 58 59 60 61 62 63 34 64 96 94 93 95 92 97 114
|
||||
27 2 3 6 5 11 12 15 14 65 66 67 68 56 32 69 70 71 54 72 73 102 100 99 101 98 103 115
|
||||
18 3 6 4 12 15 13 66 74 46 32 31 33 54 72 53 100 104 89
|
||||
18 4 6 7 13 15 16 74 76 75 31 42 41 53 72 77 104 106 105
|
||||
18 12 21 13 9 18 10 34 27 33 63 78 48 50 59 49 94 107 91
|
||||
18 13 21 22 10 18 19 27 36 37 78 80 79 49 59 81 107 109 108
|
||||
18 11 20 14 12 21 15 64 82 70 34 28 32 56 60 69 95 110 103
|
||||
18 15 24 21 14 23 20 40 38 28 84 83 82 69 85 60 112 111 110
|
||||
CELL_TYPES 14
|
||||
24
|
||||
24
|
||||
24
|
||||
24
|
||||
24
|
||||
29
|
||||
29
|
||||
29
|
||||
32
|
||||
32
|
||||
32
|
||||
32
|
||||
32
|
||||
32
|
||||
CELL_DATA 14
|
||||
SCALARS material int
|
||||
LOOKUP_TABLE default
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
@@ -0,0 +1,96 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
#
|
||||
|
||||
dimension
|
||||
3
|
||||
|
||||
elements
|
||||
14
|
||||
1 4 13 15 21 25
|
||||
1 4 12 13 15 21
|
||||
1 4 13 21 22 25
|
||||
1 4 15 24 21 25
|
||||
1 4 13 15 25 16
|
||||
1 5 0 1 4 3 9 10 13 12
|
||||
1 5 8 9 12 11 17 18 21 20
|
||||
1 5 2 3 6 5 11 12 15 14
|
||||
1 6 3 4 6 12 13 15
|
||||
1 6 4 7 6 13 16 15
|
||||
1 6 12 13 21 9 10 18
|
||||
1 6 13 22 21 10 19 18
|
||||
1 6 11 14 20 12 15 21
|
||||
1 6 15 21 24 14 20 23
|
||||
|
||||
boundary
|
||||
30
|
||||
1 3 5 6 3 2
|
||||
2 2 3 6 4
|
||||
2 2 4 6 7
|
||||
3 3 3 4 1 0
|
||||
4 3 11 12 9 8
|
||||
5 3 2 3 12 11
|
||||
6 3 0 1 10 9
|
||||
7 2 9 10 18
|
||||
7 2 10 19 18
|
||||
8 3 8 9 18 17
|
||||
9 3 1 4 13 10
|
||||
10 3 4 7 16 13
|
||||
11 2 13 16 25
|
||||
11 2 13 25 22
|
||||
12 3 10 13 22 19
|
||||
13 3 7 6 15 16
|
||||
14 3 6 5 14 15
|
||||
15 3 15 14 23 24
|
||||
16 2 16 15 25
|
||||
16 2 15 24 25
|
||||
17 3 5 2 11 14
|
||||
18 3 3 0 9 12
|
||||
19 3 11 8 17 20
|
||||
20 2 11 20 14
|
||||
20 2 14 20 23
|
||||
21 3 17 18 21 20
|
||||
22 3 18 19 22 21
|
||||
23 2 21 22 25
|
||||
23 2 21 25 24
|
||||
24 3 20 21 24 23
|
||||
|
||||
vertices
|
||||
26
|
||||
3
|
||||
0 -1 -1
|
||||
1 -1 -1
|
||||
-1 0 -1
|
||||
0 0 -1
|
||||
1 0 -1
|
||||
-1 1 -1
|
||||
0 1 -1
|
||||
1 1 -1
|
||||
-1 -1 0
|
||||
0 -1 0
|
||||
1 -1 0
|
||||
-1 0 0
|
||||
0 0 0
|
||||
1 0 0
|
||||
-1 1 0
|
||||
0 1 0
|
||||
1 1 0
|
||||
-1 -1 1
|
||||
0 -1 1
|
||||
1 -1 1
|
||||
-1 0 1
|
||||
0 0 1
|
||||
1 0 1
|
||||
-1 1 1
|
||||
0 1 1
|
||||
1 1 1
|
||||
@@ -0,0 +1,9 @@
|
||||
MFEM INLINE mesh v1.0
|
||||
|
||||
type = wedge
|
||||
nx = 4
|
||||
ny = 4
|
||||
nz = 4
|
||||
sx = 1.0
|
||||
sy = 1.0
|
||||
sz = 1.0
|
||||
@@ -0,0 +1,182 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
#
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
30
|
||||
1 3 0 11 26 14
|
||||
1 3 0 14 27 17
|
||||
1 3 0 17 28 20
|
||||
1 3 0 20 29 23
|
||||
1 3 0 23 30 11
|
||||
1 2 1 26 11
|
||||
1 2 26 1 12
|
||||
1 3 26 12 3 13
|
||||
1 2 2 26 13
|
||||
1 2 26 2 14
|
||||
1 2 2 27 14
|
||||
1 2 27 2 15
|
||||
1 3 27 15 5 16
|
||||
1 2 4 27 16
|
||||
1 2 27 4 17
|
||||
1 2 4 28 17
|
||||
1 2 28 4 18
|
||||
1 3 28 18 7 19
|
||||
1 2 6 28 19
|
||||
1 2 28 6 20
|
||||
1 2 6 29 20
|
||||
1 2 29 6 21
|
||||
1 3 29 21 9 22
|
||||
1 2 8 29 22
|
||||
1 2 29 8 23
|
||||
1 2 8 30 23
|
||||
1 2 30 8 24
|
||||
1 3 30 24 10 25
|
||||
1 2 1 30 25
|
||||
1 2 30 1 11
|
||||
|
||||
boundary
|
||||
20
|
||||
1 1 13 2
|
||||
1 1 12 3
|
||||
1 1 16 4
|
||||
1 1 15 5
|
||||
1 1 19 6
|
||||
1 1 18 7
|
||||
1 1 22 8
|
||||
1 1 21 9
|
||||
1 1 25 1
|
||||
1 1 24 10
|
||||
1 1 3 13
|
||||
1 1 1 12
|
||||
1 1 5 16
|
||||
1 1 2 15
|
||||
1 1 7 19
|
||||
1 1 4 18
|
||||
1 1 9 22
|
||||
1 1 6 21
|
||||
1 1 10 25
|
||||
1 1 8 24
|
||||
|
||||
vertices
|
||||
31
|
||||
|
||||
nodes
|
||||
FiniteElementSpace
|
||||
FiniteElementCollection: H1_2D_P2
|
||||
VDim: 2
|
||||
Ordering: 1
|
||||
|
||||
0.01350768617383 -0.0075500592639684
|
||||
1 0
|
||||
0.309017 0.951057
|
||||
1.30902 0.951057
|
||||
-0.809017 0.587785
|
||||
-0.5 1.53884
|
||||
-0.809017 -0.587785
|
||||
-1.61803 0
|
||||
0.309017 -0.951057
|
||||
-0.5 -1.53884
|
||||
1.30902 -0.951057
|
||||
0.4935497789318 -0.012882964767041
|
||||
1.15451 0.475529
|
||||
0.809019 0.951057
|
||||
0.17136163619581 0.48175756223348
|
||||
-0.0954915 1.24495
|
||||
-0.654508 1.06331
|
||||
-0.41734925397369 0.28726550311701
|
||||
-1.21352 0.293893
|
||||
-1.21352 -0.293892
|
||||
-0.39460365124056 -0.30156877530663
|
||||
-0.654508 -1.06331
|
||||
-0.0954915 -1.24495
|
||||
0.14399901886801 -0.48762042397771
|
||||
0.809019 -0.951057
|
||||
1.15451 -0.475529
|
||||
0.6498356311584 0.48434918539882
|
||||
-0.24288407581812 0.75594729997554
|
||||
-0.8152592767797 0.0028387384025541
|
||||
-0.22754482186326 -0.77540708661379
|
||||
0.672255499984 -0.48174474211839
|
||||
0.22829595615988 0.0021164169942289
|
||||
0.60101450815825 0.21860266792331
|
||||
0.41883194868682 0.47605389684094
|
||||
0.07343165966527 0.21396989328966
|
||||
-0.02571592547416 0.63942139993498
|
||||
-0.32229829912758 0.53827901417123
|
||||
-0.17873676879185 0.14412581843398
|
||||
-0.6182337454462 0.14256917811499
|
||||
-0.59596471744054 -0.16569961862581
|
||||
-0.19439899436461 -0.12390276596268
|
||||
-0.33986575323528 -0.53331120777067
|
||||
-0.064647379830725 -0.60235938684263
|
||||
0.091924539036435 -0.25440885597942
|
||||
0.40469418107844 -0.47549896605132
|
||||
0.59442400974309 -0.23815570080881
|
||||
0.83567929699787 0.25605757828544
|
||||
0.73491944894413 -0.013500778246483
|
||||
1.077255 0.2377645
|
||||
0.88696375569985 0.49133008726061
|
||||
1.231765 0.713293
|
||||
1.0590195 0.951057
|
||||
0.72725653289275 0.73104100472096
|
||||
0.50225974659165 0.6904536152084
|
||||
0.559018 0.951057
|
||||
0.23657516510421 0.69857072686934
|
||||
0.011561493903121 0.87524541641085
|
||||
0.10676275 1.0980035
|
||||
-0.17127243181091 0.99863326833074
|
||||
-0.29774575 1.391895
|
||||
-0.577254 1.301075
|
||||
-0.45323351407757 0.93490604288187
|
||||
-0.55200861955087 0.66792304985565
|
||||
-0.7317625 0.8255475
|
||||
-0.58327877079184 0.4240660861124
|
||||
-0.81465656906104 0.28713104760848
|
||||
-1.0112685 0.440839
|
||||
-0.99771272279525 0.1592736885552
|
||||
-1.415775 0.1469465
|
||||
-1.415775 -0.146946
|
||||
-1.0166887889241 -0.16866723370018
|
||||
-0.80412516287867 -0.29582734656
|
||||
-1.0112685 -0.4408385
|
||||
-0.6073309356422 -0.45826153759998
|
||||
-0.55501395481483 -0.68914767547246
|
||||
-0.7317625 -0.8255475
|
||||
-0.45240617124569 -0.93833106759189
|
||||
-0.577254 -1.301075
|
||||
-0.29774575 -1.391895
|
||||
-0.1923419715726 -1.0285844005569
|
||||
0.031614306262131 -0.83601077226744
|
||||
0.10676275 -1.0980035
|
||||
0.22112358843745 -0.69009711121629
|
||||
0.50046759811715 -0.72837571286759
|
||||
0.559018 -0.951057
|
||||
0.71074483315985 -0.70826931724532
|
||||
1.0590195 -0.951057
|
||||
1.231765 -0.713293
|
||||
0.89135027612826 -0.46226040977064
|
||||
0.84948897506491 -0.23986695857234
|
||||
1.077255 -0.2377645
|
||||
0.31586449185434 0.2462788698702
|
||||
-0.13788918217579 0.40149150514309
|
||||
-0.40416548945856 0.0027692745957735
|
||||
-0.14861804521337 -0.3698676302047
|
||||
0.33007376541085 -0.24598293851351
|
||||
0.99473757603443 0.69214841080247
|
||||
-0.38122249894249 1.1629329119286
|
||||
-1.208195003484 -0.0026998371675556
|
||||
-0.35890854853443 -1.1361244276705
|
||||
0.9901912195942 -0.73640851058427
|
||||
@@ -0,0 +1,201 @@
|
||||
# vtk DataFile Version 3.0
|
||||
Generated by MFEM
|
||||
ASCII
|
||||
DATASET UNSTRUCTURED_GRID
|
||||
POINTS 101 double
|
||||
0.01350768617383 -0.0075500592639684 0
|
||||
1 0 0
|
||||
0.309017 0.951057 0
|
||||
1.30902 0.951057 0
|
||||
-0.809017 0.587785 0
|
||||
-0.5 1.53884 0
|
||||
-0.809017 -0.587785 0
|
||||
-1.61803 0 0
|
||||
0.309017 -0.951057 0
|
||||
-0.5 -1.53884 0
|
||||
1.30902 -0.951057 0
|
||||
0.4935497789318 -0.012882964767041 0
|
||||
1.15451 0.475529 0
|
||||
0.809019 0.951057 0
|
||||
0.17136163619581 0.48175756223348 0
|
||||
-0.0954915 1.24495 0
|
||||
-0.654508 1.06331 0
|
||||
-0.41734925397369 0.28726550311701 0
|
||||
-1.21352 0.293893 0
|
||||
-1.21352 -0.293892 0
|
||||
-0.39460365124056 -0.30156877530663 0
|
||||
-0.654508 -1.06331 0
|
||||
-0.0954915 -1.24495 0
|
||||
0.14399901886801 -0.48762042397771 0
|
||||
0.809019 -0.951057 0
|
||||
1.15451 -0.475529 0
|
||||
0.6498356311584 0.48434918539882 0
|
||||
-0.24288407581812 0.75594729997554 0
|
||||
-0.8152592767797 0.0028387384025541 0
|
||||
-0.22754482186326 -0.77540708661379 0
|
||||
0.672255499984 -0.48174474211839 0
|
||||
0.22829595615988 0.0021164169942289 0
|
||||
0.60101450815825 0.21860266792331 0
|
||||
0.41883194868682 0.47605389684094 0
|
||||
0.07343165966527 0.21396989328966 0
|
||||
-0.02571592547416 0.63942139993498 0
|
||||
-0.32229829912758 0.53827901417123 0
|
||||
-0.17873676879185 0.14412581843398 0
|
||||
-0.6182337454462 0.14256917811499 0
|
||||
-0.59596471744054 -0.16569961862581 0
|
||||
-0.19439899436461 -0.12390276596268 0
|
||||
-0.33986575323528 -0.53331120777067 0
|
||||
-0.064647379830725 -0.60235938684263 0
|
||||
0.091924539036435 -0.25440885597942 0
|
||||
0.40469418107844 -0.47549896605132 0
|
||||
0.59442400974309 -0.23815570080881 0
|
||||
0.83567929699787 0.25605757828544 0
|
||||
0.73491944894413 -0.013500778246483 0
|
||||
1.077255 0.2377645 0
|
||||
0.88696375569985 0.49133008726061 0
|
||||
1.231765 0.713293 0
|
||||
1.0590195 0.951057 0
|
||||
0.72725653289275 0.73104100472096 0
|
||||
0.50225974659165 0.6904536152084 0
|
||||
0.559018 0.951057 0
|
||||
0.23657516510421 0.69857072686934 0
|
||||
0.011561493903121 0.87524541641085 0
|
||||
0.10676275 1.0980035 0
|
||||
-0.17127243181091 0.99863326833074 0
|
||||
-0.29774575 1.391895 0
|
||||
-0.577254 1.301075 0
|
||||
-0.45323351407757 0.93490604288187 0
|
||||
-0.55200861955087 0.66792304985565 0
|
||||
-0.7317625 0.8255475 0
|
||||
-0.58327877079184 0.4240660861124 0
|
||||
-0.81465656906104 0.28713104760848 0
|
||||
-1.0112685 0.440839 0
|
||||
-0.99771272279525 0.1592736885552 0
|
||||
-1.415775 0.1469465 0
|
||||
-1.415775 -0.146946 0
|
||||
-1.0166887889241 -0.16866723370018 0
|
||||
-0.80412516287867 -0.29582734656 0
|
||||
-1.0112685 -0.4408385 0
|
||||
-0.6073309356422 -0.45826153759998 0
|
||||
-0.55501395481483 -0.68914767547246 0
|
||||
-0.7317625 -0.8255475 0
|
||||
-0.45240617124569 -0.93833106759189 0
|
||||
-0.577254 -1.301075 0
|
||||
-0.29774575 -1.391895 0
|
||||
-0.1923419715726 -1.0285844005569 0
|
||||
0.031614306262131 -0.83601077226744 0
|
||||
0.10676275 -1.0980035 0
|
||||
0.22112358843745 -0.69009711121629 0
|
||||
0.50046759811715 -0.72837571286759 0
|
||||
0.559018 -0.951057 0
|
||||
0.71074483315985 -0.70826931724532 0
|
||||
1.0590195 -0.951057 0
|
||||
1.231765 -0.713293 0
|
||||
0.89135027612826 -0.46226040977064 0
|
||||
0.84948897506491 -0.23986695857234 0
|
||||
1.077255 -0.2377645 0
|
||||
0.31586449185434 0.2462788698702 0
|
||||
-0.13788918217579 0.40149150514309 0
|
||||
-0.40416548945856 0.0027692745957735 0
|
||||
-0.14861804521337 -0.3698676302047 0
|
||||
0.33007376541085 -0.24598293851351 0
|
||||
0.99473757603443 0.69214841080247 0
|
||||
-0.38122249894249 1.1629329119286 0
|
||||
-1.208195003484 -0.0026998371675556 0
|
||||
-0.35890854853443 -1.1361244276705 0
|
||||
0.9901912195942 -0.73640851058427 0
|
||||
CELLS 30 240
|
||||
9 0 11 26 14 31 32 33 34 91
|
||||
9 0 14 27 17 34 35 36 37 92
|
||||
9 0 17 28 20 37 38 39 40 93
|
||||
9 0 20 29 23 40 41 42 43 94
|
||||
9 0 23 30 11 43 44 45 31 95
|
||||
6 1 26 11 46 32 47
|
||||
6 26 1 12 46 48 49
|
||||
9 26 12 3 13 49 50 51 52 96
|
||||
6 2 26 13 53 52 54
|
||||
6 26 2 14 53 55 33
|
||||
6 2 27 14 56 35 55
|
||||
6 27 2 15 56 57 58
|
||||
9 27 15 5 16 58 59 60 61 97
|
||||
6 4 27 16 62 61 63
|
||||
6 27 4 17 62 64 36
|
||||
6 4 28 17 65 38 64
|
||||
6 28 4 18 65 66 67
|
||||
9 28 18 7 19 67 68 69 70 98
|
||||
6 6 28 19 71 70 72
|
||||
6 28 6 20 71 73 39
|
||||
6 6 29 20 74 41 73
|
||||
6 29 6 21 74 75 76
|
||||
9 29 21 9 22 76 77 78 79 99
|
||||
6 8 29 22 80 79 81
|
||||
6 29 8 23 80 82 42
|
||||
6 8 30 23 83 44 82
|
||||
6 30 8 24 83 84 85
|
||||
9 30 24 10 25 85 86 87 88 100
|
||||
6 1 30 25 89 88 90
|
||||
6 30 1 11 89 47 45
|
||||
CELL_TYPES 30
|
||||
28
|
||||
28
|
||||
28
|
||||
28
|
||||
28
|
||||
22
|
||||
22
|
||||
28
|
||||
22
|
||||
22
|
||||
22
|
||||
22
|
||||
28
|
||||
22
|
||||
22
|
||||
22
|
||||
22
|
||||
28
|
||||
22
|
||||
22
|
||||
22
|
||||
22
|
||||
28
|
||||
22
|
||||
22
|
||||
22
|
||||
22
|
||||
28
|
||||
22
|
||||
22
|
||||
CELL_DATA 30
|
||||
SCALARS material int
|
||||
LOOKUP_TABLE default
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
1
|
||||
@@ -0,0 +1,107 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
#
|
||||
|
||||
dimension
|
||||
2
|
||||
|
||||
elements
|
||||
30
|
||||
1 3 0 11 26 14
|
||||
1 3 0 14 27 17
|
||||
1 3 0 17 28 20
|
||||
1 3 0 20 29 23
|
||||
1 3 0 23 30 11
|
||||
1 2 11 1 26
|
||||
1 2 1 12 26
|
||||
1 3 26 12 3 13
|
||||
1 2 26 13 2
|
||||
1 2 14 26 2
|
||||
1 2 14 2 27
|
||||
1 2 2 15 27
|
||||
1 3 27 15 5 16
|
||||
1 2 27 16 4
|
||||
1 2 17 27 4
|
||||
1 2 17 4 28
|
||||
1 2 4 18 28
|
||||
1 3 28 18 7 19
|
||||
1 2 28 19 6
|
||||
1 2 20 28 6
|
||||
1 2 20 6 29
|
||||
1 2 6 21 29
|
||||
1 3 29 21 9 22
|
||||
1 2 29 22 8
|
||||
1 2 23 29 8
|
||||
1 2 23 8 30
|
||||
1 2 8 24 30
|
||||
1 3 30 24 10 25
|
||||
1 2 30 25 1
|
||||
1 2 11 30 1
|
||||
|
||||
boundary
|
||||
20
|
||||
1 1 13 2
|
||||
1 1 12 3
|
||||
1 1 16 4
|
||||
1 1 15 5
|
||||
1 1 19 6
|
||||
1 1 18 7
|
||||
1 1 22 8
|
||||
1 1 21 9
|
||||
1 1 25 1
|
||||
1 1 24 10
|
||||
1 1 3 13
|
||||
1 1 1 12
|
||||
1 1 5 16
|
||||
1 1 2 15
|
||||
1 1 7 19
|
||||
1 1 4 18
|
||||
1 1 9 22
|
||||
1 1 6 21
|
||||
1 1 10 25
|
||||
1 1 8 24
|
||||
|
||||
vertices
|
||||
31
|
||||
2
|
||||
0 0
|
||||
1 0
|
||||
0.309017 0.951057
|
||||
1.30902 0.951057
|
||||
-0.809017 0.587785
|
||||
-0.5 1.53884
|
||||
-0.809017 -0.587785
|
||||
-1.61803 0
|
||||
0.309017 -0.951057
|
||||
-0.5 -1.53884
|
||||
1.30902 -0.951057
|
||||
0.5 0
|
||||
1.15451 0.475529
|
||||
0.809019 0.951057
|
||||
0.154508 0.475529
|
||||
-0.0954915 1.24495
|
||||
-0.654508 1.06331
|
||||
-0.404508 0.293893
|
||||
-1.21352 0.293893
|
||||
-1.21352 -0.293892
|
||||
-0.404508 -0.293893
|
||||
-0.654508 -1.06331
|
||||
-0.0954915 -1.24495
|
||||
0.154508 -0.475529
|
||||
0.809019 -0.951057
|
||||
1.15451 -0.475529
|
||||
0.654509 0.475529
|
||||
-0.25 0.769421
|
||||
-0.809016 0
|
||||
-0.25 -0.76942
|
||||
0.654509 -0.475529
|
||||
@@ -0,0 +1,350 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
#
|
||||
|
||||
dimension
|
||||
3
|
||||
|
||||
elements
|
||||
6
|
||||
1 5 0 1 2 3 4 5 6 7
|
||||
1 5 4 5 6 7 8 9 10 11
|
||||
1 5 8 9 10 11 12 13 14 15
|
||||
1 5 12 13 14 15 16 17 18 19
|
||||
1 5 16 17 18 19 20 21 22 23
|
||||
1 5 20 21 22 23 3 0 1 2
|
||||
|
||||
boundary
|
||||
24
|
||||
1 3 0 1 5 4
|
||||
1 3 1 2 6 5
|
||||
1 3 2 3 7 6
|
||||
1 3 3 0 4 7
|
||||
1 3 4 5 9 8
|
||||
1 3 5 6 10 9
|
||||
1 3 6 7 11 10
|
||||
1 3 7 4 8 11
|
||||
1 3 8 9 13 12
|
||||
1 3 9 10 14 13
|
||||
1 3 10 11 15 14
|
||||
1 3 11 8 12 15
|
||||
1 3 12 13 17 16
|
||||
1 3 13 14 18 17
|
||||
1 3 14 15 19 18
|
||||
1 3 15 12 16 19
|
||||
1 3 16 17 21 20
|
||||
1 3 17 18 22 21
|
||||
1 3 18 19 23 22
|
||||
1 3 19 16 20 23
|
||||
1 3 20 21 0 3
|
||||
1 3 21 22 1 0
|
||||
1 3 22 23 2 1
|
||||
1 3 23 20 3 2
|
||||
|
||||
vertices
|
||||
24
|
||||
|
||||
nodes
|
||||
FiniteElementSpace
|
||||
FiniteElementCollection: H1_3D_P3
|
||||
VDim: 3
|
||||
Ordering: 1
|
||||
|
||||
0.71715729 -1.7565288e-16 -0.28284271
|
||||
0.71715729 -1.7565288e-16 0.28284271
|
||||
1.2828427 -3.1420584e-16 0.28284271
|
||||
1.2828427 -3.1420584e-16 -0.28284271
|
||||
0.3 0.51961524 -2.7755576e-17
|
||||
0.5 0.8660254 0.4
|
||||
0.7 1.2124356 2.7755576e-17
|
||||
0.5 0.8660254 -0.4
|
||||
-0.35857864 0.62107643 0.28284271
|
||||
-0.64142136 1.1109744 0.28284271
|
||||
-0.64142136 1.1109744 -0.28284271
|
||||
-0.35857864 0.62107643 -0.28284271
|
||||
-1 1.2246468e-16 0.4
|
||||
-1.4 1.7145055e-16 2.7755576e-17
|
||||
-1 1.2246468e-16 -0.4
|
||||
-0.6 7.3478808e-17 -2.7755576e-17
|
||||
-0.64142136 -1.1109744 0.28284271
|
||||
-0.64142136 -1.1109744 -0.28284271
|
||||
-0.35857864 -0.62107643 -0.28284271
|
||||
-0.35857864 -0.62107643 0.28284271
|
||||
0.7 -1.2124356 8.3266727e-17
|
||||
0.5 -0.8660254 -0.4
|
||||
0.3 -0.51961524 -8.3266727e-17
|
||||
0.5 -0.8660254 0.4
|
||||
0.71715729 -1.7565288e-16 -0.12649111
|
||||
0.71715729 -1.7565288e-16 0.12649111
|
||||
0.87350889 -2.1394797e-16 0.28284271
|
||||
1.1264911 -2.7591075e-16 0.28284271
|
||||
1.2828427 -3.1420584e-16 0.12649111
|
||||
1.2828427 -3.1420584e-16 -0.12649111
|
||||
0.87350889 -2.1394797e-16 -0.28284271
|
||||
1.1264911 -2.7591075e-16 -0.28284271
|
||||
0.35527864 0.61536066 0.11055728
|
||||
0.44472136 0.77027999 0.28944272
|
||||
0.55527864 0.96177082 0.28944272
|
||||
0.64472136 1.1166902 0.11055728
|
||||
0.64472136 1.1166902 -0.11055728
|
||||
0.55527864 0.96177082 -0.28944272
|
||||
0.35527864 0.61536066 -0.11055728
|
||||
0.44472136 0.77027999 -0.28944272
|
||||
0.63530452 0.18919442 -0.21528657
|
||||
0.44264573 0.41882944 -0.086151128
|
||||
0.75207276 0.22396814 0.33712267
|
||||
0.66379961 0.62808427 0.39061232
|
||||
1.2815042 0.38163342 0.21528657
|
||||
1.01011 0.95576166 0.086151128
|
||||
1.1647359 0.3468597 -0.33712267
|
||||
0.78895615 0.74650684 -0.39061232
|
||||
-0.43675445 0.75648089 0.28284271
|
||||
-0.56324555 0.97556992 0.28284271
|
||||
-0.64142136 1.1109744 0.12649111
|
||||
-0.64142136 1.1109744 -0.12649111
|
||||
-0.56324555 0.97556992 -0.28284271
|
||||
-0.43675445 0.75648089 -0.28284271
|
||||
-0.35857864 0.62107643 0.12649111
|
||||
-0.35857864 0.62107643 -0.12649111
|
||||
0.14139407 0.59275717 0.086151128
|
||||
-0.15380509 0.64478706 0.21528657
|
||||
0.25201581 1.0565095 0.39061232
|
||||
-0.28197865 1.1821208 0.33712267
|
||||
0.32265887 1.3526618 -0.086151128
|
||||
-0.31024785 1.3006319 -0.21528657
|
||||
0.21203713 0.88890945 -0.39061232
|
||||
-0.18207429 0.76329818 -0.33712267
|
||||
-1.1105573 1.3600404e-16 0.28944272
|
||||
-1.2894427 1.5791119e-16 0.11055728
|
||||
-1.2894427 1.5791119e-16 -0.11055728
|
||||
-1.1105573 1.3600404e-16 -0.28944272
|
||||
-0.88944272 1.0892532e-16 -0.28944272
|
||||
-0.71055728 8.701817e-17 -0.11055728
|
||||
-0.88944272 1.0892532e-16 0.28944272
|
||||
-0.71055728 8.701817e-17 0.11055728
|
||||
-0.56999848 0.53933005 0.33712267
|
||||
-0.87583673 0.26082519 0.39061232
|
||||
-0.97125633 0.91899846 0.21528657
|
||||
-1.3327689 0.39690011 0.086151128
|
||||
-0.88275728 0.83526106 -0.33712267
|
||||
-1.040972 0.31000265 -0.39061232
|
||||
-0.48149943 0.45559264 -0.21528657
|
||||
-0.5840398 0.17392773 -0.086151128
|
||||
-0.64142136 -1.1109744 0.12649111
|
||||
-0.64142136 -1.1109744 -0.12649111
|
||||
-0.56324555 -0.97556992 -0.28284271
|
||||
-0.43675445 -0.75648089 -0.28284271
|
||||
-0.35857864 -0.62107643 -0.12649111
|
||||
-0.35857864 -0.62107643 0.12649111
|
||||
-0.56324555 -0.97556992 0.28284271
|
||||
-0.43675445 -0.75648089 0.28284271
|
||||
-1.040972 -0.31000265 0.39061232
|
||||
-0.88275728 -0.83526106 0.33712267
|
||||
-1.3327689 -0.39690011 -0.086151128
|
||||
-0.97125633 -0.91899846 -0.21528657
|
||||
-0.87583673 -0.26082519 -0.39061232
|
||||
-0.56999848 -0.53933005 -0.33712267
|
||||
-0.5840398 -0.17392773 0.086151128
|
||||
-0.48149943 -0.45559264 0.21528657
|
||||
0.64472136 -1.1166902 -0.11055728
|
||||
0.55527864 -0.96177082 -0.28944272
|
||||
0.44472136 -0.77027999 -0.28944272
|
||||
0.35527864 -0.61536066 -0.11055728
|
||||
0.35527864 -0.61536066 0.11055728
|
||||
0.44472136 -0.77027999 0.28944272
|
||||
0.64472136 -1.1166902 0.11055728
|
||||
0.55527864 -0.96177082 0.28944272
|
||||
-0.31024785 -1.3006319 0.21528657
|
||||
0.32265887 -1.3526618 0.086151128
|
||||
-0.28197865 -1.1821208 -0.33712267
|
||||
0.25201581 -1.0565095 -0.39061232
|
||||
-0.15380509 -0.64478706 -0.21528657
|
||||
0.14139407 -0.59275717 -0.086151128
|
||||
-0.18207429 -0.76329818 0.33712267
|
||||
0.21203713 -0.88890945 0.39061232
|
||||
1.2815042 -0.38163342 -0.21528657
|
||||
1.01011 -0.95576166 -0.086151128
|
||||
0.75207276 -0.22396814 -0.33712267
|
||||
0.66379961 -0.62808427 -0.39061232
|
||||
0.63530452 -0.18919442 0.21528657
|
||||
0.44264573 -0.41882944 0.086151128
|
||||
1.1647359 -0.3468597 0.33712267
|
||||
0.78895615 -0.74650684 0.39061232
|
||||
1.1264911 -2.7591075e-16 -0.12649111
|
||||
1.1264911 -2.7591075e-16 0.12649111
|
||||
0.87350889 -2.1394797e-16 -0.12649111
|
||||
0.87350889 -9.8977972e-16 0.12649111
|
||||
0.66757847 0.19880564 -0.062604414
|
||||
0.71979881 0.21435692 0.18444051
|
||||
0.50377116 0.47666605 0.045623048
|
||||
0.60267418 0.57024766 0.25883814
|
||||
0.89840401 0.26754575 0.303448
|
||||
1.1351729 0.33805581 0.24896124
|
||||
0.75951745 0.71865207 0.30646131
|
||||
0.91439218 0.86519386 0.17030213
|
||||
1.2492302 0.3720222 0.062604414
|
||||
1.1970099 0.35647092 -0.18444051
|
||||
0.9489846 0.89792505 -0.045623048
|
||||
0.85008158 0.80434345 -0.25883814
|
||||
1.0184047 0.30328209 -0.303448
|
||||
0.78163576 0.23277203 -0.24896124
|
||||
0.69323831 0.65593903 -0.30646131
|
||||
0.53836358 0.50939725 -0.17030213
|
||||
0.41055728 0.71110607 -1.3877788e-17
|
||||
0.5 0.8660254 0.17888544
|
||||
0.5 0.8660254 -0.17888544
|
||||
0.58944272 1.0209447 1.3877788e-17
|
||||
0.17196917 0.72093516 0.17030213
|
||||
0.22144071 0.9283315 0.30646131
|
||||
-0.18923139 0.79330244 0.24896124
|
||||
-0.24655235 1.0336054 0.303448
|
||||
0.27154107 1.138364 0.25883814
|
||||
0.30313361 1.2708073 0.045623048
|
||||
-0.28979207 1.2148764 0.18444051
|
||||
-0.30243444 1.2678762 -0.062604414
|
||||
0.29208377 1.2244838 -0.17030213
|
||||
0.24261222 1.0170874 -0.30646131
|
||||
-0.27482155 1.1521165 -0.24896124
|
||||
-0.21750059 0.91181357 -0.303448
|
||||
0.19251187 0.80705498 -0.25883814
|
||||
0.16091933 0.67461165 -0.045623048
|
||||
-0.17426087 0.73054252 -0.18444051
|
||||
-0.1616185 0.67754273 0.062604414
|
||||
-0.43675445 0.75648089 0.12649111
|
||||
-0.56324555 0.97556992 0.12649111
|
||||
-0.43675445 0.75648089 -0.12649111
|
||||
-0.56324555 0.97556992 -0.12649111
|
||||
-0.68090342 0.64426782 0.303448
|
||||
-0.86035138 0.81406069 0.24896124
|
||||
-1.0021297 0.29843537 0.30646131
|
||||
-1.2064759 0.35928993 0.17030213
|
||||
-0.94679579 0.89585401 0.062604414
|
||||
-0.90721782 0.85840551 -0.18444051
|
||||
-1.2521182 0.37288224 -0.045623048
|
||||
-1.1216227 0.33402052 -0.25883814
|
||||
-0.77185234 0.73032329 -0.303448
|
||||
-0.59240437 0.56053041 -0.24896124
|
||||
-0.91467902 0.27239247 -0.30646131
|
||||
-0.71033275 0.21153791 -0.17030213
|
||||
-0.50595997 0.47873709 -0.062604414
|
||||
-0.54553794 0.5161856 0.18444051
|
||||
-0.66469049 0.19794559 0.045623048
|
||||
-0.79518604 0.23680732 0.25883814
|
||||
-1 1.2246468e-16 0.17888544
|
||||
-1.1788854 1.4437183e-16 1.3877788e-17
|
||||
-0.82111456 1.0055753e-16 -1.3877788e-17
|
||||
-1 5.6655389e-16 -0.17888544
|
||||
-1.1216227 -0.33402052 0.25883814
|
||||
-1.2521182 -0.37288224 0.045623048
|
||||
-0.90721782 -0.85840551 0.18444051
|
||||
-0.94679579 -0.89585401 -0.062604414
|
||||
-1.2064759 -0.35928993 -0.17030213
|
||||
-1.0021297 -0.29843537 -0.30646131
|
||||
-0.86035138 -0.81406069 -0.24896124
|
||||
-0.68090342 -0.64426782 -0.303448
|
||||
-0.79518604 -0.23680732 -0.25883814
|
||||
-0.66469049 -0.19794559 -0.045623048
|
||||
-0.54553794 -0.5161856 -0.18444051
|
||||
-0.50595997 -0.47873709 0.062604414
|
||||
-0.71033275 -0.21153791 0.17030213
|
||||
-0.91467902 -0.27239247 0.30646131
|
||||
-0.59240437 -0.56053041 0.24896124
|
||||
-0.77185234 -0.73032329 0.303448
|
||||
-0.56324555 -0.97556992 0.12649111
|
||||
-0.56324555 -0.97556992 -0.12649111
|
||||
-0.43675445 -0.75648089 0.12649111
|
||||
-0.43675445 -0.75648089 -0.12649111
|
||||
-0.30243444 -1.2678762 0.062604414
|
||||
-0.28979207 -1.2148764 -0.18444051
|
||||
0.30313361 -1.2708073 -0.045623048
|
||||
0.27154107 -1.138364 -0.25883814
|
||||
-0.24655235 -1.0336054 -0.303448
|
||||
-0.18923139 -0.79330244 -0.24896124
|
||||
0.22144071 -0.9283315 -0.30646131
|
||||
0.17196917 -0.72093516 -0.17030213
|
||||
-0.1616185 -0.67754273 -0.062604414
|
||||
-0.17426087 -0.73054252 0.18444051
|
||||
0.16091933 -0.67461165 0.045623048
|
||||
0.19251187 -0.80705498 0.25883814
|
||||
-0.21750059 -0.91181357 0.303448
|
||||
-0.27482155 -1.1521165 0.24896124
|
||||
0.24261222 -1.0170874 0.30646131
|
||||
0.29208377 -1.2244838 0.17030213
|
||||
0.58944272 -1.0209447 2.7755576e-17
|
||||
0.5 -0.8660254 -0.17888544
|
||||
0.5 -0.8660254 0.17888544
|
||||
0.41055728 -0.71110607 -2.7755576e-17
|
||||
0.91439218 -0.86519386 -0.17030213
|
||||
0.75951745 -0.71865207 -0.30646131
|
||||
1.1351729 -0.33805581 -0.24896124
|
||||
0.89840401 -0.26754575 -0.303448
|
||||
0.60267418 -0.57024766 -0.25883814
|
||||
0.50377116 -0.47666605 -0.045623048
|
||||
0.71979881 -0.21435692 -0.18444051
|
||||
0.66757847 -0.19880564 0.062604414
|
||||
0.53836358 -0.50939725 0.17030213
|
||||
0.69323831 -0.65593903 0.30646131
|
||||
0.78163576 -0.23277203 0.24896124
|
||||
1.0184047 -0.30328209 0.303448
|
||||
0.85008158 -0.80434345 0.25883814
|
||||
0.9489846 -0.89792505 0.045623048
|
||||
1.1970099 -0.35647092 0.18444051
|
||||
1.2492302 -0.3720222 -0.062604414
|
||||
0.81390971 0.24238325 -0.096279082
|
||||
0.86613006 0.25793453 0.15076584
|
||||
1.0506786 0.31289331 -0.15076584
|
||||
1.102899 0.32844459 0.096279082
|
||||
0.59948901 0.56723386 -0.038527956
|
||||
0.69839202 0.66081546 0.17468714
|
||||
0.75436373 0.71377565 -0.17468714
|
||||
0.85326675 0.80735725 0.038527956
|
||||
0.19149443 0.80278964 0.038527956
|
||||
0.24096597 1.010186 0.17468714
|
||||
0.22308696 0.93523296 -0.17468714
|
||||
0.27255851 1.1426293 -0.038527956
|
||||
-0.1970448 0.82605811 0.096279082
|
||||
-0.25436576 1.066361 0.15076584
|
||||
-0.20968717 0.8790579 -0.15076584
|
||||
-0.26700813 1.1193608 -0.096279082
|
||||
-0.65644288 0.62112337 0.15076584
|
||||
-0.83589085 0.79091624 0.096279082
|
||||
-0.61686491 0.58367486 -0.096279082
|
||||
-0.79631287 0.75346774 -0.15076584
|
||||
-0.92147899 0.2744175 0.17468714
|
||||
-1.1258253 0.33527206 0.038527956
|
||||
-0.79098343 0.23555578 -0.038527956
|
||||
-0.99532971 0.29641033 -0.17468714
|
||||
-0.99532971 -0.29641033 0.17468714
|
||||
-1.1258253 -0.33527206 -0.038527956
|
||||
-0.79098343 -0.23555578 0.038527956
|
||||
-0.92147899 -0.2744175 -0.17468714
|
||||
-0.79631287 -0.75346774 0.15076584
|
||||
-0.83589085 -0.79091624 -0.096279082
|
||||
-0.61686491 -0.58367486 0.096279082
|
||||
-0.65644288 -0.62112337 -0.15076584
|
||||
-0.26700813 -1.1193608 0.096279082
|
||||
-0.25436576 -1.066361 -0.15076584
|
||||
-0.20968717 -0.8790579 0.15076584
|
||||
-0.1970448 -0.82605811 -0.096279082
|
||||
0.27255851 -1.1426293 0.038527956
|
||||
0.24096597 -1.010186 -0.17468714
|
||||
0.22308696 -0.93523296 0.17468714
|
||||
0.19149443 -0.80278964 -0.038527956
|
||||
0.85326675 -0.80735725 -0.038527956
|
||||
0.69839202 -0.66081546 -0.17468714
|
||||
0.75436373 -0.71377565 0.17468714
|
||||
0.59948901 -0.56723386 0.038527956
|
||||
1.102899 -0.32844459 -0.096279082
|
||||
0.86613006 -0.25793453 -0.15076584
|
||||
1.0506786 -0.31289331 0.15076584
|
||||
0.81390971 -0.24238325 0.096279082
|
||||
@@ -0,0 +1,236 @@
|
||||
MFEM mesh v1.0
|
||||
|
||||
#
|
||||
# MFEM Geometry Types (see mesh/geom.hpp):
|
||||
#
|
||||
# POINT = 0
|
||||
# SEGMENT = 1
|
||||
# TRIANGLE = 2
|
||||
# SQUARE = 3
|
||||
# TETRAHEDRON = 4
|
||||
# CUBE = 5
|
||||
# PRISM = 6
|
||||
#
|
||||
|
||||
dimension
|
||||
3
|
||||
|
||||
elements
|
||||
6
|
||||
1 6 0 1 2 3 4 5
|
||||
1 6 3 4 5 6 7 8
|
||||
1 6 6 7 8 9 10 11
|
||||
1 6 9 10 11 12 13 14
|
||||
1 6 12 13 14 15 16 17
|
||||
1 6 15 16 17 0 1 2
|
||||
|
||||
boundary
|
||||
18
|
||||
1 3 0 1 4 3
|
||||
1 3 1 2 5 4
|
||||
1 3 2 0 3 5
|
||||
1 3 3 4 7 6
|
||||
1 3 4 5 8 7
|
||||
1 3 5 3 6 8
|
||||
1 3 6 7 10 9
|
||||
1 3 7 8 11 10
|
||||
1 3 8 6 9 11
|
||||
1 3 9 10 13 12
|
||||
1 3 10 11 14 13
|
||||
1 3 11 9 12 14
|
||||
1 3 12 13 16 15
|
||||
1 3 13 14 17 16
|
||||
1 3 14 12 15 17
|
||||
1 3 15 16 1 0
|
||||
1 3 16 17 2 1
|
||||
1 3 17 15 0 2
|
||||
|
||||
vertices
|
||||
18
|
||||
|
||||
nodes
|
||||
FiniteElementSpace
|
||||
FiniteElementCollection: H1_3D_P3
|
||||
VDim: 3
|
||||
Ordering: 1
|
||||
|
||||
0.6 -1.4695762e-16 -9.7971744e-17
|
||||
1.2 -2.9391523e-16 0.34641016
|
||||
1.2 -1.3597293e-15 -0.34641016
|
||||
0.4 0.69282032 0.34641016
|
||||
0.7 1.2124356 2.7755576e-17
|
||||
0.4 0.69282032 -0.34641016
|
||||
-0.6 1.0392305 0.34641016
|
||||
-0.6 1.0392305 -0.34641016
|
||||
-0.3 0.51961524 -3.8651415e-16
|
||||
-1.4 1.7145055e-16 4.8985872e-17
|
||||
-0.8 9.7971744e-17 -0.34641016
|
||||
-0.8 4.5324311e-16 0.34641016
|
||||
-0.6 -1.0392305 -0.34641016
|
||||
-0.3 -0.51961524 -2.220446e-16
|
||||
-0.6 -1.0392305 0.34641016
|
||||
0.4 -0.69282032 -0.34641016
|
||||
0.4 -0.69282032 0.34641016
|
||||
0.7 -1.2124356 7.7509221e-16
|
||||
0.76583592 -8.6777464e-16 0.095745414
|
||||
1.0341641 2.5022695e-15 0.25066475
|
||||
1.2 -1.3597293e-15 0.15491933
|
||||
1.2 -2.9391523e-16 -0.15491933
|
||||
0.76583592 4.9262324e-16 -0.095745414
|
||||
1.0341641 3.4207917e-15 -0.25066475
|
||||
0.48291796 0.83643844 0.25066475
|
||||
0.61708204 1.0688174 0.095745414
|
||||
0.61708204 1.0688174 -0.095745414
|
||||
0.48291796 0.83643844 -0.25066475
|
||||
0.4 0.69282032 0.15491933
|
||||
0.4 0.69282032 -0.15491933
|
||||
0.59098879 0.17599714 0.11416557
|
||||
0.51532795 0.48760104 0.27491822
|
||||
1.2368698 0.36834126 0.27491822
|
||||
1.0048434 0.95077837 0.11416557
|
||||
1.0473544 0.31190335 -0.38908379
|
||||
0.65896232 0.62350725 -0.38908379
|
||||
-0.6 1.0392305 0.15491933
|
||||
-0.6 1.0392305 -0.15491933
|
||||
-0.51708204 0.89561236 -0.25066475
|
||||
-0.38291796 0.66323336 -0.095745414
|
||||
-0.51708204 0.89561236 0.25066475
|
||||
-0.38291796 0.66323336 0.095745414
|
||||
0.21049196 0.88243173 0.38908379
|
||||
-0.25356098 1.0629872 0.38908379
|
||||
0.32097654 1.3456091 -0.11416557
|
||||
-0.29944203 1.2553313 -0.27491822
|
||||
0.16461091 0.69008761 -0.27491822
|
||||
-0.1430764 0.59980988 -0.11416557
|
||||
-1.2341641 6.9922046e-16 -0.095745414
|
||||
-0.96583592 -1.1684711e-15 -0.25066475
|
||||
-0.8 4.5324311e-16 -0.15491933
|
||||
-0.8 9.7971744e-17 0.15491933
|
||||
-1.2341641 -3.9693744e-16 0.095745414
|
||||
-0.96583592 -1.5973885e-15 0.25066475
|
||||
-0.93742781 0.88699007 0.27491822
|
||||
-1.3258199 0.3948307 0.11416557
|
||||
-0.79379344 0.75108386 -0.38908379
|
||||
-0.86945428 0.25892449 -0.38908379
|
||||
-0.44791239 0.42381273 0.11416557
|
||||
-0.67993886 0.20248658 0.27491822
|
||||
-0.51708204 -0.89561236 -0.25066475
|
||||
-0.38291796 -0.66323336 -0.095745414
|
||||
-0.38291796 -0.66323336 0.095745414
|
||||
-0.51708204 -0.89561236 0.25066475
|
||||
-0.6 -1.0392305 -0.15491933
|
||||
-0.6 -1.0392305 0.15491933
|
||||
-1.3258199 -0.3948307 -0.11416557
|
||||
-0.93742781 -0.88699007 -0.27491822
|
||||
-0.67993886 -0.20248658 -0.27491822
|
||||
-0.44791239 -0.42381273 -0.11416557
|
||||
-0.86945428 -0.25892449 0.38908379
|
||||
-0.79379344 -0.75108386 0.38908379
|
||||
0.4 -0.69282032 -0.15491933
|
||||
0.4 -0.69282032 0.15491933
|
||||
0.48291796 -0.83643844 0.25066475
|
||||
0.61708204 -1.0688174 0.095745414
|
||||
0.48291796 -0.83643844 -0.25066475
|
||||
0.61708204 -1.0688174 -0.095745414
|
||||
-0.25356098 -1.0629872 -0.38908379
|
||||
0.21049196 -0.88243173 -0.38908379
|
||||
-0.1430764 -0.59980988 0.11416557
|
||||
0.16461091 -0.69008761 0.27491822
|
||||
-0.29944203 -1.2553313 0.27491822
|
||||
0.32097654 -1.3456091 0.11416557
|
||||
0.59098879 -0.17599714 -0.11416557
|
||||
0.51532795 -0.48760104 -0.27491822
|
||||
1.0473544 -0.31190335 0.38908379
|
||||
0.65896232 -0.62350725 0.38908379
|
||||
1.2368698 -0.36834126 -0.27491822
|
||||
1.0048434 -0.95077837 -0.11416557
|
||||
1 2.4196059e-15 -1.3788671e-16
|
||||
0.5 0.8660254 -8.6542076e-17
|
||||
0.76950592 0.22915975 0.15859651
|
||||
1.0583527 0.31517866 0.23048728
|
||||
0.65062668 0.6156201 0.23048728
|
||||
0.86954463 0.8227593 0.15859651
|
||||
1.1844891 0.35274221 0.091392579
|
||||
1.0997352 0.32750241 -0.20555815
|
||||
0.9092442 0.86032286 -0.024929133
|
||||
0.75456149 0.71396276 -0.24998909
|
||||
0.92121806 0.2743398 -0.24998909
|
||||
0.71712515 0.2135607 -0.024929133
|
||||
0.61926276 0.5859437 -0.20555815
|
||||
0.55502751 0.52516459 0.091392579
|
||||
-0.5 0.8660254 5.1344633e-17
|
||||
0.24102914 1.0104508 0.24998909
|
||||
0.29043935 1.21759 0.024929133
|
||||
-0.26624219 1.1161498 0.20555815
|
||||
-0.28676082 1.2021687 -0.091392579
|
||||
0.27775814 1.1644274 -0.15859651
|
||||
0.20782931 0.87126929 -0.23048728
|
||||
-0.25622363 1.0741497 -0.23048728
|
||||
-0.1862948 0.78099155 -0.15859651
|
||||
0.17729212 0.74325022 -0.091392579
|
||||
0.19781075 0.82926913 0.20555815
|
||||
-0.17361359 0.72782894 0.024929133
|
||||
-0.22302379 0.93496814 0.24998909
|
||||
-1 -1.2098029e-15 1.3788671e-16
|
||||
-0.89772824 0.84942651 0.091392579
|
||||
-0.833493 0.78864741 -0.20555815
|
||||
-1.1996835 0.35726714 -0.024929133
|
||||
-0.99559063 0.29648804 -0.24998909
|
||||
-0.69819427 0.66062834 -0.24998909
|
||||
-0.54351156 0.51426825 -0.024929133
|
||||
-0.8170735 0.24332543 -0.20555815
|
||||
-0.73231963 0.21808563 0.091392579
|
||||
-0.58321113 0.5518318 0.15859651
|
||||
-0.80212907 0.758971 0.23048728
|
||||
-0.85845599 0.25564918 0.23048728
|
||||
-1.1473028 0.34166809 0.15859651
|
||||
-0.5 -0.8660254 8.6542076e-17
|
||||
-1.1473028 -0.34166809 -0.15859651
|
||||
-0.85845599 -0.25564918 -0.23048728
|
||||
-0.80212907 -0.758971 -0.23048728
|
||||
-0.58321113 -0.5518318 -0.15859651
|
||||
-0.73231963 -0.21808563 -0.091392579
|
||||
-0.8170735 -0.24332543 0.20555815
|
||||
-0.54351156 -0.51426825 0.024929133
|
||||
-0.69819427 -0.66062834 0.24998909
|
||||
-0.99559063 -0.29648804 0.24998909
|
||||
-1.1996835 -0.35726714 0.024929133
|
||||
-0.833493 -0.78864741 0.20555815
|
||||
-0.89772824 -0.84942651 -0.091392579
|
||||
0.5 -0.8660254 -5.1344633e-17
|
||||
-0.22302379 -0.93496814 -0.24998909
|
||||
-0.17361359 -0.72782894 -0.024929133
|
||||
0.19781075 -0.82926913 -0.20555815
|
||||
0.17729212 -0.74325022 0.091392579
|
||||
-0.1862948 -0.78099155 0.15859651
|
||||
-0.25622363 -1.0741497 0.23048728
|
||||
0.20782931 -0.87126929 0.23048728
|
||||
0.27775814 -1.1644274 0.15859651
|
||||
-0.28676082 -1.2021687 0.091392579
|
||||
-0.26624219 -1.1161498 -0.20555815
|
||||
0.29043935 -1.21759 -0.024929133
|
||||
0.24102914 -1.0104508 -0.24998909
|
||||
0.55502751 -0.52516459 -0.091392579
|
||||
0.61926276 -0.5859437 0.20555815
|
||||
0.71712515 -0.2135607 0.024929133
|
||||
0.92121806 -0.2743398 0.24998909
|
||||
0.75456149 -0.71396276 0.24998909
|
||||
0.9092442 -0.86032286 0.024929133
|
||||
1.0997352 -0.32750241 0.20555815
|
||||
1.1844891 -0.35274221 -0.091392579
|
||||
0.86954463 -0.8227593 -0.15859651
|
||||
0.65062668 -0.6156201 -0.23048728
|
||||
1.0583527 -0.31517866 -0.23048728
|
||||
0.76950592 -0.22915975 -0.15859651
|
||||
0.95840435 0.28541392 -1.3795119e-16
|
||||
0.72637788 0.68729555 -1.1412456e-16
|
||||
0.23202647 0.97270947 -5.1760042e-17
|
||||
-0.23202647 0.97270947 1.2226691e-17
|
||||
-0.72637788 0.68729555 8.6191148e-17
|
||||
-0.95840435 0.28541392 1.2635125e-16
|
||||
-0.95840435 -0.28541392 1.3795119e-16
|
||||
-0.72637788 -0.68729555 1.1412456e-16
|
||||
-0.23202647 -0.97270947 5.1760042e-17
|
||||
0.23202647 -0.97270947 -1.2226691e-17
|
||||
0.72637788 -0.68729555 -8.6191148e-17
|
||||
0.95840435 -0.28541392 -1.2635125e-16
|
||||
@@ -71,6 +71,10 @@ namespace mfem {
|
||||
* - <a class="el" href="ex18p_8cpp_source.html">Example 18p</a>: parallel Discontinuous Galerkin (DG) for the Euler equations
|
||||
* - <a class="el" href="ex19_8cpp_source.html">Example 19</a>: incompressible nonlinear elasticity
|
||||
* - <a class="el" href="ex19p_8cpp_source.html">Example 19p</a>: parallel incompressible nonlinear elasticity
|
||||
* - <a class="el" href="ex20_8cpp_source.html">Example 20</a>: symplectic ODE integration
|
||||
* - <a class="el" href="ex20p_8cpp_source.html">Example 20p</a>: parallel symplectic ODE integration
|
||||
* - <a class="el" href="ex22_8cpp_source.html">Example 22</a>: adaptive mesh refinement for linear elasticity
|
||||
* - <a class="el" href="ex22p_8cpp_source.html">Example 22p</a>: parallel adaptive mesh refinement for linear elasticity
|
||||
*
|
||||
* <H4>SUNDIALS Examples</H4>
|
||||
* - Variants of Examples
|
||||
@@ -112,7 +116,9 @@ namespace mfem {
|
||||
* - <a class="el" href="joule_8cpp_source.html">Joule</a>: transient magnetics and Joule heating miniapp
|
||||
* - <a class="el" href="mobius-strip_8cpp_source.html">Mobius Strip</a>: generate various Mobius strip-like meshes
|
||||
* - <a class="el" href="klein-bottle_8cpp_source.html">Klein Bottle</a>: generate three types of Klein bottle surfaces
|
||||
* - <a class="el" href="toroid_8cpp_source.html">Toroid</a>: generate simple toroidal meshes
|
||||
* - <a class="el" href="shaper_8cpp_source.html">Shaper</a>: resolve material interfaces by mesh refinement
|
||||
* - <a class="el" href="extruder_8cpp_source.html">Extruder</a>: extrude a low-dimensional mesh into a higher dimension
|
||||
* - <a class="el" href="mesh-explorer_8cpp_source.html">Mesh Explorer</a>: visualize and manipulate meshes
|
||||
* - <a class="el" href="mesh-optimizer_8cpp_source.html">Mesh Optimizer</a>: optimize high-order meshes, <a class="el" href="mesh-optimizer_8cpp_source.html">serial</a> and <a class="el" href="pmesh-optimizer_8cpp_source.html">parallel</a> versions
|
||||
* - <a class="el" href="display-basis_8cpp_source.html">Display Basis</a>: visualize finite element basis functions
|
||||
|
||||
@@ -26,6 +26,8 @@ list(APPEND ALL_EXE_SRCS
|
||||
ex17.cpp
|
||||
ex18.cpp
|
||||
ex19.cpp
|
||||
ex20.cpp
|
||||
ex22.cpp
|
||||
)
|
||||
|
||||
if (MFEM_USE_MPI)
|
||||
@@ -49,6 +51,8 @@ if (MFEM_USE_MPI)
|
||||
ex17p.cpp
|
||||
ex18p.cpp
|
||||
ex19p.cpp
|
||||
ex20p.cpp
|
||||
ex22p.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -75,7 +79,7 @@ foreach(SRC_FILE ${ALL_EXE_SRCS})
|
||||
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
|
||||
else()
|
||||
add_test(NAME ${TEST_NAME}_np=4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
|
||||
${MPIEXEC_PREFLAGS}
|
||||
$<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS}
|
||||
${MPIEXEC_POSTFLAGS})
|
||||
|
||||
@@ -4,13 +4,18 @@
|
||||
//
|
||||
// Sample runs: ex1 -m ../data/square-disc.mesh
|
||||
// ex1 -m ../data/star.mesh
|
||||
// ex1 -m ../data/star-mixed.mesh
|
||||
// ex1 -m ../data/escher.mesh
|
||||
// ex1 -m ../data/fichera.mesh
|
||||
// ex1 -m ../data/fichera-mixed.mesh
|
||||
// ex1 -m ../data/toroid-wedge.mesh
|
||||
// ex1 -m ../data/square-disc-p2.vtk -o 2
|
||||
// ex1 -m ../data/square-disc-p3.mesh -o 3
|
||||
// ex1 -m ../data/square-disc-nurbs.mesh -o -1
|
||||
// ex1 -m ../data/star-mixed-p2.mesh -o 2
|
||||
// ex1 -m ../data/disc-nurbs.mesh -o -1
|
||||
// ex1 -m ../data/pipe-nurbs.mesh -o -1
|
||||
// ex1 -m ../data/fichera-mixed-p2.mesh -o 2
|
||||
// ex1 -m ../data/star-surf.mesh
|
||||
// ex1 -m ../data/square-disc-surf.mesh
|
||||
// ex1 -m ../data/inline-segment.mesh
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// ex10 -m ../data/beam-tri.mesh -s 3 -r 2 -o 2 -dt 3
|
||||
// ex10 -m ../data/beam-hex.mesh -s 2 -r 1 -o 2 -dt 3
|
||||
// ex10 -m ../data/beam-tet.mesh -s 2 -r 1 -o 2 -dt 3
|
||||
// ex10 -m ../data/beam-wedge.mesh -s 2 -r 1 -o 2 -dt 3
|
||||
// ex10 -m ../data/beam-quad.mesh -s 14 -r 2 -o 2 -dt 0.03 -vs 20
|
||||
// ex10 -m ../data/beam-hex.mesh -s 14 -r 1 -o 2 -dt 0.05 -vs 20
|
||||
// ex10 -m ../data/beam-quad-amr.mesh -s 3 -r 2 -o 2 -dt 3
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// mpirun -np 4 ex10p -m ../data/beam-tri.mesh -s 3 -rs 2 -dt 3
|
||||
// mpirun -np 4 ex10p -m ../data/beam-hex.mesh -s 2 -rs 1 -dt 3
|
||||
// mpirun -np 4 ex10p -m ../data/beam-tet.mesh -s 2 -rs 1 -dt 3
|
||||
// mpirun -np 4 ex10p -m ../data/beam-wedge.mesh -s 2 -rs 1 -dt 3
|
||||
// mpirun -np 4 ex10p -m ../data/beam-quad.mesh -s 14 -rs 2 -dt 0.03 -vs 20
|
||||
// mpirun -np 4 ex10p -m ../data/beam-hex.mesh -s 14 -rs 1 -dt 0.05 -vs 20
|
||||
// mpirun -np 4 ex10p -m ../data/beam-quad-amr.mesh -s 3 -rs 2 -dt 3
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex11p -m ../data/square-disc.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/star.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/star-mixed.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/escher.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/fichera.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/fichera-mixed.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/toroid-wedge.mesh -o 2
|
||||
// mpirun -np 4 ex11p -m ../data/square-disc-p2.vtk -o 2
|
||||
// mpirun -np 4 ex11p -m ../data/square-disc-p3.mesh -o 3
|
||||
// mpirun -np 4 ex11p -m ../data/square-disc-nurbs.mesh -o -1
|
||||
@@ -15,6 +18,11 @@
|
||||
// mpirun -np 4 ex11p -m ../data/star-surf.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/square-disc-surf.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/inline-segment.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/inline-quad.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/inline-tri.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/inline-hex.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/inline-tet.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/inline-wedge.mesh -s 83
|
||||
// mpirun -np 4 ex11p -m ../data/amr-quad.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/amr-hex.mesh
|
||||
// mpirun -np 4 ex11p -m ../data/mobius-strip.mesh -n 8
|
||||
|
||||
+3
-2
@@ -5,9 +5,10 @@
|
||||
// Sample runs:
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -n 10 -o 2 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -s 79 -n 10 -o 2 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-hex.mesh -s 3876
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh -o 2 -sys
|
||||
// mpirun -np 4 ex12p -m ../data/beam-wedge.mesh -s 79
|
||||
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh -s 3876 -o 2 -sys
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh -s 4526 -n 6 -o 3 -elast
|
||||
// mpirun -np 4 ex12p -m ../data/beam-quad-nurbs.mesh
|
||||
// mpirun -np 4 ex12p -m ../data/beam-hex-nurbs.mesh
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
//
|
||||
// Sample runs: ex14 -m ../data/inline-quad.mesh -o 0
|
||||
// ex14 -m ../data/star.mesh -r 4 -o 2
|
||||
// ex14 -m ../data/star-mixed.mesh -r 4 -o 2
|
||||
// ex14 -m ../data/escher.mesh -s 1
|
||||
// ex14 -m ../data/fichera.mesh -s 1 -k 1
|
||||
// ex14 -m ../data/fichera-mixed.mesh -s 1 -k 1
|
||||
// ex14 -m ../data/square-disc-p2.vtk -r 3 -o 2
|
||||
// ex14 -m ../data/square-disc-p3.mesh -r 2 -o 3
|
||||
// ex14 -m ../data/square-disc-nurbs.mesh -o 1
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex14p -m ../data/inline-quad.mesh -o 0
|
||||
// mpirun -np 4 ex14p -m ../data/star.mesh -o 2
|
||||
// mpirun -np 4 ex14p -m ../data/star-mixed.mesh -o 2
|
||||
// mpirun -np 4 ex14p -m ../data/escher.mesh -s 1
|
||||
// mpirun -np 4 ex14p -m ../data/fichera.mesh -s 1 -k 1
|
||||
// mpirun -np 4 ex14p -m ../data/fichera-mixed.mesh -s 1 -k 1
|
||||
// mpirun -np 4 ex14p -m ../data/square-disc-p2.vtk -o 2
|
||||
// mpirun -np 4 ex14p -m ../data/square-disc-p3.mesh -o 3
|
||||
// mpirun -np 4 ex14p -m ../data/square-disc-nurbs.mesh -o 1
|
||||
|
||||
@@ -135,6 +135,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
// Make sure tet-only meshes are marked for local refinement.
|
||||
mesh.Finalize(true);
|
||||
|
||||
// 4. All boundary attributes will be used for essential (Dirichlet) BC.
|
||||
MFEM_VERIFY(mesh.bdr_attributes.Size() > 0,
|
||||
|
||||
@@ -151,6 +151,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
}
|
||||
// Make sure tet-only meshes are marked for local refinement.
|
||||
mesh->Finalize(true);
|
||||
|
||||
// 5. Define a parallel mesh by partitioning the serial mesh. Once the
|
||||
// parallel mesh is defined, the serial mesh can be deleted.
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// ex16 -s 3 -a 0.5 -k 0.5 -o 4
|
||||
// ex16 -s 14 -dt 1.0e-4 -tf 4.0e-2 -vs 40
|
||||
// ex16 -m ../data/fichera-q2.mesh
|
||||
// ex16 -m ../data/fichera-mixed.mesh
|
||||
// ex16 -m ../data/escher.mesh
|
||||
// ex16 -m ../data/beam-tet.mesh -tf 10 -dt 0.1
|
||||
// ex16 -m ../data/amr-quad.mesh -o 4 -r 0
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// mpirun -np 8 ex16p -s 3 -a 0.5 -k 0.5 -o 4
|
||||
// mpirun -np 4 ex16p -s 14 -dt 1.0e-4 -tf 4.0e-2 -vs 40
|
||||
// mpirun -np 16 ex16p -m ../data/fichera-q2.mesh
|
||||
// mpirun -np 16 ex16p -m ../data/fichera-mixed.mesh
|
||||
// mpirun -np 16 ex16p -m ../data/escher-p2.mesh
|
||||
// mpirun -np 8 ex16p -m ../data/beam-tet.mesh -tf 10 -dt 0.1
|
||||
// mpirun -np 4 ex16p -m ../data/amr-quad.mesh -o 4 -rs 0 -rp 0
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// ex17 -m ../data/beam-quad.mesh
|
||||
// ex17 -m ../data/beam-tet.mesh
|
||||
// ex17 -m ../data/beam-hex.mesh
|
||||
// ex17 -m ../data/beam-wedge.mesh
|
||||
// ex17 -m ../data/beam-quad.mesh -r 2 -o 3
|
||||
// ex17 -m ../data/beam-quad.mesh -r 2 -o 2 -a 1 -k 1
|
||||
// ex17 -m ../data/beam-hex.mesh -r 2 -o 2
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
// mpirun -np 4 ex17p -m ../data/beam-quad.mesh
|
||||
// mpirun -np 4 ex17p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 4 ex17p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 4 ex17p -m ../data/beam-wedge.mesh
|
||||
// mpirun -np 4 ex17p -m ../data/beam-quad.mesh -rs 2 -rp 2 -o 3 -elast
|
||||
// mpirun -np 4 ex17p -m ../data/beam-quad.mesh -rs 2 -rp 3 -o 2 -a 1 -k 1
|
||||
// mpirun -np 4 ex17p -m ../data/beam-hex.mesh -rs 2 -rp 1 -o 2
|
||||
|
||||
+1
-2
@@ -509,8 +509,7 @@ bool StateIsPhysical(const Vector &state, const int dim)
|
||||
// Initial condition
|
||||
void InitialCondition(const Vector &x, Vector &y)
|
||||
{
|
||||
const int dim = x.Size();
|
||||
MFEM_ASSERT(dim == 2, "");
|
||||
MFEM_ASSERT(x.Size() == 2, "");
|
||||
|
||||
double radius = 0, Minf = 0, beta = 0;
|
||||
if (problem == 1)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// ex19 -m ../data/beam-tri.mesh
|
||||
// ex19 -m ../data/beam-hex.mesh
|
||||
// ex19 -m ../data/beam-tet.mesh
|
||||
// ex19 -m ../data/beam-wedge.mesh
|
||||
//
|
||||
// Description: This examples solves a quasi-static incompressible nonlinear
|
||||
// elasticity problem of the form 0 = H(x), where H is an
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// mpirun -np 2 ex19p -m ../data/beam-tri.mesh
|
||||
// mpirun -np 2 ex19p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 2 ex19p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 2 ex19p -m ../data/beam-wedge.mesh
|
||||
//
|
||||
// Description: This examples solves a quasi-static incompressible nonlinear
|
||||
// elasticity problem of the form 0 = H(x), where H is an
|
||||
|
||||
@@ -4,14 +4,19 @@
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex1p -m ../data/square-disc.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/star.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/star-mixed.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/escher.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/fichera.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/fichera-mixed.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/toroid-wedge.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/square-disc-p2.vtk -o 2
|
||||
// mpirun -np 4 ex1p -m ../data/square-disc-p3.mesh -o 3
|
||||
// mpirun -np 4 ex1p -m ../data/square-disc-nurbs.mesh -o -1
|
||||
// mpirun -np 4 ex1p -m ../data/star-mixed-p2.mesh -o 2
|
||||
// mpirun -np 4 ex1p -m ../data/disc-nurbs.mesh -o -1
|
||||
// mpirun -np 4 ex1p -m ../data/pipe-nurbs.mesh -o -1
|
||||
// mpirun -np 4 ex1p -m ../data/ball-nurbs.mesh -o 2
|
||||
// mpirun -np 4 ex1p -m ../data/fichera-mixed-p2.mesh -o 2
|
||||
// mpirun -np 4 ex1p -m ../data/star-surf.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/square-disc-surf.mesh
|
||||
// mpirun -np 4 ex1p -m ../data/inline-segment.mesh
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
// ex2 -m ../data/beam-quad.mesh
|
||||
// ex2 -m ../data/beam-tet.mesh
|
||||
// ex2 -m ../data/beam-hex.mesh
|
||||
// ex2 -m ../data/beam-wedge.mesh
|
||||
// ex2 -m ../data/beam-quad.mesh -o 3 -sc
|
||||
// ex2 -m ../data/beam-quad-nurbs.mesh
|
||||
// ex2 -m ../data/beam-hex-nurbs.mesh
|
||||
|
||||
@@ -0,0 +1,298 @@
|
||||
// MFEM Example 20
|
||||
//
|
||||
// Compile with: make ex20
|
||||
//
|
||||
// Sample runs: ex20
|
||||
//
|
||||
// Description: This example demonstrates the use of the variable order,
|
||||
// symplectic ODE integration algorithm. Symplectic integration
|
||||
// algorithms are designed to conserve energy when integrating, in
|
||||
// time, systems of ODEs which are derived from Hamiltonian
|
||||
// systems.
|
||||
//
|
||||
// Hamiltonian systems define the energy of a system as a function
|
||||
// of time (t), a set of generalized coordinates (q), and their
|
||||
// corresponding generalized momenta (p).
|
||||
//
|
||||
// H(q,p,t) = T(p) + V(q,t)
|
||||
//
|
||||
// Hamilton's equations then specify how q and p evolve in time:
|
||||
//
|
||||
// dq/dt = dH/dp
|
||||
// dp/dt = -dH/dq
|
||||
//
|
||||
// To use the symplectic integration classes we need to define an
|
||||
// mfem::Operator P which evaluates the action of dH/dp, and an
|
||||
// mfem::TimeDependentOperator F which computes -dH/dq.
|
||||
//
|
||||
// This example offers five simple 1D Hamiltonians:
|
||||
// 0) Simple Harmonic Oscillator (mass on a spring)
|
||||
// H = ( p^2 / m + q^2 / k ) / 2
|
||||
// 1) Pendulum
|
||||
// H = ( p^2 / m - k ( 1 - cos(q) ) ) / 2
|
||||
// 2) Gaussian Potential Well
|
||||
// H = ( p^2 / m ) / 2 - k exp(-q^2 / 2)
|
||||
// 3) Quartic Potential
|
||||
// H = ( p^2 / m + k ( 1 + q^2 ) q^2 ) / 2
|
||||
// 4) Negative Quartic Potential
|
||||
// H = ( p^2 / m + k ( 1 - q^2 /8 ) q^2 ) / 2
|
||||
//
|
||||
// In all cases these Hamiltonians are shifted by constant values
|
||||
// so that the energy will remain positive. The mean and standard
|
||||
// deviation of the computed energies at each time step are
|
||||
// displayed upon completion.
|
||||
//
|
||||
// We then use GLVis to visualize the results in a non-standard way
|
||||
// by defining the axes to be q, p, and t rather than x, y, and z.
|
||||
// In this space we build a ribbon-like mesh with nodes at (0,0,t)
|
||||
// and (q,p,t). Finally we plot the energy as a function of time
|
||||
// as a scalar field on this ribbon-like mesh.
|
||||
//
|
||||
// For a more traditional plot of the results, including q, p, and
|
||||
// H, can be obtained by selecting the "-gp" option. This creates
|
||||
// a data file and input deck for the GnuPlot application (not
|
||||
// included with MFEM). To visualize these results on most Linux
|
||||
// systems type the command "gnuplot gnuplot_ex20.inp". The data
|
||||
// file, named "ex20.dat", should be simple enough to display with
|
||||
// other plotting programs as well.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
// Constants used in the Hamiltonian
|
||||
static int prob_ = 0;
|
||||
static double m_ = 1.0;
|
||||
static double k_ = 1.0;
|
||||
|
||||
// Hamiltonian functional, see below for implementation
|
||||
double hamiltonian(double q, double p, double t);
|
||||
|
||||
class GradT : public Operator
|
||||
{
|
||||
public:
|
||||
GradT() : Operator(1) {}
|
||||
void Mult(const Vector &x, Vector &y) const { y.Set(1.0/m_, x); }
|
||||
};
|
||||
|
||||
class NegGradV : public TimeDependentOperator
|
||||
{
|
||||
public:
|
||||
NegGradV() : TimeDependentOperator(1) {}
|
||||
void Mult(const Vector &x, Vector &y) const;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Parse command-line options.
|
||||
int order = 1;
|
||||
int nsteps = 100;
|
||||
double dt = 0.1;
|
||||
bool visualization = true;
|
||||
bool gnuplot = false;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Time integration order.");
|
||||
args.AddOption(&prob_, "-p", "--problem-type",
|
||||
"Problem Type:\n"
|
||||
"\t 0 - Simple Harmonic Oscillator\n"
|
||||
"\t 1 - Pendulum\n"
|
||||
"\t 2 - Gaussian Potential Well\n"
|
||||
"\t 3 - Quartic Potential\n"
|
||||
"\t 4 - Negative Quartic Potential");
|
||||
args.AddOption(&nsteps, "-n", "--number-of-steps",
|
||||
"Number of time steps.");
|
||||
args.AddOption(&dt, "-dt", "--time-step",
|
||||
"Time step size.");
|
||||
args.AddOption(&m_, "-m", "--mass",
|
||||
"Mass.");
|
||||
args.AddOption(&k_, "-k", "--spring-const",
|
||||
"Spring constant.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&gnuplot, "-gp", "--gnuplot", "-no-gp", "--no-gnuplot",
|
||||
"Enable or disable GnuPlot visualization.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
return 1;
|
||||
}
|
||||
args.PrintOptions(cout);
|
||||
|
||||
// 2. Create and Initialize the Symplectic Integration Solver
|
||||
SIAVSolver siaSolver(order);
|
||||
GradT P;
|
||||
NegGradV F;
|
||||
siaSolver.Init(P,F);
|
||||
|
||||
// 3. Set the initial conditions
|
||||
double t = 0.0;
|
||||
Vector q(1), p(1);
|
||||
Vector e(nsteps+1);
|
||||
q(0) = 0.0;
|
||||
p(0) = 1.0;
|
||||
|
||||
// 4. Prepare GnuPlot output file if needed
|
||||
ofstream ofs;
|
||||
if (gnuplot)
|
||||
{
|
||||
ofs.open("ex20.dat");
|
||||
ofs << t << "\t" << q(0) << "\t" << p(0) << endl;
|
||||
}
|
||||
|
||||
// 5. Create a Mesh for visualization in phase space
|
||||
int nverts = (visualization) ? 2*(nsteps+1) : 0;
|
||||
int nelems = (visualization) ? nsteps : 0;
|
||||
Mesh mesh(2, nverts, nelems, 0, 3);
|
||||
|
||||
int v[4];
|
||||
Vector x0(3); x0 = 0.0;
|
||||
Vector x1(3); x1 = 0.0;
|
||||
|
||||
// 6. Perform time-stepping
|
||||
double e_mean = 0.0;
|
||||
|
||||
for (int i = 0; i < nsteps; i++)
|
||||
{
|
||||
// 6a. Record initial state
|
||||
if (i == 0)
|
||||
{
|
||||
e[0] = hamiltonian(q(0),p(0),t);
|
||||
e_mean += e[0];
|
||||
|
||||
if (visualization)
|
||||
{
|
||||
x1[0] = q(0);
|
||||
x1[1] = p(0);
|
||||
x1[2] = 0.0;
|
||||
mesh.AddVertex(x0);
|
||||
mesh.AddVertex(x1);
|
||||
}
|
||||
}
|
||||
|
||||
// 6b. Advance the state of the system
|
||||
siaSolver.Step(q,p,t,dt);
|
||||
e[i+1] = hamiltonian(q(0),p(0),t);
|
||||
e_mean += e[i+1];
|
||||
|
||||
// 6c. Record the state of the system
|
||||
if (gnuplot)
|
||||
{
|
||||
ofs << t << "\t" << q(0) << "\t" << p(0) << "\t" << e[i+1] << endl;
|
||||
}
|
||||
|
||||
// 6d. Add results to GLVis visualization
|
||||
if (visualization)
|
||||
{
|
||||
x0[2] = t;
|
||||
x1[0] = q(0);
|
||||
x1[1] = p(0);
|
||||
x1[2] = t;
|
||||
mesh.AddVertex(x0);
|
||||
mesh.AddVertex(x1);
|
||||
v[0] = 2*i;
|
||||
v[1] = 2*(i+1);
|
||||
v[2] = 2*(i+1)+1;
|
||||
v[3] = 2*i+1;
|
||||
mesh.AddQuad(v);
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Compute and display mean and standard deviation of the energy
|
||||
e_mean /= (nsteps + 1);
|
||||
double e_var = 0.0;
|
||||
for (int i=0; i<=nsteps; i++)
|
||||
{
|
||||
e_var += pow(e[i] - e_mean, 2);
|
||||
}
|
||||
e_var /= (nsteps + 1);
|
||||
double e_sd = sqrt(e_var);
|
||||
cout << endl << "Mean and standard deviation of the energy" << endl;
|
||||
cout << e_mean << "\t" << e_sd << endl;
|
||||
|
||||
// 8. Finalize the GnuPlot output
|
||||
if (gnuplot)
|
||||
{
|
||||
ofs.close();
|
||||
|
||||
ofs.open("gnuplot_ex20.inp");
|
||||
ofs << "plot 'ex20.dat' using 1:2 w l t 'q', "
|
||||
<< "'ex20.dat' using 1:3 w l t 'p', "
|
||||
<< "'ex20.dat' using 1:4 w l t 'H'" << endl;
|
||||
ofs.close();
|
||||
}
|
||||
|
||||
// 9. Finalize the GLVis output
|
||||
if (visualization)
|
||||
{
|
||||
H1_FECollection fec(order = 1, 2);
|
||||
FiniteElementSpace fespace(&mesh, &fec);
|
||||
GridFunction energy(&fespace);
|
||||
energy = 0.0;
|
||||
for (int i = 0; i <= nsteps; i++)
|
||||
{
|
||||
energy[2*i+0] = e[i];
|
||||
energy[2*i+1] = e[i];
|
||||
}
|
||||
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sock(vishost, visport);
|
||||
sock.precision(8);
|
||||
sock << "solution\n" << mesh << energy
|
||||
<< "window_title 'Energy in Phase Space'\n"
|
||||
<< "keys\n maac\n" << "axis_labels 'q' 'p' 't'\n"<< flush;
|
||||
}
|
||||
}
|
||||
|
||||
double hamiltonian(double q, double p, double t)
|
||||
{
|
||||
double h = 1.0 - 0.5 / m_ + 0.5 * p * p / m_;
|
||||
switch (prob_)
|
||||
{
|
||||
case 1:
|
||||
h += k_ * (1.0 - cos(q));
|
||||
break;
|
||||
case 2:
|
||||
h += k_ * (1.0 - exp(-0.5 * q * q));
|
||||
break;
|
||||
case 3:
|
||||
h += 0.5 * k_ * (1.0 + q * q) * q * q;
|
||||
break;
|
||||
case 4:
|
||||
h += 0.5 * k_ * (1.0 - 0.125 * q * q) * q * q;
|
||||
break;
|
||||
default:
|
||||
h += 0.5 * k_ * q * q;
|
||||
break;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
void NegGradV::Mult(const Vector &x, Vector &y) const
|
||||
{
|
||||
switch (prob_)
|
||||
{
|
||||
case 1:
|
||||
y(0) = - k_* sin(x(0));
|
||||
break;
|
||||
case 2:
|
||||
y(0) = - k_ * x(0) * exp(-0.5 * x(0) * x(0));
|
||||
break;
|
||||
case 3:
|
||||
y(0) = - k_ * (1.0 + 2.0 * x(0) * x(0)) * x(0);
|
||||
break;
|
||||
case 4:
|
||||
y(0) = - k_ * (1.0 - 0.25 * x(0) * x(0)) * x(0);
|
||||
break;
|
||||
default:
|
||||
y(0) = - k_ * x(0);
|
||||
break;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
// MFEM Example 20 - Parallel Version
|
||||
//
|
||||
// Compile with: make ex20p
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex20p
|
||||
//
|
||||
// Description: This example demonstrates the use of the variable order,
|
||||
// symplectic ODE integration algorithm. Symplectic integration
|
||||
// algorithms are designed to conserve energy when integrating, in
|
||||
// time, systems of ODEs which are derived from Hamiltonian
|
||||
// systems.
|
||||
//
|
||||
// Hamiltonian systems define the energy of a system as a function
|
||||
// of time (t), a set of generalized coordinates (q), and their
|
||||
// corresponding generalized momenta (p).
|
||||
//
|
||||
// H(q,p,t) = T(p) + V(q,t)
|
||||
//
|
||||
// Hamilton's equations then specify how q and p evolve in time:
|
||||
//
|
||||
// dq/dt = dH/dp
|
||||
// dp/dt = -dH/dq
|
||||
//
|
||||
// To use the symplectic integration classes we need to define an
|
||||
// mfem::Operator P which evaluates the action of dH/dp, and an
|
||||
// mfem::TimeDependentOperator F which computes -dH/dq.
|
||||
//
|
||||
// This example offers five simple 1D Hamiltonians:
|
||||
// 0) Simple Harmonic Oscillator (mass on a spring)
|
||||
// H = ( p^2 / m + q^2 / k ) / 2
|
||||
// 1) Pendulum
|
||||
// H = ( p^2 / m - k ( 1 - cos(q) ) ) / 2
|
||||
// 2) Gaussian Potential Well
|
||||
// H = ( p^2 / m ) / 2 - k exp(-q^2 / 2)
|
||||
// 3) Quartic Potential
|
||||
// H = ( p^2 / m + k ( 1 + q^2 ) q^2 ) / 2
|
||||
// 4) Negative Quartic Potential
|
||||
// H = ( p^2 / m + k ( 1 - q^2 /8 ) q^2 ) / 2
|
||||
//
|
||||
// In all cases these Hamiltonians are shifted by constant values
|
||||
// so that the energy will remain positive. The mean and standard
|
||||
// deviation of the computed energies at each time step are
|
||||
// displayed upon completion. When run in parallel the same
|
||||
// Hamiltonian system is evolved on each processor but starting
|
||||
// from different initial conditions.
|
||||
//
|
||||
// We then use GLVis to visualize the results in a non-standard way
|
||||
// by defining the axes to be q, p, and t rather than x, y, and z.
|
||||
// In this space we build a ribbon-like mesh on each processor with
|
||||
// nodes at (0,0,t) and (q,p,t). When these ribbons are bonded
|
||||
// together on the t-axis they resemble a Rotini pasta. Finally we
|
||||
// plot the energy as a function of time as a scalar field on this
|
||||
// Rotini-like mesh.
|
||||
//
|
||||
// For a more traditional plot of the results, including q, p, and
|
||||
// H from each processor, can be obtained by selecting the "-gp"
|
||||
// option. This creates a collection of data files and an input
|
||||
// deck for the GnuPlot application (not included with MFEM). To
|
||||
// visualize these results on most linux systems type the command
|
||||
// "gnuplot gnuplot_ex20p.inp". The data files, named
|
||||
// "ex20p_?????.dat", should be simple enough to display with other
|
||||
// plotting programs as well.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
// Constants used in the Hamiltonian
|
||||
static int prob_ = 0;
|
||||
static double m_ = 1.0;
|
||||
static double k_ = 1.0;
|
||||
|
||||
// Hamiltonian functional, see below for implementation
|
||||
double hamiltonian(double q, double p, double t);
|
||||
|
||||
class GradT : public Operator
|
||||
{
|
||||
public:
|
||||
GradT() : Operator(1) {}
|
||||
void Mult(const Vector &x, Vector &y) const { y.Set(1.0/m_, x); }
|
||||
};
|
||||
|
||||
class NegGradV : public TimeDependentOperator
|
||||
{
|
||||
public:
|
||||
NegGradV() : TimeDependentOperator(1) {}
|
||||
void Mult(const Vector &x, Vector &y) const;
|
||||
};
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Initialize MPI.
|
||||
int num_procs, myid;
|
||||
MPI_Comm comm = MPI_COMM_WORLD;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(comm, &num_procs);
|
||||
MPI_Comm_rank(comm, &myid);
|
||||
|
||||
// 2. Parse command-line options.
|
||||
int order = 1;
|
||||
int nsteps = 100;
|
||||
double dt = 0.1;
|
||||
bool visualization = true;
|
||||
bool gnuplot = false;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Time integration order.");
|
||||
args.AddOption(&prob_, "-p", "--problem-type",
|
||||
"Problem Type:\n"
|
||||
"\t 0 - Simple Harmonic Oscillator\n"
|
||||
"\t 1 - Pendulum\n"
|
||||
"\t 2 - Gaussian Potential Well\n"
|
||||
"\t 3 - Quartic Potential\n"
|
||||
"\t 4 - Negative Quartic Potential");
|
||||
args.AddOption(&nsteps, "-n", "--number-of-steps",
|
||||
"Number of time steps.");
|
||||
args.AddOption(&dt, "-dt", "--time-step",
|
||||
"Time step size.");
|
||||
args.AddOption(&m_, "-m", "--mass",
|
||||
"Mass.");
|
||||
args.AddOption(&k_, "-k", "--spring-const",
|
||||
"Spring constant.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(&gnuplot, "-gp", "--gnuplot", "-no-gp", "--no-gnuplot",
|
||||
"Enable or disable GnuPlot visualization.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
// 3. Create and Initialize the Symplectic Integration Solver
|
||||
SIAVSolver siaSolver(order);
|
||||
GradT P;
|
||||
NegGradV F;
|
||||
siaSolver.Init(P,F);
|
||||
|
||||
// 4. Set the initial conditions
|
||||
double t = 0.0;
|
||||
Vector q(1), p(1);
|
||||
Vector e(nsteps+1);
|
||||
q(0) = sin(2.0*M_PI*(double)myid/num_procs);
|
||||
p(0) = cos(2.0*M_PI*(double)myid/num_procs);
|
||||
|
||||
// 5. Prepare GnuPlot output file if needed
|
||||
ostringstream oss;
|
||||
ofstream ofs;
|
||||
if (gnuplot)
|
||||
{
|
||||
oss << "ex20p_" << setfill('0') << setw(5) << myid << ".dat";
|
||||
ofs.open(oss.str().c_str());
|
||||
ofs << t << "\t" << q(0) << "\t" << p(0) << endl;
|
||||
}
|
||||
|
||||
// 6. Create a Mesh for visualization in phase space
|
||||
int nverts = (visualization) ? (num_procs+1)*(nsteps+1) : 0;
|
||||
int nelems = (visualization) ? (nsteps * num_procs) : 0;
|
||||
Mesh mesh(2, nverts, nelems, 0, 3);
|
||||
|
||||
int *part = (visualization) ? (new int[nelems]) : NULL;
|
||||
int v[4];
|
||||
Vector x0(3); x0 = 0.0;
|
||||
Vector x1(3); x1 = 0.0;
|
||||
|
||||
// 7. Perform time-stepping
|
||||
double e_mean = 0.0;
|
||||
|
||||
for (int i = 0; i < nsteps; i++)
|
||||
{
|
||||
// 7a. Record initial state
|
||||
if (i == 0)
|
||||
{
|
||||
e[0] = hamiltonian(q(0),p(0),t);
|
||||
e_mean += e[0];
|
||||
|
||||
if (visualization)
|
||||
{
|
||||
mesh.AddVertex(x0);
|
||||
for (int j = 0; j < num_procs; j++)
|
||||
{
|
||||
x1[0] = q(0);
|
||||
x1[1] = p(0);
|
||||
x1[2] = 0.0;
|
||||
mesh.AddVertex(x1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 7b. Advance the state of the system
|
||||
siaSolver.Step(q,p,t,dt);
|
||||
e[i+1] = hamiltonian(q(0),p(0),t);
|
||||
e_mean += e[i+1];
|
||||
|
||||
// 7c. Record the state of the system
|
||||
if (gnuplot)
|
||||
{
|
||||
ofs << t << "\t" << q(0) << "\t" << p(0) << "\t" << e[i+1] << endl;
|
||||
}
|
||||
|
||||
// 7d. Add results to GLVis visualization
|
||||
if (visualization)
|
||||
{
|
||||
x0[2] = t;
|
||||
mesh.AddVertex(x0);
|
||||
for (int j = 0; j < num_procs; j++)
|
||||
{
|
||||
x1[0] = q(0);
|
||||
x1[1] = p(0);
|
||||
x1[2] = t;
|
||||
mesh.AddVertex(x1);
|
||||
v[0] = (num_procs + 1) * i;
|
||||
v[1] = (num_procs + 1) * (i + 1);
|
||||
v[2] = (num_procs + 1) * (i + 1) + j + 1;
|
||||
v[3] = (num_procs + 1) * i + j + 1;
|
||||
mesh.AddQuad(v);
|
||||
part[num_procs * i + j] = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Compute and display mean and standard deviation of the energy
|
||||
e_mean /= (nsteps + 1);
|
||||
double e_var = 0.0;
|
||||
for (int i = 0; i <= nsteps; i++)
|
||||
{
|
||||
e_var += pow(e[i] - e_mean, 2);
|
||||
}
|
||||
e_var /= (nsteps + 1);
|
||||
double e_sd = sqrt(e_var);
|
||||
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << endl << "Mean and standard deviation of the energy" << endl;
|
||||
}
|
||||
for (int i = 0; i < num_procs; i++)
|
||||
{
|
||||
if (myid == i)
|
||||
{
|
||||
cout << myid << ": " << e_mean << "\t" << e_sd << endl;
|
||||
}
|
||||
MPI_Barrier(comm);
|
||||
}
|
||||
|
||||
// 9. Finalize the GnuPlot output
|
||||
if (gnuplot)
|
||||
{
|
||||
ofs.close();
|
||||
if (myid == 0)
|
||||
{
|
||||
ofs.open("gnuplot_ex20p.inp");
|
||||
for (int i = 0; i < num_procs; i++)
|
||||
{
|
||||
ostringstream ossi;
|
||||
ossi << "ex20p_" << setfill('0') << setw(5) << i << ".dat";
|
||||
if (i == 0)
|
||||
{
|
||||
ofs << "plot";
|
||||
}
|
||||
ofs << " '" << ossi.str() << "' using 1:2 w l t 'q" << i << "',"
|
||||
<< " '" << ossi.str() << "' using 1:3 w l t 'p" << i << "',"
|
||||
<< " '" << ossi.str() << "' using 1:4 w l t 'H" << i << "'";
|
||||
if (i < num_procs-1)
|
||||
{
|
||||
ofs << ",";
|
||||
}
|
||||
else
|
||||
{
|
||||
ofs << ";" << endl;
|
||||
}
|
||||
}
|
||||
ofs.close();
|
||||
}
|
||||
}
|
||||
|
||||
// 10. Finalize the GLVis output
|
||||
if (visualization)
|
||||
{
|
||||
mesh.FinalizeQuadMesh(1);
|
||||
ParMesh pmesh(comm, mesh, part);
|
||||
delete [] part;
|
||||
|
||||
H1_FECollection fec(order = 1, 2);
|
||||
ParFiniteElementSpace fespace(&pmesh, &fec);
|
||||
ParGridFunction energy(&fespace);
|
||||
energy = 0.0;
|
||||
for (int i = 0; i <= nsteps; i++)
|
||||
{
|
||||
energy[2*i+0] = e[i];
|
||||
energy[2*i+1] = e[i];
|
||||
}
|
||||
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sock(vishost, visport);
|
||||
sock.precision(8);
|
||||
sock << "parallel " << num_procs << " " << myid << "\n"
|
||||
<< "solution\n" << pmesh << energy
|
||||
<< "window_title 'Energy in Phase Space'\n"
|
||||
<< "keys\n maac\n" << "axis_labels 'q' 'p' 't'\n"<< flush;
|
||||
}
|
||||
|
||||
MPI_Finalize();
|
||||
}
|
||||
|
||||
double hamiltonian(double q, double p, double t)
|
||||
{
|
||||
double h = 1.0 - 0.5 / m_ + 0.5 * p * p / m_;
|
||||
switch (prob_)
|
||||
{
|
||||
case 1:
|
||||
h += k_ * (1.0 - cos(q));
|
||||
break;
|
||||
case 2:
|
||||
h += k_ * (1.0 - exp(-0.5 * q * q));
|
||||
break;
|
||||
case 3:
|
||||
h += 0.5 * k_ * (1.0 + q * q) * q * q;
|
||||
break;
|
||||
case 4:
|
||||
h += 0.5 * k_ * (1.0 - 0.125 * q * q) * q * q;
|
||||
break;
|
||||
default:
|
||||
h += 0.5 * k_ * q * q;
|
||||
break;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
void NegGradV::Mult(const Vector &x, Vector &y) const
|
||||
{
|
||||
switch (prob_)
|
||||
{
|
||||
case 1:
|
||||
y(0) = - k_* sin(x(0));
|
||||
break;
|
||||
case 2:
|
||||
y(0) = - k_ * x(0) * exp(-0.5 * x(0) * x(0));
|
||||
break;
|
||||
case 3:
|
||||
y(0) = - k_ * (1.0 + 2.0 * x(0) * x(0)) * x(0);
|
||||
break;
|
||||
case 4:
|
||||
y(0) = - k_ * (1.0 - 0.25 * x(0) * x(0)) * x(0);
|
||||
break;
|
||||
default:
|
||||
y(0) = - k_ * x(0);
|
||||
break;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,310 @@
|
||||
// MFEM Example 22
|
||||
//
|
||||
// Compile with: make ex22
|
||||
//
|
||||
// Sample runs: ex22
|
||||
// ex22 -o 3
|
||||
// ex22 -m ../data/beam-quad.mesh
|
||||
// ex22 -m ../data/beam-quad.mesh -o 3
|
||||
// ex22 -m ../data/beam-quad.mesh -o 3 -f 1
|
||||
// ex22 -m ../data/beam-tet.mesh
|
||||
// ex22 -m ../data/beam-tet.mesh -o 2
|
||||
// ex22 -m ../data/beam-hex.mesh
|
||||
// ex22 -m ../data/beam-hex.mesh -o 2
|
||||
//
|
||||
// Description: This is a version of Example 2 with a simple adaptive mesh
|
||||
// refinement loop. The problem being solved is again the linear
|
||||
// elasticity describing a multi-material cantilever beam.
|
||||
// The problem is solved on a sequence of meshes which
|
||||
// are locally refined in a conforming (triangles, tetrahedrons)
|
||||
// or non-conforming (quadrilaterals, hexahedra) manner according
|
||||
// to a simple ZZ error estimator.
|
||||
//
|
||||
// The example demonstrates MFEM's capability to work with both
|
||||
// conforming and nonconforming refinements, in 2D and 3D, on
|
||||
// linear and curved meshes. Interpolation of functions from
|
||||
// coarse to fine meshes, as well as persistent GLVis
|
||||
// visualization are also illustrated.
|
||||
//
|
||||
// We recommend viewing Examples 2 and 6 before viewing this
|
||||
// example.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 1. Parse command-line options.
|
||||
const char *mesh_file = "../data/beam-tri.mesh";
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
int flux_averaging = 0;
|
||||
bool visualization = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree).");
|
||||
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&flux_averaging, "-f", "--flux-averaging",
|
||||
"Flux averaging: 0 - global, 1 - by mesh attribute.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
return 1;
|
||||
}
|
||||
args.PrintOptions(cout);
|
||||
|
||||
// 2. Read the mesh from the given mesh file. We can handle triangular,
|
||||
// quadrilateral, tetrahedral, and hexahedral meshes with the same code.
|
||||
Mesh mesh(mesh_file, 1, 1);
|
||||
int dim = mesh.Dimension();
|
||||
MFEM_VERIFY(mesh.SpaceDimension() == dim, "invalid mesh");
|
||||
|
||||
if (mesh.attributes.Max() < 2 || mesh.bdr_attributes.Max() < 2)
|
||||
{
|
||||
cerr << "\nInput mesh should have at least two materials and "
|
||||
<< "two boundary attributes! (See schematic in ex2.cpp)\n"
|
||||
<< endl;
|
||||
return 3;
|
||||
}
|
||||
|
||||
// 3. Since a NURBS mesh can currently only be refined uniformly, we need to
|
||||
// convert it to a piecewise-polynomial curved mesh. First we refine the
|
||||
// NURBS mesh a bit more and then project the curvature to quadratic Nodes.
|
||||
if (mesh.NURBSext)
|
||||
{
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
mesh.SetCurvature(2);
|
||||
}
|
||||
|
||||
// 4. Define a finite element space on the mesh. The polynomial order is
|
||||
// one (linear) by default, but this can be changed on the command line.
|
||||
H1_FECollection fec(order, dim);
|
||||
FiniteElementSpace fespace(&mesh, &fec, dim);
|
||||
|
||||
// 5. As in Example 2, we set up the linear form b(.) which corresponds to
|
||||
// the right-hand side of the FEM linear system. In this case, b_i equals
|
||||
// the boundary integral of f*phi_i where f represents a "pull down"
|
||||
// force on the Neumann part of the boundary and phi_i are the basis
|
||||
// functions in the finite element fespace. The force is defined by the
|
||||
// VectorArrayCoefficient object f, which is a vector of Coefficient
|
||||
// objects. The fact that f is non-zero on boundary attribute 2 is
|
||||
// indicated by the use of piece-wise constants coefficient for its last
|
||||
// component. We don't assemble the discrete problem yet, this will be
|
||||
// done in the main loop.
|
||||
VectorArrayCoefficient f(dim);
|
||||
for (int i = 0; i < dim-1; i++)
|
||||
{
|
||||
f.Set(i, new ConstantCoefficient(0.0));
|
||||
}
|
||||
{
|
||||
Vector pull_force(mesh.bdr_attributes.Max());
|
||||
pull_force = 0.0;
|
||||
pull_force(1) = -1.0e-2;
|
||||
f.Set(dim-1, new PWConstCoefficient(pull_force));
|
||||
}
|
||||
|
||||
LinearForm b(&fespace);
|
||||
b.AddDomainIntegrator(new VectorBoundaryLFIntegrator(f));
|
||||
|
||||
// 6. Set up the bilinear form a(.,.) on the finite element space
|
||||
// corresponding to the linear elasticity integrator with piece-wise
|
||||
// constants coefficient lambda and mu.
|
||||
Vector lambda(mesh.attributes.Max());
|
||||
lambda = 1.0;
|
||||
lambda(0) = lambda(1)*50;
|
||||
PWConstCoefficient lambda_func(lambda);
|
||||
Vector mu(mesh.attributes.Max());
|
||||
mu = 1.0;
|
||||
mu(0) = mu(1)*50;
|
||||
PWConstCoefficient mu_func(mu);
|
||||
|
||||
BilinearForm a(&fespace);
|
||||
BilinearFormIntegrator *integ =
|
||||
new ElasticityIntegrator(lambda_func,mu_func);
|
||||
a.AddDomainIntegrator(integ);
|
||||
if (static_cond) { a.EnableStaticCondensation(); }
|
||||
|
||||
// 7. The solution vector x and the associated finite element grid function
|
||||
// will be maintained over the AMR iterations. We initialize it to zero.
|
||||
Vector zero_vec(dim);
|
||||
zero_vec = 0.0;
|
||||
VectorConstantCoefficient zero_vec_coeff(zero_vec);
|
||||
GridFunction x(&fespace);
|
||||
x = 0.0;
|
||||
|
||||
// 8. Determine the list of true (i.e. conforming) essential boundary dofs.
|
||||
// In this example, the boundary conditions are defined by marking only
|
||||
// boundary attribute 1 from the mesh as essential and converting it to a
|
||||
// list of true dofs. The conversion to true dofs will be done in the
|
||||
// main loop.
|
||||
Array<int> ess_bdr(mesh.bdr_attributes.Max());
|
||||
ess_bdr = 0;
|
||||
ess_bdr[0] = 1;
|
||||
|
||||
// 9. Connect to GLVis.
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock;
|
||||
if (visualization)
|
||||
{
|
||||
sol_sock.open(vishost, visport);
|
||||
sol_sock.precision(8);
|
||||
}
|
||||
|
||||
// 10. Set up an error estimator. Here we use the Zienkiewicz-Zhu estimator
|
||||
// that uses the ComputeElementFlux method of the ElasticityIntegrator to
|
||||
// recover a smoothed flux (stress) that is subtracted from the element
|
||||
// flux to get an error indicator. We need to supply the space for the
|
||||
// smoothed flux: an (H1)^tdim (i.e., vector-valued) space is used here.
|
||||
// Here, tdim represents the number of components for a symmetric (dim x
|
||||
// dim) tensor.
|
||||
const int tdim = dim*(dim+1)/2;
|
||||
FiniteElementSpace flux_fespace(&mesh, &fec, tdim);
|
||||
ZienkiewiczZhuEstimator estimator(*integ, x, flux_fespace);
|
||||
estimator.SetFluxAveraging(flux_averaging);
|
||||
|
||||
// 11. A refiner selects and refines elements based on a refinement strategy.
|
||||
// The strategy here is to refine elements with errors larger than a
|
||||
// fraction of the maximum element error. Other strategies are possible.
|
||||
// The refiner will call the given error estimator.
|
||||
ThresholdRefiner refiner(estimator);
|
||||
refiner.SetTotalErrorFraction(0.7);
|
||||
|
||||
// 12. The main AMR loop. In each iteration we solve the problem on the
|
||||
// current mesh, visualize the solution, and refine the mesh.
|
||||
const int max_dofs = 50000;
|
||||
const int max_amr_itr = 20;
|
||||
for (int it = 0; it <= max_amr_itr; it++)
|
||||
{
|
||||
int cdofs = fespace.GetTrueVSize();
|
||||
cout << "\nAMR iteration " << it << endl;
|
||||
cout << "Number of unknowns: " << cdofs << endl;
|
||||
|
||||
// 13. Assemble the stiffness matrix and the right-hand side.
|
||||
a.Assemble();
|
||||
b.Assemble();
|
||||
|
||||
// 14. Set Dirichlet boundary values in the GridFunction x.
|
||||
// Determine the list of Dirichlet true DOFs in the linear system.
|
||||
Array<int> ess_tdof_list;
|
||||
x.ProjectBdrCoefficient(zero_vec_coeff, ess_bdr);
|
||||
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
|
||||
// 15. Create the linear system: eliminate boundary conditions, constrain
|
||||
// hanging nodes and possibly apply other transformations. The system
|
||||
// will be solved for true (unconstrained) DOFs only.
|
||||
SparseMatrix A;
|
||||
Vector B, X;
|
||||
const int copy_interior = 1;
|
||||
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B, copy_interior);
|
||||
|
||||
#ifndef MFEM_USE_SUITESPARSE
|
||||
// 16. Define a simple symmetric Gauss-Seidel preconditioner and use it to
|
||||
// solve the linear system with PCG.
|
||||
GSSmoother M(A);
|
||||
PCG(A, M, B, X, 3, 2000, 1e-12, 0.0);
|
||||
#else
|
||||
// 16. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the
|
||||
// the linear system.
|
||||
UMFPackSolver umf_solver;
|
||||
umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
|
||||
umf_solver.SetOperator(A);
|
||||
umf_solver.Mult(B, X);
|
||||
#endif
|
||||
|
||||
// 17. After solving the linear system, reconstruct the solution as a
|
||||
// finite element GridFunction. Constrained nodes are interpolated
|
||||
// from true DOFs (it may therefore happen that x.Size() >= X.Size()).
|
||||
a.RecoverFEMSolution(X, b, x);
|
||||
|
||||
// 18. Send solution by socket to the GLVis server.
|
||||
if (visualization && sol_sock.good())
|
||||
{
|
||||
GridFunction nodes(&fespace), *nodes_p = &nodes;
|
||||
mesh.GetNodes(nodes);
|
||||
nodes += x;
|
||||
int own_nodes = 0;
|
||||
mesh.SwapNodes(nodes_p, own_nodes);
|
||||
x.Neg(); // visualize the backward displacement
|
||||
sol_sock << "solution\n" << mesh << x << flush;
|
||||
x.Neg();
|
||||
mesh.SwapNodes(nodes_p, own_nodes);
|
||||
if (it == 0)
|
||||
{
|
||||
sol_sock << "keys '" << ((dim == 2) ? "Rjl" : "") << "m'" << endl;
|
||||
}
|
||||
sol_sock << "window_title 'AMR iteration: " << it << "'\n"
|
||||
<< "pause" << endl;
|
||||
cout << "Visualization paused. "
|
||||
"Press <space> in the GLVis window to continue." << endl;
|
||||
}
|
||||
|
||||
if (cdofs > max_dofs)
|
||||
{
|
||||
cout << "Reached the maximum number of dofs. Stop." << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// 19. Call the refiner to modify the mesh. The refiner calls the error
|
||||
// estimator to obtain element errors, then it selects elements to be
|
||||
// refined and finally it modifies the mesh. The Stop() method can be
|
||||
// used to determine if a stopping criterion was met.
|
||||
refiner.Apply(mesh);
|
||||
if (refiner.Stop())
|
||||
{
|
||||
cout << "Stopping criterion satisfied. Stop." << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
// 20. Update the space to reflect the new state of the mesh. Also,
|
||||
// interpolate the solution x so that it lies in the new space but
|
||||
// represents the same function. This saves solver iterations later
|
||||
// since we'll have a good initial guess of x in the next step.
|
||||
// Internally, FiniteElementSpace::Update() calculates an
|
||||
// interpolation matrix which is then used by GridFunction::Update().
|
||||
fespace.Update();
|
||||
x.Update();
|
||||
|
||||
// 21. Inform also the bilinear and linear forms that the space has
|
||||
// changed.
|
||||
a.Update();
|
||||
b.Update();
|
||||
}
|
||||
|
||||
{
|
||||
ofstream mesh_ref_out("ex22_reference.mesh");
|
||||
mesh_ref_out.precision(16);
|
||||
mesh.Print(mesh_ref_out);
|
||||
|
||||
ofstream mesh_out("ex22_deformed.mesh");
|
||||
mesh_out.precision(16);
|
||||
GridFunction nodes(&fespace), *nodes_p = &nodes;
|
||||
mesh.GetNodes(nodes);
|
||||
nodes += x;
|
||||
int own_nodes = 0;
|
||||
mesh.SwapNodes(nodes_p, own_nodes);
|
||||
mesh.Print(mesh_out);
|
||||
mesh.SwapNodes(nodes_p, own_nodes);
|
||||
|
||||
ofstream x_out("ex22_displacement.sol");
|
||||
x_out.precision(16);
|
||||
x.Save(x_out);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,366 @@
|
||||
// MFEM Example 22
|
||||
//
|
||||
// Compile with: make ex22p
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex22p
|
||||
// mpirun -np 4 ex22p -o 3
|
||||
// mpirun -np 4 ex22p -m ../data/beam-quad.mesh
|
||||
// mpirun -np 4 ex22p -m ../data/beam-quad.mesh -o 3
|
||||
// mpirun -np 4 ex22p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 4 ex22p -m ../data/beam-tet.mesh -o 2
|
||||
// mpirun -np 4 ex22p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 4 ex22p -m ../data/beam-hex.mesh -o 2
|
||||
//
|
||||
// Description: This is a version of Example 2p with a simple adaptive mesh
|
||||
// refinement loop. The problem being solved is again the linear
|
||||
// elasticity describing a multi-material cantilever beam.
|
||||
// The problem is solved on a sequence of meshes which
|
||||
// are locally refined in a conforming (triangles, tetrahedrons)
|
||||
// or non-conforming (quadrilaterals, hexahedra) manner according
|
||||
// to a simple ZZ error estimator.
|
||||
//
|
||||
// The example demonstrates MFEM's capability to work with both
|
||||
// conforming and nonconforming refinements, in 2D and 3D, on
|
||||
// linear and curved meshes. Interpolation of functions from
|
||||
// coarse to fine meshes, as well as persistent GLVis
|
||||
// visualization are also illustrated.
|
||||
//
|
||||
// We recommend viewing Examples 2p and 6p before viewing this
|
||||
// example.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 0. Initialize MPI.
|
||||
int num_procs, myid;
|
||||
MPI_Init(&argc, &argv);
|
||||
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
|
||||
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
|
||||
|
||||
// 1. Parse command-line options.
|
||||
const char *mesh_file = "../data/beam-tri.mesh";
|
||||
int serial_ref_levels = 0;
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool visualization = 1;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&mesh_file, "-m", "--mesh",
|
||||
"Mesh file to use.");
|
||||
args.AddOption(&serial_ref_levels, "-rs", "--refine-serial",
|
||||
"Number of uniform serial refinements (before parallel"
|
||||
" partitioning)");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree).");
|
||||
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
// 2. Read the mesh from the given mesh file. We can handle triangular,
|
||||
// quadrilateral, tetrahedral, and hexahedral meshes with the same code.
|
||||
Mesh mesh(mesh_file, 1, 1);
|
||||
int dim = mesh.Dimension();
|
||||
MFEM_VERIFY(mesh.SpaceDimension() == dim, "invalid mesh");
|
||||
|
||||
if (mesh.attributes.Max() < 2 || mesh.bdr_attributes.Max() < 2)
|
||||
{
|
||||
cerr << "\nInput mesh should have at least two materials and "
|
||||
<< "two boundary attributes! (See schematic in ex2.cpp)\n"
|
||||
<< endl;
|
||||
MPI_Finalize();
|
||||
return 3;
|
||||
}
|
||||
|
||||
// 3. Refine the mesh before parallel partitioning. Since a NURBS mesh can
|
||||
// currently only be refined uniformly, we need to convert it to a
|
||||
// piecewise-polynomial curved mesh. First we refine the NURBS mesh a bit
|
||||
// more and then project the curvature to quadratic Nodes.
|
||||
if (mesh.NURBSext && serial_ref_levels == 0)
|
||||
{
|
||||
serial_ref_levels = 2;
|
||||
}
|
||||
for (int i = 0; i < serial_ref_levels; i++)
|
||||
{
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
if (mesh.NURBSext)
|
||||
{
|
||||
mesh.SetCurvature(2);
|
||||
}
|
||||
mesh.EnsureNCMesh();
|
||||
|
||||
ParMesh pmesh(MPI_COMM_WORLD, mesh);
|
||||
mesh.Clear();
|
||||
|
||||
// 4. Define a finite element space on the mesh. The polynomial order is
|
||||
// one (linear) by default, but this can be changed on the command line.
|
||||
H1_FECollection fec(order, dim);
|
||||
ParFiniteElementSpace fespace(&pmesh, &fec, dim);
|
||||
|
||||
// 5. As in Example 2, we set up the linear form b(.) which corresponds to
|
||||
// the right-hand side of the FEM linear system. In this case, b_i equals
|
||||
// the boundary integral of f*phi_i where f represents a "pull down"
|
||||
// force on the Neumann part of the boundary and phi_i are the basis
|
||||
// functions in the finite element fespace. The force is defined by the
|
||||
// VectorArrayCoefficient object f, which is a vector of Coefficient
|
||||
// objects. The fact that f is non-zero on boundary attribute 2 is
|
||||
// indicated by the use of piece-wise constants coefficient for its last
|
||||
// component. We don't assemble the discrete problem yet, this will be
|
||||
// done in the main loop.
|
||||
VectorArrayCoefficient f(dim);
|
||||
for (int i = 0; i < dim-1; i++)
|
||||
{
|
||||
f.Set(i, new ConstantCoefficient(0.0));
|
||||
}
|
||||
{
|
||||
Vector pull_force(pmesh.bdr_attributes.Max());
|
||||
pull_force = 0.0;
|
||||
pull_force(1) = -1.0e-2;
|
||||
f.Set(dim-1, new PWConstCoefficient(pull_force));
|
||||
}
|
||||
|
||||
ParLinearForm b(&fespace);
|
||||
b.AddDomainIntegrator(new VectorBoundaryLFIntegrator(f));
|
||||
|
||||
// 6. Set up the bilinear form a(.,.) on the finite element space
|
||||
// corresponding to the linear elasticity integrator with piece-wise
|
||||
// constants coefficient lambda and mu.
|
||||
Vector lambda(pmesh.attributes.Max());
|
||||
lambda = 1.0;
|
||||
lambda(0) = lambda(1)*50;
|
||||
PWConstCoefficient lambda_func(lambda);
|
||||
Vector mu(pmesh.attributes.Max());
|
||||
mu = 1.0;
|
||||
mu(0) = mu(1)*50;
|
||||
PWConstCoefficient mu_func(mu);
|
||||
|
||||
ParBilinearForm a(&fespace);
|
||||
BilinearFormIntegrator *integ =
|
||||
new ElasticityIntegrator(lambda_func,mu_func);
|
||||
a.AddDomainIntegrator(integ);
|
||||
if (static_cond) { a.EnableStaticCondensation(); }
|
||||
|
||||
// 7. The solution vector x and the associated finite element grid function
|
||||
// will be maintained over the AMR iterations. We initialize it to zero.
|
||||
Vector zero_vec(dim);
|
||||
zero_vec = 0.0;
|
||||
VectorConstantCoefficient zero_vec_coeff(zero_vec);
|
||||
ParGridFunction x(&fespace);
|
||||
x = 0.0;
|
||||
|
||||
// 8. Determine the list of true (i.e. conforming) essential boundary dofs.
|
||||
// In this example, the boundary conditions are defined by marking only
|
||||
// boundary attribute 1 from the mesh as essential and converting it to a
|
||||
// list of true dofs. The conversion to true dofs will be done in the
|
||||
// main loop.
|
||||
Array<int> ess_bdr(pmesh.bdr_attributes.Max());
|
||||
ess_bdr = 0;
|
||||
ess_bdr[0] = 1;
|
||||
|
||||
// 9. GLVis visualization.
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock;
|
||||
|
||||
// 10. Set up an error estimator. Here we use the Zienkiewicz-Zhu estimator
|
||||
// that uses the ComputeElementFlux method of the ElasticityIntegrator to
|
||||
// recover a smoothed flux (stress) that is subtracted from the element
|
||||
// flux to get an error indicator. We need to supply the space for the
|
||||
// smoothed flux: an (H1)^tdim (i.e., vector-valued) space is used here.
|
||||
// Here, tdim represents the number of components for a symmetric (dim x
|
||||
// dim) tensor.
|
||||
const int tdim = dim*(dim+1)/2;
|
||||
L2_FECollection flux_fec(order, dim);
|
||||
ParFiniteElementSpace flux_fespace(&pmesh, &flux_fec, tdim);
|
||||
ParFiniteElementSpace smooth_flux_fespace(&pmesh, &fec, tdim);
|
||||
L2ZienkiewiczZhuEstimator estimator(*integ, x, flux_fespace,
|
||||
smooth_flux_fespace);
|
||||
|
||||
// 11. A refiner selects and refines elements based on a refinement strategy.
|
||||
// The strategy here is to refine elements with errors larger than a
|
||||
// fraction of the maximum element error. Other strategies are possible.
|
||||
// The refiner will call the given error estimator.
|
||||
ThresholdRefiner refiner(estimator);
|
||||
refiner.SetTotalErrorFraction(0.7);
|
||||
|
||||
// 12. The main AMR loop. In each iteration we solve the problem on the
|
||||
// current mesh, visualize the solution, and refine the mesh.
|
||||
const int max_dofs = 50000;
|
||||
const int max_amr_itr = 20;
|
||||
for (int it = 0; it <= max_amr_itr; it++)
|
||||
{
|
||||
HYPRE_Int global_dofs = fespace.GlobalTrueVSize();
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "\nAMR iteration " << it << endl;
|
||||
cout << "Number of unknowns: " << global_dofs << endl;
|
||||
}
|
||||
|
||||
// 13. Assemble the stiffness matrix and the right-hand side.
|
||||
a.Assemble();
|
||||
b.Assemble();
|
||||
|
||||
// 14. Set Dirichlet boundary values in the GridFunction x.
|
||||
// Determine the list of Dirichlet true DOFs in the linear system.
|
||||
Array<int> ess_tdof_list;
|
||||
x.ProjectBdrCoefficient(zero_vec_coeff, ess_bdr);
|
||||
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
|
||||
|
||||
// 15. Create the linear system: eliminate boundary conditions, constrain
|
||||
// hanging nodes and possibly apply other transformations. The system
|
||||
// will be solved for true (unconstrained) DOFs only.
|
||||
|
||||
HypreParMatrix A;
|
||||
Vector B, X;
|
||||
const int copy_interior = 1;
|
||||
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B, copy_interior);
|
||||
|
||||
// 16. Define and apply a parallel PCG solver for AX=B with the BoomerAMG
|
||||
// preconditioner from hypre.
|
||||
HypreBoomerAMG amg;
|
||||
amg.SetPrintLevel(0);
|
||||
// amg.SetSystemsOptions(dim); // optional
|
||||
CGSolver pcg(A.GetComm());
|
||||
pcg.SetPreconditioner(amg);
|
||||
pcg.SetOperator(A);
|
||||
pcg.SetRelTol(1e-6);
|
||||
pcg.SetMaxIter(500);
|
||||
pcg.SetPrintLevel(3); // print the first and the last iterations only
|
||||
pcg.Mult(B, X);
|
||||
|
||||
// 17. After solving the linear system, reconstruct the solution as a
|
||||
// finite element GridFunction. Constrained nodes are interpolated
|
||||
// from true DOFs (it may therefore happen that x.Size() >= X.Size()).
|
||||
a.RecoverFEMSolution(X, b, x);
|
||||
|
||||
// 18. Send solution by socket to the GLVis server.
|
||||
if (visualization && it == 0)
|
||||
{
|
||||
sol_sock.open(vishost, visport);
|
||||
sol_sock.precision(8);
|
||||
}
|
||||
if (visualization && sol_sock.good())
|
||||
{
|
||||
GridFunction nodes(&fespace), *nodes_p = &nodes;
|
||||
pmesh.GetNodes(nodes);
|
||||
nodes += x;
|
||||
int own_nodes = 0;
|
||||
pmesh.SwapNodes(nodes_p, own_nodes);
|
||||
x.Neg(); // visualize the backward displacement
|
||||
sol_sock << "parallel " << num_procs << ' ' << myid << '\n';
|
||||
sol_sock << "solution\n" << pmesh << x << flush;
|
||||
x.Neg();
|
||||
pmesh.SwapNodes(nodes_p, own_nodes);
|
||||
if (it == 0)
|
||||
{
|
||||
sol_sock << "keys '" << ((dim == 2) ? "Rjl" : "") << "m'" << endl;
|
||||
}
|
||||
sol_sock << "window_title 'AMR iteration: " << it << "'\n"
|
||||
<< "pause" << endl;
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Visualization paused. "
|
||||
"Press <space> in the GLVis window to continue." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (global_dofs > max_dofs)
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Reached the maximum number of dofs. Stop." << endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 19. Call the refiner to modify the mesh. The refiner calls the error
|
||||
// estimator to obtain element errors, then it selects elements to be
|
||||
// refined and finally it modifies the mesh. The Stop() method can be
|
||||
// used to determine if a stopping criterion was met.
|
||||
refiner.Apply(pmesh);
|
||||
if (refiner.Stop())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "Stopping criterion satisfied. Stop." << endl;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// 20. Update the space to reflect the new state of the mesh. Also,
|
||||
// interpolate the solution x so that it lies in the new space but
|
||||
// represents the same function. This saves solver iterations later
|
||||
// since we'll have a good initial guess of x in the next step.
|
||||
// Internally, FiniteElementSpace::Update() calculates an
|
||||
// interpolation matrix which is then used by GridFunction::Update().
|
||||
fespace.Update();
|
||||
x.Update();
|
||||
|
||||
// 21. Load balance the mesh, and update the space and solution. Currently
|
||||
// available only for nonconforming meshes.
|
||||
if (pmesh.Nonconforming())
|
||||
{
|
||||
pmesh.Rebalance();
|
||||
|
||||
// Update the space and the GridFunction. This time the update matrix
|
||||
// redistributes the GridFunction among the processors.
|
||||
fespace.Update();
|
||||
x.Update();
|
||||
}
|
||||
|
||||
// 22. Inform also the bilinear and linear forms that the space has
|
||||
// changed.
|
||||
a.Update();
|
||||
b.Update();
|
||||
}
|
||||
|
||||
{
|
||||
ostringstream mref_name, mesh_name, sol_name;
|
||||
mref_name << "ex22p_reference_mesh." << setfill('0') << setw(6) << myid;
|
||||
mesh_name << "ex22p_deformed_mesh." << setfill('0') << setw(6) << myid;
|
||||
sol_name << "ex22p_displacement." << setfill('0') << setw(6) << myid;
|
||||
|
||||
ofstream mesh_ref_out(mref_name.str().c_str());
|
||||
mesh_ref_out.precision(16);
|
||||
pmesh.Print(mesh_ref_out);
|
||||
|
||||
ofstream mesh_out(mesh_name.str().c_str());
|
||||
mesh_out.precision(16);
|
||||
GridFunction nodes(&fespace), *nodes_p = &nodes;
|
||||
pmesh.GetNodes(nodes);
|
||||
nodes += x;
|
||||
int own_nodes = 0;
|
||||
pmesh.SwapNodes(nodes_p, own_nodes);
|
||||
pmesh.Print(mesh_out);
|
||||
pmesh.SwapNodes(nodes_p, own_nodes);
|
||||
|
||||
ofstream x_out(sol_name.str().c_str());
|
||||
x_out.precision(16);
|
||||
x.Save(x_out);
|
||||
}
|
||||
|
||||
MPI_Finalize();
|
||||
return 0;
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
// mpirun -np 4 ex2p -m ../data/beam-quad.mesh
|
||||
// mpirun -np 4 ex2p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 4 ex2p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 4 ex2p -m ../data/beam-wedge.mesh
|
||||
// mpirun -np 4 ex2p -m ../data/beam-tri.mesh -o 2 -sys
|
||||
// mpirun -np 4 ex2p -m ../data/beam-quad.mesh -o 3 -elast
|
||||
// mpirun -np 4 ex2p -m ../data/beam-quad.mesh -o 3 -sc
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// ex3 -m ../data/beam-tet.mesh
|
||||
// ex3 -m ../data/beam-hex.mesh
|
||||
// ex3 -m ../data/escher.mesh
|
||||
// ex3 -m ../data/escher.mesh -o 2
|
||||
// ex3 -m ../data/fichera.mesh
|
||||
// ex3 -m ../data/fichera-q2.vtk
|
||||
// ex3 -m ../data/fichera-q3.mesh
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
// mpirun -np 4 ex3p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/escher.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/escher.mesh -o 2
|
||||
// mpirun -np 4 ex3p -m ../data/fichera.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/fichera-q2.vtk
|
||||
// mpirun -np 4 ex3p -m ../data/fichera-q3.mesh
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
// equation -Delta u = 1 with homogeneous Dirichlet boundary
|
||||
// conditions. The problem is solved on a sequence of meshes which
|
||||
// are locally refined in a conforming (triangles, tetrahedrons)
|
||||
// or non-conforming (quadrilateral, hexahedrons) manner according
|
||||
// or non-conforming (quadrilaterals, hexahedra) manner according
|
||||
// to a simple ZZ error estimator.
|
||||
//
|
||||
// The example demonstrates MFEM's capability to work with both
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
// equation -Delta u = 1 with homogeneous Dirichlet boundary
|
||||
// conditions. The problem is solved on a sequence of meshes which
|
||||
// are locally refined in a conforming (triangles, tetrahedrons)
|
||||
// or non-conforming (quadrilateral, hexahedrons) manner according
|
||||
// or non-conforming (quadrilaterals, hexahedra) manner according
|
||||
// to a simple ZZ error estimator.
|
||||
//
|
||||
// The example demonstrates MFEM's capability to work with both
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
//
|
||||
// Sample runs: ex8 -m ../data/square-disc.mesh
|
||||
// ex8 -m ../data/star.mesh
|
||||
// ex8 -m ../data/star-mixed.mesh
|
||||
// ex8 -m ../data/escher.mesh
|
||||
// ex8 -m ../data/fichera.mesh
|
||||
// ex8 -m ../data/fichera-mixed.mesh
|
||||
// ex8 -m ../data/square-disc-p2.vtk
|
||||
// ex8 -m ../data/square-disc-p3.mesh
|
||||
// ex8 -m ../data/star-surf.mesh -o 2
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex8p -m ../data/square-disc.mesh
|
||||
// mpirun -np 4 ex8p -m ../data/star.mesh
|
||||
// mpirun -np 4 ex8p -m ../data/star-mixed.mesh
|
||||
// mpirun -np 4 ex8p -m ../data/escher.mesh
|
||||
// mpirun -np 4 ex8p -m ../data/fichera.mesh
|
||||
// mpirun -np 4 ex8p -m ../data/fichera-mixed.mesh
|
||||
// mpirun -np 4 ex8p -m ../data/square-disc-p2.vtk
|
||||
// mpirun -np 4 ex8p -m ../data/square-disc-p3.mesh
|
||||
// mpirun -np 4 ex8p -m ../data/star-surf.mesh -o 2
|
||||
@@ -123,9 +125,13 @@ int main(int argc, char *argv[])
|
||||
test_order++;
|
||||
}
|
||||
if (test_order < trial_order)
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
cerr << "Warning, test space not enriched enough to handle primal"
|
||||
<< " trial space\n";
|
||||
}
|
||||
}
|
||||
|
||||
FiniteElementCollection *x0_fec, *xhat_fec, *test_fec;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// ex9 -m ../data/periodic-hexagon.mesh -p 1 -r 2 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/amr-quad.mesh -p 1 -r 2 -dt 0.002 -tf 9
|
||||
// ex9 -m ../data/star-q3.mesh -p 1 -r 2 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/star-mixed.mesh -p 1 -r 2 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/disc-nurbs.mesh -p 1 -r 3 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/disc-nurbs.mesh -p 2 -r 3 -dt 0.005 -tf 9
|
||||
// ex9 -m ../data/periodic-square.mesh -p 3 -r 4 -dt 0.0025 -tf 9 -vs 20
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// mpirun -np 4 ex9p -m ../data/periodic-hexagon.mesh -p 1 -dt 0.005 -tf 9
|
||||
// mpirun -np 4 ex9p -m ../data/amr-quad.mesh -p 1 -rp 1 -dt 0.002 -tf 9
|
||||
// mpirun -np 4 ex9p -m ../data/star-q3.mesh -p 1 -rp 1 -dt 0.004 -tf 9
|
||||
// mpirun -np 4 ex9p -m ../data/star-mixed.mesh -p 1 -rp 1 -dt 0.004 -tf 9
|
||||
// mpirun -np 4 ex9p -m ../data/disc-nurbs.mesh -p 1 -rp 1 -dt 0.005 -tf 9
|
||||
// mpirun -np 4 ex9p -m ../data/disc-nurbs.mesh -p 2 -rp 1 -dt 0.005 -tf 9
|
||||
// mpirun -np 4 ex9p -m ../data/periodic-square.mesh -p 3 -rp 2 -dt 0.0025 -tf 9 -vs 20
|
||||
|
||||
+4
-2
@@ -22,9 +22,9 @@ MFEM_LIB_FILE = mfem_is_not_built
|
||||
-include $(CONFIG_MK)
|
||||
|
||||
SEQ_EXAMPLES = ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 ex17\
|
||||
ex18 ex19
|
||||
ex18 ex19 ex20 ex22
|
||||
PAR_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex8p ex9p ex10p ex11p ex12p\
|
||||
ex13p ex14p ex15p ex16p ex17p ex18p ex19p
|
||||
ex13p ex14p ex15p ex16p ex17p ex18p ex19p ex20p ex22p
|
||||
|
||||
ifeq ($(MFEM_USE_MPI),NO)
|
||||
EXAMPLES = $(SEQ_EXAMPLES)
|
||||
@@ -118,3 +118,5 @@ clean-exec:
|
||||
@rm -f ex16.mesh ex16-mesh.* ex16-init.* ex16-final.*
|
||||
@rm -f vortex-mesh.* vortex.mesh vortex-?-init.* vortex-?-final.*
|
||||
@rm -f deformation.* pressure.*
|
||||
@rm -f ex20.dat ex20p_?????.dat gnuplot_ex20.inp gnuplot_ex20p.inp
|
||||
@rm -f ex22*.mesh ex22*.sol ex22p_*.*
|
||||
|
||||
@@ -96,7 +96,7 @@ foreach(TEST_OPTIONS_VAR
|
||||
# All PETSC tests are parallel.
|
||||
if (MFEM_USE_MPI)
|
||||
add_test(NAME ${TEST_NAME_FULL}_np=4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
|
||||
${MPIEXEC_PREFLAGS}
|
||||
$<TARGET_FILE:${TEST_NAME}> ${TEST_OPTIONS}
|
||||
${MPIEXEC_POSTFLAGS})
|
||||
|
||||
@@ -239,7 +239,7 @@ int main(int argc, char *argv[])
|
||||
// 2b. We initialize PETSc
|
||||
if (use_petsc)
|
||||
{
|
||||
PetscInitialize(NULL,NULL,petscrc_file,NULL);
|
||||
MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL);
|
||||
}
|
||||
|
||||
// 3. Read the serial mesh from the given mesh file on all processors. We can
|
||||
@@ -446,7 +446,7 @@ int main(int argc, char *argv[])
|
||||
delete oper;
|
||||
|
||||
// We finalize PETSc
|
||||
if (use_petsc) { PetscFinalize(); }
|
||||
if (use_petsc) { MFEMFinalizePetsc(); }
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// 2b. We initialize PETSc
|
||||
PetscInitialize(NULL,NULL,petscrc_file,NULL);
|
||||
MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL);
|
||||
|
||||
// 3. Read the (serial) mesh from the given mesh file on all processors. We
|
||||
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
|
||||
@@ -266,7 +266,6 @@ int main(int argc, char *argv[])
|
||||
if (visualization && petscmonitor)
|
||||
{
|
||||
pcg->SetMonitor(&mymon);
|
||||
pcg->SetPrintLevel(4);
|
||||
pcg->iterative_mode = true;
|
||||
X.Randomize();
|
||||
}
|
||||
@@ -314,7 +313,7 @@ int main(int argc, char *argv[])
|
||||
delete pmesh;
|
||||
|
||||
// We finalize PETSc
|
||||
PetscFinalize();
|
||||
MFEMFinalizePetsc();
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// 2b. We initialize PETSc
|
||||
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
|
||||
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
|
||||
|
||||
// 3. Read the (serial) mesh from the given mesh file on all processors. We
|
||||
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
|
||||
@@ -359,7 +359,7 @@ int main(int argc, char *argv[])
|
||||
delete pmesh;
|
||||
|
||||
// We finalize PETSc
|
||||
if (use_petsc) { PetscFinalize(); }
|
||||
if (use_petsc) { MFEMFinalizePetsc(); }
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
|
||||
@@ -96,7 +96,7 @@ int main(int argc, char *argv[])
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
// 2b. We initialize PETSc
|
||||
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
|
||||
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
|
||||
kappa = freq * M_PI;
|
||||
|
||||
// 3. Read the (serial) mesh from the given mesh file on all processors. We
|
||||
@@ -309,7 +309,7 @@ int main(int argc, char *argv[])
|
||||
delete pmesh;
|
||||
|
||||
// We finalize PETSc
|
||||
if (use_petsc) { PetscFinalize(); }
|
||||
if (use_petsc) { MFEMFinalizePetsc(); }
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ int main(int argc, char *argv[])
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
// 2b. We initialize PETSc
|
||||
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
|
||||
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
|
||||
kappa = freq * M_PI;
|
||||
|
||||
// 3. Read the (serial) mesh from the given mesh file on all processors. We
|
||||
@@ -330,7 +330,7 @@ int main(int argc, char *argv[])
|
||||
delete pmesh;
|
||||
|
||||
// We finalize PETSc
|
||||
if (use_petsc) { PetscFinalize(); }
|
||||
if (use_petsc) { MFEMFinalizePetsc(); }
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ int main(int argc, char *argv[])
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
// 2b. We initialize PETSc
|
||||
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
|
||||
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
|
||||
|
||||
// 3. Read the (serial) mesh from the given mesh file on all processors. We
|
||||
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
|
||||
@@ -544,7 +544,7 @@ int main(int argc, char *argv[])
|
||||
delete pmesh;
|
||||
|
||||
// We finalize PETSc
|
||||
if (use_petsc) { PetscFinalize(); }
|
||||
if (use_petsc) { MFEMFinalizePetsc(); }
|
||||
|
||||
MPI_Finalize();
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// equation -Delta u = 1 with homogeneous Dirichlet boundary
|
||||
// conditions. The problem is solved on a sequence of meshes which
|
||||
// are locally refined in a conforming (triangles, tetrahedrons)
|
||||
// or non-conforming (quadrilateral, hexahedrons) manner according
|
||||
// or non-conforming (quadrilaterals, hexahedra) manner according
|
||||
// to a simple ZZ error estimator.
|
||||
//
|
||||
// The example demonstrates MFEM's capability to work with both
|
||||
@@ -88,7 +88,7 @@ int main(int argc, char *argv[])
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
// 2b. We initialize PETSc
|
||||
if (use_petsc) { PetscInitialize(NULL,NULL,petscrc_file,NULL); }
|
||||
if (use_petsc) { MFEMInitializePetsc(NULL,NULL,petscrc_file,NULL); }
|
||||
|
||||
// 3. Read the (serial) mesh from the given mesh file on all processors. We
|
||||
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
|
||||
@@ -315,7 +315,7 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// We finalize PETSc
|
||||
if (use_petsc) { PetscFinalize(); }
|
||||
if (use_petsc) { MFEMFinalizePetsc(); }
|
||||
|
||||
MPI_Finalize();
|
||||
return 0;
|
||||
|
||||
@@ -248,7 +248,7 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
// When using PETSc, we just create the ODE solver. We use command line
|
||||
// customization to select a specific solver.
|
||||
PetscInitialize(NULL, NULL, petscrc_file, NULL);
|
||||
MFEMInitializePetsc(NULL, NULL, petscrc_file, NULL);
|
||||
ode_solver = pode_solver = new PetscODESolver(MPI_COMM_WORLD);
|
||||
}
|
||||
|
||||
@@ -481,7 +481,7 @@ int main(int argc, char *argv[])
|
||||
delete pmon;
|
||||
|
||||
// We finalize PETSc
|
||||
if (use_petsc) { PetscFinalize(); }
|
||||
if (use_petsc) { MFEMFinalizePetsc(); }
|
||||
|
||||
MPI_Finalize();
|
||||
return 0;
|
||||
|
||||
@@ -40,7 +40,8 @@ add_mfem_examples(PUMI_EXAMPLES_SRCS ${PFX} "" test_pumi)
|
||||
# Command line options for the tests.
|
||||
# TODO...
|
||||
|
||||
# Set the number of processors for the parallel examples.
|
||||
# Set the number of processors for the parallel examples. The value of
|
||||
# MFEM_MPI_NP is ignored.
|
||||
set(EX1_TEST_NP 1)
|
||||
set(EX1P_TEST_NP 8)
|
||||
set(EX2_TEST_NP 1)
|
||||
|
||||
@@ -209,15 +209,15 @@ int main(int argc, char *argv[])
|
||||
Transform(Geometries.GetCenter(mesh->GetElementBaseGeometry(el)),cent);
|
||||
if (cent(0) <= -0.05)
|
||||
{
|
||||
mesh->SetAttribute(el , 1);
|
||||
mesh->SetAttribute(el, 1);
|
||||
}
|
||||
else if (cent(0) >= 0.05)
|
||||
{
|
||||
mesh->SetAttribute(el , 2);
|
||||
mesh->SetAttribute(el, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh->SetAttribute(el , 3);
|
||||
mesh->SetAttribute(el, 3);
|
||||
}
|
||||
}
|
||||
mesh->SetAttributes();
|
||||
|
||||
@@ -68,7 +68,7 @@ foreach(SRC_FILE ${SUNDIALS_EXAMPLES_SRCS})
|
||||
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
|
||||
else()
|
||||
add_test(NAME ${TEST_NAME}_np=4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} 4
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
|
||||
${MPIEXEC_PREFLAGS}
|
||||
$<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS}
|
||||
${MPIEXEC_POSTFLAGS})
|
||||
|
||||
+31
-32
@@ -79,9 +79,6 @@ BilinearForm::BilinearForm (FiniteElementSpace * f)
|
||||
BilinearForm::BilinearForm (FiniteElementSpace * f, BilinearForm * bf, int ps)
|
||||
: Matrix (f->GetVSize())
|
||||
{
|
||||
int i;
|
||||
Array<BilinearFormIntegrator*> *bfi;
|
||||
|
||||
fes = f;
|
||||
sequence = f->GetSequence();
|
||||
mat_e = NULL;
|
||||
@@ -92,33 +89,16 @@ BilinearForm::BilinearForm (FiniteElementSpace * f, BilinearForm * bf, int ps)
|
||||
precompute_sparsity = ps;
|
||||
diag_policy = DIAG_KEEP;
|
||||
|
||||
bfi = bf->GetDBFI();
|
||||
dbfi.SetSize (bfi->Size());
|
||||
for (i = 0; i < bfi->Size(); i++)
|
||||
{
|
||||
dbfi[i] = (*bfi)[i];
|
||||
}
|
||||
// Copy the pointers to the integrators
|
||||
dbfi = bf->dbfi;
|
||||
|
||||
bfi = bf->GetBBFI();
|
||||
bbfi.SetSize (bfi->Size());
|
||||
for (i = 0; i < bfi->Size(); i++)
|
||||
{
|
||||
bbfi[i] = (*bfi)[i];
|
||||
}
|
||||
bbfi = bf->bbfi;
|
||||
bbfi_marker = bf->bbfi_marker;
|
||||
|
||||
bfi = bf->GetFBFI();
|
||||
fbfi.SetSize (bfi->Size());
|
||||
for (i = 0; i < bfi->Size(); i++)
|
||||
{
|
||||
fbfi[i] = (*bfi)[i];
|
||||
}
|
||||
fbfi = bf->fbfi;
|
||||
|
||||
bfi = bf->GetBFBFI();
|
||||
bfbfi.SetSize (bfi->Size());
|
||||
for (i = 0; i < bfi->Size(); i++)
|
||||
{
|
||||
bfbfi[i] = (*bfi)[i];
|
||||
}
|
||||
bfbfi = bf->bfbfi;
|
||||
bfbfi_marker = bf->bfbfi_marker;
|
||||
|
||||
AllocMat();
|
||||
}
|
||||
@@ -941,6 +921,23 @@ MixedBilinearForm::MixedBilinearForm (FiniteElementSpace *tr_fes,
|
||||
trial_fes = tr_fes;
|
||||
test_fes = te_fes;
|
||||
mat = NULL;
|
||||
extern_bfs = 0;
|
||||
}
|
||||
|
||||
MixedBilinearForm::MixedBilinearForm (FiniteElementSpace *tr_fes,
|
||||
FiniteElementSpace *te_fes,
|
||||
MixedBilinearForm * mbf)
|
||||
: Matrix(te_fes->GetVSize(), tr_fes->GetVSize())
|
||||
{
|
||||
trial_fes = tr_fes;
|
||||
test_fes = te_fes;
|
||||
mat = NULL;
|
||||
extern_bfs = 1;
|
||||
|
||||
// Copy the pointers to the integrators
|
||||
dom = mbf->dom;
|
||||
bdr = mbf->bdr;
|
||||
skt = mbf->skt;
|
||||
}
|
||||
|
||||
double & MixedBilinearForm::Elem (int i, int j)
|
||||
@@ -1177,12 +1174,14 @@ void MixedBilinearForm::Update()
|
||||
|
||||
MixedBilinearForm::~MixedBilinearForm()
|
||||
{
|
||||
int i;
|
||||
|
||||
if (mat) { delete mat; }
|
||||
for (i = 0; i < dom.Size(); i++) { delete dom[i]; }
|
||||
for (i = 0; i < bdr.Size(); i++) { delete bdr[i]; }
|
||||
for (i = 0; i < skt.Size(); i++) { delete skt[i]; }
|
||||
if (!extern_bfs)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < dom.Size(); i++) { delete dom[i]; }
|
||||
for (i = 0; i < bdr.Size(); i++) { delete bdr[i]; }
|
||||
for (i = 0; i < skt.Size(); i++) { delete skt[i]; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+133
-40
@@ -29,19 +29,21 @@ namespace mfem
|
||||
class BilinearForm : public Matrix
|
||||
{
|
||||
protected:
|
||||
/// Sparse matrix to be associated with the form.
|
||||
/// Sparse matrix to be associated with the form. Owned.
|
||||
SparseMatrix *mat;
|
||||
|
||||
/// Matrix used to eliminate b.c.
|
||||
/// Matrix used to eliminate b.c. Owned.
|
||||
SparseMatrix *mat_e;
|
||||
|
||||
/// FE space on which the form lives.
|
||||
/// FE space on which the form lives. Not owned.
|
||||
FiniteElementSpace *fes;
|
||||
|
||||
/// Indicates the Mesh::sequence corresponding to the current state of the
|
||||
/// BilinearForm.
|
||||
long sequence;
|
||||
|
||||
/** @brief Indicates the BilinearFormIntegrator%s stored in #dbfi, #bbfi,
|
||||
#fbfi, and #bfbfi are owned by another BilinearForm. */
|
||||
int extern_bfs;
|
||||
|
||||
/// Set of Domain Integrators to be applied.
|
||||
@@ -49,22 +51,22 @@ protected:
|
||||
|
||||
/// Set of Boundary Integrators to be applied.
|
||||
Array<BilinearFormIntegrator*> bbfi;
|
||||
Array<Array<int>*> bbfi_marker;
|
||||
Array<Array<int>*> bbfi_marker; ///< Entries are not owned.
|
||||
|
||||
/// Set of interior face Integrators to be applied.
|
||||
Array<BilinearFormIntegrator*> fbfi;
|
||||
|
||||
/// Set of boundary face Integrators to be applied.
|
||||
Array<BilinearFormIntegrator*> bfbfi;
|
||||
Array<Array<int>*> bfbfi_marker;
|
||||
Array<Array<int>*> bfbfi_marker; ///< Entries are not owned.
|
||||
|
||||
DenseMatrix elemmat;
|
||||
Array<int> vdofs;
|
||||
|
||||
DenseTensor *element_matrices;
|
||||
DenseTensor *element_matrices; ///< Owned.
|
||||
|
||||
StaticCondensation *static_cond;
|
||||
Hybridization *hybridization;
|
||||
StaticCondensation *static_cond; ///< Owned.
|
||||
Hybridization *hybridization; ///< Owned.
|
||||
|
||||
/**
|
||||
* This member allows one to specify what should be done
|
||||
@@ -89,10 +91,28 @@ protected:
|
||||
diag_policy = DIAG_KEEP;
|
||||
}
|
||||
|
||||
private:
|
||||
/// Copy construction is not supported; body is undefined.
|
||||
BilinearForm(const BilinearForm &);
|
||||
|
||||
/// Copy assignment is not supported; body is undefined.
|
||||
BilinearForm &operator=(const BilinearForm &);
|
||||
|
||||
public:
|
||||
/// Creates bilinear form associated with FE space @a *f.
|
||||
/** The pointer @a f is not owned by the newly constructed object. */
|
||||
BilinearForm(FiniteElementSpace *f);
|
||||
|
||||
/** @brief Create a BilinearForm on the FiniteElementSpace @a f, using the
|
||||
same integrators as the BilinearForm @a bf.
|
||||
|
||||
The pointer @a f is not owned by the newly constructed object.
|
||||
|
||||
The integrators in @a bf are copied as pointers and they are not owned by
|
||||
the newly constructed BilinearForm.
|
||||
|
||||
The optional parameter @a ps is used to initialize the internal flag
|
||||
#precompute_sparsity, see UsePrecomputedSparsity() for details. */
|
||||
BilinearForm(FiniteElementSpace *f, BilinearForm *bf, int ps = 0);
|
||||
|
||||
/// Get the size of the BilinearForm as a square matrix.
|
||||
@@ -143,13 +163,25 @@ public:
|
||||
finalized) and the entries are initialized with zeros. */
|
||||
void AllocateMatrix() { if (mat == NULL) { AllocMat(); } }
|
||||
|
||||
/// Access all integrators added with AddDomainIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetDBFI() { return &dbfi; }
|
||||
|
||||
/// Access all integrators added with AddBoundaryIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetBBFI() { return &bbfi; }
|
||||
/** @brief Access all boundary markers added with AddBoundaryIntegrator().
|
||||
If no marker was specified when the integrator was added, the
|
||||
corresponding pointer (to Array<int>) will be NULL. */
|
||||
Array<Array<int>*> *GetBBFI_Marker() { return &bbfi_marker; }
|
||||
|
||||
/// Access all integrators added with AddInteriorFaceIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetFBFI() { return &fbfi; }
|
||||
|
||||
/// Access all integrators added with AddBdrFaceIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetBFBFI() { return &bfbfi; }
|
||||
/** @brief Access all boundary markers added with AddBdrFaceIntegrator().
|
||||
If no marker was specified when the integrator was added, the
|
||||
corresponding pointer (to Array<int>) will be NULL. */
|
||||
Array<Array<int>*> *GetBFBFI_Marker() { return &bfbfi_marker; }
|
||||
|
||||
const double &operator()(int i, int j) { return (*mat)(i,j); }
|
||||
|
||||
@@ -175,10 +207,10 @@ public:
|
||||
const double a = 1.0) const
|
||||
{ mat->AddMultTranspose(x, y, a); }
|
||||
|
||||
void FullAddMultTranspose (const Vector & x, Vector & y) const
|
||||
void FullAddMultTranspose(const Vector & x, Vector & y) const
|
||||
{ mat->AddMultTranspose(x, y); mat_e->AddMultTranspose(x, y); }
|
||||
|
||||
virtual void MultTranspose (const Vector & x, Vector & y) const
|
||||
virtual void MultTranspose(const Vector & x, Vector & y) const
|
||||
{ y = 0.0; AddMultTranspose (x, y); }
|
||||
|
||||
double InnerProduct(const Vector &x, const Vector &y) const
|
||||
@@ -215,25 +247,31 @@ public:
|
||||
return *mat_e;
|
||||
}
|
||||
|
||||
/// Adds new Domain Integrator.
|
||||
/// Adds new Domain Integrator. Assumes ownership of @a bfi.
|
||||
void AddDomainIntegrator(BilinearFormIntegrator *bfi);
|
||||
|
||||
/// Adds new Boundary Integrator.
|
||||
/// Adds new Boundary Integrator. Assumes ownership of @a bfi.
|
||||
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi);
|
||||
|
||||
/** @brief Adds new Boundary Integrator, restricted to specific boundary
|
||||
attributes. */
|
||||
void AddBoundaryIntegrator(BilinearFormIntegrator * bfi,
|
||||
attributes.
|
||||
|
||||
Assumes ownership of @a bfi. The array @a bdr_marker is stored internally
|
||||
as a pointer to the given Array<int> object. */
|
||||
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi,
|
||||
Array<int> &bdr_marker);
|
||||
|
||||
/// Adds new interior Face Integrator.
|
||||
/// Adds new interior Face Integrator. Assumes ownership of @a bfi.
|
||||
void AddInteriorFaceIntegrator(BilinearFormIntegrator *bfi);
|
||||
|
||||
/// Adds new boundary Face Integrator.
|
||||
/// Adds new boundary Face Integrator. Assumes ownership of @a bfi.
|
||||
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi);
|
||||
|
||||
/** @brief Adds new boundary Face Integrator, restricted to specific boundary
|
||||
attributes. */
|
||||
attributes.
|
||||
|
||||
Assumes ownership of @a bfi. The array @a bdr_marker is stored internally
|
||||
as a pointer to the given Array<int> object. */
|
||||
void AddBdrFaceIntegrator(BilinearFormIntegrator *bfi,
|
||||
Array<int> &bdr_marker);
|
||||
|
||||
@@ -393,36 +431,68 @@ public:
|
||||
class MixedBilinearForm : public Matrix
|
||||
{
|
||||
protected:
|
||||
SparseMatrix *mat;
|
||||
SparseMatrix *mat; ///< Owned.
|
||||
|
||||
FiniteElementSpace *trial_fes, *test_fes;
|
||||
FiniteElementSpace *trial_fes, ///< Not owned
|
||||
*test_fes; ///< Not owned
|
||||
|
||||
/** @brief Indicates the BilinearFormIntegrator%s stored in #dom, #bdr, and
|
||||
#skt are owned by another MixedBilinearForm. */
|
||||
int extern_bfs;
|
||||
|
||||
/// Domain integrators.
|
||||
Array<BilinearFormIntegrator*> dom;
|
||||
/// Boundary integrators.
|
||||
Array<BilinearFormIntegrator*> bdr;
|
||||
Array<BilinearFormIntegrator*> skt; // trace face integrators
|
||||
/// Trace face (skeleton) integrators.
|
||||
Array<BilinearFormIntegrator*> skt;
|
||||
|
||||
private:
|
||||
/// Copy construction is not supported; body is undefined.
|
||||
MixedBilinearForm(const MixedBilinearForm &);
|
||||
|
||||
/// Copy assignment is not supported; body is undefined.
|
||||
MixedBilinearForm &operator=(const MixedBilinearForm &);
|
||||
|
||||
public:
|
||||
MixedBilinearForm (FiniteElementSpace *tr_fes,
|
||||
FiniteElementSpace *te_fes);
|
||||
/** @brief Construct a MixedBilinearForm on the given trial, @a tr_fes, and
|
||||
test, @a te_fes, FiniteElementSpace%s. */
|
||||
/** The pointers @a tr_fes and @a te_fes are not owned by the newly
|
||||
constructed object. */
|
||||
MixedBilinearForm(FiniteElementSpace *tr_fes,
|
||||
FiniteElementSpace *te_fes);
|
||||
|
||||
virtual double& Elem (int i, int j);
|
||||
/** @brief Create a MixedBilinearForm on the given trial, @a tr_fes, and
|
||||
test, @a te_fes, FiniteElementSpace%s, using the same integrators as the
|
||||
MixedBilinearForm @a mbf.
|
||||
|
||||
virtual const double& Elem (int i, int j) const;
|
||||
The pointers @a tr_fes and @a te_fes are not owned by the newly
|
||||
constructed object.
|
||||
|
||||
virtual void Mult (const Vector & x, Vector & y) const;
|
||||
The integrators in @a mbf are copied as pointers and they are not owned
|
||||
by the newly constructed MixedBilinearForm. */
|
||||
MixedBilinearForm(FiniteElementSpace *tr_fes,
|
||||
FiniteElementSpace *te_fes,
|
||||
MixedBilinearForm *mbf);
|
||||
|
||||
virtual void AddMult (const Vector & x, Vector & y,
|
||||
const double a = 1.0) const;
|
||||
virtual double &Elem(int i, int j);
|
||||
|
||||
virtual void AddMultTranspose (const Vector & x, Vector & y,
|
||||
const double a = 1.0) const;
|
||||
virtual const double &Elem(int i, int j) const;
|
||||
|
||||
virtual void MultTranspose (const Vector & x, Vector & y) const
|
||||
virtual void Mult(const Vector & x, Vector & y) const;
|
||||
|
||||
virtual void AddMult(const Vector & x, Vector & y,
|
||||
const double a = 1.0) const;
|
||||
|
||||
virtual void AddMultTranspose(const Vector & x, Vector & y,
|
||||
const double a = 1.0) const;
|
||||
|
||||
virtual void MultTranspose(const Vector & x, Vector & y) const
|
||||
{ y = 0.0; AddMultTranspose (x, y); }
|
||||
|
||||
virtual MatrixInverse * Inverse() const;
|
||||
virtual MatrixInverse *Inverse() const;
|
||||
|
||||
virtual void Finalize (int skip_zeros = 1);
|
||||
virtual void Finalize(int skip_zeros = 1);
|
||||
|
||||
/** Extract the associated matrix as SparseMatrix blocks. The number of
|
||||
block rows and columns is given by the vector dimensions (vdim) of the
|
||||
@@ -433,24 +503,31 @@ public:
|
||||
SparseMatrix &SpMat() { return *mat; }
|
||||
SparseMatrix *LoseMat() { SparseMatrix *tmp = mat; mat = NULL; return tmp; }
|
||||
|
||||
void AddDomainIntegrator (BilinearFormIntegrator * bfi);
|
||||
/// Adds a domain integrator. Assumes ownership of @a bfi.
|
||||
void AddDomainIntegrator(BilinearFormIntegrator *bfi);
|
||||
|
||||
void AddBoundaryIntegrator (BilinearFormIntegrator * bfi);
|
||||
/// Adds a boundary integrator. Assumes ownership of @a bfi.
|
||||
void AddBoundaryIntegrator(BilinearFormIntegrator *bfi);
|
||||
|
||||
/** Add a trace face integrator. This type of integrator assembles terms
|
||||
over all faces of the mesh using the face FE from the trial space and the
|
||||
two adjacent volume FEs from the test space. */
|
||||
void AddTraceFaceIntegrator (BilinearFormIntegrator * bfi);
|
||||
/** @brief Add a trace face integrator. Assumes ownership of @a bfi.
|
||||
|
||||
This type of integrator assembles terms over all faces of the mesh using
|
||||
the face FE from the trial space and the two adjacent volume FEs from the
|
||||
test space. */
|
||||
void AddTraceFaceIntegrator(BilinearFormIntegrator *bfi);
|
||||
|
||||
/// Access all integrators added with AddDomainIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetDBFI() { return &dom; }
|
||||
|
||||
/// Access all integrators added with AddBoundaryIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetBBFI() { return &bdr; }
|
||||
|
||||
/// Access all integrators added with AddTraceFaceIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetTFBFI() { return &skt; }
|
||||
|
||||
void operator= (const double a) { *mat = a; }
|
||||
void operator=(const double a) { *mat = a; }
|
||||
|
||||
void Assemble (int skip_zeros = 1);
|
||||
void Assemble(int skip_zeros = 1);
|
||||
|
||||
/** For partially conforming trial and/or test FE spaces, complete the
|
||||
assembly process by performing A := P2^t A P1 where A is the internal
|
||||
@@ -505,19 +582,35 @@ public:
|
||||
*/
|
||||
class DiscreteLinearOperator : public MixedBilinearForm
|
||||
{
|
||||
private:
|
||||
/// Copy construction is not supported; body is undefined.
|
||||
DiscreteLinearOperator(const DiscreteLinearOperator &);
|
||||
|
||||
/// Copy assignment is not supported; body is undefined.
|
||||
DiscreteLinearOperator &operator=(const DiscreteLinearOperator &);
|
||||
|
||||
public:
|
||||
/** @brief Construct a DiscreteLinearOperator on the given
|
||||
FiniteElementSpace%s @a domain_fes and @a range_fes. */
|
||||
/** The pointers @a domain_fes and @a range_fes are not owned by the newly
|
||||
constructed object. */
|
||||
DiscreteLinearOperator(FiniteElementSpace *domain_fes,
|
||||
FiniteElementSpace *range_fes)
|
||||
: MixedBilinearForm(domain_fes, range_fes) { }
|
||||
|
||||
/// Adds a domain interpolator. Assumes ownership of @a di.
|
||||
void AddDomainInterpolator(DiscreteInterpolator *di)
|
||||
{ AddDomainIntegrator(di); }
|
||||
|
||||
/// Adds a trace face interpolator. Assumes ownership of @a di.
|
||||
void AddTraceFaceInterpolator(DiscreteInterpolator *di)
|
||||
{ AddTraceFaceIntegrator(di); }
|
||||
|
||||
/// Access all interpolators added with AddDomainInterpolator().
|
||||
Array<BilinearFormIntegrator*> *GetDI() { return &dom; }
|
||||
|
||||
/** @brief Construct the internal matrix representation of the discrete
|
||||
linear operator. */
|
||||
virtual void Assemble(int skip_zeros = 1);
|
||||
};
|
||||
|
||||
|
||||
+235
-55
@@ -962,8 +962,8 @@ void VectorMassIntegrator::AssembleElementMatrix
|
||||
|
||||
double norm;
|
||||
|
||||
// Get vdim from VQ, MQ, or the space dimension
|
||||
int vdim = (VQ) ? (VQ -> GetVDim()) : ((MQ) ? (MQ -> GetVDim()) : spaceDim);
|
||||
// If vdim is not set, set it to the space dimension
|
||||
vdim = (vdim == -1) ? spaceDim : vdim;
|
||||
|
||||
elmat.SetSize(nd*vdim);
|
||||
shape.SetSize(nd);
|
||||
@@ -1041,13 +1041,11 @@ void VectorMassIntegrator::AssembleElementMatrix2(
|
||||
{
|
||||
int tr_nd = trial_fe.GetDof();
|
||||
int te_nd = test_fe.GetDof();
|
||||
int dim = trial_fe.GetDim();
|
||||
int vdim;
|
||||
|
||||
double norm;
|
||||
|
||||
// Get vdim from the ElementTransformation Trans ?
|
||||
vdim = (VQ) ? (VQ -> GetVDim()) : ((MQ) ? (MQ -> GetVDim()) : (dim));
|
||||
// If vdim is not set, set it to the space dimension
|
||||
vdim = (vdim == -1) ? Trans.GetSpaceDim() : vdim;
|
||||
|
||||
elmat.SetSize(te_nd*vdim, tr_nd*vdim);
|
||||
shape.SetSize(tr_nd);
|
||||
@@ -2180,11 +2178,12 @@ void ElasticityIntegrator::AssembleElementMatrix(
|
||||
int dim = el.GetDim();
|
||||
double w, L, M;
|
||||
|
||||
MFEM_ASSERT(dim == Trans.GetSpaceDim(), "");
|
||||
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
DenseMatrix dshape(dof, dim), Jinv(dim), gshape(dof, dim), pelmat(dof);
|
||||
DenseMatrix dshape(dof, dim), gshape(dof, dim), pelmat(dof);
|
||||
Vector divshape(dim*dof);
|
||||
#else
|
||||
Jinv.SetSize(dim);
|
||||
dshape.SetSize(dof, dim);
|
||||
gshape.SetSize(dof, dim);
|
||||
pelmat.SetSize(dof);
|
||||
@@ -2210,8 +2209,7 @@ void ElasticityIntegrator::AssembleElementMatrix(
|
||||
|
||||
Trans.SetIntPoint(&ip);
|
||||
w = ip.weight * Trans.Weight();
|
||||
CalcInverse(Trans.Jacobian(), Jinv);
|
||||
Mult(dshape, Jinv, gshape);
|
||||
Mult(dshape, Trans.InverseJacobian(), gshape);
|
||||
MultAAt(gshape, pelmat);
|
||||
gshape.GradToDiv (divshape);
|
||||
|
||||
@@ -2246,14 +2244,184 @@ void ElasticityIntegrator::AssembleElementMatrix(
|
||||
{
|
||||
for (int k = 0; k < dof; k++)
|
||||
for (int l = 0; l < dof; l++)
|
||||
{
|
||||
elmat(dof*i+k, dof*j+l) +=
|
||||
(M * w) * gshape(k, j) * gshape(l, i);
|
||||
// + (L * w) * gshape(k, i) * gshape(l, j)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ElasticityIntegrator::ComputeElementFlux(
|
||||
const mfem::FiniteElement &el, ElementTransformation &Trans,
|
||||
Vector &u, const mfem::FiniteElement &fluxelem, Vector &flux,
|
||||
int with_coef)
|
||||
{
|
||||
const int dof = el.GetDof();
|
||||
const int dim = el.GetDim();
|
||||
const int tdim = dim*(dim+1)/2; // num. entries in a symmetric tensor
|
||||
double L, M;
|
||||
|
||||
MFEM_ASSERT(dim == 2 || dim == 3,
|
||||
"dimension is not supported: dim = " << dim);
|
||||
MFEM_ASSERT(dim == Trans.GetSpaceDim(), "");
|
||||
MFEM_ASSERT(fluxelem.GetMapType() == FiniteElement::VALUE, "");
|
||||
MFEM_ASSERT(dynamic_cast<const NodalFiniteElement*>(&fluxelem), "");
|
||||
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
DenseMatrix dshape(dof, dim);
|
||||
#else
|
||||
dshape.SetSize(dof, dim);
|
||||
#endif
|
||||
|
||||
double gh_data[9], grad_data[9];
|
||||
DenseMatrix gh(gh_data, dim, dim);
|
||||
DenseMatrix grad(grad_data, dim, dim);
|
||||
|
||||
const IntegrationRule &ir = fluxelem.GetNodes();
|
||||
const int fnd = ir.GetNPoints();
|
||||
flux.SetSize(fnd * tdim);
|
||||
|
||||
DenseMatrix loc_data_mat(u.GetData(), dof, dim);
|
||||
for (int i = 0; i < fnd; i++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir.IntPoint(i);
|
||||
el.CalcDShape(ip, dshape);
|
||||
MultAtB(loc_data_mat, dshape, gh);
|
||||
|
||||
Trans.SetIntPoint(&ip);
|
||||
Mult(gh, Trans.InverseJacobian(), grad);
|
||||
|
||||
M = mu->Eval(Trans, ip);
|
||||
if (lambda)
|
||||
{
|
||||
L = lambda->Eval(Trans, ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
L = q_lambda * M;
|
||||
M = q_mu * M;
|
||||
}
|
||||
|
||||
// stress = 2*M*e(u) + L*tr(e(u))*I, where
|
||||
// e(u) = (1/2)*(grad(u) + grad(u)^T)
|
||||
const double M2 = 2.0*M;
|
||||
if (dim == 2)
|
||||
{
|
||||
L *= (grad(0,0) + grad(1,1));
|
||||
// order of the stress entries: s_xx, s_yy, s_xy
|
||||
flux(i+fnd*0) = M2*grad(0,0) + L;
|
||||
flux(i+fnd*1) = M2*grad(1,1) + L;
|
||||
flux(i+fnd*2) = M*(grad(0,1) + grad(1,0));
|
||||
}
|
||||
else if (dim == 3)
|
||||
{
|
||||
L *= (grad(0,0) + grad(1,1) + grad(2,2));
|
||||
// order of the stress entries: s_xx, s_yy, s_zz, s_xy, s_xz, s_yz
|
||||
flux(i+fnd*0) = M2*grad(0,0) + L;
|
||||
flux(i+fnd*1) = M2*grad(1,1) + L;
|
||||
flux(i+fnd*2) = M2*grad(2,2) + L;
|
||||
flux(i+fnd*3) = M*(grad(0,1) + grad(1,0));
|
||||
flux(i+fnd*4) = M*(grad(0,2) + grad(2,0));
|
||||
flux(i+fnd*5) = M*(grad(1,2) + grad(2,1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double ElasticityIntegrator::ComputeFluxEnergy(const FiniteElement &fluxelem,
|
||||
ElementTransformation &Trans,
|
||||
Vector &flux, Vector *d_energy)
|
||||
{
|
||||
const int dof = fluxelem.GetDof();
|
||||
const int dim = fluxelem.GetDim();
|
||||
const int tdim = dim*(dim+1)/2; // num. entries in a symmetric tensor
|
||||
double L, M;
|
||||
|
||||
// The MFEM_ASSERT constraints in ElasticityIntegrator::ComputeElementFlux
|
||||
// are assumed here too.
|
||||
MFEM_ASSERT(d_energy == NULL, "anisotropic estimates are not supported");
|
||||
MFEM_ASSERT(flux.Size() == dof*tdim, "invalid 'flux' vector");
|
||||
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
shape.SetSize(dof);
|
||||
#else
|
||||
Vector shape(dof);
|
||||
#endif
|
||||
double pointstress_data[6];
|
||||
Vector pointstress(pointstress_data, tdim);
|
||||
|
||||
// View of the 'flux' vector as a (dof x tdim) matrix
|
||||
DenseMatrix flux_mat(flux.GetData(), dof, tdim);
|
||||
|
||||
// Use the same integration rule as in AssembleElementMatrix, replacing 'el'
|
||||
// with 'fluxelem' when 'IntRule' is not set.
|
||||
// Should we be using a different (more accurate) rule here?
|
||||
const IntegrationRule *ir = IntRule;
|
||||
if (ir == NULL)
|
||||
{
|
||||
int order = 2 * Trans.OrderGrad(&fluxelem);
|
||||
ir = &IntRules.Get(fluxelem.GetGeomType(), order);
|
||||
}
|
||||
|
||||
double energy = 0.0;
|
||||
|
||||
for (int i = 0; i < ir->GetNPoints(); i++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir->IntPoint(i);
|
||||
fluxelem.CalcShape(ip, shape);
|
||||
|
||||
flux_mat.MultTranspose(shape, pointstress);
|
||||
|
||||
Trans.SetIntPoint(&ip);
|
||||
double w = Trans.Weight() * ip.weight;
|
||||
|
||||
M = mu->Eval(Trans, ip);
|
||||
if (lambda)
|
||||
{
|
||||
L = lambda->Eval(Trans, ip);
|
||||
}
|
||||
else
|
||||
{
|
||||
L = q_lambda * M;
|
||||
M = q_mu * M;
|
||||
}
|
||||
|
||||
// The strain energy density at a point is given by (1/2)*(s : e) where s
|
||||
// and e are the stress and strain tensors, respectively. Since we only
|
||||
// have the stress, we need to compute the strain from the stress:
|
||||
// s = 2*mu*e + lambda*tr(e)*I
|
||||
// Taking trace on both sides we find:
|
||||
// tr(s) = 2*mu*tr(e) + lambda*tr(e)*dim = (2*mu + dim*lambda)*tr(e)
|
||||
// which gives:
|
||||
// tr(e) = tr(s)/(2*mu + dim*lambda)
|
||||
// Then from the first identity above we can find the strain:
|
||||
// e = (1/(2*mu))*(s - lambda*tr(e)*I)
|
||||
|
||||
double pt_e; // point strain energy density
|
||||
const double *s = pointstress_data;
|
||||
if (dim == 2)
|
||||
{
|
||||
// s entries: s_xx, s_yy, s_xy
|
||||
const double tr_e = (s[0] + s[1])/(2*(M + L));
|
||||
L *= tr_e;
|
||||
pt_e = (0.25/M)*(s[0]*(s[0] - L) + s[1]*(s[1] - L) + 2*s[2]*s[2]);
|
||||
}
|
||||
else // (dim == 3)
|
||||
{
|
||||
// s entries: s_xx, s_yy, s_zz, s_xy, s_xz, s_yz
|
||||
const double tr_e = (s[0] + s[1] + s[2])/(2*M + 3*L);
|
||||
L *= tr_e;
|
||||
pt_e = (0.25/M)*(s[0]*(s[0] - L) + s[1]*(s[1] - L) + s[2]*(s[2] - L) +
|
||||
2*(s[3]*s[3] + s[4]*s[4] + s[5]*s[5]));
|
||||
}
|
||||
|
||||
energy += w * pt_e;
|
||||
}
|
||||
|
||||
return energy;
|
||||
}
|
||||
|
||||
void DGTraceIntegrator::AssembleFaceMatrix(const FiniteElement &el1,
|
||||
const FiniteElement &el2,
|
||||
FaceElementTransformations &Trans,
|
||||
@@ -3047,32 +3215,38 @@ void NormalInterpolator::AssembleElementMatrix2(
|
||||
}
|
||||
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
// Scalar shape functions scaled by scalar coefficient.
|
||||
// Used in the implementation of class ScalarProductInterpolator below.
|
||||
struct ShapeCoefficient : public VectorCoefficient
|
||||
{
|
||||
Coefficient &Q;
|
||||
const FiniteElement &fe;
|
||||
|
||||
ShapeCoefficient(Coefficient &q, const FiniteElement &fe_)
|
||||
: VectorCoefficient(fe_.GetDof()), Q(q), fe(fe_) { }
|
||||
|
||||
using VectorCoefficient::Eval;
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
V.SetSize(vdim);
|
||||
fe.CalcPhysShape(T, V);
|
||||
V *= Q.Eval(T, ip);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ScalarProductInterpolator::AssembleElementMatrix2(const FiniteElement &dom_fe,
|
||||
const FiniteElement &ran_fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &elmat)
|
||||
{
|
||||
// Scalar shape functions scaled by scalar coefficient
|
||||
struct ShapeCoefficient : public VectorCoefficient
|
||||
{
|
||||
Coefficient &Q;
|
||||
const FiniteElement &fe;
|
||||
|
||||
ShapeCoefficient(Coefficient &q, const FiniteElement &fe_)
|
||||
: VectorCoefficient(fe_.GetDof()), Q(q), fe(fe_) { }
|
||||
|
||||
using VectorCoefficient::Eval;
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
V.SetSize(vdim);
|
||||
fe.CalcPhysShape(T, V);
|
||||
V *= Q.Eval(T, ip);
|
||||
}
|
||||
};
|
||||
|
||||
ShapeCoefficient dom_shape_coeff(Q, dom_fe);
|
||||
internal::ShapeCoefficient dom_shape_coeff(Q, dom_fe);
|
||||
|
||||
elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
|
||||
|
||||
@@ -3209,6 +3383,35 @@ VectorCrossProductInterpolator::AssembleElementMatrix2(
|
||||
}
|
||||
|
||||
|
||||
namespace internal
|
||||
{
|
||||
|
||||
// Vector shape functions dot product with a vector coefficient.
|
||||
// Used in the implementation of class VectorInnerProductInterpolator below.
|
||||
struct VDotVShapeCoefficient : public VectorCoefficient
|
||||
{
|
||||
VectorCoefficient &VQ;
|
||||
const FiniteElement &fe;
|
||||
DenseMatrix vshape;
|
||||
Vector vc;
|
||||
|
||||
VDotVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
|
||||
: VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
|
||||
vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
|
||||
|
||||
using VectorCoefficient::Eval;
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
V.SetSize(vdim);
|
||||
VQ.Eval(vc, T, ip);
|
||||
fe.CalcPhysVShape(T, vshape);
|
||||
vshape.Mult(vc, V);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
VectorInnerProductInterpolator::AssembleElementMatrix2(
|
||||
const FiniteElement &dom_fe,
|
||||
@@ -3216,30 +3419,7 @@ VectorInnerProductInterpolator::AssembleElementMatrix2(
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &elmat)
|
||||
{
|
||||
// Vector shape functions dot product with a vector coefficient
|
||||
struct VDotVShapeCoefficient : public VectorCoefficient
|
||||
{
|
||||
VectorCoefficient &VQ;
|
||||
const FiniteElement &fe;
|
||||
DenseMatrix vshape;
|
||||
Vector vc;
|
||||
|
||||
VDotVShapeCoefficient(VectorCoefficient &vq, const FiniteElement &fe_)
|
||||
: VectorCoefficient(fe_.GetDof()), VQ(vq), fe(fe_),
|
||||
vshape(vdim, vq.GetVDim()), vc(vq.GetVDim()) { }
|
||||
|
||||
using VectorCoefficient::Eval;
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
V.SetSize(vdim);
|
||||
VQ.Eval(vc, T, ip);
|
||||
fe.CalcPhysVShape(T, vshape);
|
||||
vshape.Mult(vc, V);
|
||||
}
|
||||
};
|
||||
|
||||
VDotVShapeCoefficient dom_shape_coeff(VQ, dom_fe);
|
||||
internal::VDotVShapeCoefficient dom_shape_coeff(VQ, dom_fe);
|
||||
|
||||
elmat.SetSize(ran_fe.GetDof(),dom_fe.GetDof());
|
||||
|
||||
|
||||
+86
-6
@@ -69,12 +69,60 @@ public:
|
||||
const Vector &elfun, DenseMatrix &elmat)
|
||||
{ AssembleFaceMatrix(el1, el2, Tr, elmat); }
|
||||
|
||||
/** @brief Virtual method required for Zienkiewicz-Zhu type error estimators.
|
||||
|
||||
The purpose of the method is to compute a local "flux" finite element
|
||||
function given a local finite element solution. The "flux" function has
|
||||
to be computed in terms of its coefficients (represented by the Vector
|
||||
@a flux) which multiply the basis functions defined by the FiniteElement
|
||||
@a fluxelem. Typically, the "flux" function will have more than one
|
||||
component and consequently @a flux should be store the coefficients of
|
||||
all components: first all coefficient for component 0, then all
|
||||
coefficients for component 1, etc. What the "flux" function represents
|
||||
depends on the specific integrator. For example, in the case of
|
||||
DiffusionIntegrator, the flux is the gradient of the solution multiplied
|
||||
by the diffusion coefficient.
|
||||
|
||||
@param[in] el FiniteElement of the solution.
|
||||
@param[in] Trans The ElementTransformation describing the physical
|
||||
position of the mesh element.
|
||||
@param[in] u Solution coefficients representing the expansion of the
|
||||
solution function in the basis of @a el.
|
||||
@param[in] fluxelem FiniteElement of the "flux".
|
||||
@param[out] flux "Flux" coefficients representing the expansion of the
|
||||
"flux" function in the basis of @a fluxelem. The size
|
||||
of @a flux as a Vector has to be set by this method,
|
||||
e.g. using Vector::SetSize().
|
||||
@param[in] with_coef If zero (the default value is 1) the implementation
|
||||
of the method may choose not to scale the "flux"
|
||||
function by any coefficients describing the
|
||||
integrator.
|
||||
*/
|
||||
virtual void ComputeElementFlux(const FiniteElement &el,
|
||||
ElementTransformation &Trans,
|
||||
Vector &u,
|
||||
const FiniteElement &fluxelem,
|
||||
Vector &flux, int with_coef = 1) { }
|
||||
|
||||
/** @brief Virtual method required for Zienkiewicz-Zhu type error estimators.
|
||||
|
||||
The purpose of this method is to compute a local number that measures the
|
||||
energy of a given "flux" function (see ComputeElementFlux() for a
|
||||
description of the "flux" function). Typically, the energy of a "flux"
|
||||
function should be equal to a_local(u,u), if the "flux" is defined from
|
||||
a solution u; here a_local(.,.) denotes the element-local bilinear
|
||||
form represented by the integrator.
|
||||
|
||||
@param[in] fluxelem FiniteElement of the "flux".
|
||||
@param[in] Trans The ElementTransformation describing the physical
|
||||
position of the mesh element.
|
||||
@param[in] flux "Flux" coefficients representing the expansion of the
|
||||
"flux" function in the basis of @a fluxelem.
|
||||
@param[out] d_energy If not NULL, the given Vector should be set to
|
||||
represent directional energy split that can be used
|
||||
for anisotropic error estimation.
|
||||
@returns The computed energy.
|
||||
*/
|
||||
virtual double ComputeFluxEnergy(const FiniteElement &fluxelem,
|
||||
ElementTransformation &Trans,
|
||||
Vector &flux, Vector *d_energy = NULL)
|
||||
@@ -1706,6 +1754,7 @@ public:
|
||||
class VectorMassIntegrator: public BilinearFormIntegrator
|
||||
{
|
||||
private:
|
||||
int vdim;
|
||||
Vector shape, te_shape, vec;
|
||||
DenseMatrix partelmat;
|
||||
DenseMatrix mcoeff;
|
||||
@@ -1718,22 +1767,25 @@ private:
|
||||
public:
|
||||
/// Construct an integrator with coefficient 1.0
|
||||
VectorMassIntegrator()
|
||||
{ Q = NULL; VQ = NULL; MQ = NULL; Q_order = 0; }
|
||||
: vdim(-1), Q(NULL), VQ(NULL), MQ(NULL), Q_order(0) { }
|
||||
/** Construct an integrator with scalar coefficient q.
|
||||
If possible, save memory by using a scalar integrator since
|
||||
the resulting matrix is block diagonal with the same diagonal
|
||||
block repeated. */
|
||||
VectorMassIntegrator(Coefficient &q, int qo = 0)
|
||||
: Q(&q) { VQ = NULL; MQ = NULL; Q_order = qo; }
|
||||
: vdim(-1), Q(&q) { VQ = NULL; MQ = NULL; Q_order = qo; }
|
||||
VectorMassIntegrator(Coefficient &q, const IntegrationRule *ir)
|
||||
: BilinearFormIntegrator(ir), Q(&q)
|
||||
: BilinearFormIntegrator(ir), vdim(-1), Q(&q)
|
||||
{ VQ = NULL; MQ = NULL; Q_order = 0; }
|
||||
/// Construct an integrator with diagonal coefficient q
|
||||
VectorMassIntegrator(VectorCoefficient &q, int qo = 0)
|
||||
: VQ(&q) { Q = NULL; MQ = NULL; Q_order = qo; }
|
||||
: vdim(q.GetVDim()), VQ(&q) { Q = NULL; MQ = NULL; Q_order = qo; }
|
||||
/// Construct an integrator with matrix coefficient q
|
||||
VectorMassIntegrator(MatrixCoefficient &q, int qo = 0)
|
||||
: MQ(&q) { Q = NULL; VQ = NULL; Q_order = qo; }
|
||||
: vdim(q.GetVDim()), MQ(&q) { Q = NULL; VQ = NULL; Q_order = qo; }
|
||||
|
||||
int GetVDim() const { return vdim; }
|
||||
void SetVDim(int vdim) { this->vdim = vdim; }
|
||||
|
||||
virtual void AssembleElementMatrix(const FiniteElement &el,
|
||||
ElementTransformation &Trans,
|
||||
@@ -2018,7 +2070,8 @@ private:
|
||||
Coefficient *lambda, *mu;
|
||||
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
DenseMatrix dshape, Jinv, gshape, pelmat;
|
||||
Vector shape;
|
||||
DenseMatrix dshape, gshape, pelmat;
|
||||
Vector divshape;
|
||||
#endif
|
||||
|
||||
@@ -2033,6 +2086,33 @@ public:
|
||||
virtual void AssembleElementMatrix(const FiniteElement &,
|
||||
ElementTransformation &,
|
||||
DenseMatrix &);
|
||||
|
||||
/** Compute the stress corresponding to the local displacement @a u and
|
||||
interpolate it at the nodes of the given @a fluxelem. Only the symmetric
|
||||
part of the stress is stored, so that the size of @a flux is equal to
|
||||
the number of DOFs in @a fluxelem times dim*(dim+1)/2. In 2D, the order
|
||||
of the stress components is: s_xx, s_yy, s_xy. In 3D, it is: s_xx, s_yy,
|
||||
s_zz, s_xy, s_xz, s_yz. In other words, @a flux is the local vector for
|
||||
a FE space with dim*(dim+1)/2 vector components, based on the finite
|
||||
element @a fluxelem. */
|
||||
virtual void ComputeElementFlux(const FiniteElement &el,
|
||||
ElementTransformation &Trans,
|
||||
Vector &u,
|
||||
const FiniteElement &fluxelem,
|
||||
Vector &flux, int with_coef = 1);
|
||||
|
||||
/** Compute the element energy (integral of the strain energy density)
|
||||
corresponding to the stress represented by @a flux which is a vector of
|
||||
coefficients multiplying the basis functions defined by @a fluxelem. In
|
||||
other words, @a flux is the local vector for a FE space with
|
||||
dim*(dim+1)/2 vector components, based on the finite element @a fluxelem.
|
||||
The number of components, dim*(dim+1)/2 is such that it represents the
|
||||
symmetric part of the (symmetric) stress tensor. The order of the
|
||||
components is: s_xx, s_yy, s_xy in 2D, and s_xx, s_yy, s_zz, s_xy, s_xz,
|
||||
s_yz in 3D. */
|
||||
virtual double ComputeFluxEnergy(const FiniteElement &fluxelem,
|
||||
ElementTransformation &Trans,
|
||||
Vector &flux, Vector *d_energy = NULL);
|
||||
};
|
||||
|
||||
/** Integrator for the DG form:
|
||||
|
||||
+279
-2
@@ -87,7 +87,6 @@ double DeltaCoefficient::EvalDelta(ElementTransformation &T,
|
||||
return weight ? weight->Eval(T, ip, GetTime())*w : w;
|
||||
}
|
||||
|
||||
|
||||
void VectorCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationRule &ir)
|
||||
{
|
||||
@@ -153,11 +152,17 @@ void VectorArrayCoefficient::Eval(Vector &V, ElementTransformation &T,
|
||||
}
|
||||
|
||||
VectorGridFunctionCoefficient::VectorGridFunctionCoefficient (
|
||||
GridFunction *gf) : VectorCoefficient (gf -> VectorDim())
|
||||
GridFunction *gf)
|
||||
: VectorCoefficient ((gf) ? gf -> VectorDim() : 0)
|
||||
{
|
||||
GridFunc = gf;
|
||||
}
|
||||
|
||||
void VectorGridFunctionCoefficient::SetGridFunction(GridFunction *gf)
|
||||
{
|
||||
GridFunc = gf; vdim = (gf) ? gf -> VectorDim() : 0;
|
||||
}
|
||||
|
||||
void VectorGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
@@ -170,6 +175,64 @@ void VectorGridFunctionCoefficient::Eval(
|
||||
GridFunc->GetVectorValues(T, ir, M);
|
||||
}
|
||||
|
||||
GradientGridFunctionCoefficient::GradientGridFunctionCoefficient (
|
||||
GridFunction *gf)
|
||||
: VectorCoefficient((gf) ?
|
||||
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0)
|
||||
{
|
||||
GridFunc = gf;
|
||||
}
|
||||
|
||||
void GradientGridFunctionCoefficient::SetGridFunction(GridFunction *gf)
|
||||
{
|
||||
GridFunc = gf; vdim = (gf) ?
|
||||
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0;
|
||||
}
|
||||
|
||||
void GradientGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
GridFunc->GetGradient(T, V);
|
||||
}
|
||||
|
||||
void GradientGridFunctionCoefficient::Eval(
|
||||
DenseMatrix &M, ElementTransformation &T, const IntegrationRule &ir)
|
||||
{
|
||||
GridFunc->GetGradients(T, ir, M);
|
||||
}
|
||||
|
||||
CurlGridFunctionCoefficient::CurlGridFunctionCoefficient (
|
||||
GridFunction *gf)
|
||||
: VectorCoefficient ((gf) ?
|
||||
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0)
|
||||
{
|
||||
GridFunc = gf;
|
||||
}
|
||||
|
||||
void CurlGridFunctionCoefficient::SetGridFunction(GridFunction *gf)
|
||||
{
|
||||
GridFunc = gf; vdim = (gf) ?
|
||||
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0;
|
||||
}
|
||||
|
||||
void CurlGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
GridFunc->GetCurl(T, V);
|
||||
}
|
||||
|
||||
DivergenceGridFunctionCoefficient::DivergenceGridFunctionCoefficient (
|
||||
GridFunction *gf) : Coefficient()
|
||||
{
|
||||
GridFunc = gf;
|
||||
}
|
||||
|
||||
double DivergenceGridFunctionCoefficient::Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
return GridFunc->GetDivergence(T);
|
||||
}
|
||||
|
||||
void VectorDeltaCoefficient::SetDirection(const Vector &_d)
|
||||
{
|
||||
dir = _d;
|
||||
@@ -287,6 +350,220 @@ void MatrixRestrictedCoefficient::Eval(DenseMatrix &K, ElementTransformation &T,
|
||||
}
|
||||
}
|
||||
|
||||
InnerProductCoefficient::InnerProductCoefficient(VectorCoefficient &A,
|
||||
VectorCoefficient &B)
|
||||
: a(&A), b(&B)
|
||||
{
|
||||
MFEM_ASSERT(A.GetVDim() == B.GetVDim(),
|
||||
"InnerProductCoefficient: "
|
||||
"Arguments have incompatible dimensions.");
|
||||
}
|
||||
|
||||
double InnerProductCoefficient::Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
a->Eval(va, T, ip);
|
||||
b->Eval(vb, T, ip);
|
||||
return va * vb;
|
||||
}
|
||||
|
||||
VectorRotProductCoefficient::VectorRotProductCoefficient(VectorCoefficient &A,
|
||||
VectorCoefficient &B)
|
||||
: a(&A), b(&B), va(A.GetVDim()), vb(B.GetVDim())
|
||||
{
|
||||
MFEM_ASSERT(A.GetVDim() == 2 && B.GetVDim() == 2,
|
||||
"VectorRotProductCoefficient: "
|
||||
"Arguments must have dimension equal to two.");
|
||||
}
|
||||
|
||||
double VectorRotProductCoefficient::Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
a->Eval(va, T, ip);
|
||||
b->Eval(vb, T, ip);
|
||||
return va[0] * vb[1] - va[1] * vb[0];
|
||||
}
|
||||
|
||||
DeterminantCoefficient::DeterminantCoefficient(MatrixCoefficient &A)
|
||||
: a(&A), ma(A.GetHeight(), A.GetWidth())
|
||||
{
|
||||
MFEM_ASSERT(A.GetHeight() == A.GetWidth(),
|
||||
"DeterminantCoefficient: "
|
||||
"Argument must be a square matrix.");
|
||||
}
|
||||
|
||||
double DeterminantCoefficient::Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
a->Eval(ma, T, ip);
|
||||
return ma.Det();
|
||||
}
|
||||
|
||||
VectorSumCoefficient::VectorSumCoefficient(VectorCoefficient &A,
|
||||
VectorCoefficient &B,
|
||||
double _alpha, double _beta)
|
||||
: VectorCoefficient(A.GetVDim()), a(&A), b(&B), alpha(_alpha), beta(_beta),
|
||||
va(A.GetVDim())
|
||||
{
|
||||
MFEM_ASSERT(A.GetVDim() == B.GetVDim(),
|
||||
"VectorSumCoefficient: "
|
||||
"Arguments must have the same dimension.");
|
||||
}
|
||||
|
||||
void VectorSumCoefficient::Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
b->Eval(V, T, ip);
|
||||
if ( beta != 1.0 ) { V *= beta; }
|
||||
a->Eval(va, T, ip);
|
||||
V.Add(alpha, va);
|
||||
}
|
||||
|
||||
ScalarVectorProductCoefficient::ScalarVectorProductCoefficient(
|
||||
Coefficient &A,
|
||||
VectorCoefficient &B)
|
||||
: VectorCoefficient(B.GetVDim()), a(&A), b(&B)
|
||||
{}
|
||||
|
||||
void ScalarVectorProductCoefficient::Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
double sa = a->Eval(T, ip);
|
||||
b->Eval(V, T, ip);
|
||||
V *= sa;
|
||||
}
|
||||
|
||||
VectorCrossProductCoefficient::VectorCrossProductCoefficient(
|
||||
VectorCoefficient &A,
|
||||
VectorCoefficient &B)
|
||||
: VectorCoefficient(3), a(&A), b(&B), va(A.GetVDim()), vb(B.GetVDim())
|
||||
{
|
||||
MFEM_ASSERT(A.GetVDim() == 3 && B.GetVDim() == 3,
|
||||
"VectorCrossProductCoefficient: "
|
||||
"Arguments must have dimension equal to three.");
|
||||
}
|
||||
|
||||
void VectorCrossProductCoefficient::Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
a->Eval(va, T, ip);
|
||||
b->Eval(vb, T, ip);
|
||||
V.SetSize(3);
|
||||
V[0] = va[1] * vb[2] - va[2] * vb[1];
|
||||
V[1] = va[2] * vb[0] - va[0] * vb[2];
|
||||
V[2] = va[0] * vb[1] - va[1] * vb[0];
|
||||
}
|
||||
|
||||
MatVecCoefficient::MatVecCoefficient(MatrixCoefficient &A,
|
||||
VectorCoefficient &B)
|
||||
: VectorCoefficient(A.GetHeight()), a(&A), b(&B),
|
||||
ma(A.GetHeight(), A.GetWidth()), vb(B.GetVDim())
|
||||
{
|
||||
MFEM_ASSERT(A.GetWidth() == B.GetVDim(),
|
||||
"MatVecCoefficient: Arguments have incompatible dimensions.");
|
||||
}
|
||||
|
||||
void MatVecCoefficient::Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
a->Eval(ma, T, ip);
|
||||
b->Eval(vb, T, ip);
|
||||
ma.Mult(vb, V);
|
||||
}
|
||||
|
||||
void IdentityMatrixCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
M.SetSize(dim);
|
||||
M = 0.0;
|
||||
for (int d=0; d<dim; d++) { M(d,d) = 1.0; }
|
||||
}
|
||||
|
||||
MatrixSumCoefficient::MatrixSumCoefficient(MatrixCoefficient &A,
|
||||
MatrixCoefficient &B,
|
||||
double _alpha, double _beta)
|
||||
: MatrixCoefficient(A.GetHeight(), A.GetWidth()),
|
||||
a(&A), b(&B), alpha(_alpha), beta(_beta),
|
||||
ma(A.GetHeight(), A.GetWidth())
|
||||
{
|
||||
MFEM_ASSERT(A.GetHeight() == B.GetHeight() && A.GetWidth() == B.GetWidth(),
|
||||
"MatrixSumCoefficient: "
|
||||
"Arguments must have the same dimensions.");
|
||||
}
|
||||
|
||||
void MatrixSumCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
b->Eval(M, T, ip);
|
||||
if ( beta != 1.0 ) { M *= beta; }
|
||||
a->Eval(ma, T, ip);
|
||||
M.Add(alpha, ma);
|
||||
}
|
||||
|
||||
ScalarMatrixProductCoefficient::ScalarMatrixProductCoefficient(
|
||||
Coefficient &A,
|
||||
MatrixCoefficient &B)
|
||||
: MatrixCoefficient(B.GetHeight(), B.GetWidth()), a(&A), b(&B)
|
||||
{}
|
||||
|
||||
void ScalarMatrixProductCoefficient::Eval(DenseMatrix &M,
|
||||
ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
double sa = a->Eval(T, ip);
|
||||
b->Eval(M, T, ip);
|
||||
M *= sa;
|
||||
}
|
||||
|
||||
TransposeMatrixCoefficient::TransposeMatrixCoefficient(MatrixCoefficient &A)
|
||||
: MatrixCoefficient(A.GetWidth(), A.GetHeight()), a(&A)
|
||||
{}
|
||||
|
||||
void TransposeMatrixCoefficient::Eval(DenseMatrix &M,
|
||||
ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
a->Eval(M, T, ip);
|
||||
M.Transpose();
|
||||
}
|
||||
|
||||
InverseMatrixCoefficient::InverseMatrixCoefficient(MatrixCoefficient &A)
|
||||
: MatrixCoefficient(A.GetHeight(), A.GetWidth()), a(&A)
|
||||
{
|
||||
MFEM_ASSERT(A.GetHeight() == A.GetWidth(),
|
||||
"InverseMatrixCoefficient: "
|
||||
"Argument must be a square matrix.");
|
||||
}
|
||||
|
||||
void InverseMatrixCoefficient::Eval(DenseMatrix &M,
|
||||
ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
a->Eval(M, T, ip);
|
||||
M.Invert();
|
||||
}
|
||||
|
||||
OuterProductCoefficient::OuterProductCoefficient(VectorCoefficient &A,
|
||||
VectorCoefficient &B)
|
||||
: MatrixCoefficient(A.GetVDim(), B.GetVDim()), a(&A), b(&B),
|
||||
va(A.GetVDim()), vb(B.GetVDim())
|
||||
{}
|
||||
|
||||
void OuterProductCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
a->Eval(va, T, ip);
|
||||
b->Eval(vb, T, ip);
|
||||
M.SetSize(va.Size(), vb.Size());
|
||||
for (int i=0; i<va.Size(); i++)
|
||||
{
|
||||
for (int j=0; j<vb.Size(); j++)
|
||||
{
|
||||
M(i, j) = va[i] * vb[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double LpNormLoop(double p, Coefficient &coeff, Mesh &mesh,
|
||||
const IntegrationRule *irs[])
|
||||
{
|
||||
|
||||
+368
-6
@@ -39,9 +39,19 @@ public:
|
||||
void SetTime(double t) { time = t; }
|
||||
double GetTime() { return time; }
|
||||
|
||||
/** @brief Evaluate the coefficient in the element described by @a T at the
|
||||
point @a ip. */
|
||||
/** @note When this method is called, the caller must make sure that the
|
||||
IntegrationPoint associated with @a T is the same as @a ip. This can be
|
||||
achieved by calling T.SetIntPoint(&ip). */
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip) = 0;
|
||||
|
||||
/** @brief Evaluate the coefficient in the element described by @a T at the
|
||||
point @a ip at time @a t. */
|
||||
/** @note When this method is called, the caller must make sure that the
|
||||
IntegrationPoint associated with @a T is the same as @a ip. This can be
|
||||
achieved by calling T.SetIntPoint(&ip). */
|
||||
double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip, double t)
|
||||
{
|
||||
@@ -157,6 +167,7 @@ private:
|
||||
int Component;
|
||||
|
||||
public:
|
||||
GridFunctionCoefficient() : GridF(NULL), Component(1) { }
|
||||
/** Construct GridFunctionCoefficient from a given GridFunction, and
|
||||
optionally specify a component to use if it is a vector GridFunction. */
|
||||
GridFunctionCoefficient (GridFunction *gf, int comp = 1)
|
||||
@@ -242,7 +253,7 @@ public:
|
||||
Coefficient *Weight() { return weight; }
|
||||
void GetDeltaCenter(Vector& center);
|
||||
/// Return the Scale() multiplied by the weight Coefficient, if any.
|
||||
double EvalDelta(ElementTransformation &T, const IntegrationPoint &ip);
|
||||
virtual double EvalDelta(ElementTransformation &T, const IntegrationPoint &ip);
|
||||
/** @brief A DeltaFunction cannot be evaluated. Calling this method will
|
||||
cause an MFEM error, terminating the application. */
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
|
||||
@@ -280,11 +291,26 @@ public:
|
||||
/// Returns dimension of the vector.
|
||||
int GetVDim() { return vdim; }
|
||||
|
||||
/** @brief Evaluate the vector coefficient in the element described by @a T
|
||||
at the point @a ip, storing the result in @a V. */
|
||||
/** @note When this method is called, the caller must make sure that the
|
||||
IntegrationPoint associated with @a T is the same as @a ip. This can be
|
||||
achieved by calling T.SetIntPoint(&ip). */
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip) = 0;
|
||||
|
||||
// General implementation using the Eval method for one IntegrationPoint.
|
||||
// Can be overloaded for more efficient implementation.
|
||||
/** @brief Evaluate the vector coefficient in the element described by @a T
|
||||
at all points of @a ir, storing the result in @a M. */
|
||||
/** The dimensions of @a M are GetVDim() by ir.GetNPoints() and they must be
|
||||
set by the implementation of this method.
|
||||
|
||||
The general implementation provided by the base class (using the Eval
|
||||
method for one IntegrationPoint at a time) can be overloaded for more
|
||||
efficient implementation.
|
||||
|
||||
@note The IntegrationPoint associated with @a T is not used, and this
|
||||
method will generally modify this IntegrationPoint associated with @a T.
|
||||
*/
|
||||
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationRule &ir);
|
||||
|
||||
@@ -374,9 +400,10 @@ protected:
|
||||
GridFunction *GridFunc;
|
||||
|
||||
public:
|
||||
VectorGridFunctionCoefficient() : VectorCoefficient(0), GridFunc(NULL) { }
|
||||
VectorGridFunctionCoefficient(GridFunction *gf);
|
||||
|
||||
void SetGridFunction(GridFunction *gf) { GridFunc = gf; }
|
||||
void SetGridFunction(GridFunction *gf);
|
||||
GridFunction * GetGridFunction() const { return GridFunc; }
|
||||
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
@@ -388,6 +415,63 @@ public:
|
||||
virtual ~VectorGridFunctionCoefficient() { }
|
||||
};
|
||||
|
||||
/// Vector coefficient defined as the Gradient of a scalar GridFunction
|
||||
class GradientGridFunctionCoefficient : public VectorCoefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *GridFunc;
|
||||
|
||||
public:
|
||||
GradientGridFunctionCoefficient(GridFunction *gf);
|
||||
|
||||
void SetGridFunction(GridFunction *gf);
|
||||
GridFunction * GetGridFunction() const { return GridFunc; }
|
||||
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
|
||||
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationRule &ir);
|
||||
|
||||
virtual ~GradientGridFunctionCoefficient() { }
|
||||
};
|
||||
|
||||
/// Vector coefficient defined as the Curl of a vector GridFunction
|
||||
class CurlGridFunctionCoefficient : public VectorCoefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *GridFunc;
|
||||
|
||||
public:
|
||||
CurlGridFunctionCoefficient(GridFunction *gf);
|
||||
|
||||
void SetGridFunction(GridFunction *gf);
|
||||
GridFunction * GetGridFunction() const { return GridFunc; }
|
||||
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
|
||||
virtual ~CurlGridFunctionCoefficient() { }
|
||||
};
|
||||
|
||||
/// Scalar coefficient defined as the Divergence of a vector GridFunction
|
||||
class DivergenceGridFunctionCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *GridFunc;
|
||||
|
||||
public:
|
||||
DivergenceGridFunctionCoefficient(GridFunction *gf);
|
||||
|
||||
void SetGridFunction(GridFunction *gf) { GridFunc = gf; }
|
||||
GridFunction * GetGridFunction() const { return GridFunc; }
|
||||
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
|
||||
virtual ~DivergenceGridFunctionCoefficient() { }
|
||||
};
|
||||
|
||||
/// VectorDeltaCoefficient: DeltaCoefficient with a direction
|
||||
class VectorDeltaCoefficient : public VectorCoefficient
|
||||
{
|
||||
@@ -420,8 +504,8 @@ public:
|
||||
/** @brief Return the specified direction vector multiplied by the value
|
||||
returned by DeltaCoefficient::EvalDelta() of the associated scalar
|
||||
DeltaCoefficient. */
|
||||
void EvalDelta(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
virtual void EvalDelta(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
using VectorCoefficient::Eval;
|
||||
/** @brief A VectorDeltaFunction cannot be evaluated. Calling this method
|
||||
will cause an MFEM error, terminating the application. */
|
||||
@@ -470,6 +554,11 @@ public:
|
||||
// For backward compatibility
|
||||
int GetVDim() const { return width; }
|
||||
|
||||
/** @brief Evaluate the matrix coefficient in the element described by @a T
|
||||
at the point @a ip, storing the result in @a K. */
|
||||
/** @note When this method is called, the caller must make sure that the
|
||||
IntegrationPoint associated with @a T is the same as @a ip. This can be
|
||||
achieved by calling T.SetIntPoint(&ip). */
|
||||
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
|
||||
const IntegrationPoint &ip) = 0;
|
||||
|
||||
@@ -571,6 +660,279 @@ public:
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Coefficients based on sums and products of other coefficients
|
||||
|
||||
/// Scalar coefficient defined as the sum of two scalar coefficients
|
||||
class SumCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
Coefficient * a;
|
||||
Coefficient * b;
|
||||
|
||||
double alpha;
|
||||
double beta;
|
||||
|
||||
public:
|
||||
// Result is _alpha * A + _beta * B
|
||||
SumCoefficient(Coefficient &A, Coefficient &B,
|
||||
double _alpha = 1.0, double _beta = 1.0)
|
||||
: a(&A), b(&B), alpha(_alpha), beta(_beta) { }
|
||||
|
||||
/// Evaluate the coefficient
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{ return alpha * a->Eval(T, ip) + beta * b->Eval(T, ip); }
|
||||
};
|
||||
|
||||
/// Scalar coefficient defined as the product of two scalar coefficients
|
||||
class ProductCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
Coefficient * a;
|
||||
Coefficient * b;
|
||||
|
||||
public:
|
||||
ProductCoefficient(Coefficient &A, Coefficient &B)
|
||||
: a(&A), b(&B) { }
|
||||
|
||||
/// Evaluate the coefficient
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{ return a->Eval(T, ip) * b->Eval(T, ip); }
|
||||
};
|
||||
|
||||
/// Scalar coefficient defined as a scalar raised to a power
|
||||
class PowerCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
Coefficient * a;
|
||||
|
||||
double p;
|
||||
|
||||
public:
|
||||
// Result is A^p
|
||||
PowerCoefficient(Coefficient &A, double _p)
|
||||
: a(&A), p(_p) { }
|
||||
|
||||
/// Evaluate the coefficient
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{ return pow(a->Eval(T, ip), p); }
|
||||
};
|
||||
|
||||
/// Scalar coefficient defined as the inner product of two vector coefficients
|
||||
class InnerProductCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
VectorCoefficient * a;
|
||||
VectorCoefficient * b;
|
||||
|
||||
mutable Vector va;
|
||||
mutable Vector vb;
|
||||
public:
|
||||
InnerProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
|
||||
|
||||
/// Evaluate the coefficient
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Scalar coefficient defined as a cross product of two vectors in 2D
|
||||
class VectorRotProductCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
VectorCoefficient * a;
|
||||
VectorCoefficient * b;
|
||||
|
||||
mutable Vector va;
|
||||
mutable Vector vb;
|
||||
|
||||
public:
|
||||
VectorRotProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
|
||||
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Scalar coefficient defined as the determinant of a matrix coefficient
|
||||
class DeterminantCoefficient : public Coefficient
|
||||
{
|
||||
private:
|
||||
MatrixCoefficient * a;
|
||||
|
||||
mutable DenseMatrix ma;
|
||||
|
||||
public:
|
||||
DeterminantCoefficient(MatrixCoefficient &A);
|
||||
|
||||
/// Evaluate the coefficient
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Vector coefficient defined as the sum of two vector coefficients
|
||||
class VectorSumCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
VectorCoefficient * a;
|
||||
VectorCoefficient * b;
|
||||
|
||||
double alpha;
|
||||
double beta;
|
||||
|
||||
mutable Vector va;
|
||||
|
||||
public:
|
||||
// Result is _alpha * A + _beta * B
|
||||
VectorSumCoefficient(VectorCoefficient &A, VectorCoefficient &B,
|
||||
double _alpha = 1.0, double _beta = 1.0);
|
||||
|
||||
/// Evaluate the coefficient
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Vector coefficient defined as a product of a scalar and a vector
|
||||
class ScalarVectorProductCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
Coefficient * a;
|
||||
VectorCoefficient * b;
|
||||
|
||||
public:
|
||||
ScalarVectorProductCoefficient(Coefficient &A, VectorCoefficient &B);
|
||||
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Vector coefficient defined as a cross product of two vectors
|
||||
class VectorCrossProductCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
VectorCoefficient * a;
|
||||
VectorCoefficient * b;
|
||||
|
||||
mutable Vector va;
|
||||
mutable Vector vb;
|
||||
|
||||
public:
|
||||
VectorCrossProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
|
||||
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Vector coefficient defined as a matrix vector product
|
||||
class MatVecCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
MatrixCoefficient * a;
|
||||
VectorCoefficient * b;
|
||||
|
||||
mutable DenseMatrix ma;
|
||||
mutable Vector vb;
|
||||
|
||||
public:
|
||||
MatVecCoefficient(MatrixCoefficient &A, VectorCoefficient &B);
|
||||
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Matrix coefficient defined as the identity of dimension d
|
||||
class IdentityMatrixCoefficient : public MatrixCoefficient
|
||||
{
|
||||
private:
|
||||
int dim;
|
||||
|
||||
public:
|
||||
IdentityMatrixCoefficient(int d)
|
||||
: MatrixCoefficient(d, d), dim(d) { }
|
||||
|
||||
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Matrix coefficient defined as the sum of two matrix coefficients
|
||||
class MatrixSumCoefficient : public MatrixCoefficient
|
||||
{
|
||||
private:
|
||||
MatrixCoefficient * a;
|
||||
MatrixCoefficient * b;
|
||||
|
||||
double alpha;
|
||||
double beta;
|
||||
|
||||
mutable DenseMatrix ma;
|
||||
|
||||
public:
|
||||
// Result is _alpha * A + _beta * B
|
||||
MatrixSumCoefficient(MatrixCoefficient &A, MatrixCoefficient &B,
|
||||
double _alpha = 1.0, double _beta = 1.0);
|
||||
|
||||
/// Evaluate the coefficient
|
||||
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Matrix coefficient defined as a product of a scalar and a matrix
|
||||
class ScalarMatrixProductCoefficient : public MatrixCoefficient
|
||||
{
|
||||
private:
|
||||
Coefficient * a;
|
||||
MatrixCoefficient * b;
|
||||
|
||||
public:
|
||||
ScalarMatrixProductCoefficient(Coefficient &A, MatrixCoefficient &B);
|
||||
|
||||
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Matrix coefficient defined as the transpose a matrix
|
||||
class TransposeMatrixCoefficient : public MatrixCoefficient
|
||||
{
|
||||
private:
|
||||
MatrixCoefficient * a;
|
||||
|
||||
public:
|
||||
TransposeMatrixCoefficient(MatrixCoefficient &A);
|
||||
|
||||
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Matrix coefficient defined as the inverse a matrix
|
||||
class InverseMatrixCoefficient : public MatrixCoefficient
|
||||
{
|
||||
private:
|
||||
MatrixCoefficient * a;
|
||||
|
||||
public:
|
||||
InverseMatrixCoefficient(MatrixCoefficient &A);
|
||||
|
||||
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/// Matrix coefficient defined as the outer product of two vectors
|
||||
class OuterProductCoefficient : public MatrixCoefficient
|
||||
{
|
||||
private:
|
||||
VectorCoefficient * a;
|
||||
VectorCoefficient * b;
|
||||
|
||||
mutable Vector va;
|
||||
mutable Vector vb;
|
||||
|
||||
public:
|
||||
OuterProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
|
||||
|
||||
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
|
||||
const IntegrationPoint &ip);
|
||||
};
|
||||
|
||||
/** Compute the Lp norm of a function f.
|
||||
\f$ \| f \|_{Lp} = ( \int_\Omega | f |^p d\Omega)^{1/p} \f$ */
|
||||
double ComputeLpNorm(double p, Coefficient &coeff, Mesh &mesh,
|
||||
|
||||
@@ -699,8 +699,7 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
n_topo["type"] = "unstructured";
|
||||
n_topo["coordset"] = coordset_name;
|
||||
|
||||
Element::Type ele_type = static_cast<Element::Type>(mesh->GetElement(
|
||||
0)->GetType());
|
||||
Element::Type ele_type = mesh->GetElementType(0);
|
||||
|
||||
std::string ele_shape = ElementTypeToShapeName(ele_type);
|
||||
|
||||
@@ -774,8 +773,7 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
|
||||
n_bndry_topo["type"] = "unstructured";
|
||||
n_bndry_topo["coordset"] = coordset_name;
|
||||
|
||||
Element::Type bndry_ele_type = static_cast<Element::Type>(mesh->GetBdrElement(
|
||||
0)->GetType());
|
||||
Element::Type bndry_ele_type = mesh->GetBdrElementType(0);
|
||||
|
||||
std::string bndry_ele_shape = ElementTypeToShapeName(bndry_ele_type);
|
||||
|
||||
@@ -1163,6 +1161,8 @@ ConduitDataCollection::ElementTypeToShapeName(Element::Type element_type)
|
||||
case Element::QUADRILATERAL: return "quad";
|
||||
case Element::TETRAHEDRON: return "tet";
|
||||
case Element::HEXAHEDRON: return "hex";
|
||||
case Element::WEDGE:
|
||||
default: ;
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
|
||||
+3
-1
@@ -367,7 +367,8 @@ int InverseElementTransformation::Transform(const Vector &pt,
|
||||
}
|
||||
|
||||
|
||||
void IsoparametricTransformation::SetIdentityTransformation(int GeomType)
|
||||
void IsoparametricTransformation::SetIdentityTransformation(
|
||||
Geometry::Type GeomType)
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -377,6 +378,7 @@ void IsoparametricTransformation::SetIdentityTransformation(int GeomType)
|
||||
case Geometry::SQUARE : FElem = &QuadrilateralFE; break;
|
||||
case Geometry::TETRAHEDRON : FElem = &TetrahedronFE; break;
|
||||
case Geometry::CUBE : FElem = &HexahedronFE; break;
|
||||
case Geometry::PRISM : FElem = &WedgeFE; break;
|
||||
default:
|
||||
MFEM_ABORT("unknown Geometry::Type!");
|
||||
}
|
||||
|
||||
+4
-3
@@ -34,7 +34,8 @@ protected:
|
||||
ADJUGATE_MASK = 4,
|
||||
INVERSE_MASK = 8
|
||||
};
|
||||
int geom, space_dim;
|
||||
Geometry::Type geom;
|
||||
int space_dim;
|
||||
|
||||
// Evaluate the Jacobian of the transformation at the IntPoint and store it
|
||||
// in dFdx.
|
||||
@@ -82,7 +83,7 @@ public:
|
||||
virtual int OrderGrad(const FiniteElement *fe) = 0;
|
||||
|
||||
/// Return the Geometry::Type of the reference element.
|
||||
int GetGeometryType() const { return geom; }
|
||||
Geometry::Type GetGeometryType() const { return geom; }
|
||||
|
||||
/// Return the dimension of the reference element.
|
||||
int GetDimension() const { return Geometry::Dimension[geom]; }
|
||||
@@ -312,7 +313,7 @@ public:
|
||||
DenseMatrix &GetPointMat() { return PointMat; }
|
||||
void FinalizeTransformation() { space_dim = PointMat.Height(); }
|
||||
|
||||
void SetIdentityTransformation(int GeomType);
|
||||
void SetIdentityTransformation(Geometry::Type GeomType);
|
||||
|
||||
virtual void Transform(const IntegrationPoint &, Vector &);
|
||||
virtual void Transform(const IntegrationRule &, DenseMatrix &);
|
||||
|
||||
+3
-2
@@ -17,13 +17,14 @@ namespace mfem
|
||||
void ZienkiewiczZhuEstimator::ComputeEstimates()
|
||||
{
|
||||
flux_space->Update(false);
|
||||
// In parallel, 'flux' can be a GridFunction, as long as 'flux_space' is a
|
||||
// ParFiniteElementSpace and 'solution' is a ParGridFunction.
|
||||
GridFunction flux(flux_space);
|
||||
|
||||
if (!anisotropic) { aniso_flags.SetSize(0); }
|
||||
const int with_subdomains = 1;
|
||||
total_error = ZZErrorEstimator(*integ, *solution, flux, error_estimates,
|
||||
anisotropic ? &aniso_flags : NULL,
|
||||
with_subdomains);
|
||||
flux_averaging);
|
||||
|
||||
current_sequence = solution->FESpace()->GetMesh()->GetSequence();
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ protected:
|
||||
double total_error;
|
||||
bool anisotropic;
|
||||
Array<int> aniso_flags;
|
||||
int flux_averaging; // see SetFluxAveraging()
|
||||
|
||||
BilinearFormIntegrator *integ; ///< Not owned.
|
||||
GridFunction *solution; ///< Not owned.
|
||||
@@ -109,6 +110,7 @@ public:
|
||||
: current_sequence(-1),
|
||||
total_error(),
|
||||
anisotropic(false),
|
||||
flux_averaging(0),
|
||||
integ(&integ),
|
||||
solution(&sol),
|
||||
flux_space(flux_fes),
|
||||
@@ -127,6 +129,7 @@ public:
|
||||
: current_sequence(-1),
|
||||
total_error(),
|
||||
anisotropic(false),
|
||||
flux_averaging(0),
|
||||
integ(&integ),
|
||||
solution(&sol),
|
||||
flux_space(&flux_fes),
|
||||
@@ -138,6 +141,14 @@ public:
|
||||
ComputeFluxEnergy() method. */
|
||||
void SetAnisotropic(bool aniso = true) { anisotropic = aniso; }
|
||||
|
||||
/** @brief Set the way the flux is averaged (smoothed) across elements.
|
||||
|
||||
When @a fa is zero (default), averaging is performed globally. When @a fa
|
||||
is non-zero, the flux averaging is performed locally for each mesh
|
||||
attribute, i.e. the flux is not averaged across interfaces between
|
||||
different mesh attributes. */
|
||||
void SetFluxAveraging(int fa) { flux_averaging = fa; }
|
||||
|
||||
/// Return the total error from the last error estimate.
|
||||
double GetTotalError() const { return total_error; }
|
||||
|
||||
|
||||
+641
-2
@@ -22,7 +22,7 @@ namespace mfem
|
||||
|
||||
using namespace std;
|
||||
|
||||
FiniteElement::FiniteElement(int D, int G, int Do, int O, int F)
|
||||
FiniteElement::FiniteElement(int D, Geometry::Type G, int Do, int O, int F)
|
||||
: Nodes(Do)
|
||||
{
|
||||
Dim = D ; GeomType = G ; Dof = Do ; Order = O ; FuncSpace = F;
|
||||
@@ -114,6 +114,12 @@ void FiniteElement::GetLocalInterpolation (ElementTransformation &Trans,
|
||||
mfem_error ("GetLocalInterpolation (...) is not overloaded !");
|
||||
}
|
||||
|
||||
void FiniteElement::GetLocalRestriction(ElementTransformation &,
|
||||
DenseMatrix &) const
|
||||
{
|
||||
mfem_error("FiniteElement::GetLocalRestriction() is not overloaded !");
|
||||
}
|
||||
|
||||
void FiniteElement::GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -292,6 +298,51 @@ void NodalFiniteElement::ProjectCurl_2D(
|
||||
}
|
||||
}
|
||||
|
||||
void InvertLinearTrans(ElementTransformation &trans,
|
||||
const IntegrationPoint &pt, Vector &x)
|
||||
{
|
||||
// invert a linear transform with one Newton step
|
||||
IntegrationPoint p0;
|
||||
p0.Set3(0, 0, 0);
|
||||
trans.Transform(p0, x);
|
||||
|
||||
double store[3];
|
||||
Vector v(store, x.Size());
|
||||
pt.Get(v, x.Size());
|
||||
v -= x;
|
||||
|
||||
trans.InverseJacobian().Mult(v, x);
|
||||
}
|
||||
|
||||
void NodalFiniteElement::GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{
|
||||
IntegrationPoint ipt;
|
||||
Vector pt(&ipt.x, Dim);
|
||||
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector c_shape(Dof);
|
||||
#endif
|
||||
|
||||
Trans.SetIntPoint(&Nodes[0]);
|
||||
|
||||
for (int j = 0; j < Dof; j++)
|
||||
{
|
||||
InvertLinearTrans(Trans, Nodes[j], pt);
|
||||
if (Geometries.CheckPoint(GeomType, ipt)) // do we need an epsilon here?
|
||||
{
|
||||
CalcShape(ipt, c_shape);
|
||||
R.SetRow(j, c_shape);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the whole row to avoid valgrind warnings in R.Threshold().
|
||||
R.SetRow(j, infinity());
|
||||
}
|
||||
}
|
||||
R.Threshold(1e-12);
|
||||
}
|
||||
|
||||
void NodalFiniteElement::Project (
|
||||
Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
|
||||
{
|
||||
@@ -466,6 +517,24 @@ void PositiveFiniteElement::Project(
|
||||
}
|
||||
}
|
||||
|
||||
void PositiveFiniteElement::Project(
|
||||
VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
|
||||
{
|
||||
MFEM_ASSERT(dofs.Size() == vc.GetVDim()*Dof, "");
|
||||
Vector x(vc.GetVDim());
|
||||
|
||||
for (int i = 0; i < Dof; i++)
|
||||
{
|
||||
const IntegrationPoint &ip = Nodes.IntPoint(i);
|
||||
Trans.SetIntPoint(&ip);
|
||||
vc.Eval (x, Trans, ip);
|
||||
for (int j = 0; j < x.Size(); j++)
|
||||
{
|
||||
dofs(Dof*j+i) = x(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PositiveFiniteElement::Project(
|
||||
const FiniteElement &fe, ElementTransformation &Trans, DenseMatrix &I) const
|
||||
{
|
||||
@@ -933,6 +1002,90 @@ void VectorFiniteElement::LocalInterpolation_ND(
|
||||
}
|
||||
}
|
||||
|
||||
void VectorFiniteElement::LocalRestriction_RT(
|
||||
const double *nk, const Array<int> &d2n, ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{
|
||||
double pt_data[Geometry::MaxDim];
|
||||
IntegrationPoint ip;
|
||||
Vector pt(pt_data, Dim);
|
||||
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
DenseMatrix vshape(Dof, Dim);
|
||||
#endif
|
||||
|
||||
Trans.SetIntPoint(&Geometries.GetCenter(GeomType));
|
||||
const DenseMatrix &J = Trans.Jacobian();
|
||||
const double weight = Trans.Weight();
|
||||
for (int j = 0; j < Dof; j++)
|
||||
{
|
||||
InvertLinearTrans(Trans, Nodes.IntPoint(j), pt);
|
||||
ip.Set(pt_data, Dim);
|
||||
if (Geometries.CheckPoint(GeomType, ip)) // do we need an epsilon here?
|
||||
{
|
||||
CalcVShape(ip, vshape);
|
||||
J.MultTranspose(nk+Dim*d2n[j], pt_data);
|
||||
pt /= weight;
|
||||
for (int k = 0; k < Dof; k++)
|
||||
{
|
||||
double R_jk = 0.0;
|
||||
for (int d = 0; d < Dim; d++)
|
||||
{
|
||||
R_jk += vshape(k,d)*pt_data[d];
|
||||
}
|
||||
R(j,k) = R_jk;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the whole row to avoid valgrind warnings in R.Threshold().
|
||||
R.SetRow(j, infinity());
|
||||
}
|
||||
}
|
||||
R.Threshold(1e-12);
|
||||
}
|
||||
|
||||
void VectorFiniteElement::LocalRestriction_ND(
|
||||
const double *tk, const Array<int> &d2t, ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{
|
||||
double pt_data[Geometry::MaxDim];
|
||||
IntegrationPoint ip;
|
||||
Vector pt(pt_data, Dim);
|
||||
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
DenseMatrix vshape(Dof, Dim);
|
||||
#endif
|
||||
|
||||
Trans.SetIntPoint(&Geometries.GetCenter(GeomType));
|
||||
const DenseMatrix &Jinv = Trans.InverseJacobian();
|
||||
for (int j = 0; j < Dof; j++)
|
||||
{
|
||||
InvertLinearTrans(Trans, Nodes.IntPoint(j), pt);
|
||||
ip.Set(pt_data, Dim);
|
||||
if (Geometries.CheckPoint(GeomType, ip)) // do we need an epsilon here?
|
||||
{
|
||||
CalcVShape(ip, vshape);
|
||||
Jinv.Mult(tk+Dim*d2t[j], pt_data);
|
||||
for (int k = 0; k < Dof; k++)
|
||||
{
|
||||
double R_jk = 0.0;
|
||||
for (int d = 0; d < Dim; d++)
|
||||
{
|
||||
R_jk += vshape(k,d)*pt_data[d];
|
||||
}
|
||||
R(j,k) = R_jk;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the whole row to avoid valgrind warnings in R.Threshold().
|
||||
R.SetRow(j, infinity());
|
||||
}
|
||||
}
|
||||
R.Threshold(1e-12);
|
||||
}
|
||||
|
||||
|
||||
PointFiniteElement::PointFiniteElement()
|
||||
: NodalFiniteElement(0, Geometry::POINT, 1, 0)
|
||||
@@ -2550,6 +2703,7 @@ void TriLinear3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
|
||||
dshape(7,2) = ox * y;
|
||||
}
|
||||
|
||||
|
||||
P0SegmentFiniteElement::P0SegmentFiniteElement(int Ord)
|
||||
: NodalFiniteElement(1, Geometry::SEGMENT, 1, Ord) // defaul Ord = 0
|
||||
{
|
||||
@@ -6697,8 +6851,8 @@ Poly_1D::~Poly_1D()
|
||||
}
|
||||
}
|
||||
|
||||
Poly_1D poly1d;
|
||||
Array2D<int> Poly_1D::binom;
|
||||
Poly_1D poly1d;
|
||||
|
||||
|
||||
TensorBasisElement::TensorBasisElement(const int dims, const int p,
|
||||
@@ -8250,6 +8404,294 @@ void H1Pos_TetrahedronElement::CalcDShape(const IntegrationPoint &ip,
|
||||
}
|
||||
|
||||
|
||||
H1_WedgeElement::H1_WedgeElement(const int p,
|
||||
const int btype)
|
||||
: NodalFiniteElement(3, Geometry::PRISM, ((p + 1)*(p + 1)*(p + 2))/2,
|
||||
p, FunctionSpace::Qk),
|
||||
TriangleFE(p, btype),
|
||||
SegmentFE(p, btype)
|
||||
{
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
t_shape.SetSize(TriangleFE.GetDof());
|
||||
s_shape.SetSize(SegmentFE.GetDof());
|
||||
t_dshape.SetSize(TriangleFE.GetDof(), 2);
|
||||
s_dshape.SetSize(SegmentFE.GetDof(), 1);
|
||||
#endif
|
||||
|
||||
t_dof.SetSize(Dof);
|
||||
s_dof.SetSize(Dof);
|
||||
|
||||
// Nodal DoFs
|
||||
t_dof[0] = 0; s_dof[0] = 0;
|
||||
t_dof[1] = 1; s_dof[1] = 0;
|
||||
t_dof[2] = 2; s_dof[2] = 0;
|
||||
t_dof[3] = 0; s_dof[3] = 1;
|
||||
t_dof[4] = 1; s_dof[4] = 1;
|
||||
t_dof[5] = 2; s_dof[5] = 1;
|
||||
|
||||
// Edge DoFs
|
||||
int ne = p-1;
|
||||
for (int i=1; i<p; i++)
|
||||
{
|
||||
t_dof[5 + 0 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 0 * ne + i] = 0;
|
||||
t_dof[5 + 1 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 1 * ne + i] = 0;
|
||||
t_dof[5 + 2 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 2 * ne + i] = 0;
|
||||
t_dof[5 + 3 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 3 * ne + i] = 1;
|
||||
t_dof[5 + 4 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 4 * ne + i] = 1;
|
||||
t_dof[5 + 5 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 5 * ne + i] = 1;
|
||||
t_dof[5 + 6 * ne + i] = 0; s_dof[5 + 6 * ne + i] = i + 1;
|
||||
t_dof[5 + 7 * ne + i] = 1; s_dof[5 + 7 * ne + i] = i + 1;
|
||||
t_dof[5 + 8 * ne + i] = 2; s_dof[5 + 8 * ne + i] = i + 1;
|
||||
}
|
||||
|
||||
// Triangular Face DoFs
|
||||
int k=0;
|
||||
int nt = (p-1)*(p-2)/2;
|
||||
for (int j=1; j<p; j++)
|
||||
{
|
||||
for (int i=1; i<p-j; i++)
|
||||
{
|
||||
int l = j - p + (((2 * p - 1) - i) * i) / 2;
|
||||
t_dof[6 + 9 * ne + k] = 3 * p + l; s_dof[6 + 9 * ne + k] = 0;
|
||||
t_dof[6 + 9 * ne + nt + k] = 3 * p + k; s_dof[6 + 9 * ne + nt + k] = 1;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Quadrilateral Face DoFs
|
||||
k=0;
|
||||
int nq = (p-1)*(p-1);
|
||||
for (int j=1; j<p; j++)
|
||||
{
|
||||
for (int i=1; i<p; i++)
|
||||
{
|
||||
t_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 2 + 0 * ne + i;
|
||||
t_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 2 + 1 * ne + i;
|
||||
t_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 2 + 2 * ne + i;
|
||||
|
||||
s_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 1 + j;
|
||||
s_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 1 + j;
|
||||
s_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 1 + j;
|
||||
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Interior DoFs
|
||||
int m=0;
|
||||
for (int k=1; k<p; k++)
|
||||
{
|
||||
int l=0;
|
||||
for (int j=1; j<p; j++)
|
||||
{
|
||||
for (int i=1; i<j; i++)
|
||||
{
|
||||
t_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 3 * p + l;
|
||||
s_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 1 + k;
|
||||
l++; m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define Nodes
|
||||
const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
|
||||
const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
|
||||
Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
|
||||
Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
|
||||
}
|
||||
}
|
||||
|
||||
void H1_WedgeElement::CalcShape(const IntegrationPoint &ip,
|
||||
Vector &shape) const
|
||||
{
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector t_shape(TriangleFE.GetDof());
|
||||
Vector s_shape(SegmentFE.GetDof());
|
||||
#endif
|
||||
|
||||
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
|
||||
|
||||
TriangleFE.CalcShape(ip, t_shape);
|
||||
SegmentFE.CalcShape(ipz, s_shape);
|
||||
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void H1_WedgeElement::CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const
|
||||
{
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector t_shape(TriangleFE.GetDof());
|
||||
DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
|
||||
Vector s_shape(SegmentFE.GetDof());
|
||||
DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
|
||||
#endif
|
||||
|
||||
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
|
||||
|
||||
TriangleFE.CalcShape(ip, t_shape);
|
||||
TriangleFE.CalcDShape(ip, t_dshape);
|
||||
SegmentFE.CalcShape(ipz, s_shape);
|
||||
SegmentFE.CalcDShape(ipz, s_dshape);
|
||||
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
|
||||
dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
|
||||
dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
H1Pos_WedgeElement::H1Pos_WedgeElement(const int p)
|
||||
: PositiveFiniteElement(3, Geometry::PRISM,
|
||||
((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
|
||||
TriangleFE(p),
|
||||
SegmentFE(p)
|
||||
{
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
t_shape.SetSize(TriangleFE.GetDof());
|
||||
s_shape.SetSize(SegmentFE.GetDof());
|
||||
t_dshape.SetSize(TriangleFE.GetDof(), 2);
|
||||
s_dshape.SetSize(SegmentFE.GetDof(), 1);
|
||||
#endif
|
||||
|
||||
t_dof.SetSize(Dof);
|
||||
s_dof.SetSize(Dof);
|
||||
|
||||
// Nodal DoFs
|
||||
t_dof[0] = 0; s_dof[0] = 0;
|
||||
t_dof[1] = 1; s_dof[1] = 0;
|
||||
t_dof[2] = 2; s_dof[2] = 0;
|
||||
t_dof[3] = 0; s_dof[3] = 1;
|
||||
t_dof[4] = 1; s_dof[4] = 1;
|
||||
t_dof[5] = 2; s_dof[5] = 1;
|
||||
|
||||
// Edge DoFs
|
||||
int ne = p-1;
|
||||
for (int i=1; i<p; i++)
|
||||
{
|
||||
t_dof[5 + 0 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 0 * ne + i] = 0;
|
||||
t_dof[5 + 1 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 1 * ne + i] = 0;
|
||||
t_dof[5 + 2 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 2 * ne + i] = 0;
|
||||
t_dof[5 + 3 * ne + i] = 2 + 0 * ne + i; s_dof[5 + 3 * ne + i] = 1;
|
||||
t_dof[5 + 4 * ne + i] = 2 + 1 * ne + i; s_dof[5 + 4 * ne + i] = 1;
|
||||
t_dof[5 + 5 * ne + i] = 2 + 2 * ne + i; s_dof[5 + 5 * ne + i] = 1;
|
||||
t_dof[5 + 6 * ne + i] = 0; s_dof[5 + 6 * ne + i] = i + 1;
|
||||
t_dof[5 + 7 * ne + i] = 1; s_dof[5 + 7 * ne + i] = i + 1;
|
||||
t_dof[5 + 8 * ne + i] = 2; s_dof[5 + 8 * ne + i] = i + 1;
|
||||
}
|
||||
|
||||
// Triangular Face DoFs
|
||||
int k=0;
|
||||
int nt = (p-1)*(p-2)/2;
|
||||
for (int j=1; j<p; j++)
|
||||
{
|
||||
for (int i=1; i<j; i++)
|
||||
{
|
||||
t_dof[6 + 9 * ne + k] = 3 * p + k; s_dof[6 + 9 * ne + k] = 0;
|
||||
t_dof[6 + 9 * ne + nt + k] = 3 * p + k; s_dof[6 + 9 * ne + nt + k] = 1;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Quadrilateral Face DoFs
|
||||
k=0;
|
||||
int nq = (p-1)*(p-1);
|
||||
for (int j=1; j<p; j++)
|
||||
{
|
||||
for (int i=1; i<p; i++)
|
||||
{
|
||||
t_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 2 + 0 * ne + i;
|
||||
t_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 2 + 1 * ne + i;
|
||||
t_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 2 + 2 * ne + i;
|
||||
|
||||
s_dof[6 + 9 * ne + 2 * nt + 0 * nq + k] = 1 + j;
|
||||
s_dof[6 + 9 * ne + 2 * nt + 1 * nq + k] = 1 + j;
|
||||
s_dof[6 + 9 * ne + 2 * nt + 2 * nq + k] = 1 + j;
|
||||
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
// Interior DoFs
|
||||
int m=0;
|
||||
for (int k=1; k<p; k++)
|
||||
{
|
||||
int l=0;
|
||||
for (int j=1; j<p; j++)
|
||||
{
|
||||
for (int i=1; i<j; i++)
|
||||
{
|
||||
t_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 3 * p + l;
|
||||
s_dof[6 + 9 * ne + 2 * nt + 3 * nq + m] = 1 + k;
|
||||
l++; m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define Nodes
|
||||
const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
|
||||
const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
|
||||
Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
|
||||
Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
|
||||
}
|
||||
}
|
||||
|
||||
void H1Pos_WedgeElement::CalcShape(const IntegrationPoint &ip,
|
||||
Vector &shape) const
|
||||
{
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector t_shape(TriangleFE.GetDof());
|
||||
Vector s_shape(SegmentFE.GetDof());
|
||||
#endif
|
||||
|
||||
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
|
||||
|
||||
TriangleFE.CalcShape(ip, t_shape);
|
||||
SegmentFE.CalcShape(ipz, s_shape);
|
||||
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void H1Pos_WedgeElement::CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const
|
||||
{
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector t_shape(TriangleFE.GetDof());
|
||||
DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
|
||||
Vector s_shape(SegmentFE.GetDof());
|
||||
DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
|
||||
#endif
|
||||
|
||||
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
|
||||
|
||||
TriangleFE.CalcShape(ip, t_shape);
|
||||
TriangleFE.CalcDShape(ip, t_dshape);
|
||||
SegmentFE.CalcShape(ipz, s_shape);
|
||||
SegmentFE.CalcDShape(ipz, s_dshape);
|
||||
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
|
||||
dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
|
||||
dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
L2_SegmentElement::L2_SegmentElement(const int p, const int btype)
|
||||
: NodalTensorFiniteElement(1, p, VerifyOpen(btype), L2_DOF_MAP)
|
||||
{
|
||||
@@ -9153,6 +9595,182 @@ void L2Pos_TetrahedronElement::ProjectDelta(int vertex, Vector &dofs) const
|
||||
}
|
||||
|
||||
|
||||
L2_WedgeElement::L2_WedgeElement(const int p, const int btype)
|
||||
: NodalFiniteElement(3, Geometry::PRISM, ((p + 1)*(p + 1)*(p + 2))/2,
|
||||
p, FunctionSpace::Qk),
|
||||
TriangleFE(p, btype),
|
||||
SegmentFE(p, btype)
|
||||
{
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
t_shape.SetSize(TriangleFE.GetDof());
|
||||
s_shape.SetSize(SegmentFE.GetDof());
|
||||
t_dshape.SetSize(TriangleFE.GetDof(), 2);
|
||||
s_dshape.SetSize(SegmentFE.GetDof(), 1);
|
||||
#endif
|
||||
|
||||
t_dof.SetSize(Dof);
|
||||
s_dof.SetSize(Dof);
|
||||
|
||||
// Interior DoFs
|
||||
int m=0;
|
||||
for (int k=0; k<=p; k++)
|
||||
{
|
||||
int l=0;
|
||||
for (int j=0; j<=p; j++)
|
||||
{
|
||||
for (int i=0; i<=j; i++)
|
||||
{
|
||||
t_dof[m] = l;
|
||||
s_dof[m] = k;
|
||||
l++; m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define Nodes
|
||||
const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
|
||||
const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
|
||||
Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
|
||||
Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
|
||||
}
|
||||
}
|
||||
|
||||
void L2_WedgeElement::CalcShape(const IntegrationPoint &ip,
|
||||
Vector &shape) const
|
||||
{
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector t_shape(TriangleFE.GetDof());
|
||||
Vector s_shape(SegmentFE.GetDof());
|
||||
#endif
|
||||
|
||||
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
|
||||
|
||||
TriangleFE.CalcShape(ip, t_shape);
|
||||
SegmentFE.CalcShape(ipz, s_shape);
|
||||
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void L2_WedgeElement::CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const
|
||||
{
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector t_shape(TriangleFE.GetDof());
|
||||
DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
|
||||
Vector s_shape(SegmentFE.GetDof());
|
||||
DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
|
||||
#endif
|
||||
|
||||
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
|
||||
|
||||
TriangleFE.CalcShape(ip, t_shape);
|
||||
TriangleFE.CalcDShape(ip, t_dshape);
|
||||
SegmentFE.CalcShape(ipz, s_shape);
|
||||
SegmentFE.CalcDShape(ipz, s_dshape);
|
||||
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
|
||||
dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
|
||||
dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
L2Pos_WedgeElement::L2Pos_WedgeElement(const int p)
|
||||
: PositiveFiniteElement(3, Geometry::PRISM,
|
||||
((p + 1)*(p + 1)*(p + 2))/2, p, FunctionSpace::Qk),
|
||||
TriangleFE(p),
|
||||
SegmentFE(p)
|
||||
{
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
t_shape.SetSize(TriangleFE.GetDof());
|
||||
s_shape.SetSize(SegmentFE.GetDof());
|
||||
t_dshape.SetSize(TriangleFE.GetDof(), 2);
|
||||
s_dshape.SetSize(SegmentFE.GetDof(), 1);
|
||||
#endif
|
||||
|
||||
t_dof.SetSize(Dof);
|
||||
s_dof.SetSize(Dof);
|
||||
|
||||
// Interior DoFs
|
||||
int m=0;
|
||||
for (int k=0; k<=p; k++)
|
||||
{
|
||||
int l=0;
|
||||
for (int j=0; j<=p; j++)
|
||||
{
|
||||
for (int i=0; i<=j; i++)
|
||||
{
|
||||
t_dof[m] = l;
|
||||
s_dof[m] = k;
|
||||
l++; m++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define Nodes
|
||||
const IntegrationRule & t_Nodes = TriangleFE.GetNodes();
|
||||
const IntegrationRule & s_Nodes = SegmentFE.GetNodes();
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
Nodes.IntPoint(i).x = t_Nodes.IntPoint(t_dof[i]).x;
|
||||
Nodes.IntPoint(i).y = t_Nodes.IntPoint(t_dof[i]).y;
|
||||
Nodes.IntPoint(i).z = s_Nodes.IntPoint(s_dof[i]).x;
|
||||
}
|
||||
}
|
||||
|
||||
void L2Pos_WedgeElement::CalcShape(const IntegrationPoint &ip,
|
||||
Vector &shape) const
|
||||
{
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector t_shape(TriangleFE.GetDof());
|
||||
Vector s_shape(SegmentFE.GetDof());
|
||||
#endif
|
||||
|
||||
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
|
||||
|
||||
TriangleFE.CalcShape(ip, t_shape);
|
||||
SegmentFE.CalcShape(ipz, s_shape);
|
||||
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
shape[i] = t_shape[t_dof[i]] * s_shape[s_dof[i]];
|
||||
}
|
||||
}
|
||||
|
||||
void L2Pos_WedgeElement::CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const
|
||||
{
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
Vector t_shape(TriangleFE.GetDof());
|
||||
DenseMatrix t_dshape(TriangleFE.GetDof(), 2);
|
||||
Vector s_shape(SegmentFE.GetDof());
|
||||
DenseMatrix s_dshape(SegmentFE.GetDof(), 1);
|
||||
#endif
|
||||
|
||||
IntegrationPoint ipz; ipz.x = ip.z; ipz.y = 0.0; ipz.z = 0.0;
|
||||
|
||||
TriangleFE.CalcShape(ip, t_shape);
|
||||
TriangleFE.CalcDShape(ip, t_dshape);
|
||||
SegmentFE.CalcShape(ipz, s_shape);
|
||||
SegmentFE.CalcDShape(ipz, s_dshape);
|
||||
|
||||
for (int i=0; i<Dof; i++)
|
||||
{
|
||||
dshape(i, 0) = t_dshape(t_dof[i],0) * s_shape[s_dof[i]];
|
||||
dshape(i, 1) = t_dshape(t_dof[i],1) * s_shape[s_dof[i]];
|
||||
dshape(i, 2) = t_shape[t_dof[i]] * s_dshape(s_dof[i],0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const double RT_QuadrilateralElement::nk[8] =
|
||||
{ 0., -1., 1., 0., 0., 1., -1., 0. };
|
||||
|
||||
@@ -11227,4 +11845,25 @@ void NURBS3DFiniteElement::CalcDShape(const IntegrationPoint &ip,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Global object definitions
|
||||
|
||||
|
||||
// Object declared in mesh/triangle.hpp.
|
||||
// Defined here to ensure it is constructed before 'Geometries'.
|
||||
Linear2DFiniteElement TriangleFE;
|
||||
|
||||
// Object declared in mesh/tetrahedron.hpp.
|
||||
// Defined here to ensure it is constructed before 'Geometries'.
|
||||
Linear3DFiniteElement TetrahedronFE;
|
||||
|
||||
// Object declared in mesh/wedge.hpp.
|
||||
// Defined here to ensure it is constructed after 'poly1d' and before
|
||||
// 'Geometries'.
|
||||
H1_WedgeElement WedgeFE(1);
|
||||
|
||||
// Object declared in geom.hpp.
|
||||
// Construct 'Geometries' after 'TriangleFE', 'TetrahedronFE', and 'WedgeFE'.
|
||||
Geometry Geometries;
|
||||
|
||||
}
|
||||
|
||||
+192
-14
@@ -140,13 +140,13 @@ class KnotVector;
|
||||
class FiniteElement
|
||||
{
|
||||
protected:
|
||||
int Dim, ///< Dimension of reference space
|
||||
GeomType, ///< Geometry::Type of the reference element
|
||||
FuncSpace, RangeType, MapType,
|
||||
int Dim; ///< Dimension of reference space
|
||||
Geometry::Type GeomType; ///< Geometry::Type of the reference element
|
||||
int FuncSpace, RangeType, MapType,
|
||||
DerivType, DerivRangeType, DerivMapType;
|
||||
mutable
|
||||
int Dof, ///< Number of degrees of freedom
|
||||
Order; ///< Order/degree of the shape functions
|
||||
int Dof, ///< Number of degrees of freedom
|
||||
Order; ///< Order/degree of the shape functions
|
||||
mutable int Orders[Geometry::MaxDim]; ///< Anisotropic orders
|
||||
IntegrationRule Nodes;
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
@@ -205,13 +205,14 @@ public:
|
||||
@param O Order/degree of the FiniteElement
|
||||
@param F FunctionSpace type of the FiniteElement
|
||||
*/
|
||||
FiniteElement(int D, int G, int Do, int O, int F = FunctionSpace::Pk);
|
||||
FiniteElement(int D, Geometry::Type G, int Do, int O,
|
||||
int F = FunctionSpace::Pk);
|
||||
|
||||
/// Returns the reference space dimension for the finite element
|
||||
int GetDim() const { return Dim; }
|
||||
|
||||
/// Returns the Geometry::Type of the reference element
|
||||
int GetGeomType() const { return GeomType; }
|
||||
Geometry::Type GetGeomType() const { return GeomType; }
|
||||
|
||||
/// Returns the number of degrees of freedom in the finite element
|
||||
int GetDof() const { return Dof; }
|
||||
@@ -336,6 +337,24 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const;
|
||||
|
||||
/** @brief Return a local restriction matrix @a R (Dof x Dof) mapping fine
|
||||
dofs to coarse dofs.
|
||||
|
||||
The fine element is the image of the base geometry under the given
|
||||
transformation, @a Trans.
|
||||
|
||||
The assumption in this method is that a subset of the coarse dofs can be
|
||||
expressed only in terms of the dofs of the given fine element.
|
||||
|
||||
Rows in @a R corresponding to coarse dofs that cannot be expressed in
|
||||
terms of the fine dofs will be marked as invalid by setting the first
|
||||
entry (column 0) in the row to infinity().
|
||||
|
||||
This method assumes that the dimensions of @a R are set before it is
|
||||
called. */
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const;
|
||||
|
||||
/** @brief Return interpolation matrix, @a I, which maps dofs from a coarse
|
||||
element, @a fe, to the fine dofs on @a this finite element. */
|
||||
/** @a Trans represents the mapping from the reference element of @a this
|
||||
@@ -446,7 +465,8 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
ScalarFiniteElement(int D, int G, int Do, int O, int F = FunctionSpace::Pk)
|
||||
ScalarFiniteElement(int D, Geometry::Type G, int Do, int O,
|
||||
int F = FunctionSpace::Pk)
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
: FiniteElement(D, G, Do, O, F)
|
||||
{ DerivType = GRAD; DerivRangeType = VECTOR; DerivMapType = H_CURL; }
|
||||
@@ -484,13 +504,17 @@ protected:
|
||||
DenseMatrix &curl) const;
|
||||
|
||||
public:
|
||||
NodalFiniteElement(int D, int G, int Do, int O, int F = FunctionSpace::Pk)
|
||||
NodalFiniteElement(int D, Geometry::Type G, int Do, int O,
|
||||
int F = FunctionSpace::Pk)
|
||||
: ScalarFiniteElement(D, G, Do, O, F) { }
|
||||
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ NodalLocalInterpolation(Trans, I, *this); }
|
||||
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const;
|
||||
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -522,7 +546,7 @@ public:
|
||||
class PositiveFiniteElement : public ScalarFiniteElement
|
||||
{
|
||||
public:
|
||||
PositiveFiniteElement(int D, int G, int Do, int O,
|
||||
PositiveFiniteElement(int D, Geometry::Type G, int Do, int O,
|
||||
int F = FunctionSpace::Pk) :
|
||||
ScalarFiniteElement(D, G, Do, O, F)
|
||||
{ }
|
||||
@@ -543,6 +567,9 @@ public:
|
||||
virtual void Project(Coefficient &coeff,
|
||||
ElementTransformation &Trans, Vector &dofs) const;
|
||||
|
||||
virtual void Project (VectorCoefficient &vc,
|
||||
ElementTransformation &Trans, Vector &dofs) const;
|
||||
|
||||
virtual void Project(const FiniteElement &fe, ElementTransformation &Trans,
|
||||
DenseMatrix &I) const;
|
||||
};
|
||||
@@ -627,6 +654,14 @@ protected:
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const;
|
||||
|
||||
void LocalRestriction_RT(const double *nk, const Array<int> &d2n,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &R) const;
|
||||
|
||||
void LocalRestriction_ND(const double *tk, const Array<int> &d2t,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &R) const;
|
||||
|
||||
static const VectorFiniteElement &CheckVectorFE(const FiniteElement &fe)
|
||||
{
|
||||
if (fe.GetRangeType() != VECTOR)
|
||||
@@ -635,7 +670,7 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
VectorFiniteElement (int D, int G, int Do, int O, int M,
|
||||
VectorFiniteElement (int D, Geometry::Type G, int Do, int O, int M,
|
||||
int F = FunctionSpace::Pk) :
|
||||
#ifdef MFEM_THREAD_SAFE
|
||||
FiniteElement(D, G, Do, O, F)
|
||||
@@ -1018,6 +1053,7 @@ public:
|
||||
{ dofs = 0.0; dofs(vertex) = 1.0; }
|
||||
};
|
||||
|
||||
|
||||
/// Crouzeix-Raviart finite element on triangle
|
||||
class CrouzeixRaviartFiniteElement : public NodalFiniteElement
|
||||
{
|
||||
@@ -1682,14 +1718,16 @@ public:
|
||||
Array will be empty. */
|
||||
const Array<int> &GetDofMap() const { return dof_map; }
|
||||
|
||||
static int GetTensorProductGeometry(int dim)
|
||||
static Geometry::Type GetTensorProductGeometry(int dim)
|
||||
{
|
||||
switch (dim)
|
||||
{
|
||||
case 1: return Geometry::SEGMENT;
|
||||
case 2: return Geometry::SQUARE;
|
||||
case 3: return Geometry::CUBE;
|
||||
default: MFEM_ABORT("invalid dimension: " << dim); return -1;
|
||||
default:
|
||||
MFEM_ABORT("invalid dimension: " << dim);
|
||||
return Geometry::INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1919,6 +1957,71 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class H1_WedgeElement : public NodalFiniteElement
|
||||
{
|
||||
private:
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
mutable Vector t_shape, s_shape;
|
||||
mutable DenseMatrix t_dshape, s_dshape;
|
||||
#endif
|
||||
Array<int> t_dof, s_dof;
|
||||
|
||||
H1_TriangleElement TriangleFE;
|
||||
H1_SegmentElement SegmentFE;
|
||||
|
||||
public:
|
||||
H1_WedgeElement(const int p,
|
||||
const int btype = BasisType::GaussLobatto);
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
};
|
||||
|
||||
/// Class for linear FE on wedge
|
||||
class BiLinear3DFiniteElement : public H1_WedgeElement
|
||||
{
|
||||
public:
|
||||
/// Construct a linear FE on wedge
|
||||
BiLinear3DFiniteElement() : H1_WedgeElement(1) {}
|
||||
};
|
||||
|
||||
/// Class for quadratic FE on wedge
|
||||
class BiQuadratic3DFiniteElement : public H1_WedgeElement
|
||||
{
|
||||
public:
|
||||
/// Construct a quadratic FE on wedge
|
||||
BiQuadratic3DFiniteElement() : H1_WedgeElement(2) {}
|
||||
};
|
||||
|
||||
/// Class for cubic FE on wedge
|
||||
class BiCubic3DFiniteElement : public H1_WedgeElement
|
||||
{
|
||||
public:
|
||||
/// Construct a cubic FE on wedge
|
||||
BiCubic3DFiniteElement() : H1_WedgeElement(3) {}
|
||||
};
|
||||
|
||||
class H1Pos_WedgeElement : public PositiveFiniteElement
|
||||
{
|
||||
protected:
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
mutable Vector t_shape, s_shape;
|
||||
mutable DenseMatrix t_dshape, s_dshape;
|
||||
#endif
|
||||
Array<int> t_dof, s_dof;
|
||||
|
||||
H1Pos_TriangleElement TriangleFE;
|
||||
H1Pos_SegmentElement SegmentFE;
|
||||
|
||||
public:
|
||||
H1Pos_WedgeElement(const int p);
|
||||
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
};
|
||||
|
||||
|
||||
class L2_SegmentElement : public NodalTensorFiniteElement
|
||||
{
|
||||
private:
|
||||
@@ -2096,6 +2199,53 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class L2_WedgeElement : public NodalFiniteElement
|
||||
{
|
||||
private:
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
mutable Vector t_shape, s_shape;
|
||||
mutable DenseMatrix t_dshape, s_dshape;
|
||||
#endif
|
||||
Array<int> t_dof, s_dof;
|
||||
|
||||
L2_TriangleElement TriangleFE;
|
||||
L2_SegmentElement SegmentFE;
|
||||
|
||||
public:
|
||||
L2_WedgeElement(const int p,
|
||||
const int btype = BasisType::GaussLegendre);
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
};
|
||||
|
||||
class P0WedgeFiniteElement : public L2_WedgeElement
|
||||
{
|
||||
public:
|
||||
P0WedgeFiniteElement () : L2_WedgeElement(0) {}
|
||||
};
|
||||
|
||||
class L2Pos_WedgeElement : public PositiveFiniteElement
|
||||
{
|
||||
protected:
|
||||
#ifndef MFEM_THREAD_SAFE
|
||||
mutable Vector t_shape, s_shape;
|
||||
mutable DenseMatrix t_dshape, s_dshape;
|
||||
#endif
|
||||
Array<int> t_dof, s_dof;
|
||||
|
||||
L2Pos_TriangleElement TriangleFE;
|
||||
L2Pos_SegmentElement SegmentFE;
|
||||
|
||||
public:
|
||||
L2Pos_WedgeElement(const int p);
|
||||
|
||||
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
|
||||
virtual void CalcDShape(const IntegrationPoint &ip,
|
||||
DenseMatrix &dshape) const;
|
||||
};
|
||||
|
||||
|
||||
class RT_QuadrilateralElement : public VectorFiniteElement
|
||||
{
|
||||
private:
|
||||
@@ -2122,6 +2272,9 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2175,6 +2328,9 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2221,6 +2377,9 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2273,6 +2432,9 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2324,6 +2486,10 @@ public:
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
|
||||
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
|
||||
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2381,6 +2547,9 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2427,6 +2596,9 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2478,6 +2650,9 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2521,6 +2696,9 @@ public:
|
||||
virtual void GetLocalInterpolation(ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
{ LocalInterpolation_ND(*this, tk, dof2tk, Trans, I); }
|
||||
virtual void GetLocalRestriction(ElementTransformation &Trans,
|
||||
DenseMatrix &R) const
|
||||
{ LocalRestriction_ND(tk, dof2tk, Trans, R); }
|
||||
virtual void GetTransferMatrix(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &I) const
|
||||
@@ -2552,7 +2730,7 @@ protected:
|
||||
mutable Vector weights;
|
||||
|
||||
public:
|
||||
NURBSFiniteElement(int D, int G, int Do, int O, int F)
|
||||
NURBSFiniteElement(int D, Geometry::Type G, int Do, int O, int F)
|
||||
: ScalarFiniteElement(D, G, Do, O, F)
|
||||
{
|
||||
ijk = NULL;
|
||||
|
||||
+161
-107
@@ -22,12 +22,15 @@ namespace mfem
|
||||
|
||||
using namespace std;
|
||||
|
||||
int FiniteElementCollection::HasFaceDofs(int GeomType) const
|
||||
int FiniteElementCollection::HasFaceDofs(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
case Geometry::TETRAHEDRON: return DofForGeometry (Geometry::TRIANGLE);
|
||||
case Geometry::CUBE: return DofForGeometry (Geometry::SQUARE);
|
||||
case Geometry::PRISM:
|
||||
return max(DofForGeometry (Geometry::TRIANGLE),
|
||||
DofForGeometry (Geometry::SQUARE));
|
||||
default:
|
||||
mfem_error ("FiniteElementCollection::HasFaceDofs:"
|
||||
" unknown geometry type.");
|
||||
@@ -314,7 +317,7 @@ template <Geometry::Type geom, Geometry::Type f_geom,
|
||||
typename v_t, typename e_t, typename eo_t>
|
||||
inline void FiniteElementCollection::
|
||||
GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo,
|
||||
int &nf, int &f, int &fg, int &fo, const int face_info)
|
||||
int &nf, int &f, Geometry::Type &fg, int &fo, const int face_info)
|
||||
{
|
||||
typedef typename Geometry::Constants< geom> g_consts;
|
||||
typedef typename Geometry::Constants<f_geom> f_consts;
|
||||
@@ -358,7 +361,8 @@ GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo,
|
||||
}
|
||||
}
|
||||
|
||||
void FiniteElementCollection::SubDofOrder(int Geom, int SDim, int Info,
|
||||
void FiniteElementCollection::SubDofOrder(Geometry::Type Geom, int SDim,
|
||||
int Info,
|
||||
Array<int> &dofs) const
|
||||
{
|
||||
// Info = 64 * SubIndex + SubOrientation
|
||||
@@ -380,8 +384,9 @@ void FiniteElementCollection::SubDofOrder(int Geom, int SDim, int Info,
|
||||
}
|
||||
else
|
||||
{
|
||||
int v[4], e[4], eo[4], f[1], fg[1], fo[1];
|
||||
int v[4], e[4], eo[4], f[1], fo[1];
|
||||
int av = 0, nv = 0, ae = 0, ne = 0, nf = 0;
|
||||
Geometry::Type fg[1];
|
||||
|
||||
switch (Geom)
|
||||
{
|
||||
@@ -528,7 +533,7 @@ not_supp:
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
LinearFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
LinearFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -538,13 +543,14 @@ LinearFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
case Geometry::SQUARE: return &QuadrilateralFE;
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::CUBE: return &ParallelepipedFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
default:
|
||||
mfem_error ("LinearFECollection: unknown geometry type.");
|
||||
}
|
||||
return &SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int LinearFECollection::DofForGeometry(int GeomType) const
|
||||
int LinearFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -554,20 +560,22 @@ int LinearFECollection::DofForGeometry(int GeomType) const
|
||||
case Geometry::SQUARE: return 0;
|
||||
case Geometry::TETRAHEDRON: return 0;
|
||||
case Geometry::CUBE: return 0;
|
||||
case Geometry::PRISM: return 0;
|
||||
default:
|
||||
mfem_error ("LinearFECollection: unknown geometry type.");
|
||||
}
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * LinearFECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
const int *LinearFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
QuadraticFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
QuadraticFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -577,13 +585,14 @@ QuadraticFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
case Geometry::SQUARE: return &QuadrilateralFE;
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::CUBE: return &ParallelepipedFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
default:
|
||||
mfem_error ("QuadraticFECollection: unknown geometry type.");
|
||||
}
|
||||
return &SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int QuadraticFECollection::DofForGeometry(int GeomType) const
|
||||
int QuadraticFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -593,13 +602,15 @@ int QuadraticFECollection::DofForGeometry(int GeomType) const
|
||||
case Geometry::SQUARE: return 1;
|
||||
case Geometry::TETRAHEDRON: return 0;
|
||||
case Geometry::CUBE: return 1;
|
||||
case Geometry::PRISM: return 0;
|
||||
default:
|
||||
mfem_error ("QuadraticFECollection: unknown geometry type.");
|
||||
}
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * QuadraticFECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
const int *QuadraticFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
static int indexes[] = { 0 };
|
||||
|
||||
@@ -608,7 +619,8 @@ int * QuadraticFECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
QuadraticPosFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
QuadraticPosFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -620,7 +632,7 @@ QuadraticPosFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return NULL; // Make some compilers happy
|
||||
}
|
||||
|
||||
int QuadraticPosFECollection::DofForGeometry(int GeomType) const
|
||||
int QuadraticPosFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -633,8 +645,8 @@ int QuadraticPosFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * QuadraticPosFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *QuadraticPosFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
static int indexes[] = { 0 };
|
||||
|
||||
@@ -643,7 +655,7 @@ const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
CubicFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
CubicFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -653,13 +665,14 @@ CubicFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
case Geometry::SQUARE: return &QuadrilateralFE;
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::CUBE: return &ParallelepipedFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
default:
|
||||
mfem_error ("CubicFECollection: unknown geometry type.");
|
||||
}
|
||||
return &SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int CubicFECollection::DofForGeometry(int GeomType) const
|
||||
int CubicFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -669,13 +682,15 @@ int CubicFECollection::DofForGeometry(int GeomType) const
|
||||
case Geometry::SQUARE: return 4;
|
||||
case Geometry::TETRAHEDRON: return 0;
|
||||
case Geometry::CUBE: return 8;
|
||||
case Geometry::PRISM: return 2;
|
||||
default:
|
||||
mfem_error ("CubicFECollection: unknown geometry type.");
|
||||
}
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * CubicFECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
const int *CubicFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
if (GeomType == Geometry::SEGMENT)
|
||||
{
|
||||
@@ -709,7 +724,8 @@ int * CubicFECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
CrouzeixRaviartFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
CrouzeixRaviartFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -722,7 +738,7 @@ CrouzeixRaviartFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int CrouzeixRaviartFECollection::DofForGeometry(int GeomType) const
|
||||
int CrouzeixRaviartFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -736,8 +752,8 @@ int CrouzeixRaviartFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * CrouzeixRaviartFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *CrouzeixRaviartFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
static int indexes[] = { 0 };
|
||||
|
||||
@@ -746,7 +762,7 @@ const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
RT0_2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
RT0_2DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -759,7 +775,7 @@ RT0_2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int RT0_2DFECollection::DofForGeometry(int GeomType) const
|
||||
int RT0_2DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -773,8 +789,8 @@ int RT0_2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * RT0_2DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int * RT0_2DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
static int ind_pos[] = { 0 };
|
||||
static int ind_neg[] = { -1 };
|
||||
@@ -788,7 +804,7 @@ const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
RT1_2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
RT1_2DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -801,7 +817,7 @@ RT1_2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int RT1_2DFECollection::DofForGeometry(int GeomType) const
|
||||
int RT1_2DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -815,8 +831,8 @@ int RT1_2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * RT1_2DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *RT1_2DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
static int ind_pos[] = { 0, 1 };
|
||||
static int ind_neg[] = { -2, -1 };
|
||||
@@ -829,7 +845,7 @@ const
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
RT2_2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
RT2_2DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -842,7 +858,7 @@ RT2_2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int RT2_2DFECollection::DofForGeometry(int GeomType) const
|
||||
int RT2_2DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -856,8 +872,8 @@ int RT2_2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * RT2_2DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *RT2_2DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
static int ind_pos[] = { 0, 1, 2 };
|
||||
static int ind_neg[] = { -3, -2, -1 };
|
||||
@@ -871,7 +887,7 @@ const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
Const2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
Const2DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -883,7 +899,7 @@ Const2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &TriangleFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int Const2DFECollection::DofForGeometry(int GeomType) const
|
||||
int Const2DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -897,15 +913,16 @@ int Const2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * Const2DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *Const2DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
LinearDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
LinearDiscont2DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -917,7 +934,7 @@ LinearDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &TriangleFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int LinearDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
int LinearDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -931,15 +948,16 @@ int LinearDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * LinearDiscont2DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int * LinearDiscont2DFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
GaussLinearDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
GaussLinearDiscont2DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -952,7 +970,8 @@ GaussLinearDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &TriangleFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int GaussLinearDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
int GaussLinearDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType)
|
||||
const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -967,15 +986,15 @@ int GaussLinearDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * GaussLinearDiscont2DFECollection::DofOrderForOrientation(
|
||||
int GeomType, int Or) const
|
||||
const int *GaussLinearDiscont2DFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
P1OnQuadFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
P1OnQuadFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
if (GeomType != Geometry::SQUARE)
|
||||
{
|
||||
@@ -984,7 +1003,7 @@ P1OnQuadFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &QuadrilateralFE;
|
||||
}
|
||||
|
||||
int P1OnQuadFECollection::DofForGeometry(int GeomType) const
|
||||
int P1OnQuadFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -997,15 +1016,16 @@ int P1OnQuadFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * P1OnQuadFECollection::DofOrderForOrientation(
|
||||
int GeomType, int Or) const
|
||||
const int *P1OnQuadFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
QuadraticDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
QuadraticDiscont2DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1017,7 +1037,8 @@ QuadraticDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &TriangleFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int QuadraticDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
int QuadraticDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType)
|
||||
const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1031,15 +1052,16 @@ int QuadraticDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * QuadraticDiscont2DFECollection::DofOrderForOrientation(
|
||||
int GeomType, int Or) const
|
||||
const int *QuadraticDiscont2DFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
QuadraticPosDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
QuadraticPosDiscont2DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1050,7 +1072,8 @@ QuadraticPosDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return NULL; // Make some compilers happy
|
||||
}
|
||||
|
||||
int QuadraticPosDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
int QuadraticPosDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType)
|
||||
const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1065,7 +1088,8 @@ int QuadraticPosDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
GaussQuadraticDiscont2DFECollection::FiniteElementForGeometry(int GeomType)
|
||||
GaussQuadraticDiscont2DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType)
|
||||
const
|
||||
{
|
||||
switch (GeomType)
|
||||
@@ -1079,7 +1103,8 @@ const
|
||||
return &QuadrilateralFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int GaussQuadraticDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
int GaussQuadraticDiscont2DFECollection::DofForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1094,15 +1119,16 @@ int GaussQuadraticDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * GaussQuadraticDiscont2DFECollection::DofOrderForOrientation(
|
||||
int GeomType, int Or) const
|
||||
const int *GaussQuadraticDiscont2DFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
CubicDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
CubicDiscont2DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1114,7 +1140,7 @@ CubicDiscont2DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &TriangleFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int CubicDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
int CubicDiscont2DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1128,15 +1154,16 @@ int CubicDiscont2DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * CubicDiscont2DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *CubicDiscont2DFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
LinearNonConf3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
LinearNonConf3DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1150,7 +1177,7 @@ LinearNonConf3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &TriangleFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int LinearNonConf3DFECollection::DofForGeometry(int GeomType) const
|
||||
int LinearNonConf3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1166,8 +1193,8 @@ int LinearNonConf3DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * LinearNonConf3DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *LinearNonConf3DFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
static int indexes[] = { 0 };
|
||||
|
||||
@@ -1176,43 +1203,46 @@ const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
Const3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
Const3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
case Geometry::TETRAHEDRON: return &TetrahedronFE;
|
||||
case Geometry::CUBE: return &ParallelepipedFE;
|
||||
case Geometry::PRISM: return &WedgeFE;
|
||||
default:
|
||||
mfem_error ("Const3DFECollection: unknown geometry type.");
|
||||
}
|
||||
return &TetrahedronFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int Const3DFECollection::DofForGeometry(int GeomType) const
|
||||
int Const3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
case Geometry::POINT: return 0;
|
||||
case Geometry::SEGMENT: return 0;
|
||||
case Geometry::TRIANGLE: return 0;
|
||||
case Geometry::TETRAHEDRON: return 1;
|
||||
case Geometry::SQUARE: return 0;
|
||||
case Geometry::TETRAHEDRON: return 1;
|
||||
case Geometry::CUBE: return 1;
|
||||
case Geometry::PRISM: return 1;
|
||||
default:
|
||||
mfem_error ("Const3DFECollection: unknown geometry type.");
|
||||
}
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * Const3DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *Const3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
LinearDiscont3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
LinearDiscont3DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1224,7 +1254,7 @@ LinearDiscont3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &TetrahedronFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int LinearDiscont3DFECollection::DofForGeometry(int GeomType) const
|
||||
int LinearDiscont3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1240,15 +1270,16 @@ int LinearDiscont3DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * LinearDiscont3DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *LinearDiscont3DFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
QuadraticDiscont3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
QuadraticDiscont3DFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1260,7 +1291,8 @@ QuadraticDiscont3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &TetrahedronFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int QuadraticDiscont3DFECollection::DofForGeometry(int GeomType) const
|
||||
int QuadraticDiscont3DFECollection::DofForGeometry(Geometry::Type GeomType)
|
||||
const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1276,14 +1308,15 @@ int QuadraticDiscont3DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * QuadraticDiscont3DFECollection::DofOrderForOrientation(
|
||||
int GeomType, int Or) const
|
||||
const int *QuadraticDiscont3DFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
RefinedLinearFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
RefinedLinearFECollection::FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1299,7 +1332,7 @@ RefinedLinearFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int RefinedLinearFECollection::DofForGeometry(int GeomType) const
|
||||
int RefinedLinearFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1315,8 +1348,8 @@ int RefinedLinearFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * RefinedLinearFECollection::DofOrderForOrientation(int GeomType,
|
||||
int Or) const
|
||||
const int *RefinedLinearFECollection::DofOrderForOrientation(
|
||||
Geometry::Type GeomType, int Or) const
|
||||
{
|
||||
static int indexes[] = { 0 };
|
||||
|
||||
@@ -1325,7 +1358,7 @@ int * RefinedLinearFECollection::DofOrderForOrientation(int GeomType,
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
ND1_3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
ND1_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1337,7 +1370,7 @@ ND1_3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &HexahedronFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int ND1_3DFECollection::DofForGeometry(int GeomType) const
|
||||
int ND1_3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1353,8 +1386,8 @@ int ND1_3DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * ND1_3DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *ND1_3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
static int ind_pos[] = { 0 };
|
||||
static int ind_neg[] = { -1 };
|
||||
@@ -1368,7 +1401,7 @@ const
|
||||
|
||||
|
||||
const FiniteElement *
|
||||
RT0_3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
RT0_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1382,7 +1415,7 @@ RT0_3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &HexahedronFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int RT0_3DFECollection::DofForGeometry(int GeomType) const
|
||||
int RT0_3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1398,8 +1431,8 @@ int RT0_3DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * RT0_3DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *RT0_3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
static int ind_pos[] = { 0 };
|
||||
static int ind_neg[] = { -1 };
|
||||
@@ -1416,7 +1449,7 @@ const
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
RT1_3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
RT1_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1429,7 +1462,7 @@ RT1_3DFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return &HexahedronFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int RT1_3DFECollection::DofForGeometry(int GeomType) const
|
||||
int RT1_3DFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1444,8 +1477,8 @@ int RT1_3DFECollection::DofForGeometry(int GeomType) const
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int * RT1_3DFECollection::DofOrderForOrientation(int GeomType, int Or)
|
||||
const
|
||||
const int *RT1_3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
if (GeomType == Geometry::SQUARE)
|
||||
{
|
||||
@@ -1468,6 +1501,9 @@ const
|
||||
|
||||
H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
{
|
||||
MFEM_VERIFY(p >= 1, "H1_FECollection requires order >= 1.");
|
||||
MFEM_VERIFY(dim >= 0 && dim <= 3, "H1_FECollection requires 0 <= dim <= 3.");
|
||||
|
||||
const int pm1 = p - 1, pm2 = pm1 - 1, pm3 = pm2 - 1;
|
||||
|
||||
int pt_type = BasisType::GetQuadrature1D(btype);
|
||||
@@ -1601,22 +1637,26 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
|
||||
{
|
||||
H1_dof[Geometry::TETRAHEDRON] = (TriDof*pm3)/3;
|
||||
H1_dof[Geometry::CUBE] = QuadDof*pm1;
|
||||
H1_dof[Geometry::PRISM] = TriDof*pm1;
|
||||
if (b_type == BasisType::Positive)
|
||||
{
|
||||
H1_Elements[Geometry::TETRAHEDRON] = new H1Pos_TetrahedronElement(p);
|
||||
H1_Elements[Geometry::CUBE] = new H1Pos_HexahedronElement(p);
|
||||
H1_Elements[Geometry::PRISM] = new H1Pos_WedgeElement(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
H1_Elements[Geometry::TETRAHEDRON] =
|
||||
new H1_TetrahedronElement(p, btype);
|
||||
H1_Elements[Geometry::CUBE] = new H1_HexahedronElement(p, btype);
|
||||
H1_Elements[Geometry::PRISM] = new H1_WedgeElement(p, btype);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int *H1_FECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
const int *H1_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
if (GeomType == Geometry::SEGMENT)
|
||||
{
|
||||
@@ -1652,7 +1692,7 @@ FiniteElementCollection *H1_FECollection::GetTraceCollection() const
|
||||
return (dim < 0) ? NULL : new H1_Trace_FECollection(p, dim, b_type);
|
||||
}
|
||||
|
||||
const int *H1_FECollection::GetDofMap(int GeomType) const
|
||||
const int *H1_FECollection::GetDofMap(Geometry::Type GeomType) const
|
||||
{
|
||||
const int *dof_map = NULL;
|
||||
const FiniteElement *fe = H1_Elements[GeomType];
|
||||
@@ -1708,6 +1748,8 @@ H1_Trace_FECollection::H1_Trace_FECollection(const int p, const int dim,
|
||||
L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
const int map_type)
|
||||
{
|
||||
MFEM_VERIFY(p >= 0, "L2_FECollection requires order >= 0.");
|
||||
|
||||
b_type = BasisType::Check(btype);
|
||||
const char *prefix = NULL;
|
||||
switch (map_type)
|
||||
@@ -1820,22 +1862,26 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
{
|
||||
L2_Elements[Geometry::TETRAHEDRON] = new L2Pos_TetrahedronElement(p);
|
||||
L2_Elements[Geometry::CUBE] = new L2Pos_HexahedronElement(p);
|
||||
L2_Elements[Geometry::PRISM] = new L2Pos_WedgeElement(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
L2_Elements[Geometry::TETRAHEDRON] =
|
||||
new L2_TetrahedronElement(p, btype);
|
||||
L2_Elements[Geometry::CUBE] = new L2_HexahedronElement(p, btype);
|
||||
L2_Elements[Geometry::PRISM] = new L2_WedgeElement(p, btype);
|
||||
}
|
||||
L2_Elements[Geometry::TETRAHEDRON]->SetMapType(map_type);
|
||||
L2_Elements[Geometry::CUBE]->SetMapType(map_type);
|
||||
L2_Elements[Geometry::PRISM]->SetMapType(map_type);
|
||||
// All trace element use the default Gauss-Legendre nodal points
|
||||
Tr_Elements[Geometry::TRIANGLE] = new L2_TriangleElement(p);
|
||||
Tr_Elements[Geometry::SQUARE] = new L2_QuadrilateralElement(p);
|
||||
|
||||
const int TetDof = L2_Elements[Geometry::TETRAHEDRON]->GetDof();
|
||||
const int HexDof = L2_Elements[Geometry::CUBE]->GetDof();
|
||||
const int MaxDof = std::max(TetDof, HexDof);
|
||||
const int PriDof = L2_Elements[Geometry::PRISM]->GetDof();
|
||||
const int MaxDof = std::max(TetDof, std::max(PriDof, HexDof));
|
||||
OtherDofOrd = new int[MaxDof];
|
||||
for (int j = 0; j < MaxDof; j++)
|
||||
{
|
||||
@@ -1850,7 +1896,8 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
|
||||
}
|
||||
}
|
||||
|
||||
int *L2_FECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
const int *L2_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -1882,6 +1929,8 @@ RT_FECollection::RT_FECollection(const int p, const int dim,
|
||||
const int cb_type, const int ob_type)
|
||||
: ob_type(ob_type)
|
||||
{
|
||||
MFEM_VERIFY(p >= 0, "RT_FECollection requires order >= 0.");
|
||||
|
||||
int cp_type = BasisType::GetQuadrature1D(cb_type);
|
||||
int op_type = BasisType::GetQuadrature1D(ob_type);
|
||||
|
||||
@@ -2069,7 +2118,8 @@ void RT_FECollection::InitFaces(const int p, const int dim, const int map_type,
|
||||
}
|
||||
}
|
||||
|
||||
int *RT_FECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
const int *RT_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
if (GeomType == Geometry::SEGMENT)
|
||||
{
|
||||
@@ -2157,6 +2207,9 @@ DG_Interface_FECollection::DG_Interface_FECollection(const int p, const int dim,
|
||||
ND_FECollection::ND_FECollection(const int p, const int dim,
|
||||
const int cb_type, const int ob_type)
|
||||
{
|
||||
MFEM_VERIFY(p >= 1, "ND_FECollection requires order >= 1.");
|
||||
MFEM_VERIFY(dim >= 1 && dim <= 3, "ND_FECollection requires 1 <= dim <= 3.");
|
||||
|
||||
const int pm1 = p - 1, pm2 = p - 2;
|
||||
|
||||
if (cb_type == BasisType::GaussLobatto &&
|
||||
@@ -2310,7 +2363,8 @@ ND_FECollection::ND_FECollection(const int p, const int dim,
|
||||
}
|
||||
}
|
||||
|
||||
int *ND_FECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
const int *ND_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
if (GeomType == Geometry::SEGMENT)
|
||||
{
|
||||
@@ -2320,8 +2374,7 @@ int *ND_FECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
{
|
||||
if (Or != 0 && Or != 5)
|
||||
{
|
||||
MFEM_ABORT("ND_FECollection::DofOrderForOrientation: "
|
||||
"triangle face orientation " << Or << " is not supported! "
|
||||
MFEM_ABORT("triangle face orientation " << Or << " is not supported! "
|
||||
"Use Mesh::ReorientTetMesh to fix it.");
|
||||
}
|
||||
return TriDofOrd[Or%6];
|
||||
@@ -2457,7 +2510,7 @@ NURBSFECollection::~NURBSFECollection()
|
||||
}
|
||||
|
||||
const FiniteElement *
|
||||
NURBSFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
NURBSFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
switch (GeomType)
|
||||
{
|
||||
@@ -2470,13 +2523,14 @@ NURBSFECollection::FiniteElementForGeometry(int GeomType) const
|
||||
return SegmentFE; // Make some compilers happy
|
||||
}
|
||||
|
||||
int NURBSFECollection::DofForGeometry(int GeomType) const
|
||||
int NURBSFECollection::DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
mfem_error("NURBSFECollection::DofForGeometry");
|
||||
return 0; // Make some compilers happy
|
||||
}
|
||||
|
||||
int *NURBSFECollection::DofOrderForOrientation(int GeomType, int Or) const
|
||||
const int *NURBSFECollection::DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{
|
||||
mfem_error("NURBSFECollection::DofOrderForOrientation");
|
||||
return NULL;
|
||||
|
||||
+148
-104
@@ -36,23 +36,26 @@ protected:
|
||||
template <Geometry::Type geom, Geometry::Type f_geom,
|
||||
typename v_t, typename e_t, typename eo_t>
|
||||
static inline void GetFace(int &nv, v_t &v, int &ne, e_t &e, eo_t &eo,
|
||||
int &nf, int &f, int &fg, int &fo,
|
||||
int &nf, int &f, Geometry::Type &fg, int &fo,
|
||||
const int face_info);
|
||||
|
||||
public:
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const = 0;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const = 0;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const = 0;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const = 0;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const = 0;
|
||||
/** @brief Returns an array, say p, that maps a local permuted index i to
|
||||
a local base index: base_i = p[i]. */
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const = 0;
|
||||
|
||||
virtual const char * Name() const { return "Undefined"; }
|
||||
|
||||
int HasFaceDofs(int GeomType) const;
|
||||
int HasFaceDofs(Geometry::Type GeomType) const;
|
||||
|
||||
virtual const FiniteElement *TraceFiniteElementForGeometry(
|
||||
int GeomType) const
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
return FiniteElementForGeometry(GeomType);
|
||||
}
|
||||
@@ -72,7 +75,8 @@ public:
|
||||
the sub-manifold (inside Geom) and its orientation are given by the
|
||||
parameter Info = 64 * SubIndex + SubOrientation. Naturally, it is assumed
|
||||
that 0 <= SDim <= Dim(Geom). */
|
||||
void SubDofOrder(int Geom, int SDim, int Info, Array<int> &dofs) const;
|
||||
void SubDofOrder(Geometry::Type Geom, int SDim, int Info,
|
||||
Array<int> &dofs) const;
|
||||
};
|
||||
|
||||
/// Arbitrary order H1-conforming (continuous) finite elements.
|
||||
@@ -90,17 +94,19 @@ public:
|
||||
explicit H1_FECollection(const int p, const int dim = 3,
|
||||
const int btype = BasisType::GaussLobatto);
|
||||
|
||||
virtual const FiniteElement *FiniteElementForGeometry(int GeomType) const
|
||||
virtual const FiniteElement *FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{ return H1_Elements[GeomType]; }
|
||||
virtual int DofForGeometry(int GeomType) const
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const
|
||||
{ return H1_dof[GeomType]; }
|
||||
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
virtual const char *Name() const { return h1_name; }
|
||||
FiniteElementCollection *GetTraceCollection() const;
|
||||
|
||||
int GetBasisType() const { return b_type; }
|
||||
/// Get the Cartesian to local H1 dof map
|
||||
const int *GetDofMap(int GeomType) const;
|
||||
const int *GetDofMap(Geometry::Type GeomType) const;
|
||||
|
||||
virtual ~H1_FECollection();
|
||||
};
|
||||
@@ -141,9 +147,10 @@ public:
|
||||
const int btype = BasisType::GaussLegendre,
|
||||
const int map_type = FiniteElement::VALUE);
|
||||
|
||||
virtual const FiniteElement *FiniteElementForGeometry(int GeomType) const
|
||||
virtual const FiniteElement *FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{ return L2_Elements[GeomType]; }
|
||||
virtual int DofForGeometry(int GeomType) const
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const
|
||||
{
|
||||
if (L2_Elements[GeomType])
|
||||
{
|
||||
@@ -151,11 +158,12 @@ public:
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
virtual const char *Name() const { return d_name; }
|
||||
|
||||
virtual const FiniteElement *TraceFiniteElementForGeometry(
|
||||
int GeomType) const
|
||||
Geometry::Type GeomType) const
|
||||
{
|
||||
return Tr_Elements[GeomType];
|
||||
}
|
||||
@@ -193,11 +201,13 @@ public:
|
||||
const int cb_type = BasisType::GaussLobatto,
|
||||
const int ob_type = BasisType::GaussLegendre);
|
||||
|
||||
virtual const FiniteElement *FiniteElementForGeometry(int GeomType) const
|
||||
virtual const FiniteElement *FiniteElementForGeometry(
|
||||
Geometry::Type GeomType) const
|
||||
{ return RT_Elements[GeomType]; }
|
||||
virtual int DofForGeometry(int GeomType) const
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const
|
||||
{ return RT_dof[GeomType]; }
|
||||
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
virtual const char *Name() const { return rt_name; }
|
||||
FiniteElementCollection *GetTraceCollection() const;
|
||||
|
||||
@@ -240,11 +250,13 @@ public:
|
||||
const int cb_type = BasisType::GaussLobatto,
|
||||
const int ob_type = BasisType::GaussLegendre);
|
||||
|
||||
virtual const FiniteElement *FiniteElementForGeometry(int GeomType) const
|
||||
virtual const FiniteElement *FiniteElementForGeometry(Geometry::Type GeomType)
|
||||
const
|
||||
{ return ND_Elements[GeomType]; }
|
||||
virtual int DofForGeometry(int GeomType) const
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const
|
||||
{ return ND_dof[GeomType]; }
|
||||
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
virtual const char *Name() const { return nd_name; }
|
||||
FiniteElementCollection *GetTraceCollection() const;
|
||||
|
||||
@@ -301,11 +313,12 @@ public:
|
||||
void SetOrder(int Order) const;
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int *DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char *Name() const { return name; }
|
||||
|
||||
@@ -325,15 +338,17 @@ private:
|
||||
const BiLinear2DFiniteElement QuadrilateralFE;
|
||||
const Linear3DFiniteElement TetrahedronFE;
|
||||
const TriLinear3DFiniteElement ParallelepipedFE;
|
||||
const H1_WedgeElement WedgeFE;
|
||||
public:
|
||||
LinearFECollection() { }
|
||||
LinearFECollection() : WedgeFE(1) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "Linear"; }
|
||||
};
|
||||
@@ -348,16 +363,18 @@ private:
|
||||
const BiQuad2DFiniteElement QuadrilateralFE;
|
||||
const Quadratic3DFiniteElement TetrahedronFE;
|
||||
const LagrangeHexFiniteElement ParallelepipedFE;
|
||||
const H1_WedgeElement WedgeFE;
|
||||
|
||||
public:
|
||||
QuadraticFECollection() : ParallelepipedFE(2) { }
|
||||
QuadraticFECollection() : ParallelepipedFE(2), WedgeFE(2) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "Quadratic"; }
|
||||
};
|
||||
@@ -373,11 +390,12 @@ public:
|
||||
QuadraticPosFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "QuadraticPos"; }
|
||||
};
|
||||
@@ -392,16 +410,19 @@ private:
|
||||
const BiCubic2DFiniteElement QuadrilateralFE;
|
||||
const Cubic3DFiniteElement TetrahedronFE;
|
||||
const LagrangeHexFiniteElement ParallelepipedFE;
|
||||
const H1_WedgeElement WedgeFE;
|
||||
|
||||
public:
|
||||
CubicFECollection() : ParallelepipedFE(3) { }
|
||||
CubicFECollection()
|
||||
: ParallelepipedFE(3), WedgeFE(3, BasisType::ClosedUniform) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "Cubic"; }
|
||||
};
|
||||
@@ -417,11 +438,12 @@ public:
|
||||
CrouzeixRaviartFECollection() : SegmentFE(1) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "CrouzeixRaviart"; }
|
||||
};
|
||||
@@ -439,11 +461,12 @@ public:
|
||||
LinearNonConf3DFECollection () { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "LinearNonConf3D"; }
|
||||
};
|
||||
@@ -461,11 +484,12 @@ public:
|
||||
RT0_2DFECollection() : SegmentFE(0) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "RT0_2D"; }
|
||||
};
|
||||
@@ -482,11 +506,12 @@ public:
|
||||
RT1_2DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "RT1_2D"; }
|
||||
};
|
||||
@@ -503,11 +528,12 @@ public:
|
||||
RT2_2DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "RT2_2D"; }
|
||||
};
|
||||
@@ -523,11 +549,12 @@ public:
|
||||
Const2DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "Const2D"; }
|
||||
};
|
||||
@@ -544,11 +571,12 @@ public:
|
||||
LinearDiscont2DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "LinearDiscont2D"; }
|
||||
};
|
||||
@@ -565,11 +593,12 @@ public:
|
||||
GaussLinearDiscont2DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "GaussLinearDiscont2D"; }
|
||||
};
|
||||
@@ -582,9 +611,10 @@ private:
|
||||
public:
|
||||
P1OnQuadFECollection() { }
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
virtual const char * Name() const { return "P1OnQuad"; }
|
||||
};
|
||||
|
||||
@@ -600,11 +630,12 @@ public:
|
||||
QuadraticDiscont2DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "QuadraticDiscont2D"; }
|
||||
};
|
||||
@@ -618,9 +649,10 @@ private:
|
||||
public:
|
||||
QuadraticPosDiscont2DFECollection() { }
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{ return NULL; }
|
||||
virtual const char * Name() const { return "QuadraticPosDiscont2D"; }
|
||||
};
|
||||
@@ -637,11 +669,12 @@ public:
|
||||
GaussQuadraticDiscont2DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "GaussQuadraticDiscont2D"; }
|
||||
};
|
||||
@@ -658,11 +691,12 @@ public:
|
||||
CubicDiscont2DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "CubicDiscont2D"; }
|
||||
};
|
||||
@@ -674,16 +708,18 @@ class Const3DFECollection : public FiniteElementCollection
|
||||
private:
|
||||
const P0TetFiniteElement TetrahedronFE;
|
||||
const P0HexFiniteElement ParallelepipedFE;
|
||||
const L2_WedgeElement WedgeFE;
|
||||
|
||||
public:
|
||||
Const3DFECollection () { }
|
||||
Const3DFECollection() : WedgeFE(0) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "Const3D"; }
|
||||
};
|
||||
@@ -700,11 +736,12 @@ public:
|
||||
LinearDiscont3DFECollection () { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "LinearDiscont3D"; }
|
||||
};
|
||||
@@ -721,11 +758,12 @@ public:
|
||||
QuadraticDiscont3DFECollection () : ParallelepipedFE(2) { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "QuadraticDiscont3D"; }
|
||||
};
|
||||
@@ -745,11 +783,12 @@ public:
|
||||
RefinedLinearFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "RefinedLinear"; }
|
||||
};
|
||||
@@ -766,11 +805,12 @@ public:
|
||||
ND1_3DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "ND1_3D"; }
|
||||
};
|
||||
@@ -788,11 +828,12 @@ public:
|
||||
RT0_3DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "RT0_3D"; }
|
||||
};
|
||||
@@ -809,11 +850,12 @@ public:
|
||||
RT1_3DFECollection() { }
|
||||
|
||||
virtual const FiniteElement *
|
||||
FiniteElementForGeometry(int GeomType) const;
|
||||
FiniteElementForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int DofForGeometry(int GeomType) const;
|
||||
virtual int DofForGeometry(Geometry::Type GeomType) const;
|
||||
|
||||
virtual int * DofOrderForOrientation(int GeomType, int Or) const;
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const;
|
||||
|
||||
virtual const char * Name() const { return "RT1_3D"; }
|
||||
};
|
||||
@@ -823,17 +865,19 @@ class Local_FECollection : public FiniteElementCollection
|
||||
{
|
||||
private:
|
||||
char d_name[32];
|
||||
int GeomType;
|
||||
Geometry::Type GeomType;
|
||||
FiniteElement *Local_Element;
|
||||
|
||||
public:
|
||||
Local_FECollection(const char *fe_name);
|
||||
|
||||
virtual const FiniteElement *FiniteElementForGeometry(int _GeomType) const
|
||||
virtual const FiniteElement *FiniteElementForGeometry(
|
||||
Geometry::Type _GeomType) const
|
||||
{ return (GeomType == _GeomType) ? Local_Element : NULL; }
|
||||
virtual int DofForGeometry(int _GeomType) const
|
||||
virtual int DofForGeometry(Geometry::Type _GeomType) const
|
||||
{ return (GeomType == _GeomType) ? Local_Element->GetDof() : 0; }
|
||||
virtual int *DofOrderForOrientation(int GeomType, int Or) const
|
||||
virtual const int *DofOrderForOrientation(Geometry::Type GeomType,
|
||||
int Or) const
|
||||
{ return NULL; }
|
||||
virtual const char *Name() const { return d_name; }
|
||||
|
||||
|
||||
+151
-112
@@ -93,13 +93,13 @@ FiniteElementSpace::FiniteElementSpace(const FiniteElementSpace &orig,
|
||||
|
||||
int FiniteElementSpace::GetOrder(int i) const
|
||||
{
|
||||
int GeomType = mesh->GetElementBaseGeometry(i);
|
||||
Geometry::Type GeomType = mesh->GetElementBaseGeometry(i);
|
||||
return fec->FiniteElementForGeometry(GeomType)->GetOrder();
|
||||
}
|
||||
|
||||
int FiniteElementSpace::GetFaceOrder(int i) const
|
||||
{
|
||||
int GeomType = mesh->GetFaceBaseGeometry(i);
|
||||
Geometry::Type GeomType = mesh->GetFaceBaseGeometry(i);
|
||||
return fec->FiniteElementForGeometry(GeomType)->GetOrder();
|
||||
}
|
||||
|
||||
@@ -497,23 +497,27 @@ FiniteElementSpace::H2L_GlobalRestrictionMatrix (FiniteElementSpace *lfes)
|
||||
|
||||
R = new SparseMatrix (lfes -> GetNDofs(), ndofs);
|
||||
|
||||
if (!lfes->GetNE())
|
||||
{
|
||||
R->Finalize();
|
||||
return R;
|
||||
}
|
||||
|
||||
const FiniteElement *h_fe = this -> GetFE (0);
|
||||
const FiniteElement *l_fe = lfes -> GetFE (0);
|
||||
Geometry::Type cached_geom = Geometry::INVALID;
|
||||
const FiniteElement *h_fe = NULL;
|
||||
const FiniteElement *l_fe = NULL;
|
||||
IsoparametricTransformation T;
|
||||
T.SetIdentityTransformation(h_fe->GetGeomType());
|
||||
h_fe->Project(*l_fe, T, loc_restr);
|
||||
|
||||
for (int i = 0; i < mesh -> GetNE(); i++)
|
||||
{
|
||||
this -> GetElementDofs (i, h_dofs);
|
||||
lfes -> GetElementDofs (i, l_dofs);
|
||||
|
||||
// Assuming 'loc_restr' depends only on the Geometry::Type.
|
||||
const Geometry::Type geom = mesh->GetElementBaseGeometry(i);
|
||||
if (geom != cached_geom)
|
||||
{
|
||||
h_fe = this -> GetFE (i);
|
||||
l_fe = lfes -> GetFE (i);
|
||||
T.SetIdentityTransformation(h_fe->GetGeomType());
|
||||
h_fe->Project(*l_fe, T, loc_restr);
|
||||
cached_geom = geom;
|
||||
}
|
||||
|
||||
R -> SetSubMatrix (l_dofs, h_dofs, loc_restr, 1);
|
||||
}
|
||||
|
||||
@@ -599,7 +603,7 @@ void FiniteElementSpace::BuildConformingInterpolation() const
|
||||
if (entity > 1) { T.SetFE(&QuadrilateralFE); }
|
||||
else { T.SetFE(&SegmentFE); }
|
||||
|
||||
int geom = (entity > 1) ? Geometry::SQUARE : Geometry::SEGMENT;
|
||||
Geometry::Type geom = (entity > 1) ? Geometry::SQUARE : Geometry::SEGMENT;
|
||||
const FiniteElement* fe = fec->FiniteElementForGeometry(geom);
|
||||
if (!fe) { continue; }
|
||||
|
||||
@@ -780,17 +784,25 @@ int FiniteElementSpace::GetNConformingDofs() const
|
||||
|
||||
SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
|
||||
const int coarse_ndofs, const Table &coarse_elem_dof,
|
||||
const DenseTensor &localP) const
|
||||
const DenseTensor localP[]) const
|
||||
{
|
||||
MFEM_VERIFY(mesh->GetLastOperation() == Mesh::REFINE, "");
|
||||
|
||||
Array<int> dofs, coarse_dofs, coarse_vdofs;
|
||||
Vector row;
|
||||
|
||||
const int coarse_ldof = localP.SizeJ();
|
||||
const int fine_ldof = localP.SizeI();
|
||||
SparseMatrix *P = new SparseMatrix(GetVSize(), coarse_ndofs*vdim,
|
||||
coarse_ldof);
|
||||
Mesh::GeometryList elem_geoms(*mesh);
|
||||
|
||||
SparseMatrix *P;
|
||||
if (elem_geoms.Size() == 1)
|
||||
{
|
||||
const int coarse_ldof = localP[elem_geoms[0]].SizeJ();
|
||||
P = new SparseMatrix(GetVSize(), coarse_ndofs*vdim, coarse_ldof);
|
||||
}
|
||||
else
|
||||
{
|
||||
P = new SparseMatrix(GetVSize(), coarse_ndofs*vdim);
|
||||
}
|
||||
|
||||
Array<int> mark(P->Height());
|
||||
mark = 0;
|
||||
@@ -800,7 +812,9 @@ SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
|
||||
for (int k = 0; k < mesh->GetNE(); k++)
|
||||
{
|
||||
const Embedding &emb = rtrans.embeddings[k];
|
||||
const DenseMatrix &lP = localP(emb.matrix);
|
||||
const Geometry::Type geom = mesh->GetElementBaseGeometry(k);
|
||||
const DenseMatrix &lP = localP[geom](emb.matrix);
|
||||
const int fine_ldof = localP[geom].SizeI();
|
||||
|
||||
elem_dof->GetRow(k, dofs);
|
||||
coarse_elem_dof.GetRow(emb.parent, coarse_dofs);
|
||||
@@ -826,17 +840,19 @@ SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
|
||||
}
|
||||
|
||||
MFEM_ASSERT(mark.Sum() == P->Height(), "Not all rows of P set.");
|
||||
if (elem_geoms.Size() != 1) { P->Finalize(); }
|
||||
return P;
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetLocalRefinementMatrices(DenseTensor &localP) const
|
||||
void FiniteElementSpace::GetLocalRefinementMatrices(
|
||||
Geometry::Type geom, DenseTensor &localP) const
|
||||
{
|
||||
int geom = mesh->GetElementBaseGeometry(); // assuming the same geom
|
||||
const FiniteElement *fe = fec->FiniteElementForGeometry(geom);
|
||||
|
||||
const CoarseFineTransformations &rtrans = mesh->GetRefinementTransforms();
|
||||
const DenseTensor &pmats = rtrans.GetPointMatrices(geom);
|
||||
|
||||
int nmat = rtrans.point_matrices.SizeK();
|
||||
int nmat = pmats.SizeK();
|
||||
int ldof = fe->GetDof(); // assuming the same FE everywhere
|
||||
|
||||
IsoparametricTransformation isotr;
|
||||
@@ -846,7 +862,7 @@ void FiniteElementSpace::GetLocalRefinementMatrices(DenseTensor &localP) const
|
||||
localP.SetSize(ldof, ldof, nmat);
|
||||
for (int i = 0; i < nmat; i++)
|
||||
{
|
||||
isotr.GetPointMat() = rtrans.point_matrices(i);
|
||||
isotr.GetPointMat() = pmats(i);
|
||||
isotr.FinalizeTransformation();
|
||||
fe->GetLocalInterpolation(isotr, localP(i));
|
||||
}
|
||||
@@ -857,8 +873,13 @@ SparseMatrix* FiniteElementSpace::RefinementMatrix(int old_ndofs,
|
||||
{
|
||||
MFEM_VERIFY(ndofs >= old_ndofs, "Previous space is not coarser.");
|
||||
|
||||
DenseTensor localP;
|
||||
GetLocalRefinementMatrices(localP);
|
||||
Mesh::GeometryList elem_geoms(*mesh);
|
||||
|
||||
DenseTensor localP[Geometry::NumGeom];
|
||||
for (int i = 0; i < elem_geoms.Size(); i++)
|
||||
{
|
||||
GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
|
||||
}
|
||||
|
||||
return RefinementMatrix_main(old_ndofs, *old_elem_dof, localP);
|
||||
}
|
||||
@@ -874,7 +895,12 @@ FiniteElementSpace::RefinementOperator::RefinementOperator
|
||||
width = old_ndofs * fespace->GetVDim();
|
||||
height = fespace->GetVSize();
|
||||
|
||||
fespace->GetLocalRefinementMatrices(localP);
|
||||
Mesh::GeometryList elem_geoms(*fespace->GetMesh());
|
||||
|
||||
for (int i = 0; i < elem_geoms.Size(); i++)
|
||||
{
|
||||
fespace->GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
|
||||
}
|
||||
}
|
||||
|
||||
FiniteElementSpace::RefinementOperator::RefinementOperator(
|
||||
@@ -882,7 +908,14 @@ FiniteElementSpace::RefinementOperator::RefinementOperator(
|
||||
: Operator(fespace->GetVSize(), coarse_fes->GetVSize()),
|
||||
fespace(fespace), old_elem_dof(NULL)
|
||||
{
|
||||
fespace->GetLocalRefinementMatrices(*coarse_fes, localP);
|
||||
Mesh::GeometryList elem_geoms(*fespace->GetMesh());
|
||||
|
||||
for (int i = 0; i < elem_geoms.Size(); i++)
|
||||
{
|
||||
fespace->GetLocalRefinementMatrices(*coarse_fes, elem_geoms[i],
|
||||
localP[elem_geoms[i]]);
|
||||
}
|
||||
|
||||
// Make a copy of the coarse elem_dof Table.
|
||||
old_elem_dof = new Table(coarse_fes->GetElementToDofTable());
|
||||
}
|
||||
@@ -909,7 +942,8 @@ void FiniteElementSpace::RefinementOperator
|
||||
for (int k = 0; k < mesh->GetNE(); k++)
|
||||
{
|
||||
const Embedding &emb = rtrans.embeddings[k];
|
||||
const DenseMatrix &lP = localP(emb.matrix);
|
||||
const Geometry::Type geom = mesh->GetElementBaseGeometry(k);
|
||||
const DenseMatrix &lP = localP[geom](emb.matrix);
|
||||
|
||||
fespace->GetElementDofs(k, dofs);
|
||||
old_elem_dof->GetRow(emb.parent, old_dofs);
|
||||
@@ -941,70 +975,29 @@ void FiniteElementSpace::RefinementOperator
|
||||
}
|
||||
}
|
||||
|
||||
void InvertLinearTrans(IsoparametricTransformation &trans,
|
||||
const DenseMatrix &invdfdx,
|
||||
const IntegrationPoint &pt, Vector &x)
|
||||
void FiniteElementSpace::GetLocalDerefinementMatrices(Geometry::Type geom,
|
||||
DenseTensor &localR) const
|
||||
{
|
||||
// invert a linear transform with one Newton step
|
||||
IntegrationPoint p0;
|
||||
p0.Set3(0, 0, 0);
|
||||
trans.Transform(p0, x);
|
||||
|
||||
double store[3];
|
||||
Vector v(store, x.Size());
|
||||
pt.Get(v, x.Size());
|
||||
v -= x;
|
||||
|
||||
invdfdx.Mult(v, x);
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetLocalDerefinementMatrices(DenseTensor &localR) const
|
||||
{
|
||||
int geom = mesh->GetElementBaseGeometry(); // assuming the same geom
|
||||
const FiniteElement *fe = fec->FiniteElementForGeometry(geom);
|
||||
const IntegrationRule &nodes = fe->GetNodes();
|
||||
|
||||
const CoarseFineTransformations &dtrans =
|
||||
mesh->ncmesh->GetDerefinementTransforms();
|
||||
const DenseTensor &pmats = dtrans.GetPointMatrices(geom);
|
||||
|
||||
int nmat = dtrans.point_matrices.SizeK();
|
||||
int ldof = fe->GetDof();
|
||||
int dim = mesh->Dimension();
|
||||
const int nmat = pmats.SizeK();
|
||||
const int ldof = fe->GetDof();
|
||||
|
||||
LinearFECollection linfec;
|
||||
IsoparametricTransformation isotr;
|
||||
isotr.SetFE(linfec.FiniteElementForGeometry(geom));
|
||||
|
||||
DenseMatrix invdfdx(dim);
|
||||
IntegrationPoint ipt;
|
||||
Vector pt(&ipt.x, dim), shape(ldof);
|
||||
isotr.SetIdentityTransformation(geom);
|
||||
|
||||
// calculate local restriction matrices for all refinement types
|
||||
localR.SetSize(ldof, ldof, nmat);
|
||||
for (int i = 0; i < nmat; i++)
|
||||
{
|
||||
DenseMatrix &lR = localR(i);
|
||||
lR = infinity(); // marks invalid rows
|
||||
|
||||
isotr.GetPointMat() = dtrans.point_matrices(i);
|
||||
isotr.GetPointMat() = pmats(i);
|
||||
isotr.FinalizeTransformation();
|
||||
isotr.SetIntPoint(&nodes[0]);
|
||||
CalcInverse(isotr.Jacobian(), invdfdx);
|
||||
|
||||
for (int j = 0; j < nodes.Size(); j++)
|
||||
{
|
||||
InvertLinearTrans(isotr, invdfdx, nodes[j], pt);
|
||||
if (Geometries.CheckPoint(geom, ipt)) // do we need an epsilon here?
|
||||
{
|
||||
IntegrationPoint ip;
|
||||
ip.Set(pt, dim);
|
||||
MFEM_ASSERT(dynamic_cast<const NodalFiniteElement*>(fe),
|
||||
"only nodal FEs are implemented");
|
||||
fe->CalcShape(ip, shape); // TODO: H(curl), etc.?
|
||||
lR.SetRow(j, shape);
|
||||
}
|
||||
}
|
||||
lR.Threshold(1e-12);
|
||||
fe->GetLocalRestriction(isotr, localR(i));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1018,21 +1011,38 @@ SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
|
||||
Array<int> dofs, old_dofs, old_vdofs;
|
||||
Vector row;
|
||||
|
||||
DenseTensor localR;
|
||||
GetLocalDerefinementMatrices(localR);
|
||||
Mesh::GeometryList elem_geoms(*mesh);
|
||||
|
||||
SparseMatrix *R = new SparseMatrix(ndofs*vdim, old_ndofs*vdim,
|
||||
localR.SizeI());
|
||||
DenseTensor localR[Geometry::NumGeom];
|
||||
for (int i = 0; i < elem_geoms.Size(); i++)
|
||||
{
|
||||
GetLocalDerefinementMatrices(elem_geoms[i], localR[elem_geoms[i]]);
|
||||
}
|
||||
|
||||
SparseMatrix *R;
|
||||
if (elem_geoms.Size() == 1)
|
||||
{
|
||||
R = new SparseMatrix(ndofs*vdim, old_ndofs*vdim,
|
||||
localR[elem_geoms[0]].SizeI());
|
||||
}
|
||||
else
|
||||
{
|
||||
R = new SparseMatrix(ndofs*vdim, old_ndofs*vdim);
|
||||
}
|
||||
Array<int> mark(R->Height());
|
||||
mark = 0;
|
||||
|
||||
const CoarseFineTransformations &dtrans =
|
||||
mesh->ncmesh->GetDerefinementTransforms();
|
||||
|
||||
MFEM_ASSERT(dtrans.embeddings.Size() == old_elem_dof->Size(), "");
|
||||
|
||||
int num_marked = 0;
|
||||
for (int k = 0; k < dtrans.embeddings.Size(); k++)
|
||||
{
|
||||
const Embedding &emb = dtrans.embeddings[k];
|
||||
DenseMatrix &lR = localR(emb.matrix);
|
||||
const Geometry::Type geom = mesh->GetElementBaseGeometry(emb.parent);
|
||||
DenseMatrix &lR = localR[geom](emb.matrix);
|
||||
|
||||
elem_dof->GetRow(emb.parent, dofs);
|
||||
old_elem_dof->GetRow(k, old_dofs);
|
||||
@@ -1054,36 +1064,41 @@ SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
|
||||
lR.GetRow(i, row);
|
||||
R->SetRow(r, old_vdofs, row);
|
||||
mark[m] = 1;
|
||||
num_marked++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MFEM_ASSERT(mark.Sum() == R->Height(), "Not all rows of R set.");
|
||||
MFEM_VERIFY(num_marked == R->Height(),
|
||||
"internal error: not all rows of R were set.");
|
||||
if (elem_geoms.Size() != 1) { R->Finalize(); }
|
||||
return R;
|
||||
}
|
||||
|
||||
void FiniteElementSpace::GetLocalRefinementMatrices(
|
||||
const FiniteElementSpace &coarse_fes, DenseTensor &localP) const
|
||||
const FiniteElementSpace &coarse_fes, Geometry::Type geom,
|
||||
DenseTensor &localP) const
|
||||
{
|
||||
// Assumptions: see the declaration of the method.
|
||||
|
||||
int fine_geom = mesh->GetElementBaseGeometry(0);
|
||||
const FiniteElement *fine_fe = fec->FiniteElementForGeometry(fine_geom);
|
||||
const FiniteElement *coarse_fe = coarse_fes.GetFE(0);
|
||||
const FiniteElement *fine_fe = fec->FiniteElementForGeometry(geom);
|
||||
const FiniteElement *coarse_fe =
|
||||
coarse_fes.fec->FiniteElementForGeometry(geom);
|
||||
|
||||
const CoarseFineTransformations &rtrans = mesh->GetRefinementTransforms();
|
||||
const DenseTensor &pmats = rtrans.GetPointMatrices(geom);
|
||||
|
||||
int nmat = rtrans.point_matrices.SizeK();
|
||||
int nmat = pmats.SizeK();
|
||||
|
||||
IsoparametricTransformation isotr;
|
||||
isotr.SetIdentityTransformation(fine_geom);
|
||||
isotr.SetIdentityTransformation(geom);
|
||||
|
||||
// Calculate the local interpolation matrices for all refinement types
|
||||
localP.SetSize(fine_fe->GetDof(), coarse_fe->GetDof(), nmat);
|
||||
for (int i = 0; i < nmat; i++)
|
||||
{
|
||||
isotr.GetPointMat() = rtrans.point_matrices(i);
|
||||
isotr.GetPointMat() = pmats(i);
|
||||
isotr.FinalizeTransformation();
|
||||
fine_fe->GetTransferMatrix(*coarse_fe, isotr, localP(i));
|
||||
}
|
||||
@@ -1191,22 +1206,25 @@ void FiniteElementSpace::Construct()
|
||||
cP_is_set = false;
|
||||
// Th is initialized/destroyed before this method is called.
|
||||
|
||||
if (mesh->Dimension() == 3 && mesh->GetNE())
|
||||
if (mesh->GetNFaces() > 0)
|
||||
{
|
||||
// Here we assume that all faces in the mesh have the same base
|
||||
// geometry -- the base geometry of the 0-th face element.
|
||||
// The class Mesh assumes the same inside GetFaceBaseGeometry(...).
|
||||
// Thus we do not need to generate all the faces in the mesh
|
||||
// if we do not need them.
|
||||
int fdof = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
|
||||
if (fdof > 0)
|
||||
bool have_face_dofs = false;
|
||||
for (int g = Geometry::DimStart[2]; g < Geometry::DimStart[3]; g++)
|
||||
{
|
||||
if (mesh->HasGeometry(Geometry::Type(g)) &&
|
||||
fec->DofForGeometry(Geometry::Type(g)) > 0)
|
||||
{
|
||||
have_face_dofs = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (have_face_dofs)
|
||||
{
|
||||
fdofs = new int[mesh->GetNFaces()+1];
|
||||
fdofs[0] = 0;
|
||||
for (int i = 0; i < mesh->GetNFaces(); i++)
|
||||
{
|
||||
nfdofs += fdof;
|
||||
// nfdofs += fec->DofForGeometry(mesh->GetFaceBaseGeometry(i));
|
||||
nfdofs += fec->DofForGeometry(mesh->GetFaceBaseGeometry(i));
|
||||
fdofs[i+1] = nfdofs;
|
||||
}
|
||||
}
|
||||
@@ -1218,7 +1236,7 @@ void FiniteElementSpace::Construct()
|
||||
bdofs[0] = 0;
|
||||
for (int i = 0; i < mesh->GetNE(); i++)
|
||||
{
|
||||
int geom = mesh->GetElementBaseGeometry(i);
|
||||
Geometry::Type geom = mesh->GetElementBaseGeometry(i);
|
||||
nbdofs += fec->DofForGeometry(geom);
|
||||
bdofs[i+1] = nbdofs;
|
||||
}
|
||||
@@ -1239,8 +1257,8 @@ void FiniteElementSpace::GetElementDofs (int i, Array<int> &dofs) const
|
||||
else
|
||||
{
|
||||
Array<int> V, E, Eo, F, Fo;
|
||||
int k, j, nv, ne, nf, nb, nfd, nd;
|
||||
int *ind, dim;
|
||||
int k, j, nv, ne, nf, nb, nfd, nd, dim;
|
||||
const int *ind;
|
||||
|
||||
dim = mesh->Dimension();
|
||||
nv = fec->DofForGeometry(Geometry::POINT);
|
||||
@@ -1354,8 +1372,8 @@ void FiniteElementSpace::GetBdrElementDofs(int i, Array<int> &dofs) const
|
||||
else
|
||||
{
|
||||
Array<int> V, E, Eo;
|
||||
int k, j, nv, ne, nf, nd, iF, oF;
|
||||
int *ind, dim;
|
||||
int k, j, nv, ne, nf, nd, iF, oF, dim;
|
||||
const int *ind;
|
||||
|
||||
dim = mesh->Dimension();
|
||||
nv = fec->DofForGeometry(Geometry::POINT);
|
||||
@@ -1411,8 +1429,8 @@ void FiniteElementSpace::GetBdrElementDofs(int i, Array<int> &dofs) const
|
||||
// if (dim == 3)
|
||||
{
|
||||
ne = nv + ne * E.Size();
|
||||
ind = (fec->DofOrderForOrientation(
|
||||
mesh->GetBdrElementBaseGeometry(i), oF));
|
||||
ind = fec->DofOrderForOrientation(
|
||||
mesh->GetBdrElementBaseGeometry(i), oF);
|
||||
for (j = 0; j < nf; j++)
|
||||
{
|
||||
if (ind[j] < 0)
|
||||
@@ -1623,7 +1641,7 @@ const FiniteElement *FiniteElementSpace::GetEdgeElement(int i) const
|
||||
}
|
||||
|
||||
const FiniteElement *FiniteElementSpace::GetTraceElement(
|
||||
int i, int geom_type) const
|
||||
int i, Geometry::Type geom_type) const
|
||||
{
|
||||
return fec->TraceFiniteElementForGeometry(geom_type);
|
||||
}
|
||||
@@ -1663,8 +1681,14 @@ void FiniteElementSpace::GetTransferOperator(
|
||||
|
||||
if (T.Type() == Operator::MFEM_SPARSEMAT)
|
||||
{
|
||||
DenseTensor localP;
|
||||
GetLocalRefinementMatrices(coarse_fes, localP);
|
||||
Mesh::GeometryList elem_geoms(*mesh);
|
||||
|
||||
DenseTensor localP[Geometry::NumGeom];
|
||||
for (int i = 0; i < elem_geoms.Size(); i++)
|
||||
{
|
||||
GetLocalRefinementMatrices(coarse_fes, elem_geoms[i],
|
||||
localP[elem_geoms[i]]);
|
||||
}
|
||||
T.Reset(RefinementMatrix_main(coarse_fes.GetNDofs(),
|
||||
coarse_fes.GetElementToDofTable(),
|
||||
localP));
|
||||
@@ -1812,8 +1836,9 @@ void FiniteElementSpace::Save(std::ostream &out) const
|
||||
const double eps = 5e-14;
|
||||
nurbs_unit_weights = (NURBSext->GetWeights().Min() >= 1.0-eps &&
|
||||
NURBSext->GetWeights().Max() <= 1.0+eps);
|
||||
if (NURBSext->GetOrder() == NURBSFECollection::VariableOrder ||
|
||||
(NURBSext != mesh->NURBSext && !nurbs_unit_weights))
|
||||
if ((NURBSext->GetOrder() == NURBSFECollection::VariableOrder) ||
|
||||
(NURBSext != mesh->NURBSext && !nurbs_unit_weights) ||
|
||||
(NURBSext->GetMaster().Size() != 0 ))
|
||||
{
|
||||
fes_format = 100; // v1.0 format
|
||||
}
|
||||
@@ -1843,6 +1868,13 @@ void FiniteElementSpace::Save(std::ostream &out) const
|
||||
// 1 = do not write the size, just the entries:
|
||||
NURBSext->GetOrders().Save(out, 1);
|
||||
}
|
||||
// If periodic BCs are given, write connectivity
|
||||
if (NURBSext->GetMaster().Size() != 0 )
|
||||
{
|
||||
out <<"NURBS_periodic\n";
|
||||
NURBSext->GetMaster().Save(out);
|
||||
NURBSext->GetSlave().Save(out);
|
||||
}
|
||||
// If the weights are not unit, write them to the output:
|
||||
if (!nurbs_unit_weights)
|
||||
{
|
||||
@@ -1920,6 +1952,13 @@ FiniteElementCollection *FiniteElementSpace::Load(Mesh *m, std::istream &input)
|
||||
NURBSext = new NURBSExtension(m->NURBSext, orders);
|
||||
}
|
||||
}
|
||||
else if (buff == "NURBS_periodic")
|
||||
{
|
||||
Array<int> master, slave;
|
||||
master.Load(input);
|
||||
slave.Load(input);
|
||||
NURBSext->ConnectBoundaries(master,slave);
|
||||
}
|
||||
else if (buff == "NURBS_weights")
|
||||
{
|
||||
MFEM_VERIFY(NURBSext, "NURBS_weights: NURBS_orders have to be "
|
||||
|
||||
+15
-9
@@ -136,7 +136,7 @@ protected:
|
||||
class RefinementOperator : public Operator
|
||||
{
|
||||
const FiniteElementSpace* fespace;
|
||||
DenseTensor localP;
|
||||
DenseTensor localP[Geometry::NumGeom];
|
||||
Table* old_elem_dof; // Owned.
|
||||
|
||||
public:
|
||||
@@ -152,15 +152,18 @@ protected:
|
||||
|
||||
// This method makes the same assumptions as the method:
|
||||
// void GetLocalRefinementMatrices(
|
||||
// const FiniteElementSpace &coarse_fes, DenseTensor &localP) const
|
||||
// const FiniteElementSpace &coarse_fes, Geometry::Type geom,
|
||||
// DenseTensor &localP) const
|
||||
// which is defined below. It also assumes that the coarse fes and this have
|
||||
// the same vector dimension, vdim.
|
||||
SparseMatrix *RefinementMatrix_main(const int coarse_ndofs,
|
||||
const Table &coarse_elem_dof,
|
||||
const DenseTensor &localP) const;
|
||||
const DenseTensor localP[]) const;
|
||||
|
||||
void GetLocalRefinementMatrices(DenseTensor &localP) const;
|
||||
void GetLocalDerefinementMatrices(DenseTensor &localR) const;
|
||||
void GetLocalRefinementMatrices(Geometry::Type geom,
|
||||
DenseTensor &localP) const;
|
||||
void GetLocalDerefinementMatrices(Geometry::Type geom,
|
||||
DenseTensor &localR) const;
|
||||
|
||||
/** Calculate explicit GridFunction interpolation matrix (after mesh
|
||||
refinement). NOTE: consider using the RefinementOperator class instead
|
||||
@@ -173,10 +176,10 @@ protected:
|
||||
// This method assumes that this->mesh is a refinement of coarse_fes->mesh
|
||||
// and that the CoarseFineTransformations of this->mesh are set accordingly.
|
||||
// Another assumption is that the FEs of this use the same MapType as the FEs
|
||||
// of coarse_fes. Finally, it assumes that this->mesh and coarse_fes->mesh
|
||||
// are NOT mixed meshes, and that the spaces this and coarse_fes are NOT
|
||||
// variable-order spaces.
|
||||
// of coarse_fes. Finally, it assumes that the spaces this and coarse_fes are
|
||||
// NOT variable-order spaces.
|
||||
void GetLocalRefinementMatrices(const FiniteElementSpace &coarse_fes,
|
||||
Geometry::Type geom,
|
||||
DenseTensor &localP) const;
|
||||
|
||||
/// Help function for constructors + Load().
|
||||
@@ -266,8 +269,11 @@ public:
|
||||
|
||||
const FiniteElementCollection *FEColl() const { return fec; }
|
||||
|
||||
/// Number of all scalar vertex dofs
|
||||
int GetNVDofs() const { return nvdofs; }
|
||||
/// Number of all scalar edge-interior dofs
|
||||
int GetNEDofs() const { return nedofs; }
|
||||
/// Number of all scalar face-interior dofs
|
||||
int GetNFDofs() const { return nfdofs; }
|
||||
|
||||
/// Returns number of vertices in the mesh.
|
||||
@@ -398,7 +404,7 @@ public:
|
||||
const FiniteElement *GetEdgeElement(int i) const;
|
||||
|
||||
/// Return the trace element from element 'i' to the given 'geom_type'
|
||||
const FiniteElement *GetTraceElement(int i, int geom_type) const;
|
||||
const FiniteElement *GetTraceElement(int i, Geometry::Type geom_type) const;
|
||||
|
||||
/** Mark degrees of freedom associated with boundary elements with
|
||||
the specified boundary attributes (marked in 'bdr_attr_is_ess').
|
||||
|
||||
+216
-23
@@ -10,15 +10,16 @@
|
||||
// Software Foundation) version 2.1 dated February 1999.
|
||||
|
||||
#include "fem.hpp"
|
||||
#include "../mesh/wedge.hpp"
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
const char *Geometry::Name[NumGeom] =
|
||||
{ "Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube" };
|
||||
{ "Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube", "Prism" };
|
||||
|
||||
const double Geometry::Volume[NumGeom] =
|
||||
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0 };
|
||||
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0, 0.5 };
|
||||
|
||||
Geometry::Geometry()
|
||||
{
|
||||
@@ -112,6 +113,32 @@ Geometry::Geometry()
|
||||
GeomVert[5]->IntPoint(7).y = 1.0;
|
||||
GeomVert[5]->IntPoint(7).z = 1.0;
|
||||
|
||||
// Vertices for Geometry::PRISM
|
||||
GeomVert[6] = new IntegrationRule(6);
|
||||
GeomVert[6]->IntPoint(0).x = 0.0;
|
||||
GeomVert[6]->IntPoint(0).y = 0.0;
|
||||
GeomVert[6]->IntPoint(0).z = 0.0;
|
||||
|
||||
GeomVert[6]->IntPoint(1).x = 1.0;
|
||||
GeomVert[6]->IntPoint(1).y = 0.0;
|
||||
GeomVert[6]->IntPoint(1).z = 0.0;
|
||||
|
||||
GeomVert[6]->IntPoint(2).x = 0.0;
|
||||
GeomVert[6]->IntPoint(2).y = 1.0;
|
||||
GeomVert[6]->IntPoint(2).z = 0.0;
|
||||
|
||||
GeomVert[6]->IntPoint(3).x = 0.0;
|
||||
GeomVert[6]->IntPoint(3).y = 0.0;
|
||||
GeomVert[6]->IntPoint(3).z = 1.0;
|
||||
|
||||
GeomVert[6]->IntPoint(4).x = 1.0;
|
||||
GeomVert[6]->IntPoint(4).y = 0.0;
|
||||
GeomVert[6]->IntPoint(4).z = 1.0;
|
||||
|
||||
GeomVert[6]->IntPoint(5).x = 0.0;
|
||||
GeomVert[6]->IntPoint(5).y = 1.0;
|
||||
GeomVert[6]->IntPoint(5).z = 1.0;
|
||||
|
||||
GeomCenter[POINT].x = 0.0;
|
||||
GeomCenter[POINT].y = 0.0;
|
||||
GeomCenter[POINT].z = 0.0;
|
||||
@@ -136,12 +163,17 @@ Geometry::Geometry()
|
||||
GeomCenter[CUBE].y = 0.5;
|
||||
GeomCenter[CUBE].z = 0.5;
|
||||
|
||||
GeomCenter[PRISM].x = 1.0 / 3.0;
|
||||
GeomCenter[PRISM].y = 1.0 / 3.0;
|
||||
GeomCenter[PRISM].z = 0.5;
|
||||
|
||||
GeomToPerfGeomJac[POINT] = NULL;
|
||||
GeomToPerfGeomJac[SEGMENT] = new DenseMatrix(1);
|
||||
GeomToPerfGeomJac[TRIANGLE] = new DenseMatrix(2);
|
||||
GeomToPerfGeomJac[SQUARE] = new DenseMatrix(2);
|
||||
GeomToPerfGeomJac[TETRAHEDRON] = new DenseMatrix(3);
|
||||
GeomToPerfGeomJac[CUBE] = new DenseMatrix(3);
|
||||
GeomToPerfGeomJac[PRISM] = new DenseMatrix(3);
|
||||
|
||||
PerfGeomToGeomJac[POINT] = NULL;
|
||||
PerfGeomToGeomJac[SEGMENT] = NULL;
|
||||
@@ -149,12 +181,12 @@ Geometry::Geometry()
|
||||
PerfGeomToGeomJac[SQUARE] = NULL;
|
||||
PerfGeomToGeomJac[TETRAHEDRON] = new DenseMatrix(3);
|
||||
PerfGeomToGeomJac[CUBE] = NULL;
|
||||
PerfGeomToGeomJac[PRISM] = new DenseMatrix(3);
|
||||
|
||||
GeomToPerfGeomJac[SEGMENT]->Diag(1.0, 1);
|
||||
{
|
||||
Linear2DFiniteElement TriFE;
|
||||
IsoparametricTransformation tri_T;
|
||||
tri_T.SetFE(&TriFE);
|
||||
tri_T.SetFE(&TriangleFE);
|
||||
GetPerfPointMat (TRIANGLE, tri_T.GetPointMat());
|
||||
tri_T.FinalizeTransformation();
|
||||
tri_T.SetIntPoint(&GeomCenter[TRIANGLE]);
|
||||
@@ -163,9 +195,8 @@ Geometry::Geometry()
|
||||
}
|
||||
GeomToPerfGeomJac[SQUARE]->Diag(1.0, 2);
|
||||
{
|
||||
Linear3DFiniteElement TetFE;
|
||||
IsoparametricTransformation tet_T;
|
||||
tet_T.SetFE(&TetFE);
|
||||
tet_T.SetFE(&TetrahedronFE);
|
||||
GetPerfPointMat (TETRAHEDRON, tet_T.GetPointMat());
|
||||
tet_T.FinalizeTransformation();
|
||||
tet_T.SetIntPoint(&GeomCenter[TETRAHEDRON]);
|
||||
@@ -173,6 +204,15 @@ Geometry::Geometry()
|
||||
CalcInverse(tet_T.Jacobian(), *PerfGeomToGeomJac[TETRAHEDRON]);
|
||||
}
|
||||
GeomToPerfGeomJac[CUBE]->Diag(1.0, 3);
|
||||
{
|
||||
IsoparametricTransformation pri_T;
|
||||
pri_T.SetFE(&WedgeFE);
|
||||
GetPerfPointMat (PRISM, pri_T.GetPointMat());
|
||||
pri_T.FinalizeTransformation();
|
||||
pri_T.SetIntPoint(&GeomCenter[PRISM]);
|
||||
*GeomToPerfGeomJac[PRISM] = pri_T.Jacobian();
|
||||
CalcInverse(pri_T.Jacobian(), *PerfGeomToGeomJac[PRISM]);
|
||||
}
|
||||
}
|
||||
|
||||
Geometry::~Geometry()
|
||||
@@ -195,6 +235,7 @@ const IntegrationRule * Geometry::GetVertices(int GeomType)
|
||||
case Geometry::SQUARE: return GeomVert[3];
|
||||
case Geometry::TETRAHEDRON: return GeomVert[4];
|
||||
case Geometry::CUBE: return GeomVert[5];
|
||||
case Geometry::PRISM: return GeomVert[6];
|
||||
default:
|
||||
mfem_error ("Geometry::GetVertices(...)");
|
||||
}
|
||||
@@ -262,6 +303,16 @@ void Geometry::GetRandomPoint(int GeomType, IntegrationPoint &ip)
|
||||
ip.y = double(rand()) / RAND_MAX;
|
||||
ip.z = double(rand()) / RAND_MAX;
|
||||
break;
|
||||
case Geometry::PRISM:
|
||||
ip.x = double(rand()) / RAND_MAX;
|
||||
ip.y = double(rand()) / RAND_MAX;
|
||||
ip.z = double(rand()) / RAND_MAX;
|
||||
if (ip.x + ip.y > 1.0)
|
||||
{
|
||||
ip.x = 1.0 - ip.x;
|
||||
ip.y = 1.0 - ip.y;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MFEM_ABORT("Unknown type of reference element!");
|
||||
}
|
||||
@@ -319,6 +370,10 @@ bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip)
|
||||
if (ip.x < 0.0 || ip.x > 1.0 || ip.y < 0.0 || ip.y > 1.0 ||
|
||||
ip.z < 0.0 || ip.z > 1.0) { return false; }
|
||||
break;
|
||||
case Geometry::PRISM:
|
||||
if (ip.x < 0.0 || ip.y < 0.0 || ip.x+ip.y > 1.0 ||
|
||||
ip.z < 0.0 || ip.z > 1.0) { return false; }
|
||||
break;
|
||||
default:
|
||||
MFEM_ABORT("Unknown type of reference element!");
|
||||
}
|
||||
@@ -379,6 +434,16 @@ bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip, double eps)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case Geometry::PRISM:
|
||||
if ( internal::FuzzyLT(ip.x, 0.0, eps)
|
||||
|| internal::FuzzyLT(ip.y, 0.0, eps)
|
||||
|| internal::FuzzyGT(ip.x+ip.y, 1.0, eps)
|
||||
|| internal::FuzzyLT(ip.z, 0.0, eps)
|
||||
|| internal::FuzzyGT(ip.z, 1.0, eps) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MFEM_ABORT("Unknown type of reference element!");
|
||||
}
|
||||
@@ -461,14 +526,14 @@ bool Geometry::ProjectPoint(int GeomType, const IntegrationPoint &beg,
|
||||
}
|
||||
case Geometry::TRIANGLE:
|
||||
{
|
||||
double lend[3] = { end.x, end.y, 1-end.x-end.y };
|
||||
double lbeg[3] = { beg.x, beg.y, 1-beg.x-beg.y };
|
||||
double lend[3] = { end.x, end.y, 1.0-end.x-end.y };
|
||||
double lbeg[3] = { beg.x, beg.y, 1.0-beg.x-beg.y };
|
||||
return internal::IntersectSegment<3,2>(lbeg, lend, end);
|
||||
}
|
||||
case Geometry::SQUARE:
|
||||
{
|
||||
double lend[4] = { end.x, end.y, 1-end.x, 1.0-end.y };
|
||||
double lbeg[4] = { beg.x, beg.y, 1-beg.x, 1.0-beg.y };
|
||||
double lend[4] = { end.x, end.y, 1.0-end.x, 1.0-end.y };
|
||||
double lbeg[4] = { beg.x, beg.y, 1.0-beg.x, 1.0-beg.y };
|
||||
return internal::IntersectSegment<4,2>(lbeg, lend, end);
|
||||
}
|
||||
case Geometry::TETRAHEDRON:
|
||||
@@ -487,6 +552,12 @@ bool Geometry::ProjectPoint(int GeomType, const IntegrationPoint &beg,
|
||||
};
|
||||
return internal::IntersectSegment<6,3>(lbeg, lend, end);
|
||||
}
|
||||
case Geometry::PRISM:
|
||||
{
|
||||
double lend[5] = { end.x, end.y, end.z, 1.0-end.x-end.y, 1.0-end.z };
|
||||
double lbeg[5] = { beg.x, beg.y, beg.z, 1.0-beg.x-beg.y, 1.0-beg.z };
|
||||
return internal::IntersectSegment<5,3>(lbeg, lend, end);
|
||||
}
|
||||
default:
|
||||
MFEM_ABORT("Unknown type of reference element!");
|
||||
}
|
||||
@@ -574,6 +645,16 @@ bool Geometry::ProjectPoint(int GeomType, IntegrationPoint &ip)
|
||||
return in_x && in_y && in_z;
|
||||
}
|
||||
|
||||
case PRISM:
|
||||
{
|
||||
bool in_tri, in_z;
|
||||
in_tri = internal::ProjectTriangle(ip.x, ip.y);
|
||||
if (ip.z < 0.0) { in_z = false; ip.z = 0.0; }
|
||||
else if (ip.z > 1.0) { in_z = false; ip.z = 1.0; }
|
||||
else { in_z = true; }
|
||||
return in_tri && in_z;
|
||||
}
|
||||
|
||||
default:
|
||||
MFEM_ABORT("Reference element type is not supported!");
|
||||
}
|
||||
@@ -636,6 +717,18 @@ void Geometry::GetPerfPointMat(int GeomType, DenseMatrix &pm)
|
||||
}
|
||||
break;
|
||||
|
||||
case Geometry::PRISM:
|
||||
{
|
||||
pm.SetSize (3, 6);
|
||||
pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0;
|
||||
pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0;
|
||||
pm(0,2) = 0.5; pm(1,2) = 0.86602540378443864676; pm(2,2) = 0.0;
|
||||
pm(0,3) = 0.0; pm(1,3) = 0.0; pm(2,3) = 1.0;
|
||||
pm(0,4) = 1.0; pm(1,4) = 0.0; pm(2,4) = 1.0;
|
||||
pm(0,5) = 0.5; pm(1,5) = 0.86602540378443864676; pm(2,5) = 1.0;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
mfem_error ("Geometry::GetPerfPointMat (...)");
|
||||
}
|
||||
@@ -654,11 +747,13 @@ void Geometry::JacToPerfJac(int GeomType, const DenseMatrix &J,
|
||||
}
|
||||
}
|
||||
|
||||
const int Geometry::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6 };
|
||||
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3 };
|
||||
const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8 };
|
||||
const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12 };
|
||||
const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6 };
|
||||
const int Geometry::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6, 5 };
|
||||
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3, 3 };
|
||||
const int Geometry::DimStart[MaxDim+2] =
|
||||
{ POINT, SEGMENT, TRIANGLE, TETRAHEDRON, NUM_GEOMETRIES };
|
||||
const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8, 6 };
|
||||
const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12, 9 };
|
||||
const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6, 5 };
|
||||
|
||||
const int Geometry::
|
||||
Constants<Geometry::POINT>::Orient[1][1] = {{0}};
|
||||
@@ -723,7 +818,11 @@ const int Geometry::
|
||||
Constants<Geometry::TETRAHEDRON>::VertToVert::I[4] = {0, 3, 5, 6};
|
||||
const int Geometry::
|
||||
Constants<Geometry::TETRAHEDRON>::VertToVert::J[6][2] =
|
||||
{{1, 0}, {2, 1}, {3, 2}, {2, 3}, {3, 4}, {3, 5}};
|
||||
{
|
||||
{1, 0}, {2, 1}, {3, 2}, // 0,1:0 0,2:1 0,3:2
|
||||
{2, 3}, {3, 4}, // 1,2:3 1,3:4
|
||||
{3, 5} // 2,3:5
|
||||
};
|
||||
|
||||
const int Geometry::
|
||||
Constants<Geometry::CUBE>::Edges[12][2] =
|
||||
@@ -757,7 +856,29 @@ Constants<Geometry::CUBE>::VertToVert::J[12][2] =
|
||||
{7,-7} // 6,7:-7
|
||||
};
|
||||
|
||||
Geometry Geometries;
|
||||
const int Geometry::
|
||||
Constants<Geometry::PRISM>::Edges[9][2] =
|
||||
{{0, 1}, {1, 2}, {2, 0}, {3, 4}, {4, 5}, {5, 3}, {0, 3}, {1, 4}, {2, 5}};
|
||||
const int Geometry::
|
||||
Constants<Geometry::PRISM>::FaceTypes[5] =
|
||||
{
|
||||
Geometry::TRIANGLE, Geometry::TRIANGLE,
|
||||
Geometry::SQUARE, Geometry::SQUARE, Geometry::SQUARE
|
||||
};
|
||||
const int Geometry::
|
||||
Constants<Geometry::PRISM>::FaceVert[5][4] =
|
||||
{{0, 2, 1, -1}, {3, 4, 5, -1}, {0, 1, 4, 3}, {1, 2, 5, 4}, {2, 0, 3, 5}};
|
||||
const int Geometry::
|
||||
Constants<Geometry::PRISM>::VertToVert::I[6] = {0, 3, 5, 6, 8, 9};
|
||||
const int Geometry::
|
||||
Constants<Geometry::PRISM>::VertToVert::J[9][2] =
|
||||
{
|
||||
{1, 0}, {2, -3}, {3, 6}, // 0,1:0 0,2:-3 0,3:6
|
||||
{2, 1}, {4, 7}, // 1,2:1 1,4:7
|
||||
{5, 8}, // 2,5:8
|
||||
{4, 3}, {5, -6}, // 3,4:3 3,5:-6
|
||||
{5, 4} // 4,5:4
|
||||
};
|
||||
|
||||
|
||||
GeometryRefiner::GeometryRefiner()
|
||||
@@ -774,7 +895,8 @@ GeometryRefiner::~GeometryRefiner()
|
||||
}
|
||||
}
|
||||
|
||||
RefinedGeometry *GeometryRefiner::FindInRGeom(int Geom, int Times, int ETimes,
|
||||
RefinedGeometry *GeometryRefiner::FindInRGeom(Geometry::Type Geom,
|
||||
int Times, int ETimes,
|
||||
int Type)
|
||||
{
|
||||
Array<RefinedGeometry *> &RGA = RGeom[Geom];
|
||||
@@ -789,7 +911,7 @@ RefinedGeometry *GeometryRefiner::FindInRGeom(int Geom, int Times, int ETimes,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
IntegrationRule *GeometryRefiner::FindInIntPts(int Geom, int NPts)
|
||||
IntegrationRule *GeometryRefiner::FindInIntPts(Geometry::Type Geom, int NPts)
|
||||
{
|
||||
Array<IntegrationRule *> &IPA = IntPts[Geom];
|
||||
for (int i = 0; i < IPA.Size(); i++)
|
||||
@@ -800,9 +922,10 @@ IntegrationRule *GeometryRefiner::FindInIntPts(int Geom, int NPts)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RefinedGeometry * GeometryRefiner::Refine(int Geom, int Times, int ETimes)
|
||||
RefinedGeometry * GeometryRefiner::Refine(Geometry::Type Geom,
|
||||
int Times, int ETimes)
|
||||
{
|
||||
int i, j, k, l;
|
||||
int i, j, k, l, m;
|
||||
|
||||
Times = std::max(Times, 1);
|
||||
ETimes = std::max(ETimes, 1);
|
||||
@@ -1024,7 +1147,7 @@ RefinedGeometry * GeometryRefiner::Refine(int Geom, int Times, int ETimes)
|
||||
// enumerate and define the vertices
|
||||
Array<int> vi((n+1)*(n+1)*(n+1));
|
||||
vi = -1;
|
||||
int m = 0;
|
||||
m = 0;
|
||||
for (k = 0; k <= n; k++)
|
||||
for (j = 0; j <= k; j++)
|
||||
for (i = 0; i <= j; i++)
|
||||
@@ -1115,13 +1238,83 @@ RefinedGeometry * GeometryRefiner::Refine(int Geom, int Times, int ETimes)
|
||||
return RG;
|
||||
}
|
||||
|
||||
case Geometry::PRISM:
|
||||
{
|
||||
const int n = Times;
|
||||
RG = new RefinedGeometry ((n+1)*(n+1)*(n+2)/2, 6*n*n*n, 0);
|
||||
RG->Times = Times;
|
||||
RG->ETimes = ETimes;
|
||||
RG->Type = type;
|
||||
// enumerate and define the vertices
|
||||
m = 0;
|
||||
for (l = k = 0; k <= n; k++)
|
||||
for (j = 0; j <= n; j++)
|
||||
for (i = 0; i <= n-j; i++, l++)
|
||||
{
|
||||
IntegrationPoint &ip = RG->RefPts.IntPoint(l);
|
||||
if (type == 0)
|
||||
{
|
||||
ip.x = double(i) / n;
|
||||
ip.y = double(j) / n;
|
||||
ip.z = double(k) / n;
|
||||
}
|
||||
else
|
||||
{
|
||||
ip.x = cp[i]/(cp[i] + cp[j] + cp[n-i-j]);
|
||||
ip.y = cp[j]/(cp[i] + cp[j] + cp[n-i-j]);
|
||||
ip.z = cp[k];
|
||||
}
|
||||
m++;
|
||||
}
|
||||
if (m != (n+1)*(n+1)*(n+2)/2)
|
||||
{
|
||||
mfem_error("GeometryRefiner::Refine() for PRISM #1");
|
||||
}
|
||||
// elements
|
||||
Array<int> &G = RG->RefGeoms;
|
||||
m = 0;
|
||||
for (m = k = 0; k < n; k++)
|
||||
for (l = j = 0; j < n; j++, l++)
|
||||
for (i = 0; i < n-j; i++, l++)
|
||||
{
|
||||
G[m++] = l + (k+0) * (n+1) * (n+2) / 2;
|
||||
G[m++] = l + 1 + (k+0) * (n+1) * (n+2) / 2;
|
||||
G[m++] = l - j + (2 + (k+0) * (n+2)) * (n+1) / 2;
|
||||
G[m++] = l + (k+1) * (n+1) * (n+2) / 2;
|
||||
G[m++] = l + 1 + (k+1) * (n+1) * (Times+2) / 2;
|
||||
G[m++] = l - j + (2 + (k+1) * (n+2)) * (n+1) / 2;
|
||||
if (i+j+1 < n)
|
||||
{
|
||||
G[m++] = l + 1 + (k+0) * (n+1) * (n+2)/2;
|
||||
G[m++] = l - j + (2 + (k+0) * (n+1)) * (n+2) / 2;
|
||||
G[m++] = l - j + (2 + (k+0) * (n+2)) * (n+1) / 2;
|
||||
G[m++] = l + 1 + (k+1) * (n+1) * (n+2) / 2;
|
||||
G[m++] = l - j + (2 + (k+1) * (n+1)) * (n+2) / 2;
|
||||
G[m++] = l - j + (2 + (k+1) * (n+2)) * (n+1) / 2;
|
||||
}
|
||||
}
|
||||
if (m != 6*n*n*n)
|
||||
{
|
||||
mfem_error("GeometryRefiner::Refine() for PRISM #2");
|
||||
}
|
||||
for (i = 0; i < m; i++)
|
||||
if (G[i] < 0)
|
||||
{
|
||||
mfem_error("GeometryRefiner::Refine() for PRISM #3");
|
||||
}
|
||||
|
||||
RGeom[Geometry::PRISM].Append(RG);
|
||||
return RG;
|
||||
}
|
||||
|
||||
default:
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const IntegrationRule *GeometryRefiner::RefineInterior(int Geom, int Times)
|
||||
const IntegrationRule *GeometryRefiner::RefineInterior(Geometry::Type Geom,
|
||||
int Times)
|
||||
{
|
||||
IntegrationRule *ir = NULL;
|
||||
|
||||
|
||||
+40
-11
@@ -25,18 +25,26 @@ namespace mfem
|
||||
Geometry::TRIANGLE - triangle with vertices (0,0), (1,0), (0,1)
|
||||
Geometry::SQUARE - the unit square (0,1)x(0,1)
|
||||
Geometry::TETRAHEDRON - w/ vert. (0,0,0),(1,0,0),(0,1,0),(0,0,1)
|
||||
Geometry::CUBE - the unit cube */
|
||||
Geometry::CUBE - the unit cube
|
||||
Geometry::PRISM - w/ vert. (0,0,0),(1,0,0),(0,1,0),(0,0,1),(1,0,1),(0,1,1)
|
||||
*/
|
||||
class Geometry
|
||||
{
|
||||
public:
|
||||
enum Type { POINT, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE };
|
||||
enum Type
|
||||
{
|
||||
INVALID = -1,
|
||||
POINT = 0, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE, PRISM,
|
||||
NUM_GEOMETRIES
|
||||
};
|
||||
|
||||
static const int NumGeom = 6;
|
||||
static const int NumGeom = NUM_GEOMETRIES;
|
||||
static const int MaxDim = 3;
|
||||
static const int NumBdrArray[NumGeom];
|
||||
static const char *Name[NumGeom];
|
||||
static const double Volume[NumGeom];
|
||||
static const int Dimension[NumGeom];
|
||||
static const int DimStart[MaxDim+2]; // including MaxDim+1
|
||||
static const int NumVerts[NumGeom];
|
||||
static const int NumEdges[NumGeom];
|
||||
static const int NumFaces[NumGeom];
|
||||
@@ -126,7 +134,7 @@ template <> struct Geometry::Constants<Geometry::TRIANGLE>
|
||||
static const int NumVert = 3;
|
||||
static const int NumEdges = 3;
|
||||
static const int Edges[NumEdges][2];
|
||||
// Lower-triangular part of the local vertex-to-vertex graph.
|
||||
// Upper-triangular part of the local vertex-to-vertex graph.
|
||||
struct VertToVert
|
||||
{
|
||||
static const int I[NumVert];
|
||||
@@ -152,7 +160,7 @@ template <> struct Geometry::Constants<Geometry::SQUARE>
|
||||
static const int NumVert = 4;
|
||||
static const int NumEdges = 4;
|
||||
static const int Edges[NumEdges][2];
|
||||
// Lower-triangular part of the local vertex-to-vertex graph.
|
||||
// Upper-triangular part of the local vertex-to-vertex graph.
|
||||
struct VertToVert
|
||||
{
|
||||
static const int I[NumVert];
|
||||
@@ -176,7 +184,7 @@ template <> struct Geometry::Constants<Geometry::TETRAHEDRON>
|
||||
static const int FaceTypes[NumFaces];
|
||||
static const int MaxFaceVert = 3;
|
||||
static const int FaceVert[NumFaces][MaxFaceVert];
|
||||
// Lower-triangular part of the local vertex-to-vertex graph.
|
||||
// Upper-triangular part of the local vertex-to-vertex graph.
|
||||
struct VertToVert
|
||||
{
|
||||
static const int I[NumVert];
|
||||
@@ -194,7 +202,7 @@ template <> struct Geometry::Constants<Geometry::CUBE>
|
||||
static const int FaceTypes[NumFaces];
|
||||
static const int MaxFaceVert = 4;
|
||||
static const int FaceVert[NumFaces][MaxFaceVert];
|
||||
// Lower-triangular part of the local vertex-to-vertex graph.
|
||||
// Upper-triangular part of the local vertex-to-vertex graph.
|
||||
struct VertToVert
|
||||
{
|
||||
static const int I[NumVert];
|
||||
@@ -202,8 +210,28 @@ template <> struct Geometry::Constants<Geometry::CUBE>
|
||||
};
|
||||
};
|
||||
|
||||
template <> struct Geometry::Constants<Geometry::PRISM>
|
||||
{
|
||||
static const int Dimension = 3;
|
||||
static const int NumVert = 6;
|
||||
static const int NumEdges = 9;
|
||||
static const int Edges[NumEdges][2];
|
||||
static const int NumFaces = 5;
|
||||
static const int FaceTypes[NumFaces];
|
||||
static const int MaxFaceVert = 4;
|
||||
static const int FaceVert[NumFaces][MaxFaceVert];
|
||||
// Upper-triangular part of the local vertex-to-vertex graph.
|
||||
struct VertToVert
|
||||
{
|
||||
static const int I[NumVert];
|
||||
static const int J[NumEdges][2]; // {end,edge_idx}
|
||||
};
|
||||
};
|
||||
|
||||
// Defined in fe.cpp to ensure construction after 'mfem::WedgeFE'.
|
||||
extern Geometry Geometries;
|
||||
|
||||
|
||||
class RefinedGeometry
|
||||
{
|
||||
public:
|
||||
@@ -224,8 +252,9 @@ private:
|
||||
Array<RefinedGeometry *> RGeom[Geometry::NumGeom];
|
||||
Array<IntegrationRule *> IntPts[Geometry::NumGeom];
|
||||
|
||||
RefinedGeometry *FindInRGeom(int Geom, int Times, int ETimes, int Type);
|
||||
IntegrationRule *FindInIntPts(int Geom, int NPts);
|
||||
RefinedGeometry *FindInRGeom(Geometry::Type Geom, int Times, int ETimes,
|
||||
int Type);
|
||||
IntegrationRule *FindInIntPts(Geometry::Type Geom, int NPts);
|
||||
|
||||
public:
|
||||
GeometryRefiner();
|
||||
@@ -235,10 +264,10 @@ public:
|
||||
/// Get the Quadrature1D type of points used for subdivision.
|
||||
int GetType() const { return type; }
|
||||
|
||||
RefinedGeometry *Refine(int Geom, int Times, int ETimes = 1);
|
||||
RefinedGeometry *Refine(Geometry::Type Geom, int Times, int ETimes = 1);
|
||||
|
||||
/// @note This method always uses Quadrature1D::OpenUniform points.
|
||||
const IntegrationRule *RefineInterior(int Geom, int Times);
|
||||
const IntegrationRule *RefineInterior(Geometry::Type Geom, int Times);
|
||||
|
||||
~GeometryRefiner();
|
||||
};
|
||||
|
||||
+419
-157
@@ -294,7 +294,7 @@ int GridFunction::VectorDim() const
|
||||
if (!fes->GetNE())
|
||||
{
|
||||
const FiniteElementCollection *fec = fes->FEColl();
|
||||
static const int geoms[3] =
|
||||
static const Geometry::Type geoms[3] =
|
||||
{ Geometry::SEGMENT, Geometry::TRIANGLE, Geometry::TETRAHEDRON };
|
||||
fe = fec->FiniteElementForGeometry(geoms[fes->GetMesh()->Dimension()-1]);
|
||||
}
|
||||
@@ -915,9 +915,7 @@ double GridFunction::GetDivergence(ElementTransformation &tr) const
|
||||
"invalid FE map type");
|
||||
DenseMatrix grad_hat;
|
||||
GetVectorGradientHat(tr, grad_hat);
|
||||
const DenseMatrix &J = tr.Jacobian();
|
||||
DenseMatrix Jinv(J.Width(), J.Height());
|
||||
CalcInverse(J, Jinv);
|
||||
const DenseMatrix &Jinv = tr.InverseJacobian();
|
||||
div_v = 0.0;
|
||||
for (int i = 0; i < Jinv.Width(); i++)
|
||||
{
|
||||
@@ -950,9 +948,7 @@ void GridFunction::GetCurl(ElementTransformation &tr, Vector &curl) const
|
||||
"invalid FE map type");
|
||||
DenseMatrix grad_hat;
|
||||
GetVectorGradientHat(tr, grad_hat);
|
||||
const DenseMatrix &J = tr.Jacobian();
|
||||
DenseMatrix Jinv(J.Width(), J.Height());
|
||||
CalcInverse(J, Jinv);
|
||||
const DenseMatrix &Jinv = tr.InverseJacobian();
|
||||
DenseMatrix grad(grad_hat.Height(), Jinv.Width()); // vdim x FElem->Dim
|
||||
Mult(grad_hat, Jinv, grad);
|
||||
MFEM_ASSERT(grad.Height() == grad.Width(), "");
|
||||
@@ -999,7 +995,7 @@ void GridFunction::GetGradient(ElementTransformation &tr, Vector &grad) const
|
||||
const FiniteElement *fe = fes->GetFE(elNo);
|
||||
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE, "invalid FE map type");
|
||||
int dim = fe->GetDim(), dof = fe->GetDof();
|
||||
DenseMatrix dshape(dof, dim), Jinv(dim);
|
||||
DenseMatrix dshape(dof, dim);
|
||||
Vector lval, gh(dim);
|
||||
Array<int> dofs;
|
||||
|
||||
@@ -1008,21 +1004,20 @@ void GridFunction::GetGradient(ElementTransformation &tr, Vector &grad) const
|
||||
GetSubVector(dofs, lval);
|
||||
fe->CalcDShape(tr.GetIntPoint(), dshape);
|
||||
dshape.MultTranspose(lval, gh);
|
||||
CalcInverse(tr.Jacobian(), Jinv);
|
||||
Jinv.MultTranspose(gh, grad);
|
||||
tr.InverseJacobian().MultTranspose(gh, grad);
|
||||
}
|
||||
|
||||
void GridFunction::GetGradients(const int elem, const IntegrationRule &ir,
|
||||
void GridFunction::GetGradients(ElementTransformation &tr,
|
||||
const IntegrationRule &ir,
|
||||
DenseMatrix &grad) const
|
||||
{
|
||||
const FiniteElement *fe = fes->GetFE(elem);
|
||||
int elNo = tr.ElementNo;
|
||||
const FiniteElement *fe = fes->GetFE(elNo);
|
||||
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE, "invalid FE map type");
|
||||
ElementTransformation *Tr = fes->GetElementTransformation(elem);
|
||||
DenseMatrix dshape(fe->GetDof(), fe->GetDim());
|
||||
DenseMatrix Jinv(fe->GetDim());
|
||||
Vector lval, gh(fe->GetDim()), gcol;
|
||||
Array<int> dofs;
|
||||
fes->GetElementDofs(elem, dofs);
|
||||
fes->GetElementDofs(elNo, dofs);
|
||||
GetSubVector(dofs, lval);
|
||||
grad.SetSize(fe->GetDim(), ir.GetNPoints());
|
||||
for (int i = 0; i < ir.GetNPoints(); i++)
|
||||
@@ -1030,9 +1025,9 @@ void GridFunction::GetGradients(const int elem, const IntegrationRule &ir,
|
||||
const IntegrationPoint &ip = ir.IntPoint(i);
|
||||
fe->CalcDShape(ip, dshape);
|
||||
dshape.MultTranspose(lval, gh);
|
||||
Tr->SetIntPoint(&ip);
|
||||
tr.SetIntPoint(&ip);
|
||||
grad.GetColumnReference(i, gcol);
|
||||
CalcInverse(Tr->Jacobian(), Jinv);
|
||||
const DenseMatrix &Jinv = tr.InverseJacobian();
|
||||
Jinv.MultTranspose(gh, gcol);
|
||||
}
|
||||
}
|
||||
@@ -1044,9 +1039,7 @@ void GridFunction::GetVectorGradient(
|
||||
"invalid FE map type");
|
||||
DenseMatrix grad_hat;
|
||||
GetVectorGradientHat(tr, grad_hat);
|
||||
const DenseMatrix &J = tr.Jacobian();
|
||||
DenseMatrix Jinv(J.Width(), J.Height());
|
||||
CalcInverse(J, Jinv);
|
||||
const DenseMatrix &Jinv = tr.InverseJacobian();
|
||||
grad.SetSize(grad_hat.Height(), Jinv.Width());
|
||||
Mult(grad_hat, Jinv, grad);
|
||||
}
|
||||
@@ -1083,26 +1076,37 @@ void GridFunction::GetElementAverages(GridFunction &avgs) const
|
||||
|
||||
void GridFunction::ProjectGridFunction(const GridFunction &src)
|
||||
{
|
||||
// Assuming that the projection matrix is the same for all elements
|
||||
Mesh *mesh = fes->GetMesh();
|
||||
bool sameP = false;
|
||||
DenseMatrix P;
|
||||
|
||||
if (!fes->GetNE())
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (!mesh->GetNE()) { return; }
|
||||
|
||||
Geometry::Type geom, cached_geom = Geometry::INVALID;
|
||||
if (mesh->GetNumGeometries(mesh->Dimension()) == 1)
|
||||
{
|
||||
// Assuming that the projection matrix is the same for all elements
|
||||
sameP = true;
|
||||
fes->GetFE(0)->Project(*src.fes->GetFE(0),
|
||||
*mesh->GetElementTransformation(0), P);
|
||||
}
|
||||
const int vdim = fes->GetVDim();
|
||||
MFEM_VERIFY(vdim == src.fes->GetVDim(), "incompatible vector dimensions!");
|
||||
|
||||
fes->GetFE(0)->Project(*src.fes->GetFE(0),
|
||||
*mesh->GetElementTransformation(0), P);
|
||||
int vdim = fes->GetVDim();
|
||||
if (vdim != src.fes->GetVDim())
|
||||
mfem_error("GridFunction::ProjectGridFunction() :"
|
||||
" incompatible vector dimensions!");
|
||||
Array<int> src_vdofs, dest_vdofs;
|
||||
Vector src_lvec, dest_lvec(vdim*P.Height());
|
||||
|
||||
for (int i = 0; i < mesh->GetNE(); i++)
|
||||
{
|
||||
// Assuming the projection matrix P depends only on the element geometry
|
||||
if ( !sameP && (geom = mesh->GetElementBaseGeometry(i)) != cached_geom )
|
||||
{
|
||||
fes->GetFE(i)->Project(*src.fes->GetFE(i),
|
||||
*mesh->GetElementTransformation(i), P);
|
||||
dest_lvec.SetSize(vdim*P.Height());
|
||||
cached_geom = geom;
|
||||
}
|
||||
|
||||
src.fes->GetElementVDofs(i, src_vdofs);
|
||||
src.GetSubVector(src_vdofs, src_lvec);
|
||||
for (int vd = 0; vd < vdim; vd++)
|
||||
@@ -1288,6 +1292,194 @@ void GridFunction::AccumulateAndCountZones(VectorCoefficient &vcoeff,
|
||||
}
|
||||
}
|
||||
|
||||
void GridFunction::AccumulateAndCountBdrValues(
|
||||
Coefficient *coeff[], VectorCoefficient *vcoeff, Array<int> &attr,
|
||||
Array<int> &values_counter)
|
||||
{
|
||||
int i, j, fdof, d, ind, vdim;
|
||||
double val;
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *transf;
|
||||
Array<int> vdofs;
|
||||
Vector vc;
|
||||
|
||||
values_counter.SetSize(Size());
|
||||
values_counter = 0;
|
||||
|
||||
vdim = fes->GetVDim();
|
||||
for (i = 0; i < fes->GetNBE(); i++)
|
||||
{
|
||||
if (attr[fes->GetBdrAttribute(i) - 1] == 0) { continue; }
|
||||
|
||||
fe = fes->GetBE(i);
|
||||
fdof = fe->GetDof();
|
||||
transf = fes->GetBdrElementTransformation(i);
|
||||
const IntegrationRule &ir = fe->GetNodes();
|
||||
fes->GetBdrElementVDofs(i, vdofs);
|
||||
|
||||
for (j = 0; j < fdof; j++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir.IntPoint(j);
|
||||
transf->SetIntPoint(&ip);
|
||||
if (vcoeff) { vcoeff->Eval(vc, *transf, ip); }
|
||||
for (d = 0; d < vdim; d++)
|
||||
{
|
||||
if (!vcoeff && !coeff[d]) { continue; }
|
||||
|
||||
val = vcoeff ? vc(d) : coeff[d]->Eval(*transf, ip);
|
||||
if ( (ind = vdofs[fdof*d+j]) < 0 )
|
||||
{
|
||||
val = -val, ind = -1-ind;
|
||||
}
|
||||
if (++values_counter[ind] == 1)
|
||||
{
|
||||
(*this)(ind) = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*this)(ind) += val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In the case of partially conforming space, i.e. (fes->cP != NULL), we need
|
||||
// to set the values of all dofs on which the dofs set above depend.
|
||||
// Dependency is defined from the matrix A = cP.cR: dof i depends on dof j
|
||||
// iff A_ij != 0. It is sufficient to resolve just the first level of
|
||||
// dependency, since A is a projection matrix: A^n = A due to cR.cP = I.
|
||||
// Cases like these arise in 3D when boundary edges are constrained by
|
||||
// (depend on) internal faces/elements. We use the virtual method
|
||||
// GetBoundaryClosure from NCMesh to resolve the dependencies.
|
||||
|
||||
if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
Vector vals;
|
||||
Mesh *mesh = fes->GetMesh();
|
||||
NCMesh *ncmesh = mesh->ncmesh;
|
||||
Array<int> bdr_edges, bdr_vertices;
|
||||
ncmesh->GetBoundaryClosure(attr, bdr_vertices, bdr_edges);
|
||||
|
||||
for (i = 0; i < bdr_edges.Size(); i++)
|
||||
{
|
||||
int edge = bdr_edges[i];
|
||||
fes->GetEdgeVDofs(edge, vdofs);
|
||||
if (vdofs.Size() == 0) { continue; }
|
||||
|
||||
transf = mesh->GetEdgeTransformation(edge);
|
||||
transf->Attribute = -1; // FIXME: set the boundary attribute
|
||||
fe = fes->GetEdgeElement(edge);
|
||||
if (!vcoeff)
|
||||
{
|
||||
vals.SetSize(fe->GetDof());
|
||||
for (d = 0; d < vdim; d++)
|
||||
{
|
||||
if (!coeff[d]) { continue; }
|
||||
|
||||
fe->Project(*coeff[d], *transf, vals);
|
||||
for (int k = 0; k < vals.Size(); k++)
|
||||
{
|
||||
ind = vdofs[d*vals.Size()+k];
|
||||
if (++values_counter[ind] == 1)
|
||||
{
|
||||
(*this)(ind) = vals(k);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*this)(ind) += vals(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // vcoeff != NULL
|
||||
{
|
||||
vals.SetSize(vdim*fe->GetDof());
|
||||
fe->Project(*vcoeff, *transf, vals);
|
||||
for (int k = 0; k < vals.Size(); k++)
|
||||
{
|
||||
ind = vdofs[k];
|
||||
if (++values_counter[ind] == 1)
|
||||
{
|
||||
(*this)(ind) = vals(k);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*this)(ind) += vals(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void accumulate_dofs(const Array<int> &dofs, const Vector &vals,
|
||||
Vector &gf, Array<int> &values_counter)
|
||||
{
|
||||
for (int i = 0; i < dofs.Size(); i++)
|
||||
{
|
||||
int k = dofs[i];
|
||||
double val = vals(i);
|
||||
if (k < 0) { k = -1 - k; val = -val; }
|
||||
if (++values_counter[k] == 1)
|
||||
{
|
||||
gf(k) = val;
|
||||
}
|
||||
else
|
||||
{
|
||||
gf(k) += val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GridFunction::AccumulateAndCountBdrTangentValues(
|
||||
VectorCoefficient &vcoeff, Array<int> &bdr_attr,
|
||||
Array<int> &values_counter)
|
||||
{
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *T;
|
||||
Array<int> dofs;
|
||||
Vector lvec;
|
||||
|
||||
values_counter.SetSize(Size());
|
||||
values_counter = 0;
|
||||
|
||||
for (int i = 0; i < fes->GetNBE(); i++)
|
||||
{
|
||||
if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fe = fes->GetBE(i);
|
||||
T = fes->GetBdrElementTransformation(i);
|
||||
fes->GetBdrElementDofs(i, dofs);
|
||||
lvec.SetSize(fe->GetDof());
|
||||
fe->Project(vcoeff, *T, lvec);
|
||||
accumulate_dofs(dofs, lvec, *this, values_counter);
|
||||
}
|
||||
|
||||
if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
Mesh *mesh = fes->GetMesh();
|
||||
NCMesh *ncmesh = mesh->ncmesh;
|
||||
Array<int> bdr_edges, bdr_vertices;
|
||||
ncmesh->GetBoundaryClosure(bdr_attr, bdr_vertices, bdr_edges);
|
||||
|
||||
for (int i = 0; i < bdr_edges.Size(); i++)
|
||||
{
|
||||
int edge = bdr_edges[i];
|
||||
fes->GetEdgeDofs(edge, dofs);
|
||||
if (dofs.Size() == 0) { continue; }
|
||||
|
||||
T = mesh->GetEdgeTransformation(edge);
|
||||
T->Attribute = -1; // FIXME: set the boundary attribute
|
||||
fe = fes->GetEdgeElement(edge);
|
||||
lvec.SetSize(fe->GetDof());
|
||||
fe->Project(vcoeff, *T, lvec);
|
||||
accumulate_dofs(dofs, lvec, *this, values_counter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GridFunction::ComputeMeans(AvgType type, Array<int> &zones_per_vdof)
|
||||
{
|
||||
switch (type)
|
||||
@@ -1295,14 +1487,16 @@ void GridFunction::ComputeMeans(AvgType type, Array<int> &zones_per_vdof)
|
||||
case ARITHMETIC:
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
(*this)(i) /= zones_per_vdof[i];
|
||||
const int nz = zones_per_vdof[i];
|
||||
if (nz) { (*this)(i) /= nz; }
|
||||
}
|
||||
break;
|
||||
|
||||
case HARMONIC:
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
(*this)(i) = zones_per_vdof[i]/(*this)(i);
|
||||
const int nz = zones_per_vdof[i];
|
||||
if (nz) { (*this)(i) = nz/(*this)(i); }
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1562,85 +1756,37 @@ void GridFunction::ProjectDiscCoefficient(VectorCoefficient &coeff,
|
||||
ComputeMeans(type, zones_per_vdof);
|
||||
}
|
||||
|
||||
void GridFunction::ProjectBdrCoefficient(
|
||||
Coefficient *coeff[], Array<int> &attr)
|
||||
void GridFunction::ProjectBdrCoefficient(VectorCoefficient &vcoeff,
|
||||
Array<int> &attr)
|
||||
{
|
||||
int i, j, fdof, d, ind, vdim;
|
||||
double val;
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *transf;
|
||||
Array<int> vdofs;
|
||||
|
||||
vdim = fes->GetVDim();
|
||||
for (i = 0; i < fes->GetNBE(); i++)
|
||||
Array<int> values_counter;
|
||||
AccumulateAndCountBdrValues(NULL, &vcoeff, attr, values_counter);
|
||||
ComputeMeans(ARITHMETIC, values_counter);
|
||||
#ifdef MFEM_DEBUG
|
||||
Array<int> ess_vdofs_marker;
|
||||
fes->GetEssentialVDofs(attr, ess_vdofs_marker);
|
||||
for (int i = 0; i < values_counter.Size(); i++)
|
||||
{
|
||||
if (attr[fes->GetBdrAttribute(i) - 1])
|
||||
{
|
||||
fe = fes->GetBE(i);
|
||||
fdof = fe->GetDof();
|
||||
transf = fes->GetBdrElementTransformation(i);
|
||||
const IntegrationRule &ir = fe->GetNodes();
|
||||
fes->GetBdrElementVDofs(i, vdofs);
|
||||
|
||||
for (j = 0; j < fdof; j++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir.IntPoint(j);
|
||||
transf->SetIntPoint(&ip);
|
||||
for (d = 0; d < vdim; d++)
|
||||
{
|
||||
if (!coeff[d]) { continue; }
|
||||
|
||||
val = coeff[d]->Eval(*transf, ip);
|
||||
if ( (ind = vdofs[fdof*d+j]) < 0 )
|
||||
{
|
||||
val = -val, ind = -1-ind;
|
||||
}
|
||||
(*this)(ind) = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
MFEM_ASSERT(bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
|
||||
"internal error");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// In the case of partially conforming space, i.e. (fes->cP != NULL), we need
|
||||
// to set the values of all dofs on which the dofs set above depend.
|
||||
// Dependency is defined from the matrix A = cP.cR: dof i depends on dof j
|
||||
// iff A_ij != 0. It is sufficient to resolve just the first level of
|
||||
// dependency since A is a projection matrix: A^n = A due to cR.cP = I.
|
||||
// Cases like this arise in 3D when boundary edges are constrained by (depend
|
||||
// on) internal faces/elements.
|
||||
// We use the virtual method GetBoundaryClosure from NCMesh to resolve the
|
||||
// dependencies.
|
||||
|
||||
if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
|
||||
void GridFunction::ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr)
|
||||
{
|
||||
Array<int> values_counter;
|
||||
AccumulateAndCountBdrValues(coeff, NULL, attr, values_counter);
|
||||
ComputeMeans(ARITHMETIC, values_counter);
|
||||
#ifdef MFEM_DEBUG
|
||||
Array<int> ess_vdofs_marker;
|
||||
fes->GetEssentialVDofs(attr, ess_vdofs_marker);
|
||||
for (int i = 0; i < values_counter.Size(); i++)
|
||||
{
|
||||
Vector vals;
|
||||
Mesh *mesh = fes->GetMesh();
|
||||
NCMesh *ncmesh = mesh->ncmesh;
|
||||
Array<int> bdr_edges, bdr_vertices;
|
||||
ncmesh->GetBoundaryClosure(attr, bdr_vertices, bdr_edges);
|
||||
|
||||
for (i = 0; i < bdr_edges.Size(); i++)
|
||||
{
|
||||
int edge = bdr_edges[i];
|
||||
fes->GetEdgeVDofs(edge, vdofs);
|
||||
if (vdofs.Size() == 0) { continue; }
|
||||
|
||||
transf = mesh->GetEdgeTransformation(edge);
|
||||
transf->Attribute = -1; // FIXME: set the boundary attribute
|
||||
fe = fes->GetEdgeElement(edge);
|
||||
vals.SetSize(fe->GetDof());
|
||||
for (d = 0; d < vdim; d++)
|
||||
{
|
||||
if (!coeff[d]) { continue; }
|
||||
|
||||
fe->Project(*coeff[d], *transf, vals);
|
||||
for (int k = 0; k < vals.Size(); k++)
|
||||
{
|
||||
(*this)(vdofs[d*vals.Size()+k]) = vals(k);
|
||||
}
|
||||
}
|
||||
}
|
||||
MFEM_ASSERT(bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
|
||||
"internal error");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GridFunction::ProjectBdrCoefficientNormal(
|
||||
@@ -1717,46 +1863,18 @@ void GridFunction::ProjectBdrCoefficientNormal(
|
||||
void GridFunction::ProjectBdrCoefficientTangent(
|
||||
VectorCoefficient &vcoeff, Array<int> &bdr_attr)
|
||||
{
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *T;
|
||||
Array<int> dofs;
|
||||
Vector lvec;
|
||||
|
||||
for (int i = 0; i < fes->GetNBE(); i++)
|
||||
Array<int> values_counter;
|
||||
AccumulateAndCountBdrTangentValues(vcoeff, bdr_attr, values_counter);
|
||||
ComputeMeans(ARITHMETIC, values_counter);
|
||||
#ifdef MFEM_DEBUG
|
||||
Array<int> ess_vdofs_marker;
|
||||
fes->GetEssentialVDofs(bdr_attr, ess_vdofs_marker);
|
||||
for (int i = 0; i < values_counter.Size(); i++)
|
||||
{
|
||||
if (bdr_attr[fes->GetBdrAttribute(i)-1] == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
fe = fes->GetBE(i);
|
||||
T = fes->GetBdrElementTransformation(i);
|
||||
fes->GetBdrElementDofs(i, dofs);
|
||||
lvec.SetSize(fe->GetDof());
|
||||
fe->Project(vcoeff, *T, lvec);
|
||||
SetSubVector(dofs, lvec);
|
||||
}
|
||||
|
||||
if (fes->Nonconforming() && fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
Mesh *mesh = fes->GetMesh();
|
||||
NCMesh *ncmesh = mesh->ncmesh;
|
||||
Array<int> bdr_edges, bdr_vertices;
|
||||
ncmesh->GetBoundaryClosure(bdr_attr, bdr_vertices, bdr_edges);
|
||||
|
||||
for (int i = 0; i < bdr_edges.Size(); i++)
|
||||
{
|
||||
int edge = bdr_edges[i];
|
||||
fes->GetEdgeDofs(edge, dofs);
|
||||
if (dofs.Size() == 0) { continue; }
|
||||
|
||||
T = mesh->GetEdgeTransformation(edge);
|
||||
T->Attribute = -1; // FIXME: set the boundary attribute
|
||||
fe = fes->GetEdgeElement(edge);
|
||||
lvec.SetSize(fe->GetDof());
|
||||
fe->Project(vcoeff, *T, lvec);
|
||||
SetSubVector(dofs, lvec);
|
||||
}
|
||||
MFEM_ASSERT(bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
|
||||
"internal error");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
double GridFunction::ComputeL2Error(
|
||||
@@ -2237,6 +2355,69 @@ double GridFunction::ComputeLpError(const double p, Coefficient &exsol,
|
||||
return error;
|
||||
}
|
||||
|
||||
void GridFunction::ComputeElementLpErrors(const double p, Coefficient &exsol,
|
||||
GridFunction &error,
|
||||
Coefficient *weight,
|
||||
const IntegrationRule *irs[]) const
|
||||
{
|
||||
error = 0.0;
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *T;
|
||||
Vector vals;
|
||||
|
||||
for (int i = 0; i < fes->GetNE(); i++)
|
||||
{
|
||||
fe = fes->GetFE(i);
|
||||
const IntegrationRule *ir;
|
||||
if (irs)
|
||||
{
|
||||
ir = irs[fe->GetGeomType()];
|
||||
}
|
||||
else
|
||||
{
|
||||
int intorder = 2*fe->GetOrder() + 1; // <----------
|
||||
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
|
||||
}
|
||||
GetValues(i, *ir, vals);
|
||||
T = fes->GetElementTransformation(i);
|
||||
for (int j = 0; j < ir->GetNPoints(); j++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir->IntPoint(j);
|
||||
T->SetIntPoint(&ip);
|
||||
double err = fabs(vals(j) - exsol.Eval(*T, ip));
|
||||
if (p < infinity())
|
||||
{
|
||||
err = pow(err, p);
|
||||
if (weight)
|
||||
{
|
||||
err *= weight->Eval(*T, ip);
|
||||
}
|
||||
error[i] += ip.weight * T->Weight() * err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (weight)
|
||||
{
|
||||
err *= weight->Eval(*T, ip);
|
||||
}
|
||||
error[i] = std::max(error[i], err);
|
||||
}
|
||||
}
|
||||
if (p < infinity())
|
||||
{
|
||||
// negative quadrature weights may cause the error to be negative
|
||||
if (error[i] < 0.)
|
||||
{
|
||||
error[i] = -pow(-error[i], 1./p);
|
||||
}
|
||||
else
|
||||
{
|
||||
error[i] = pow(error[i], 1./p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double GridFunction::ComputeLpError(const double p, VectorCoefficient &exsol,
|
||||
Coefficient *weight,
|
||||
VectorCoefficient *v_weight,
|
||||
@@ -2328,6 +2509,96 @@ double GridFunction::ComputeLpError(const double p, VectorCoefficient &exsol,
|
||||
return error;
|
||||
}
|
||||
|
||||
void GridFunction::ComputeElementLpErrors(const double p,
|
||||
VectorCoefficient &exsol,
|
||||
GridFunction &error,
|
||||
Coefficient *weight,
|
||||
VectorCoefficient *v_weight,
|
||||
const IntegrationRule *irs[]) const
|
||||
{
|
||||
error = 0.0;
|
||||
const FiniteElement *fe;
|
||||
ElementTransformation *T;
|
||||
DenseMatrix vals, exact_vals;
|
||||
Vector loc_errs;
|
||||
|
||||
for (int i = 0; i < fes->GetNE(); i++)
|
||||
{
|
||||
fe = fes->GetFE(i);
|
||||
const IntegrationRule *ir;
|
||||
if (irs)
|
||||
{
|
||||
ir = irs[fe->GetGeomType()];
|
||||
}
|
||||
else
|
||||
{
|
||||
int intorder = 2*fe->GetOrder() + 1; // <----------
|
||||
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
|
||||
}
|
||||
T = fes->GetElementTransformation(i);
|
||||
GetVectorValues(*T, *ir, vals);
|
||||
exsol.Eval(exact_vals, *T, *ir);
|
||||
vals -= exact_vals;
|
||||
loc_errs.SetSize(vals.Width());
|
||||
if (!v_weight)
|
||||
{
|
||||
// compute the lengths of the errors at the integration points
|
||||
// thus the vector norm is rotationally invariant
|
||||
vals.Norm2(loc_errs);
|
||||
}
|
||||
else
|
||||
{
|
||||
v_weight->Eval(exact_vals, *T, *ir);
|
||||
// column-wise dot product of the vector error (in vals) and the
|
||||
// vector weight (in exact_vals)
|
||||
for (int j = 0; j < vals.Width(); j++)
|
||||
{
|
||||
double err = 0.0;
|
||||
for (int d = 0; d < vals.Height(); d++)
|
||||
{
|
||||
err += vals(d,j)*exact_vals(d,j);
|
||||
}
|
||||
loc_errs(j) = fabs(err);
|
||||
}
|
||||
}
|
||||
for (int j = 0; j < ir->GetNPoints(); j++)
|
||||
{
|
||||
const IntegrationPoint &ip = ir->IntPoint(j);
|
||||
T->SetIntPoint(&ip);
|
||||
double err = loc_errs(j);
|
||||
if (p < infinity())
|
||||
{
|
||||
err = pow(err, p);
|
||||
if (weight)
|
||||
{
|
||||
err *= weight->Eval(*T, ip);
|
||||
}
|
||||
error[i] += ip.weight * T->Weight() * err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (weight)
|
||||
{
|
||||
err *= weight->Eval(*T, ip);
|
||||
}
|
||||
error[i] = std::max(error[i], err);
|
||||
}
|
||||
}
|
||||
if (p < infinity())
|
||||
{
|
||||
// negative quadrature weights may cause the error to be negative
|
||||
if (error[i] < 0.)
|
||||
{
|
||||
error[i] = -pow(-error[i], 1./p);
|
||||
}
|
||||
else
|
||||
{
|
||||
error[i] = pow(error[i], 1./p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridFunction & GridFunction::operator=(double value)
|
||||
{
|
||||
Vector::operator=(value);
|
||||
@@ -2341,11 +2612,6 @@ GridFunction & GridFunction::operator=(const Vector &v)
|
||||
return *this;
|
||||
}
|
||||
|
||||
GridFunction & GridFunction::operator=(const GridFunction &v)
|
||||
{
|
||||
return this->operator=((const Vector &)v);
|
||||
}
|
||||
|
||||
void GridFunction::Save(std::ostream &out) const
|
||||
{
|
||||
fes->Save(out);
|
||||
@@ -2489,11 +2755,11 @@ void GridFunction::SaveSTL(std::ostream &out, int TimesToRefine)
|
||||
bbox[2][0] = bbox[2][1] = 0.0;
|
||||
for (i = 0; i < mesh->GetNE(); i++)
|
||||
{
|
||||
n = fes->GetFE(i)->GetGeomType();
|
||||
RefG = GlobGeometryRefiner.Refine(n, TimesToRefine);
|
||||
Geometry::Type geom = mesh->GetElementBaseGeometry(i);
|
||||
RefG = GlobGeometryRefiner.Refine(geom, TimesToRefine);
|
||||
GetValues(i, RefG->RefPts, values, pointmat);
|
||||
Array<int> &RG = RefG->RefGeoms;
|
||||
n = Geometries.NumBdr(n);
|
||||
n = Geometries.NumBdr(geom);
|
||||
for (k = 0; k < RG.Size()/n; k++)
|
||||
{
|
||||
for (j = 0; j < n; j++)
|
||||
@@ -2645,11 +2911,7 @@ double ZZErrorEstimator(BilinearFormIntegrator &blfi,
|
||||
int nsd = 1;
|
||||
if (with_subdomains)
|
||||
{
|
||||
for (int i = 0; i < nfe; i++)
|
||||
{
|
||||
int attr = ufes->GetAttribute(i);
|
||||
if (attr > nsd) { nsd = attr; }
|
||||
}
|
||||
nsd = ufes->GetMesh()->attributes.Max();
|
||||
}
|
||||
|
||||
double total_error = 0.0;
|
||||
|
||||
+118
-21
@@ -27,10 +27,13 @@ namespace mfem
|
||||
class GridFunction : public Vector
|
||||
{
|
||||
protected:
|
||||
/// FE space on which grid function lives.
|
||||
/// FE space on which the grid function lives. Owned if #fec is not NULL.
|
||||
FiniteElementSpace *fes;
|
||||
|
||||
/// Used when the grid function is read from a file
|
||||
/** @brief Used when the grid function is read from a file. It can also be
|
||||
set explicitly, see MakeOwner().
|
||||
|
||||
If not NULL, this pointer is owned by the GridFunction. */
|
||||
FiniteElementCollection *fec;
|
||||
|
||||
long sequence; // see FiniteElementSpace::sequence, Mesh::sequence
|
||||
@@ -67,7 +70,7 @@ public:
|
||||
|
||||
GridFunction() { fes = NULL; fec = NULL; sequence = 0; }
|
||||
|
||||
/// Copy constructor.
|
||||
/// Copy constructor. The internal true-dof vector #t_vec is not copied.
|
||||
GridFunction(const GridFunction &orig)
|
||||
: Vector(orig), fes(orig.fes), fec(NULL), sequence(orig.sequence) { }
|
||||
|
||||
@@ -92,6 +95,15 @@ public:
|
||||
|
||||
GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces);
|
||||
|
||||
/// Copy assignment. Only the data of the base class Vector is copied.
|
||||
/** It is assumed that this object and @a rhs use FiniteElementSpace%s that
|
||||
have the same size.
|
||||
|
||||
@note Defining this method overwrites the implicitly defined copy
|
||||
assignemnt operator. */
|
||||
GridFunction &operator=(const GridFunction &rhs)
|
||||
{ return operator=((const Vector &)rhs); }
|
||||
|
||||
/// Make the GridFunction the owner of 'fec' and 'fes'
|
||||
void MakeOwner(FiniteElementCollection *_fec) { fec = _fec; }
|
||||
|
||||
@@ -173,9 +185,13 @@ public:
|
||||
|
||||
void GetGradient(ElementTransformation &tr, Vector &grad) const;
|
||||
|
||||
void GetGradients(const int elem, const IntegrationRule &ir,
|
||||
void GetGradients(ElementTransformation &tr, const IntegrationRule &ir,
|
||||
DenseMatrix &grad) const;
|
||||
|
||||
void GetGradients(const int elem, const IntegrationRule &ir,
|
||||
DenseMatrix &grad) const
|
||||
{ GetGradients(*fes->GetElementTransformation(elem), ir, grad); }
|
||||
|
||||
void GetVectorGradient(ElementTransformation &tr, DenseMatrix &grad) const;
|
||||
|
||||
/** Compute \f$ (\int_{\Omega} (*this) \psi_i)/(\int_{\Omega} \psi_i) \f$,
|
||||
@@ -235,18 +251,40 @@ protected:
|
||||
void AccumulateAndCountZones(VectorCoefficient &vcoeff, AvgType type,
|
||||
Array<int> &zones_per_vdof);
|
||||
|
||||
void AccumulateAndCountBdrValues(Coefficient *coeff[],
|
||||
VectorCoefficient *vcoeff, Array<int> &attr,
|
||||
Array<int> &values_counter);
|
||||
|
||||
void AccumulateAndCountBdrTangentValues(VectorCoefficient &vcoeff,
|
||||
Array<int> &bdr_attr,
|
||||
Array<int> &values_counter);
|
||||
|
||||
// Complete the computation of averages; called e.g. after
|
||||
// AccumulateAndCountZones().
|
||||
void ComputeMeans(AvgType type, Array<int> &zones_per_vdof);
|
||||
|
||||
public:
|
||||
/** @brief Project a Coefficient on the GridFunction, modifying only DOFs on
|
||||
the boundary associated with the boundary attributes marked in the
|
||||
@a attr array. */
|
||||
void ProjectBdrCoefficient(Coefficient &coeff, Array<int> &attr)
|
||||
{
|
||||
Coefficient *coeff_p = &coeff;
|
||||
ProjectBdrCoefficient(&coeff_p, attr);
|
||||
}
|
||||
|
||||
void ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr);
|
||||
/** @brief Project a VectorCoefficient on the GridFunction, modifying only
|
||||
DOFs on the boundary associated with the boundary attributes marked in
|
||||
the @a attr array. */
|
||||
virtual void ProjectBdrCoefficient(VectorCoefficient &vcoeff,
|
||||
Array<int> &attr);
|
||||
|
||||
/** @brief Project a set of Coefficient%s on the components of the
|
||||
GridFunction, modifying only DOFs on the boundary associated with the
|
||||
boundary attributed marked in the @a attr array. */
|
||||
/** If a Coefficient pointer in the array @a coeff is NULL, that component
|
||||
will not be touched. */
|
||||
virtual void ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr);
|
||||
|
||||
/** Project the normal component of the given VectorCoefficient on
|
||||
the boundary. Only boundary attributes that are marked in
|
||||
@@ -254,11 +292,11 @@ public:
|
||||
void ProjectBdrCoefficientNormal(VectorCoefficient &vcoeff,
|
||||
Array<int> &bdr_attr);
|
||||
|
||||
/** Project the tangential components of the given VectorCoefficient on
|
||||
the boundary. Only boundary attributes that are marked in
|
||||
'bdr_attr' are projected. Assumes ND-type VectorFE GridFunction. */
|
||||
void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
|
||||
Array<int> &bdr_attr);
|
||||
/** @brief Project the tangential components of the given VectorCoefficient
|
||||
on the boundary. Only boundary attributes that are marked in @a bdr_attr
|
||||
are projected. Assumes ND-type VectorFE GridFunction. */
|
||||
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
|
||||
Array<int> &bdr_attr);
|
||||
|
||||
virtual double ComputeL2Error(Coefficient &exsol,
|
||||
const IntegrationRule *irs[] = NULL) const
|
||||
@@ -306,6 +344,33 @@ public:
|
||||
Coefficient *weight = NULL,
|
||||
const IntegrationRule *irs[] = NULL) const;
|
||||
|
||||
/** Compute the Lp error in each element of the mesh and store the results in
|
||||
the GridFunction @a error. The result should be an L2 GridFunction of
|
||||
order zero using map type VALUE. */
|
||||
virtual void ComputeElementLpErrors(const double p, Coefficient &exsol,
|
||||
GridFunction &error,
|
||||
Coefficient *weight = NULL,
|
||||
const IntegrationRule *irs[] = NULL
|
||||
) const;
|
||||
|
||||
virtual void ComputeElementL1Errors(Coefficient &exsol,
|
||||
GridFunction &error,
|
||||
const IntegrationRule *irs[] = NULL
|
||||
) const
|
||||
{ ComputeElementLpErrors(1.0, exsol, error, NULL, irs); }
|
||||
|
||||
virtual void ComputeElementL2Errors(Coefficient &exsol,
|
||||
GridFunction &error,
|
||||
const IntegrationRule *irs[] = NULL
|
||||
) const
|
||||
{ ComputeElementLpErrors(2.0, exsol, error, NULL, irs); }
|
||||
|
||||
virtual void ComputeElementMaxErrors(Coefficient &exsol,
|
||||
GridFunction &error,
|
||||
const IntegrationRule *irs[] = NULL
|
||||
) const
|
||||
{ ComputeElementLpErrors(infinity(), exsol, error, NULL, irs); }
|
||||
|
||||
/** When given a vector weight, compute the pointwise (scalar) error as the
|
||||
dot product of the vector error with the vector weight. Otherwise, the
|
||||
scalar error is the l_2 norm of the vector error. */
|
||||
@@ -314,6 +379,34 @@ public:
|
||||
VectorCoefficient *v_weight = NULL,
|
||||
const IntegrationRule *irs[] = NULL) const;
|
||||
|
||||
/** Compute the Lp error in each element of the mesh and store the results in
|
||||
the GridFunction @ error. The result should be an L2 GridFunction of
|
||||
order zero using map type VALUE. */
|
||||
virtual void ComputeElementLpErrors(const double p, VectorCoefficient &exsol,
|
||||
GridFunction &error,
|
||||
Coefficient *weight = NULL,
|
||||
VectorCoefficient *v_weight = NULL,
|
||||
const IntegrationRule *irs[] = NULL
|
||||
) const;
|
||||
|
||||
virtual void ComputeElementL1Errors(VectorCoefficient &exsol,
|
||||
GridFunction &error,
|
||||
const IntegrationRule *irs[] = NULL
|
||||
) const
|
||||
{ ComputeElementLpErrors(1.0, exsol, error, NULL, NULL, irs); }
|
||||
|
||||
virtual void ComputeElementL2Errors(VectorCoefficient &exsol,
|
||||
GridFunction &error,
|
||||
const IntegrationRule *irs[] = NULL
|
||||
) const
|
||||
{ ComputeElementLpErrors(2.0, exsol, error, NULL, NULL, irs); }
|
||||
|
||||
virtual void ComputeElementMaxErrors(VectorCoefficient &exsol,
|
||||
GridFunction &error,
|
||||
const IntegrationRule *irs[] = NULL
|
||||
) const
|
||||
{ ComputeElementLpErrors(infinity(), exsol, error, NULL, NULL, irs); }
|
||||
|
||||
virtual void ComputeFlux(BilinearFormIntegrator &blfi,
|
||||
GridFunction &flux,
|
||||
int wcoef = 1, int subdomain = -1);
|
||||
@@ -322,15 +415,10 @@ public:
|
||||
GridFunction &operator=(double value);
|
||||
|
||||
/// Copy the data from @a v.
|
||||
/** The size of @a v must be equal to the size of the FiniteElementSpace
|
||||
@a fes. */
|
||||
/** The size of @a v must be equal to the size of the associated
|
||||
FiniteElementSpace #fes. */
|
||||
GridFunction &operator=(const Vector &v);
|
||||
|
||||
/// Copy the data from @a v.
|
||||
/** The GridFunctions @a v and @a *this must have FiniteElementSpaces with
|
||||
the same size. */
|
||||
GridFunction &operator=(const GridFunction &v);
|
||||
|
||||
/// Transform by the Space UpdateMatrix (e.g., on Mesh change).
|
||||
virtual void Update();
|
||||
|
||||
@@ -411,6 +499,12 @@ public:
|
||||
QuadratureFunction()
|
||||
: qspace(NULL), vdim(0), own_qspace(false) { }
|
||||
|
||||
/** @brief Copy constructor. The QuadratureSpace ownership flag, #own_qspace,
|
||||
in the new object is set to false. */
|
||||
QuadratureFunction(const QuadratureFunction &orig)
|
||||
: Vector(orig),
|
||||
qspace(orig.qspace), vdim(orig.vdim), own_qspace(false) { }
|
||||
|
||||
/// Create a QuadratureFunction based on the given QuadratureSpace.
|
||||
/** The QuadratureFunction does not assume ownership of the QuadratureSpace.
|
||||
@note The Vector data is not initialized. */
|
||||
@@ -476,13 +570,16 @@ public:
|
||||
QuadratureFunction &operator=(double value);
|
||||
|
||||
/// Copy the data from @a v.
|
||||
/** The size of @a v must be equal to the size of the QuadratureSpace
|
||||
@a qspace. */
|
||||
/** The size of @a v must be equal to the size of the associated
|
||||
QuadratureSpace #qspace. */
|
||||
QuadratureFunction &operator=(const Vector &v);
|
||||
|
||||
/// Copy the data from @a v.
|
||||
/// Copy assignment. Only the data of the base class Vector is copied.
|
||||
/** The QuadratureFunctions @a v and @a *this must have QuadratureSpaces with
|
||||
the same size. */
|
||||
the same size.
|
||||
|
||||
@note Defining this method overwrites the implicitly defined copy
|
||||
assignemnt operator. */
|
||||
QuadratureFunction &operator=(const QuadratureFunction &v);
|
||||
|
||||
/// Get the IntegrationRule associated with mesh element @a idx.
|
||||
|
||||
@@ -854,6 +854,9 @@ IntegrationRules::IntegrationRules(int Ref, int _type):
|
||||
TetrahedronIntRules.SetSize(32);
|
||||
TetrahedronIntRules = NULL;
|
||||
|
||||
PrismIntRules.SetSize(32);
|
||||
PrismIntRules = NULL;
|
||||
|
||||
CubeIntRules.SetSize(32);
|
||||
CubeIntRules = NULL;
|
||||
}
|
||||
@@ -870,6 +873,7 @@ const IntegrationRule &IntegrationRules::Get(int GeomType, int Order)
|
||||
case Geometry::SQUARE: ir_array = &SquareIntRules; break;
|
||||
case Geometry::TETRAHEDRON: ir_array = &TetrahedronIntRules; break;
|
||||
case Geometry::CUBE: ir_array = &CubeIntRules; break;
|
||||
case Geometry::PRISM: ir_array = &PrismIntRules; break;
|
||||
default:
|
||||
mfem_error("IntegrationRules::Get(...) : Unknown geometry type!");
|
||||
ir_array = NULL;
|
||||
@@ -915,6 +919,7 @@ void IntegrationRules::Set(int GeomType, int Order, IntegrationRule &IntRule)
|
||||
case Geometry::SQUARE: ir_array = &SquareIntRules; break;
|
||||
case Geometry::TETRAHEDRON: ir_array = &TetrahedronIntRules; break;
|
||||
case Geometry::CUBE: ir_array = &CubeIntRules; break;
|
||||
case Geometry::PRISM: ir_array = &PrismIntRules; break;
|
||||
default:
|
||||
mfem_error("IntegrationRules::Set(...) : Unknown geometry type!");
|
||||
ir_array = NULL;
|
||||
@@ -957,6 +962,7 @@ IntegrationRules::~IntegrationRules()
|
||||
DeleteIntRuleArray(SquareIntRules);
|
||||
DeleteIntRuleArray(TetrahedronIntRules);
|
||||
DeleteIntRuleArray(CubeIntRules);
|
||||
DeleteIntRuleArray(PrismIntRules);
|
||||
}
|
||||
|
||||
|
||||
@@ -977,6 +983,8 @@ IntegrationRule *IntegrationRules::GenerateIntegrationRule(int GeomType,
|
||||
return TetrahedronIntegrationRule(Order);
|
||||
case Geometry::CUBE:
|
||||
return CubeIntegrationRule(Order);
|
||||
case Geometry::PRISM:
|
||||
return PrismIntegrationRule(Order);
|
||||
default:
|
||||
mfem_error("IntegrationRules::Set(...) : Unknown geometry type!");
|
||||
return NULL;
|
||||
@@ -1584,6 +1592,33 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
}
|
||||
}
|
||||
|
||||
// Integration rules for reference prism
|
||||
IntegrationRule *IntegrationRules::PrismIntegrationRule(int Order)
|
||||
{
|
||||
IntegrationRule * irt = GenerateIntegrationRule(Geometry::TRIANGLE, Order);
|
||||
IntegrationRule * irs = GenerateIntegrationRule(Geometry::SEGMENT, Order);
|
||||
int nt = irt->GetNPoints();
|
||||
int ns = irs->GetNPoints();
|
||||
AllocIntRule(PrismIntRules, Order);
|
||||
PrismIntRules[Order] = new IntegrationRule(nt * ns);
|
||||
|
||||
for (int ks=0; ks<ns; ks++)
|
||||
{
|
||||
const IntegrationPoint & ips = irs->IntPoint(ks);
|
||||
for (int kt=0; kt<nt; kt++)
|
||||
{
|
||||
int kp = ks * nt + kt;
|
||||
const IntegrationPoint & ipt = irt->IntPoint(kt);
|
||||
IntegrationPoint & ipp = PrismIntRules[Order]->IntPoint(kp);
|
||||
ipp.x = ipt.x;
|
||||
ipp.y = ipt.y;
|
||||
ipp.z = ips.x;
|
||||
ipp.weight = ipt.weight * ips.weight;
|
||||
}
|
||||
}
|
||||
return PrismIntRules[Order];
|
||||
}
|
||||
|
||||
// Integration rules for reference cube
|
||||
IntegrationRule *IntegrationRules::CubeIntegrationRule(int Order)
|
||||
{
|
||||
|
||||
@@ -306,6 +306,7 @@ private:
|
||||
Array<IntegrationRule *> TriangleIntRules;
|
||||
Array<IntegrationRule *> SquareIntRules;
|
||||
Array<IntegrationRule *> TetrahedronIntRules;
|
||||
Array<IntegrationRule *> PrismIntRules;
|
||||
Array<IntegrationRule *> CubeIntRules;
|
||||
|
||||
void AllocIntRule(Array<IntegrationRule *> &ir_array, int Order)
|
||||
@@ -330,6 +331,7 @@ private:
|
||||
IntegrationRule *TriangleIntegrationRule(int Order);
|
||||
IntegrationRule *SquareIntegrationRule(int Order);
|
||||
IntegrationRule *TetrahedronIntegrationRule(int Order);
|
||||
IntegrationRule *PrismIntegrationRule(int Order);
|
||||
IntegrationRule *CubeIntegrationRule(int Order);
|
||||
|
||||
void DeleteIntRuleArray(Array<IntegrationRule *> &ir_array);
|
||||
|
||||
+77
-8
@@ -16,6 +16,23 @@
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
LinearForm::LinearForm(FiniteElementSpace *f, LinearForm *lf)
|
||||
: Vector(f->GetVSize())
|
||||
{
|
||||
fes = f;
|
||||
extern_lfs = 1;
|
||||
|
||||
// Copy the pointers to the integrators
|
||||
dlfi = lf->dlfi;
|
||||
|
||||
dlfi_delta = lf->dlfi_delta;
|
||||
|
||||
blfi = lf->blfi;
|
||||
|
||||
flfi = lf->flfi;
|
||||
flfi_marker = lf->flfi_marker;
|
||||
}
|
||||
|
||||
void LinearForm::AddDomainIntegrator(LinearFormIntegrator *lfi)
|
||||
{
|
||||
DeltaLFIntegrator *maybe_delta =
|
||||
@@ -33,6 +50,14 @@ void LinearForm::AddDomainIntegrator(LinearFormIntegrator *lfi)
|
||||
void LinearForm::AddBoundaryIntegrator (LinearFormIntegrator * lfi)
|
||||
{
|
||||
blfi.Append (lfi);
|
||||
blfi_marker.Append(NULL); // NULL -> all attributes are active
|
||||
}
|
||||
|
||||
void LinearForm::AddBoundaryIntegrator (LinearFormIntegrator * lfi,
|
||||
Array<int> &bdr_attr_marker)
|
||||
{
|
||||
blfi.Append (lfi);
|
||||
blfi_marker.Append(&bdr_attr_marker);
|
||||
}
|
||||
|
||||
void LinearForm::AddBdrFaceIntegrator (LinearFormIntegrator * lfi)
|
||||
@@ -59,6 +84,7 @@ void LinearForm::Assemble()
|
||||
Vector::operator=(0.0);
|
||||
|
||||
if (dlfi.Size())
|
||||
{
|
||||
for (i = 0; i < fes -> GetNE(); i++)
|
||||
{
|
||||
fes -> GetElementVDofs (i, vdofs);
|
||||
@@ -69,12 +95,38 @@ void LinearForm::Assemble()
|
||||
AddElementVector (vdofs, elemvect);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
AssembleDelta();
|
||||
|
||||
if (blfi.Size())
|
||||
{
|
||||
Mesh *mesh = fes->GetMesh();
|
||||
|
||||
// Which boundary attributes need to be processed?
|
||||
Array<int> bdr_attr_marker(mesh->bdr_attributes.Size() ?
|
||||
mesh->bdr_attributes.Max() : 0);
|
||||
bdr_attr_marker = 0;
|
||||
for (int k = 0; k < blfi.Size(); k++)
|
||||
{
|
||||
if (blfi_marker[k] == NULL)
|
||||
{
|
||||
bdr_attr_marker = 1;
|
||||
break;
|
||||
}
|
||||
Array<int> &bdr_marker = *blfi_marker[k];
|
||||
MFEM_ASSERT(bdr_marker.Size() == bdr_attr_marker.Size(),
|
||||
"invalid boundary marker for boundary integrator #"
|
||||
<< k << ", counting from zero");
|
||||
for (int i = 0; i < bdr_attr_marker.Size(); i++)
|
||||
{
|
||||
bdr_attr_marker[i] |= bdr_marker[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < fes -> GetNBE(); i++)
|
||||
{
|
||||
const int bdr_attr = mesh->GetBdrAttribute(i);
|
||||
if (bdr_attr_marker[bdr_attr-1] == 0) { continue; }
|
||||
fes -> GetBdrElementVDofs (i, vdofs);
|
||||
eltrans = fes -> GetBdrElementTransformation (i);
|
||||
for (int k=0; k < blfi.Size(); k++)
|
||||
@@ -83,7 +135,7 @@ void LinearForm::Assemble()
|
||||
AddElementVector (vdofs, elemvect);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (flfi.Size())
|
||||
{
|
||||
FaceElementTransformations *tr;
|
||||
@@ -180,13 +232,30 @@ void LinearForm::AssembleDelta()
|
||||
}
|
||||
}
|
||||
|
||||
LinearForm::~LinearForm()
|
||||
LinearForm & LinearForm::operator=(double value)
|
||||
{
|
||||
int k;
|
||||
for (k=0; k < dlfi_delta.Size(); k++) { delete dlfi_delta[k]; }
|
||||
for (k=0; k < dlfi.Size(); k++) { delete dlfi[k]; }
|
||||
for (k=0; k < blfi.Size(); k++) { delete blfi[k]; }
|
||||
for (k=0; k < flfi.Size(); k++) { delete flfi[k]; }
|
||||
Vector::operator=(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LinearForm & LinearForm::operator=(const Vector &v)
|
||||
{
|
||||
MFEM_ASSERT(fes && v.Size() == fes->GetVSize(), "");
|
||||
Vector::operator=(v);
|
||||
return *this;
|
||||
}
|
||||
|
||||
LinearForm::~LinearForm()
|
||||
{
|
||||
if (!extern_lfs)
|
||||
{
|
||||
int k;
|
||||
for (k=0; k < dlfi_delta.Size(); k++) { delete dlfi_delta[k]; }
|
||||
for (k=0; k < dlfi.Size(); k++) { delete dlfi[k]; }
|
||||
for (k=0; k < blfi.Size(); k++) { delete blfi[k]; }
|
||||
for (k=0; k < flfi.Size(); k++) { delete flfi[k]; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+98
-17
@@ -22,9 +22,13 @@ namespace mfem
|
||||
/// Class for linear form - Vector with associated FE space and LFIntegrators.
|
||||
class LinearForm : public Vector
|
||||
{
|
||||
private:
|
||||
/// FE space on which LF lives.
|
||||
FiniteElementSpace * fes;
|
||||
protected:
|
||||
/// FE space on which the LinearForm lives. Not owned.
|
||||
FiniteElementSpace *fes;
|
||||
|
||||
/** @brief Indicates the LinerFormIntegrator%s stored in #dlfi, #dlfi_delta,
|
||||
#blfi, and #flfi are owned by another LinearForm. */
|
||||
int extern_lfs;
|
||||
|
||||
/// Set of Domain Integrators to be applied.
|
||||
Array<LinearFormIntegrator*> dlfi;
|
||||
@@ -34,10 +38,11 @@ private:
|
||||
|
||||
/// Set of Boundary Integrators to be applied.
|
||||
Array<LinearFormIntegrator*> blfi;
|
||||
Array<Array<int>*> blfi_marker; ///< Entries are not owned.
|
||||
|
||||
/// Set of Boundary Face Integrators to be applied.
|
||||
Array<LinearFormIntegrator*> flfi;
|
||||
Array<Array<int>*> flfi_marker;
|
||||
Array<Array<int>*> flfi_marker; ///< Entries are not owned.
|
||||
|
||||
/// The element ids where the centers of the delta functions lie
|
||||
Array<int> dlfi_delta_elem_id;
|
||||
@@ -51,47 +56,115 @@ private:
|
||||
/// Force (re)computation of delta locations.
|
||||
void ResetDeltaLocations() { dlfi_delta_elem_id.SetSize(0); }
|
||||
|
||||
public:
|
||||
/// Creates linear form associated with FE space *f.
|
||||
LinearForm (FiniteElementSpace * f) : Vector (f -> GetVSize())
|
||||
{ fes = f; }
|
||||
private:
|
||||
/// Copy construction is not supported; body is undefined.
|
||||
LinearForm(const LinearForm &);
|
||||
|
||||
LinearForm() { fes = NULL; }
|
||||
public:
|
||||
/// Creates linear form associated with FE space @a *f.
|
||||
/** The pointer @a f is not owned by the newly constructed object. */
|
||||
LinearForm(FiniteElementSpace *f) : Vector(f->GetVSize())
|
||||
{ fes = f; extern_lfs = 0; }
|
||||
|
||||
/** @brief Create a LinearForm on the FiniteElementSpace @a f, using the
|
||||
same integrators as the LinearForm @a lf.
|
||||
|
||||
The pointer @a f is not owned by the newly constructed object.
|
||||
|
||||
The integrators in @a lf are copied as pointers and they are not owned by
|
||||
the newly constructed LinearForm. */
|
||||
LinearForm(FiniteElementSpace *f, LinearForm *lf);
|
||||
|
||||
/// Create an empty LinearForm without an associated FiniteElementSpace.
|
||||
/** The associated FiniteElementSpace can be set later using one of the
|
||||
methods: Update(FiniteElementSpace *) or
|
||||
Update(FiniteElementSpace *, Vector &, int). */
|
||||
LinearForm() { fes = NULL; extern_lfs = 0; }
|
||||
|
||||
/// Copy assignment. Only the data of the base class Vector is copied.
|
||||
/** It is assumed that this object and @a rhs use FiniteElementSpace%s that
|
||||
have the same size.
|
||||
|
||||
@note Defining this method overwrites the implicitly defined copy
|
||||
assignemnt operator. */
|
||||
LinearForm &operator=(const LinearForm &rhs)
|
||||
{ return operator=((const Vector &)rhs); }
|
||||
|
||||
/// (DEPRECATED) Return the FE space associated with the LinearForm.
|
||||
/** @deprecated Use FESpace() instead. */
|
||||
FiniteElementSpace * GetFES() { return fes; }
|
||||
FiniteElementSpace *GetFES() { return fes; }
|
||||
|
||||
/// Read+write access to the associated FiniteElementSpace.
|
||||
FiniteElementSpace *FESpace() { return fes; }
|
||||
/// Read-only access to the associated FiniteElementSpace.
|
||||
const FiniteElementSpace *FESpace() const { return fes; }
|
||||
|
||||
/// Adds new Domain Integrator.
|
||||
void AddDomainIntegrator (LinearFormIntegrator * lfi);
|
||||
/// Adds new Domain Integrator. Assumes ownership of @a lfi.
|
||||
void AddDomainIntegrator(LinearFormIntegrator *lfi);
|
||||
|
||||
/// Adds new Boundary Integrator.
|
||||
void AddBoundaryIntegrator (LinearFormIntegrator * lfi);
|
||||
/// Adds new Boundary Integrator. Assumes ownership of @a lfi.
|
||||
void AddBoundaryIntegrator(LinearFormIntegrator *lfi);
|
||||
|
||||
/// Adds new Boundary Face Integrator.
|
||||
void AddBdrFaceIntegrator (LinearFormIntegrator * lfi);
|
||||
/** @brief Add new Boundary Integrator, restricted to the given boundary
|
||||
attributes.
|
||||
|
||||
Assumes ownership of @a lfi. The array @a bdr_attr_marker is stored
|
||||
internally as a pointer to the given Array<int> object. */
|
||||
void AddBoundaryIntegrator(LinearFormIntegrator *lfi,
|
||||
Array<int> &bdr_attr_marker);
|
||||
|
||||
/// Adds new Boundary Face Integrator. Assumes ownership of @a lfi.
|
||||
void AddBdrFaceIntegrator(LinearFormIntegrator *lfi);
|
||||
|
||||
/** @brief Add new Boundary Face Integrator, restricted to the given boundary
|
||||
attributes. */
|
||||
attributes.
|
||||
|
||||
Assumes ownership of @a lfi. The array @a bdr_attr_marker is stored
|
||||
internally as a pointer to the given Array<int> object. */
|
||||
void AddBdrFaceIntegrator(LinearFormIntegrator *lfi,
|
||||
Array<int> &bdr_attr_marker);
|
||||
|
||||
/** @brief Access all integrators added with AddDomainIntegrator() which are
|
||||
not DeltaLFIntegrator%s or they are DeltaLFIntegrator%s with non-delta
|
||||
coefficients. */
|
||||
Array<LinearFormIntegrator*> *GetDLFI() { return &dlfi; }
|
||||
|
||||
/** @brief Access all integrators added with AddDomainIntegrator() which are
|
||||
DeltaLFIntegrator%s with delta coefficients. */
|
||||
Array<DeltaLFIntegrator*> *GetDLFI_Delta() { return &dlfi_delta; }
|
||||
|
||||
/// Access all integrators added with AddBoundaryIntegrator().
|
||||
Array<LinearFormIntegrator*> *GetBLFI() { return &blfi; }
|
||||
|
||||
/// Access all integrators added with AddBdrFaceIntegrator().
|
||||
Array<LinearFormIntegrator*> *GetFLFI() { return &flfi; }
|
||||
|
||||
/** @brief Access all boundary markers added with AddBdrFaceIntegrator().
|
||||
If no marker was specified when the integrator was added, the
|
||||
corresponding pointer (to Array<int>) will be NULL. */
|
||||
Array<Array<int>*> *GetFLFI_Marker() { return &flfi_marker; }
|
||||
|
||||
/// Assembles the linear form i.e. sums over all domain/bdr integrators.
|
||||
void Assemble();
|
||||
|
||||
/// Assembles delta functions of the linear form
|
||||
void AssembleDelta();
|
||||
|
||||
/// Update the object according to the associated FE space #fes.
|
||||
/** This method should be called when the asscociated FE space #fes has been
|
||||
updated, e.g. after its associated Mesh object has been refined.
|
||||
|
||||
@note This method does not perform assembly. */
|
||||
void Update() { SetSize(fes->GetVSize()); ResetDeltaLocations(); }
|
||||
|
||||
/// Associate a new FE space, @a *f, with this object and Update() it. */
|
||||
void Update(FiniteElementSpace *f)
|
||||
{ fes = f; SetSize(f->GetVSize()); ResetDeltaLocations(); }
|
||||
|
||||
/** @brief Associate a new FE space, @a *f, with this object and use the data
|
||||
of @a v, offset by @a v_offset, to initialize this object's Vector::data.
|
||||
|
||||
@note This method does not perform assembly. */
|
||||
void Update(FiniteElementSpace *f, Vector &v, int v_offset);
|
||||
|
||||
/// Return the action of the LinearForm as a linear mapping.
|
||||
@@ -101,6 +174,14 @@ public:
|
||||
and GridFunction. */
|
||||
double operator()(const GridFunction &gf) const { return (*this)*gf; }
|
||||
|
||||
/// Redefine '=' for LinearForm = constant.
|
||||
LinearForm &operator=(double value);
|
||||
|
||||
/// Copy the data from @a v.
|
||||
/** The size of @a v must be equal to the size of the associated
|
||||
FiniteElementSpace #fes. */
|
||||
LinearForm &operator=(const Vector &v);
|
||||
|
||||
/// Destroys linear form.
|
||||
~LinearForm();
|
||||
};
|
||||
|
||||
+67
-3
@@ -28,8 +28,10 @@ namespace mfem
|
||||
class ParBilinearForm : public BilinearForm
|
||||
{
|
||||
protected:
|
||||
ParFiniteElementSpace *pfes;
|
||||
mutable ParGridFunction X, Y; // used in TrueAddMult
|
||||
ParFiniteElementSpace *pfes; ///< Points to the same object as #fes
|
||||
|
||||
/// Auxiliary objects used in TrueAddMult().
|
||||
mutable ParGridFunction X, Y;
|
||||
|
||||
OperatorHandle p_mat, p_mat_e;
|
||||
|
||||
@@ -40,12 +42,28 @@ protected:
|
||||
|
||||
void AssembleSharedFaces(int skip_zeros = 1);
|
||||
|
||||
private:
|
||||
/// Copy construction is not supported; body is undefined.
|
||||
ParBilinearForm(const ParBilinearForm &);
|
||||
|
||||
/// Copy assignment is not supported; body is undefined.
|
||||
ParBilinearForm &operator=(const ParBilinearForm &);
|
||||
|
||||
public:
|
||||
/// Creates parallel bilinear form associated with the FE space @a *pf.
|
||||
/** The pointer @a pf is not owned by the newly constructed object. */
|
||||
ParBilinearForm(ParFiniteElementSpace *pf)
|
||||
: BilinearForm(pf), pfes(pf),
|
||||
p_mat(Operator::Hypre_ParCSR), p_mat_e(Operator::Hypre_ParCSR)
|
||||
{ keep_nbr_block = false; }
|
||||
|
||||
/** @brief Create a ParBilinearForm on the ParFiniteElementSpace @a *pf,
|
||||
using the same integrators as the ParBilinearForm @a *bf.
|
||||
|
||||
The pointer @a pf is not owned by the newly constructed object.
|
||||
|
||||
The integrators in @a bf are copied as pointers and they are not owned by
|
||||
the newly constructed ParBilinearForm. */
|
||||
ParBilinearForm(ParFiniteElementSpace *pf, ParBilinearForm *bf)
|
||||
: BilinearForm(pf, bf), pfes(pf),
|
||||
p_mat(Operator::Hypre_ParCSR), p_mat_e(Operator::Hypre_ParCSR)
|
||||
@@ -219,11 +237,25 @@ public:
|
||||
class ParMixedBilinearForm : public MixedBilinearForm
|
||||
{
|
||||
protected:
|
||||
/// Points to the same object as #trial_fes
|
||||
ParFiniteElementSpace *trial_pfes;
|
||||
/// Points to the same object as #test_fes
|
||||
ParFiniteElementSpace *test_pfes;
|
||||
mutable ParGridFunction X, Y; // used in TrueAddMult
|
||||
/// Auxiliary objects used in TrueAddMult().
|
||||
mutable ParGridFunction X, Y;
|
||||
|
||||
private:
|
||||
/// Copy construction is not supported; body is undefined.
|
||||
ParMixedBilinearForm(const ParMixedBilinearForm &);
|
||||
|
||||
/// Copy assignment is not supported; body is undefined.
|
||||
ParMixedBilinearForm &operator=(const ParMixedBilinearForm &);
|
||||
|
||||
public:
|
||||
/** @brief Construct a ParMixedBilinearForm on the given FiniteElementSpace%s
|
||||
@a trial_fes and @a test_fes. */
|
||||
/** The pointers @a trial_fes and @a test_fes are not owned by the newly
|
||||
constructed object. */
|
||||
ParMixedBilinearForm(ParFiniteElementSpace *trial_fes,
|
||||
ParFiniteElementSpace *test_fes)
|
||||
: MixedBilinearForm(trial_fes, test_fes)
|
||||
@@ -232,6 +264,24 @@ public:
|
||||
test_pfes = test_fes;
|
||||
}
|
||||
|
||||
/** @brief Create a ParMixedBilinearForm on the given FiniteElementSpace%s
|
||||
@a trial_fes and @a test_fes, using the same integrators as the
|
||||
ParMixedBilinearForm @a mbf.
|
||||
|
||||
The pointers @a trial_fes and @a test_fes are not owned by the newly
|
||||
constructed object.
|
||||
|
||||
The integrators in @a mbf are copied as pointers and they are not owned
|
||||
by the newly constructed ParMixedBilinearForm. */
|
||||
ParMixedBilinearForm(ParFiniteElementSpace *trial_fes,
|
||||
ParFiniteElementSpace *test_fes,
|
||||
ParMixedBilinearForm * mbf)
|
||||
: MixedBilinearForm(trial_fes, test_fes, mbf)
|
||||
{
|
||||
trial_pfes = trial_fes;
|
||||
test_pfes = test_fes;
|
||||
}
|
||||
|
||||
/// Returns the matrix assembled on the true dofs, i.e. P_test^t A P_trial.
|
||||
HypreParMatrix *ParallelAssemble();
|
||||
|
||||
@@ -251,10 +301,24 @@ public:
|
||||
class ParDiscreteLinearOperator : public DiscreteLinearOperator
|
||||
{
|
||||
protected:
|
||||
/// Points to the same object as #trial_fes
|
||||
ParFiniteElementSpace *domain_fes;
|
||||
/// Points to the same object as #test_fes
|
||||
ParFiniteElementSpace *range_fes;
|
||||
|
||||
private:
|
||||
/// Copy construction is not supported; body is undefined.
|
||||
ParDiscreteLinearOperator(const ParDiscreteLinearOperator &);
|
||||
|
||||
/// Copy assignment is not supported; body is undefined.
|
||||
ParDiscreteLinearOperator &operator=(const ParDiscreteLinearOperator &);
|
||||
|
||||
public:
|
||||
/** @brief Construct a ParDiscreteLinearOperator on the given
|
||||
FiniteElementSpace%s @a dfes (domain FE space) and @a rfes (range FE
|
||||
space). */
|
||||
/** The pointers @a dfes and @a rfes are not owned by the newly constructed
|
||||
object. */
|
||||
ParDiscreteLinearOperator(ParFiniteElementSpace *dfes,
|
||||
ParFiniteElementSpace *rfes)
|
||||
: DiscreteLinearOperator(dfes, rfes) { domain_fes=dfes; range_fes=rfes; }
|
||||
|
||||
+217
-55
@@ -140,6 +140,13 @@ void ParFiniteElementSpace::Construct()
|
||||
}
|
||||
else // Nonconforming()
|
||||
{
|
||||
// Initialize 'gcomm' for the cut (aka "partially conforming") space.
|
||||
// In the process, the array 'ldof_ltdof' is also initialized (for the cut
|
||||
// space) and used; however, it will be overwritten below with the real
|
||||
// true dofs. Also, 'ldof_sign' and 'ldof_group' are constructed for the
|
||||
// cut space.
|
||||
ConstructTrueDofs();
|
||||
|
||||
// calculate number of ghost DOFs
|
||||
ngvdofs = pncmesh->GetNGhostVertices()
|
||||
* fec->DofForGeometry(Geometry::POINT);
|
||||
@@ -153,7 +160,7 @@ void ParFiniteElementSpace::Construct()
|
||||
if (pmesh->Dimension() > 2)
|
||||
{
|
||||
ngfdofs = pncmesh->GetNGhostFaces()
|
||||
* fec->DofForGeometry(mesh->GetBdrElementBaseGeometry());
|
||||
* fec->DofForGeometry(pncmesh->GetGhostFaceGeometry(0));
|
||||
}
|
||||
|
||||
// total number of ghost DOFs. Ghost DOFs start at index 'ndofs', i.e.,
|
||||
@@ -171,12 +178,51 @@ void ParFiniteElementSpace::Construct()
|
||||
}
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::PrintPartitionStats()
|
||||
{
|
||||
long ltdofs = ltdof_size;
|
||||
long min_ltdofs, max_ltdofs, sum_ltdofs;
|
||||
|
||||
MPI_Reduce(<dofs, &min_ltdofs, 1, MPI_LONG, MPI_MIN, 0, MyComm);
|
||||
MPI_Reduce(<dofs, &max_ltdofs, 1, MPI_LONG, MPI_MAX, 0, MyComm);
|
||||
MPI_Reduce(<dofs, &sum_ltdofs, 1, MPI_LONG, MPI_SUM, 0, MyComm);
|
||||
|
||||
if (MyRank == 0)
|
||||
{
|
||||
double avg = double(sum_ltdofs) / NRanks;
|
||||
mfem::out << "True DOF partitioning: min " << min_ltdofs
|
||||
<< ", avg " << std::fixed << std::setprecision(1) << avg
|
||||
<< ", max " << max_ltdofs
|
||||
<< ", (max-avg)/avg " << 100.0*(max_ltdofs - avg)/avg
|
||||
<< "%" << std::endl;
|
||||
}
|
||||
|
||||
if (NRanks <= 32)
|
||||
{
|
||||
if (MyRank == 0)
|
||||
{
|
||||
mfem::out << "True DOFs by rank: " << ltdofs;
|
||||
for (int i = 1; i < NRanks; i++)
|
||||
{
|
||||
MPI_Status status;
|
||||
MPI_Recv(<dofs, 1, MPI_LONG, i, 123, MyComm, &status);
|
||||
mfem::out << " " << ltdofs;
|
||||
}
|
||||
mfem::out << "\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
MPI_Send(<dofs, 1, MPI_LONG, 0, 123, MyComm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::GetGroupComm(
|
||||
GroupCommunicator &gc, int ldof_type, Array<int> *ldof_sign)
|
||||
{
|
||||
int gr;
|
||||
int ng = pmesh->GetNGroups();
|
||||
int nvd, ned, nfd;
|
||||
int nvd, ned, ntd = 0, nqd = 0;
|
||||
Array<int> dofs;
|
||||
|
||||
int group_ldof_counter;
|
||||
@@ -184,8 +230,18 @@ void ParFiniteElementSpace::GetGroupComm(
|
||||
|
||||
nvd = fec->DofForGeometry(Geometry::POINT);
|
||||
ned = fec->DofForGeometry(Geometry::SEGMENT);
|
||||
// Assuming all faces are the same type:
|
||||
nfd = (fdofs) ? (fdofs[1]-fdofs[0]) : (0);
|
||||
|
||||
if (fdofs)
|
||||
{
|
||||
if (mesh->HasGeometry(Geometry::TRIANGLE))
|
||||
{
|
||||
ntd = fec->DofForGeometry(Geometry::TRIANGLE);
|
||||
}
|
||||
if (mesh->HasGeometry(Geometry::SQUARE))
|
||||
{
|
||||
nqd = fec->DofForGeometry(Geometry::SQUARE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ldof_sign)
|
||||
{
|
||||
@@ -199,7 +255,8 @@ void ParFiniteElementSpace::GetGroupComm(
|
||||
{
|
||||
group_ldof_counter += nvd * pmesh->GroupNVertices(gr);
|
||||
group_ldof_counter += ned * pmesh->GroupNEdges(gr);
|
||||
group_ldof_counter += nfd * pmesh->GroupNFaces(gr);
|
||||
group_ldof_counter += ntd * pmesh->GroupNTriangles(gr);
|
||||
group_ldof_counter += nqd * pmesh->GroupNQuadrilaterals(gr);
|
||||
}
|
||||
if (ldof_type)
|
||||
{
|
||||
@@ -213,12 +270,13 @@ void ParFiniteElementSpace::GetGroupComm(
|
||||
group_ldof.GetI()[0] = group_ldof.GetI()[1] = 0;
|
||||
for (gr = 1; gr < ng; gr++)
|
||||
{
|
||||
int j, k, l, m, o, nv, ne, nf;
|
||||
int j, k, l, m, o, nv, ne, nt, nq;
|
||||
const int *ind;
|
||||
|
||||
nv = pmesh->GroupNVertices(gr);
|
||||
ne = pmesh->GroupNEdges(gr);
|
||||
nf = pmesh->GroupNFaces(gr);
|
||||
nt = pmesh->GroupNTriangles(gr);
|
||||
nq = pmesh->GroupNQuadrilaterals(gr);
|
||||
|
||||
// vertices
|
||||
if (nvd > 0)
|
||||
@@ -284,18 +342,55 @@ void ParFiniteElementSpace::GetGroupComm(
|
||||
}
|
||||
}
|
||||
|
||||
// faces
|
||||
if (nfd > 0)
|
||||
// triangles
|
||||
if (ntd > 0)
|
||||
{
|
||||
for (j = 0; j < nf; j++)
|
||||
for (j = 0; j < nt; j++)
|
||||
{
|
||||
pmesh->GroupFace(gr, j, k, o);
|
||||
pmesh->GroupTriangle(gr, j, k, o);
|
||||
|
||||
dofs.SetSize(nfd);
|
||||
dofs.SetSize(ntd);
|
||||
m = nvdofs+nedofs+fdofs[k];
|
||||
ind = fec->DofOrderForOrientation(
|
||||
mesh->GetFaceBaseGeometry(k), o);
|
||||
for (l = 0; l < nfd; l++)
|
||||
ind = fec->DofOrderForOrientation(Geometry::TRIANGLE, o);
|
||||
for (l = 0; l < ntd; l++)
|
||||
{
|
||||
if (ind[l] < 0)
|
||||
{
|
||||
dofs[l] = m + (-1-ind[l]);
|
||||
if (ldof_sign)
|
||||
{
|
||||
(*ldof_sign)[dofs[l]] = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dofs[l] = m + ind[l];
|
||||
}
|
||||
}
|
||||
|
||||
if (ldof_type)
|
||||
{
|
||||
DofsToVDofs(dofs);
|
||||
}
|
||||
|
||||
for (l = 0; l < dofs.Size(); l++)
|
||||
{
|
||||
group_ldof.GetJ()[group_ldof_counter++] = dofs[l];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// quadrilaterals
|
||||
if (nqd > 0)
|
||||
{
|
||||
for (j = 0; j < nq; j++)
|
||||
{
|
||||
pmesh->GroupQuadrilateral(gr, j, k, o);
|
||||
|
||||
dofs.SetSize(nqd);
|
||||
m = nvdofs+nedofs+fdofs[k];
|
||||
ind = fec->DofOrderForOrientation(Geometry::SQUARE, o);
|
||||
for (l = 0; l < nqd; l++)
|
||||
{
|
||||
if (ind[l] < 0)
|
||||
{
|
||||
@@ -418,12 +513,13 @@ void ParFiniteElementSpace::GetSharedEdgeDofs(
|
||||
}
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::GetSharedFaceDofs(
|
||||
void ParFiniteElementSpace::GetSharedTriangleDofs(
|
||||
int group, int fi, Array<int> &dofs) const
|
||||
{
|
||||
int l_face, ori;
|
||||
MFEM_ASSERT(0 <= fi && fi < pmesh->GroupNFaces(group), "invalid face index");
|
||||
pmesh->GroupFace(group, fi, l_face, ori);
|
||||
MFEM_ASSERT(0 <= fi && fi < pmesh->GroupNTriangles(group),
|
||||
"invalid triangular face index");
|
||||
pmesh->GroupTriangle(group, fi, l_face, ori);
|
||||
if (ori == 0)
|
||||
{
|
||||
GetFaceDofs(l_face, dofs);
|
||||
@@ -431,7 +527,31 @@ void ParFiniteElementSpace::GetSharedFaceDofs(
|
||||
else
|
||||
{
|
||||
Array<int> rdofs;
|
||||
fec->SubDofOrder(pmesh->GetFaceBaseGeometry(l_face), 2, ori, dofs);
|
||||
fec->SubDofOrder(Geometry::TRIANGLE, 2, ori, dofs);
|
||||
GetFaceDofs(l_face, rdofs);
|
||||
for (int i = 0; i < dofs.Size(); i++)
|
||||
{
|
||||
const int di = dofs[i];
|
||||
dofs[i] = (di >= 0) ? rdofs[di] : -1-rdofs[-1-di];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParFiniteElementSpace::GetSharedQuadrilateralDofs(
|
||||
int group, int fi, Array<int> &dofs) const
|
||||
{
|
||||
int l_face, ori;
|
||||
MFEM_ASSERT(0 <= fi && fi < pmesh->GroupNQuadrilaterals(group),
|
||||
"invalid quadrilateral face index");
|
||||
pmesh->GroupQuadrilateral(group, fi, l_face, ori);
|
||||
if (ori == 0)
|
||||
{
|
||||
GetFaceDofs(l_face, dofs);
|
||||
}
|
||||
else
|
||||
{
|
||||
Array<int> rdofs;
|
||||
fec->SubDofOrder(Geometry::SQUARE, 2, ori, dofs);
|
||||
GetFaceDofs(l_face, rdofs);
|
||||
for (int i = 0; i < dofs.Size(); i++)
|
||||
{
|
||||
@@ -556,30 +676,26 @@ HypreParMatrix *ParFiniteElementSpace::GetPartialConformingInterpolation()
|
||||
|
||||
void ParFiniteElementSpace::DivideByGroupSize(double *vec)
|
||||
{
|
||||
if (Nonconforming())
|
||||
{
|
||||
MFEM_ABORT("Not implemented for NC mesh.");
|
||||
}
|
||||
|
||||
GroupTopology > = GetGroupTopo();
|
||||
|
||||
for (int i = 0; i < ldof_group.Size(); i++)
|
||||
{
|
||||
if (gt.IAmMaster(ldof_group[i])) // we are the master
|
||||
{
|
||||
vec[ldof_ltdof[i]] /= gt.GetGroupSize(ldof_group[i]);
|
||||
if (ldof_ltdof[i] >= 0) // see note below
|
||||
{
|
||||
vec[ldof_ltdof[i]] /= gt.GetGroupSize(ldof_group[i]);
|
||||
}
|
||||
// NOTE: in NC meshes, ldof_ltdof generated for the gtopo
|
||||
// groups by ConstructTrueDofs gets overwritten by
|
||||
// BuildParallelConformingInterpolation. Some DOFs that are
|
||||
// seen as true by the conforming code are actually slaves and
|
||||
// end up with a -1 in ldof_ltdof.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GroupCommunicator *ParFiniteElementSpace::ScalarGroupComm()
|
||||
{
|
||||
if (Nonconforming())
|
||||
{
|
||||
// MFEM_WARNING("Not implemented for NC mesh.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GroupCommunicator *gc = new GroupCommunicator(GetGroupTopo());
|
||||
if (NURBSext)
|
||||
{
|
||||
@@ -594,15 +710,10 @@ GroupCommunicator *ParFiniteElementSpace::ScalarGroupComm()
|
||||
|
||||
void ParFiniteElementSpace::Synchronize(Array<int> &ldof_marker) const
|
||||
{
|
||||
if (Nonconforming())
|
||||
{
|
||||
MFEM_ABORT("Not implemented for NC mesh.");
|
||||
}
|
||||
// For non-conforming mesh, synchronization is performed on the cut (aka
|
||||
// "partially conforming") space.
|
||||
|
||||
if (ldof_marker.Size() != GetVSize())
|
||||
{
|
||||
mfem_error("ParFiniteElementSpace::Synchronize");
|
||||
}
|
||||
MFEM_VERIFY(ldof_marker.Size() == GetVSize(), "invalid in/out array");
|
||||
|
||||
// implement allreduce(|) as reduce(|) + broadcast
|
||||
gcomm->Reduce<int>(ldof_marker, GroupCommunicator::BitOR);
|
||||
@@ -991,7 +1102,7 @@ void ParFiniteElementSpace::GetFaceNbrFaceVDofs(int i, Array<int> &vdofs) const
|
||||
const int nd = face_nbr_element_dof.RowSize(el2);
|
||||
const int *vol_vdofs = face_nbr_element_dof.GetRow(el2);
|
||||
const Element *face_nbr_el = pmesh->face_nbr_elements[el2];
|
||||
const int geom = face_nbr_el->GetGeometryType();
|
||||
Geometry::Type geom = face_nbr_el->GetGeometryType();
|
||||
const int face_dim = Geometry::Dimension[geom]-1;
|
||||
|
||||
fec->SubDofOrder(geom, face_dim, inf2, vdofs);
|
||||
@@ -1023,8 +1134,8 @@ const FiniteElement *ParFiniteElementSpace::GetFaceNbrFaceFE(int i) const
|
||||
{
|
||||
// Works in tandem with GetFaceNbrFaceVDofs() defined above.
|
||||
MFEM_ASSERT(Nonconforming() && !NURBSext, "");
|
||||
const int geom = (pmesh->Dimension() == 2) ?
|
||||
Geometry::SEGMENT : Geometry::SQUARE;
|
||||
Geometry::Type geom = (pmesh->Dimension() == 2) ?
|
||||
Geometry::SEGMENT : Geometry::SQUARE;
|
||||
return fec->FiniteElementForGeometry(geom);
|
||||
}
|
||||
|
||||
@@ -1175,7 +1286,9 @@ void ParFiniteElementSpace::GetGhostEdgeDofs(const MeshId &edge_id,
|
||||
void ParFiniteElementSpace::GetGhostFaceDofs(const MeshId &face_id,
|
||||
Array<int> &dofs) const
|
||||
{
|
||||
MFEM_ASSERT(mesh->GetFaceBaseGeometry(0) == Geometry::SQUARE, "");
|
||||
const int ghost_face_index = face_id.index - pncmesh->GetNFaces();
|
||||
MFEM_ASSERT(pncmesh->GetGhostFaceGeometry(ghost_face_index)
|
||||
== Geometry::SQUARE, "");
|
||||
|
||||
int nv = fec->DofForGeometry(Geometry::POINT);
|
||||
int ne = fec->DofForGeometry(Geometry::SEGMENT);
|
||||
@@ -1209,8 +1322,8 @@ void ParFiniteElementSpace::GetGhostFaceDofs(const MeshId &face_id,
|
||||
}
|
||||
}
|
||||
|
||||
int first = ndofs + ngvdofs + ngedofs +
|
||||
(face_id.index - pncmesh->GetNFaces())*nf;
|
||||
// Assuming all ghost faces have the same number of dofs:
|
||||
int first = ndofs + ngvdofs + ngedofs + ghost_face_index*nf;
|
||||
for (int j = 0; j < nf; j++)
|
||||
{
|
||||
dofs[offset++] = first + j;
|
||||
@@ -1252,7 +1365,8 @@ void ParFiniteElementSpace::GetBareDofs(int entity, int index,
|
||||
break;
|
||||
|
||||
default:
|
||||
ned = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
|
||||
MFEM_ASSERT(!pmesh->HasGeometry(Geometry::TRIANGLE), "");
|
||||
ned = fec->DofForGeometry(Geometry::SQUARE);
|
||||
ghost = pncmesh->GetNFaces();
|
||||
first = (index < ghost)
|
||||
? nvdofs + nedofs + index*ned // regular face
|
||||
@@ -1292,8 +1406,9 @@ int ParFiniteElementSpace::PackDof(int entity, int index, int edof) const
|
||||
: ndofs + ngvdofs + (index - ghost)*ned + edof; // ghost edge
|
||||
|
||||
default:
|
||||
MFEM_ASSERT(!pmesh->HasGeometry(Geometry::TRIANGLE), "");
|
||||
ghost = pncmesh->GetNFaces();
|
||||
ned = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
|
||||
ned = fec->DofForGeometry(Geometry::SQUARE);
|
||||
|
||||
return (index < ghost)
|
||||
? nvdofs + nedofs + index*ned + edof // regular face
|
||||
@@ -1326,7 +1441,8 @@ void ParFiniteElementSpace::UnpackDof(int dof,
|
||||
dof -= nedofs;
|
||||
if (dof < nfdofs) // regular face
|
||||
{
|
||||
int nf = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
|
||||
MFEM_ASSERT(!pmesh->HasGeometry(Geometry::TRIANGLE), "");
|
||||
int nf = fec->DofForGeometry(Geometry::SQUARE);
|
||||
entity = 2, index = dof / nf, edof = dof % nf;
|
||||
return;
|
||||
}
|
||||
@@ -1351,7 +1467,7 @@ void ParFiniteElementSpace::UnpackDof(int dof,
|
||||
dof -= ngedofs;
|
||||
if (dof < ngfdofs) // ghost face
|
||||
{
|
||||
int nf = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
|
||||
int nf = fec->DofForGeometry(pncmesh->GetGhostFaceGeometry(0));
|
||||
entity = 2, index = pncmesh->GetNFaces() + dof / nf, edof = dof % nf;
|
||||
return;
|
||||
}
|
||||
@@ -1578,7 +1694,7 @@ void NeighborRowMessage::Decode(int rank)
|
||||
rows.clear();
|
||||
rows.reserve(nrows);
|
||||
|
||||
int fgeom = pncmesh->GetFaceGeometry();
|
||||
Geometry::Type fgeom = pncmesh->GetFaceGeometry();
|
||||
|
||||
// read rows
|
||||
for (int ent = 0, gi = 0; ent < 3; ent++)
|
||||
@@ -1640,6 +1756,9 @@ ParFiniteElementSpace::ScheduleSendRow(const PMatrixRow &row, int dof,
|
||||
msg.AddRow(ent, idx, edof, group_id, row);
|
||||
msg.SetNCMesh(pncmesh);
|
||||
msg.SetFEC(fec);
|
||||
#ifdef MFEM_PMATRIX_STATS
|
||||
n_rows_sent++;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1662,7 +1781,9 @@ void ParFiniteElementSpace::ForwardRow(const PMatrixRow &row, int dof,
|
||||
msg.AddRow(ent, idx, edof, invalid, row);
|
||||
msg.SetNCMesh(pncmesh);
|
||||
msg.SetFEC(fec);
|
||||
|
||||
#ifdef MFEM_PMATRIX_STATS
|
||||
n_rows_fwd++;
|
||||
#endif
|
||||
#ifdef MFEM_DEBUG_PMATRIX
|
||||
mfem::out << "Rank " << pncmesh->GetMyRank() << " forwarding to "
|
||||
<< rank << ": ent " << ent << ", index" << idx
|
||||
@@ -1744,6 +1865,11 @@ int ParFiniteElementSpace
|
||||
{
|
||||
bool dg = (nvdofs == 0 && nedofs == 0 && nfdofs == 0);
|
||||
|
||||
#ifdef MFEM_PMATRIX_STATS
|
||||
n_msgs_sent = n_msgs_recv = 0;
|
||||
n_rows_sent = n_rows_recv = n_rows_fwd = 0;
|
||||
#endif
|
||||
|
||||
// *** STEP 1: build master-slave dependency lists ***
|
||||
|
||||
int total_dofs = ndofs + ngdofs;
|
||||
@@ -1763,7 +1889,8 @@ int ParFiniteElementSpace
|
||||
if (entity > 1) { T.SetFE(&QuadrilateralFE); }
|
||||
else { T.SetFE(&SegmentFE); }
|
||||
|
||||
int geom = (entity > 1) ? Geometry::SQUARE : Geometry::SEGMENT;
|
||||
Geometry::Type geom = (entity > 1) ?
|
||||
Geometry::SQUARE : Geometry::SEGMENT;
|
||||
const FiniteElement* fe = fec->FiniteElementForGeometry(geom);
|
||||
if (!fe) { continue; }
|
||||
|
||||
@@ -1921,6 +2048,9 @@ int ParFiniteElementSpace
|
||||
|
||||
// send identity rows
|
||||
NeighborRowMessage::IsendAll(send_msg.back(), MyComm);
|
||||
#ifdef MFEM_PMATRIX_STATS
|
||||
n_msgs_sent += send_msg.back().size();
|
||||
#endif
|
||||
|
||||
if (R) { (*R)->Finalize(); }
|
||||
|
||||
@@ -1948,6 +2078,10 @@ int ParFiniteElementSpace
|
||||
while (NeighborRowMessage::IProbe(rank, size, MyComm))
|
||||
{
|
||||
recv_msg.Recv(rank, size, MyComm);
|
||||
#ifdef MFEM_PMATRIX_STATS
|
||||
n_msgs_recv++;
|
||||
n_rows_recv += recv_msg.GetRows().size();
|
||||
#endif
|
||||
|
||||
const NeighborRowMessage::RowInfo::List &rows = recv_msg.GetRows();
|
||||
for (unsigned i = 0; i < rows.size(); i++)
|
||||
@@ -2022,6 +2156,9 @@ int ParFiniteElementSpace
|
||||
|
||||
// send current batch of messages
|
||||
NeighborRowMessage::IsendAll(send_msg.back(), MyComm);
|
||||
#ifdef MFEM_PMATRIX_STATS
|
||||
n_msgs_sent += send_msg.back().size();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (P)
|
||||
@@ -2045,6 +2182,31 @@ int ParFiniteElementSpace
|
||||
NeighborRowMessage::WaitAllSent(*it);
|
||||
}
|
||||
|
||||
#ifdef MFEM_PMATRIX_STATS
|
||||
int n_rounds = send_msg.size();
|
||||
int glob_rounds, glob_msgs_sent, glob_msgs_recv;
|
||||
int glob_rows_sent, glob_rows_recv, glob_rows_fwd;
|
||||
|
||||
MPI_Reduce(&n_rounds, &glob_rounds, 1, MPI_INT, MPI_SUM, 0, MyComm);
|
||||
MPI_Reduce(&n_msgs_sent, &glob_msgs_sent, 1, MPI_INT, MPI_SUM, 0, MyComm);
|
||||
MPI_Reduce(&n_msgs_recv, &glob_msgs_recv, 1, MPI_INT, MPI_SUM, 0, MyComm);
|
||||
MPI_Reduce(&n_rows_sent, &glob_rows_sent, 1, MPI_INT, MPI_SUM, 0, MyComm);
|
||||
MPI_Reduce(&n_rows_recv, &glob_rows_recv, 1, MPI_INT, MPI_SUM, 0, MyComm);
|
||||
MPI_Reduce(&n_rows_fwd, &glob_rows_fwd, 1, MPI_INT, MPI_SUM, 0, MyComm);
|
||||
|
||||
if (MyRank == 0)
|
||||
{
|
||||
mfem::out << "P matrix stats (avg per rank): "
|
||||
<< double(glob_rounds)/NRanks << " rounds, "
|
||||
<< double(glob_msgs_sent)/NRanks << " msgs sent, "
|
||||
<< double(glob_msgs_recv)/NRanks << " msgs recv, "
|
||||
<< double(glob_rows_sent)/NRanks << " rows sent, "
|
||||
<< double(glob_rows_recv)/NRanks << " rows recv, "
|
||||
<< double(glob_rows_fwd)/NRanks << " rows forwarded."
|
||||
<< std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
return num_true_dofs*vdim;
|
||||
}
|
||||
|
||||
@@ -2305,7 +2467,7 @@ ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
|
||||
Vector row;
|
||||
|
||||
ParNCMesh* pncmesh = pmesh->pncmesh;
|
||||
int geom = pncmesh->GetElementGeometry();
|
||||
Geometry::Type geom = pncmesh->GetElementGeometry();
|
||||
int ldof = fec->FiniteElementForGeometry(geom)->GetDof();
|
||||
|
||||
const CoarseFineTransformations &dtrans = pncmesh->GetDerefinementTransforms();
|
||||
@@ -2355,7 +2517,7 @@ ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
|
||||
}
|
||||
|
||||
DenseTensor localR;
|
||||
GetLocalDerefinementMatrices(localR);
|
||||
GetLocalDerefinementMatrices(geom, localR);
|
||||
|
||||
// create the diagonal part of the derefinement matrix
|
||||
SparseMatrix *diag = new SparseMatrix(ndofs*vdim, old_ndofs*vdim);
|
||||
|
||||
+16
-5
@@ -119,6 +119,11 @@ private:
|
||||
int PackDof(int entity, int index, int edof) const;
|
||||
void UnpackDof(int dof, int &entity, int &index, int &edof) const;
|
||||
|
||||
#ifdef MFEM_PMATRIX_STATS
|
||||
mutable int n_msgs_sent, n_msgs_recv;
|
||||
mutable int n_rows_sent, n_rows_recv, n_rows_fwd;
|
||||
#endif
|
||||
|
||||
void ScheduleSendRow(const struct PMatrixRow &row, int dof, GroupId group_id,
|
||||
std::map<int, class NeighborRowMessage> &send_msg) const;
|
||||
|
||||
@@ -182,7 +187,7 @@ public:
|
||||
|
||||
/** @brief Copy constructor: deep copy all data from @a orig except the
|
||||
ParMesh, the FiniteElementCollection, and some derived data. */
|
||||
/** If the @a pmesh or @a fec poiters are NULL (default), then the new
|
||||
/** If the @a pmesh or @a fec pointers are NULL (default), then the new
|
||||
ParFiniteElementSpace will reuse the respective pointers from @a orig. If
|
||||
any of these pointers is not NULL, the given pointer will be used instead
|
||||
of the one used by @a orig.
|
||||
@@ -205,7 +210,7 @@ public:
|
||||
ParFiniteElementSpace(const FiniteElementSpace &orig, ParMesh &pmesh,
|
||||
const FiniteElementCollection *fec = NULL);
|
||||
|
||||
/** @brief Construct the *local* ParFiniteElementSpace corresponing to the
|
||||
/** @brief Construct the *local* ParFiniteElementSpace corresponding to the
|
||||
global FE space, @a global_fes. */
|
||||
/** The parameter @a pm is the *local* ParMesh obtained by decomposing the
|
||||
global Mesh used by @a global_fes. The array @a partitioning represents
|
||||
@@ -260,7 +265,8 @@ public:
|
||||
virtual void GetFaceDofs(int i, Array<int> &dofs) const;
|
||||
|
||||
void GetSharedEdgeDofs(int group, int ei, Array<int> &dofs) const;
|
||||
void GetSharedFaceDofs(int group, int fi, Array<int> &dofs) const;
|
||||
void GetSharedTriangleDofs(int group, int fi, Array<int> &dofs) const;
|
||||
void GetSharedQuadrilateralDofs(int group, int fi, Array<int> &dofs) const;
|
||||
|
||||
/// The true dof-to-dof interpolation matrix
|
||||
HypreParMatrix *Dof_TrueDof_Matrix() const
|
||||
@@ -285,11 +291,14 @@ public:
|
||||
/// Return a const reference to the internal GroupCommunicator (on VDofs)
|
||||
const GroupCommunicator &GroupComm() const { return *gcomm; }
|
||||
|
||||
/// Return a new GroupCommunicator on Dofs
|
||||
/// Return a new GroupCommunicator on scalar dofs, i.e. for VDim = 1.
|
||||
/** @note The returned pointer must be deleted by the caller. */
|
||||
GroupCommunicator *ScalarGroupComm();
|
||||
|
||||
/** Given an integer array on the local degrees of freedom, perform
|
||||
/** @brief Given an integer array on the local degrees of freedom, perform
|
||||
a bitwise OR between the shared dofs. */
|
||||
/** For non-conforming mesh, synchronization is performed on the cut (aka
|
||||
"partially conforming") space. */
|
||||
void Synchronize(Array<int> &ldof_marker) const;
|
||||
|
||||
/// Determine the boundary degrees of freedom
|
||||
@@ -356,6 +365,8 @@ public:
|
||||
|
||||
virtual ~ParFiniteElementSpace() { Destroy(); }
|
||||
|
||||
void PrintPartitionStats();
|
||||
|
||||
// Obsolete, kept for backward compatibility
|
||||
int TrueVSize() const { return ltdof_size; }
|
||||
};
|
||||
|
||||
+108
-23
@@ -147,12 +147,14 @@ HypreParVector *ParGridFunction::GetTrueDofs() const
|
||||
|
||||
void ParGridFunction::ParallelAverage(Vector &tv) const
|
||||
{
|
||||
MFEM_VERIFY(pfes->Conforming(), "not implemented for NC meshes");
|
||||
pfes->GetProlongationMatrix()->MultTranspose(*this, tv);
|
||||
pfes->DivideByGroupSize(tv);
|
||||
}
|
||||
|
||||
void ParGridFunction::ParallelAverage(HypreParVector &tv) const
|
||||
{
|
||||
MFEM_VERIFY(pfes->Conforming(), "not implemented for NC meshes");
|
||||
pfes->GetProlongationMatrix()->MultTranspose(*this, tv);
|
||||
pfes->DivideByGroupSize(tv);
|
||||
}
|
||||
@@ -395,6 +397,94 @@ void ParGridFunction::ProjectDiscCoefficient(VectorCoefficient &vcoeff,
|
||||
ComputeMeans(type, zones_per_vdof);
|
||||
}
|
||||
|
||||
void ParGridFunction::ProjectBdrCoefficient(
|
||||
Coefficient *coeff[], VectorCoefficient *vcoeff, Array<int> &attr)
|
||||
{
|
||||
Array<int> values_counter;
|
||||
AccumulateAndCountBdrValues(coeff, vcoeff, attr, values_counter);
|
||||
if (pfes->Conforming())
|
||||
{
|
||||
Vector values(Size());
|
||||
for (int i = 0; i < values.Size(); i++)
|
||||
{
|
||||
values(i) = values_counter[i] ? (*this)(i) : 0.0;
|
||||
}
|
||||
// Count the values globally.
|
||||
GroupCommunicator &gcomm = pfes->GroupComm();
|
||||
gcomm.Reduce<int>(values_counter, GroupCommunicator::Sum);
|
||||
// Accumulate the values globally.
|
||||
gcomm.Reduce<double>(values, GroupCommunicator::Sum);
|
||||
// Only the values in the master are guaranteed to be correct!
|
||||
for (int i = 0; i < values.Size(); i++)
|
||||
{
|
||||
if (values_counter[i])
|
||||
{
|
||||
(*this)(i) = values(i)/values_counter[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: same as the conforming case after 'cut-mesh-groups-dev-*' is
|
||||
// merged?
|
||||
ComputeMeans(ARITHMETIC, values_counter);
|
||||
}
|
||||
#ifdef MFEM_DEBUG
|
||||
Array<int> ess_vdofs_marker;
|
||||
pfes->GetEssentialVDofs(attr, ess_vdofs_marker);
|
||||
for (int i = 0; i < values_counter.Size(); i++)
|
||||
{
|
||||
MFEM_ASSERT(pfes->GetLocalTDofNumber(i) == -1 ||
|
||||
bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
|
||||
"internal error");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParGridFunction::ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
|
||||
Array<int> &bdr_attr)
|
||||
{
|
||||
Array<int> values_counter;
|
||||
AccumulateAndCountBdrTangentValues(vcoeff, bdr_attr, values_counter);
|
||||
if (pfes->Conforming())
|
||||
{
|
||||
Vector values(Size());
|
||||
for (int i = 0; i < values.Size(); i++)
|
||||
{
|
||||
values(i) = values_counter[i] ? (*this)(i) : 0.0;
|
||||
}
|
||||
// Count the values globally.
|
||||
GroupCommunicator &gcomm = pfes->GroupComm();
|
||||
gcomm.Reduce<int>(values_counter, GroupCommunicator::Sum);
|
||||
// Accumulate the values globally.
|
||||
gcomm.Reduce<double>(values, GroupCommunicator::Sum);
|
||||
// Only the values in the master are guaranteed to be correct!
|
||||
for (int i = 0; i < values.Size(); i++)
|
||||
{
|
||||
if (values_counter[i])
|
||||
{
|
||||
(*this)(i) = values(i)/values_counter[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// FIXME: same as the conforming case after 'cut-mesh-groups-dev-*' is
|
||||
// merged?
|
||||
ComputeMeans(ARITHMETIC, values_counter);
|
||||
}
|
||||
#ifdef MFEM_DEBUG
|
||||
Array<int> ess_vdofs_marker;
|
||||
pfes->GetEssentialVDofs(bdr_attr, ess_vdofs_marker);
|
||||
for (int i = 0; i < values_counter.Size(); i++)
|
||||
{
|
||||
MFEM_ASSERT(pfes->GetLocalTDofNumber(i) == -1 ||
|
||||
bool(values_counter[i]) == bool(ess_vdofs_marker[i]),
|
||||
"internal error");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ParGridFunction::Save(std::ostream &out) const
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
@@ -589,22 +679,12 @@ void ParGridFunction::ComputeFlux(
|
||||
Array<int> count(flux.Size());
|
||||
SumFluxAndCount(blfi, flux, count, wcoef, subdomain);
|
||||
|
||||
if (ffes->Conforming()) // FIXME: nonconforming
|
||||
{
|
||||
// Accumulate flux and counts in parallel
|
||||
// Accumulate flux and counts in parallel
|
||||
ffes->GroupComm().Reduce<double>(flux, GroupCommunicator::Sum);
|
||||
ffes->GroupComm().Bcast<double>(flux);
|
||||
|
||||
ffes->GroupComm().Reduce<double>(flux, GroupCommunicator::Sum);
|
||||
ffes->GroupComm().Bcast<double>(flux);
|
||||
|
||||
ffes->GroupComm().Reduce<int>(count, GroupCommunicator::Sum);
|
||||
ffes->GroupComm().Bcast<int>(count);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Averaging on processor boundaries not implemented for "
|
||||
"NC meshes yet.\n"
|
||||
"Use L2ZZErrorEstimator() instead of ZZErrorEstimator().");
|
||||
}
|
||||
ffes->GroupComm().Reduce<int>(count, GroupCommunicator::Sum);
|
||||
ffes->GroupComm().Bcast<int>(count);
|
||||
|
||||
// complete averaging
|
||||
for (int i = 0; i < count.Size(); i++)
|
||||
@@ -658,15 +738,20 @@ double L2ZZErrorEstimator(BilinearFormIntegrator &flux_integrator,
|
||||
ParLinearForm *b = new ParLinearForm(&smooth_flux_fes);
|
||||
VectorGridFunctionCoefficient f(&flux);
|
||||
|
||||
if (smooth_flux_fes.GetFE(0)->GetRangeType() == FiniteElement::SCALAR)
|
||||
if (xfes->GetNE())
|
||||
{
|
||||
a->AddDomainIntegrator(new VectorMassIntegrator);
|
||||
b->AddDomainIntegrator(new VectorDomainLFIntegrator(f));
|
||||
}
|
||||
else
|
||||
{
|
||||
a->AddDomainIntegrator(new VectorFEMassIntegrator);
|
||||
b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
|
||||
if (smooth_flux_fes.GetFE(0)->GetRangeType() == FiniteElement::SCALAR)
|
||||
{
|
||||
VectorMassIntegrator *vmass = new VectorMassIntegrator;
|
||||
vmass->SetVDim(smooth_flux_fes.GetVDim());
|
||||
a->AddDomainIntegrator(vmass);
|
||||
b->AddDomainIntegrator(new VectorDomainLFIntegrator(f));
|
||||
}
|
||||
else
|
||||
{
|
||||
a->AddDomainIntegrator(new VectorFEMassIntegrator);
|
||||
b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
|
||||
}
|
||||
}
|
||||
|
||||
b->Assemble();
|
||||
|
||||
+35
-2
@@ -32,13 +32,22 @@ double GlobalLpNorm(const double p, double loc_norm, MPI_Comm comm);
|
||||
class ParGridFunction : public GridFunction
|
||||
{
|
||||
protected:
|
||||
ParFiniteElementSpace *pfes;
|
||||
ParFiniteElementSpace *pfes; ///< Points to the same object as #fes
|
||||
|
||||
/** @brief Vector used to store data from face-neighbor processors,
|
||||
initialized by ExchangeFaceNbrData(). */
|
||||
Vector face_nbr_data;
|
||||
|
||||
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff,
|
||||
Array<int> &attr);
|
||||
|
||||
public:
|
||||
ParGridFunction() { pfes = NULL; }
|
||||
|
||||
/// Copy constructor. The internal vector #face_nbr_data is not copied.
|
||||
ParGridFunction(const ParGridFunction &orig)
|
||||
: GridFunction(orig), pfes(orig.pfes) { }
|
||||
|
||||
ParGridFunction(ParFiniteElementSpace *pf) : GridFunction(pf), pfes(pf) { }
|
||||
|
||||
/// Construct a ParGridFunction using previously allocated array @a data.
|
||||
@@ -74,6 +83,15 @@ public:
|
||||
constructed. The new ParGridFunction assumes ownership of both. */
|
||||
ParGridFunction(ParMesh *pmesh, std::istream &input);
|
||||
|
||||
/// Copy assignment. Only the data of the base class Vector is copied.
|
||||
/** It is assumed that this object and @a rhs use ParFiniteElementSpace%s
|
||||
that have the same size.
|
||||
|
||||
@note Defining this method overwrites the implicitly defined copy
|
||||
assignemnt operator. */
|
||||
ParGridFunction &operator=(const ParGridFunction &rhs)
|
||||
{ return operator=((const Vector &)rhs); }
|
||||
|
||||
/// Assign constant values to the ParGridFunction data.
|
||||
ParGridFunction &operator=(double value)
|
||||
{ GridFunction::operator=(value); return *this; }
|
||||
@@ -138,7 +156,7 @@ public:
|
||||
/// Set the GridFunction from the given true-dof vector.
|
||||
virtual void SetFromTrueDofs(const Vector &tv) { Distribute(tv); }
|
||||
|
||||
/// Short semantic for Distribute
|
||||
/// Short semantic for Distribute()
|
||||
ParGridFunction &operator=(const HypreParVector &tv)
|
||||
{ Distribute(&tv); return (*this); }
|
||||
|
||||
@@ -197,6 +215,21 @@ public:
|
||||
|
||||
virtual void ProjectDiscCoefficient(VectorCoefficient &vcoeff, AvgType type);
|
||||
|
||||
using GridFunction::ProjectBdrCoefficient;
|
||||
|
||||
// Only the values in the master are guaranteed to be correct!
|
||||
virtual void ProjectBdrCoefficient(VectorCoefficient &vcoeff,
|
||||
Array<int> &attr)
|
||||
{ ProjectBdrCoefficient(NULL, &vcoeff, attr); }
|
||||
|
||||
// Only the values in the master are guaranteed to be correct!
|
||||
virtual void ProjectBdrCoefficient(Coefficient *coeff[], Array<int> &attr)
|
||||
{ ProjectBdrCoefficient(coeff, NULL, attr); }
|
||||
|
||||
// Only the values in the master are guaranteed to be correct!
|
||||
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
|
||||
Array<int> &bdr_attr);
|
||||
|
||||
virtual double ComputeL1Error(Coefficient *exsol[],
|
||||
const IntegrationRule *irs[] = NULL) const
|
||||
{
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user