Compare commits
508
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c95789ba3c | ||
|
|
60c8f8adbf | ||
|
|
42a506cd53 | ||
|
|
85484ed1fc | ||
|
|
79de70139c | ||
|
|
a662e29b50 | ||
|
|
787df32cb3 | ||
|
|
ef7fd16dca | ||
|
|
722d64ef3b | ||
|
|
164ac6fcff | ||
|
|
2284f6864b | ||
|
|
037201e9ad | ||
|
|
66f8e1b45c | ||
|
|
cadbb91bd1 | ||
|
|
78a69c9cc8 | ||
|
|
5ab7e7c638 | ||
|
|
1aa9d39127 | ||
|
|
1ae3aad336 | ||
|
|
88bb203290 | ||
|
|
c7bce2f75b | ||
|
|
647d8970cc | ||
|
|
14fab74111 | ||
|
|
adf2951518 | ||
|
|
4cd1a923b9 | ||
|
|
6eb8c2d270 | ||
|
|
50b14ca232 | ||
|
|
01c10910bc | ||
|
|
683aa2df24 | ||
|
|
ce3bb062dd | ||
|
|
1faba2376a | ||
|
|
cfabc24ac9 | ||
|
|
a75beafe1d | ||
|
|
1589d13f94 | ||
|
|
163a08057c | ||
|
|
35cd559791 | ||
|
|
8519bdc6be | ||
|
|
da351da0e3 | ||
|
|
fba3262eb9 | ||
|
|
b9d950aa9a | ||
|
|
328d5c088a | ||
|
|
fe3033ef0e | ||
|
|
026c42fc3c | ||
|
|
2d83759e49 | ||
|
|
568b241762 | ||
|
|
16c3f055ff | ||
|
|
e428d22e39 | ||
|
|
5bba155477 | ||
|
|
bc0153079a | ||
|
|
c27bec417c | ||
|
|
45e13dec0f | ||
|
|
2ebe366a38 | ||
|
|
2e3edffa1b | ||
|
|
291c9bce21 | ||
|
|
5cec99aaf6 | ||
|
|
a6a31ff1f7 | ||
|
|
b5e67a7ee6 | ||
|
|
4fc694b72d | ||
|
|
d47b4349a6 | ||
|
|
c5542b8b28 | ||
|
|
acbf109a23 | ||
|
|
7a28243aed | ||
|
|
1c6430c2f5 | ||
|
|
8e5c8e0148 | ||
|
|
e5ff79d23b | ||
|
|
b4b6962b66 | ||
|
|
f95a285c3f | ||
|
|
25b98cc8ab | ||
|
|
91cb6bee22 | ||
|
|
9fdc1462d5 | ||
|
|
b504bfa3ca | ||
|
|
f23de626fe | ||
|
|
2035b22945 | ||
|
|
3b8fe18288 | ||
|
|
8aa7b97764 | ||
|
|
ac31d70c95 | ||
|
|
d01640402c | ||
|
|
89fa720b26 | ||
|
|
b8376455d3 | ||
|
|
778f7a9d8d | ||
|
|
ea12a7e892 | ||
|
|
4a06040b70 | ||
|
|
80d78f5167 | ||
|
|
b9b7df82a1 | ||
|
|
336d51bb0a | ||
|
|
38618a58c9 | ||
|
|
d37b743d71 | ||
|
|
77dc5cff7b | ||
|
|
88d182e6c5 | ||
|
|
2e2f30b9df | ||
|
|
5ad603eba1 | ||
|
|
aedf61d97e | ||
|
|
2e77bdde72 | ||
|
|
2fb67e5cb5 | ||
|
|
19f30e814d | ||
|
|
c0867ca009 | ||
|
|
b8fb0faba9 | ||
|
|
0aee632a11 | ||
|
|
a49d3e5217 | ||
|
|
7fe7c9ef2a | ||
|
|
8fa61fa729 | ||
|
|
ffc7c2429c | ||
|
|
947a0d7393 | ||
|
|
89caa3ac6d | ||
|
|
0e5adc7a7c | ||
|
|
8b17779a49 | ||
|
|
6c0852dda1 | ||
|
|
a363b97bcb | ||
|
|
e8b211bd5f | ||
|
|
389af71c69 | ||
|
|
f927c87804 | ||
|
|
69fbae732d | ||
|
|
49459d0fd5 | ||
|
|
8600da6132 | ||
|
|
79c20c20ce | ||
|
|
a37cdb880c | ||
|
|
29603ec34e | ||
|
|
ff9892579d | ||
|
|
73708f6583 | ||
|
|
4d4696e4bd | ||
|
|
5beb289dc8 | ||
|
|
6a9b3b5433 | ||
|
|
a5f437cf40 | ||
|
|
464c44689a | ||
|
|
709f7c8405 | ||
|
|
a2ee2da080 | ||
|
|
b74430bfce | ||
|
|
b682477fd4 | ||
|
|
b3745da37e | ||
|
|
046a93babc | ||
|
|
d007267e90 | ||
|
|
67bfd4b188 | ||
|
|
2bf967ae3e | ||
|
|
67b1d10200 | ||
|
|
e381583f07 | ||
|
|
ecca887d3f | ||
|
|
890df6291d | ||
|
|
79e7d8b431 | ||
|
|
2c31ce6ace | ||
|
|
a7042fc866 | ||
|
|
23f1b902e5 | ||
|
|
f18c31f9c9 | ||
|
|
4584142974 | ||
|
|
9529062888 | ||
|
|
5c7fb27a42 | ||
|
|
8f7953389a | ||
|
|
afcca4036c | ||
|
|
cf44dca835 | ||
|
|
60be5ca073 | ||
|
|
42bf788749 | ||
|
|
2ac34161ea | ||
|
|
8eee277b98 | ||
|
|
d4b8975a86 | ||
|
|
ff0ea61aad | ||
|
|
ce649af7e3 | ||
|
|
1395b526b2 | ||
|
|
2fd40f22bf | ||
|
|
0913a510d2 | ||
|
|
c80186ceca | ||
|
|
b89295dec7 | ||
|
|
08c3a12b9e | ||
|
|
e99e753e96 | ||
|
|
47f69b7b2b | ||
|
|
408bec38d4 | ||
|
|
de9171ceb5 | ||
|
|
555fe133a0 | ||
|
|
28e7d2301d | ||
|
|
e9b52d4556 | ||
|
|
7cdbe94131 | ||
|
|
ee26296db2 | ||
|
|
743ba622dd | ||
|
|
4482235f80 | ||
|
|
6d81b467c2 | ||
|
|
89c8ff0281 | ||
|
|
6fd19e578e | ||
|
|
6dd0d056f4 | ||
|
|
a3f0f89512 | ||
|
|
8c0cdd51c2 | ||
|
|
21eed0fdf3 | ||
|
|
d063a4a02e | ||
|
|
8a9ca13855 | ||
|
|
f2f96b1737 | ||
|
|
7357444a84 | ||
|
|
0a704c61ba | ||
|
|
86ec2bfa8d | ||
|
|
d1ffbfb046 | ||
|
|
15107fac43 | ||
|
|
664dfa2f62 | ||
|
|
91378528ab | ||
|
|
67579a973c | ||
|
|
bb2ae08dd8 | ||
|
|
d8cbe8df22 | ||
|
|
c069b097ac | ||
|
|
9a65629fe1 | ||
|
|
c43a0694ed | ||
|
|
87af9d2bf9 | ||
|
|
534eebd513 | ||
|
|
a3e9ea0a66 | ||
|
|
6b5db0c503 | ||
|
|
7284dc092f | ||
|
|
ba0f9bba88 | ||
|
|
c1ca14ffd6 | ||
|
|
584e5e6aeb | ||
|
|
5199786617 | ||
|
|
1b69afdc8b | ||
|
|
5f56e1cc83 | ||
|
|
b0df436103 | ||
|
|
252623ff45 | ||
|
|
a4b15cc776 | ||
|
|
751d3431d9 | ||
|
|
23329a8f71 | ||
|
|
7d42a94add | ||
|
|
a2557a37b2 | ||
|
|
c8798d22bd | ||
|
|
991d893615 | ||
|
|
839f3190a0 | ||
|
|
444b8187f6 | ||
|
|
6842b88608 | ||
|
|
16b1a2a9dc | ||
|
|
6cff8dbcd9 | ||
|
|
2cb2fcd61c | ||
|
|
e922ec6de6 | ||
|
|
15fcaa5fde | ||
|
|
b5a9129c90 | ||
|
|
71b056fd5d | ||
|
|
3358309208 | ||
|
|
921997412b | ||
|
|
b8108379d7 | ||
|
|
a0d8349dda | ||
|
|
c7c650ef9b | ||
|
|
9508bac66d | ||
|
|
0788205d88 | ||
|
|
e818c916f1 | ||
|
|
80891b26a3 | ||
|
|
c5f703a30b | ||
|
|
07189adb6d | ||
|
|
64c8725594 | ||
|
|
b57486e027 | ||
|
|
5e0140e877 | ||
|
|
d3a1102f33 | ||
|
|
b5888d4b0f | ||
|
|
cda97a67bf | ||
|
|
096c35163c | ||
|
|
c7722ef0f8 | ||
|
|
181b5d5641 | ||
|
|
d651672f16 | ||
|
|
25568d690f | ||
|
|
062217b9a9 | ||
|
|
c157638b00 | ||
|
|
06e2be7cd0 | ||
|
|
b5ceaca56c | ||
|
|
329cfb998c | ||
|
|
b13bc88382 | ||
|
|
1ccb31fde6 | ||
|
|
1a0246734b | ||
|
|
65ad6dcde4 | ||
|
|
d17320661b | ||
|
|
ebddeb7597 | ||
|
|
89bfa3eda4 | ||
|
|
cff7444f0a | ||
|
|
a279b4592b | ||
|
|
40b61f789e | ||
|
|
82bd2cbf4c | ||
|
|
d4d479ca7b | ||
|
|
0933014721 | ||
|
|
fc8477a265 | ||
|
|
8519f3432f | ||
|
|
cda099923d | ||
|
|
454a96e3b7 | ||
|
|
7c6af8cab8 | ||
|
|
397abc4190 | ||
|
|
680ccf0f2d | ||
|
|
e4c0b956e8 | ||
|
|
135dfa983a | ||
|
|
1844c93b14 | ||
|
|
91561aaef1 | ||
|
|
1d1443cb1a | ||
|
|
9baadbe00e | ||
|
|
edf209a78c | ||
|
|
eb1a95acfd | ||
|
|
bee28f59f5 | ||
|
|
f3a6439117 | ||
|
|
fd01b3287b | ||
|
|
4d94ce5ac8 | ||
|
|
a0f5bd4e44 | ||
|
|
84a101a745 | ||
|
|
4a4b0062f8 | ||
|
|
aee4575404 | ||
|
|
7bec37fe5b | ||
|
|
834205ac04 | ||
|
|
37a7e5466b | ||
|
|
be168f4b78 | ||
|
|
99af756462 | ||
|
|
7f87b66763 | ||
|
|
d68a188884 | ||
|
|
8d19530dbb | ||
|
|
809087f0c8 | ||
|
|
057e25657e | ||
|
|
05c8569587 | ||
|
|
6432ff4d87 | ||
|
|
c34e4b34f4 | ||
|
|
2fc92344bc | ||
|
|
79c1749e81 | ||
|
|
74caaf1c36 | ||
|
|
c6521a189c | ||
|
|
530cd440d8 | ||
|
|
117069efd4 | ||
|
|
b4e7aecafe | ||
|
|
448b2b1b2d | ||
|
|
ce7c02b1b1 | ||
|
|
45613102e9 | ||
|
|
3776e6b2c2 | ||
|
|
838a8a3dd3 | ||
|
|
f3227ebe89 | ||
|
|
411a706e24 | ||
|
|
add10e3fc4 | ||
|
|
56eedbaf06 | ||
|
|
2ab8692165 | ||
|
|
28aa4ebe26 | ||
|
|
d5a143ce0a | ||
|
|
6a9058665e | ||
|
|
ef160a3fd0 | ||
|
|
1d9865c681 | ||
|
|
a003249bc6 | ||
|
|
2e987d7744 | ||
|
|
f280f02493 | ||
|
|
1cb8697ad1 | ||
|
|
bae1d521ec | ||
|
|
a300efe718 | ||
|
|
22aae443b9 | ||
|
|
037031bae6 | ||
|
|
fc13314a10 | ||
|
|
f0a5e74bab | ||
|
|
cfeb3e51b6 | ||
|
|
6afb81b41c | ||
|
|
91199ccb6c | ||
|
|
e034066a09 | ||
|
|
9ac053ce28 | ||
|
|
5946cd62fd | ||
|
|
6b3e60ebda | ||
|
|
1adead75ec | ||
|
|
73aa96adbf | ||
|
|
d193264b40 | ||
|
|
65193feefb | ||
|
|
78e758bbbb | ||
|
|
6ea9dc4113 | ||
|
|
f1e73e4d2f | ||
|
|
9d87ea3ee0 | ||
|
|
1c39ef9958 | ||
|
|
04d34e4de1 | ||
|
|
912e4c6001 | ||
|
|
54ed63d76e | ||
|
|
04ef6d2187 | ||
|
|
2d3eb3dc97 | ||
|
|
24a12cb57d | ||
|
|
e383bb979e | ||
|
|
5c06c96c31 | ||
|
|
2a46b2893a | ||
|
|
78de80e89a | ||
|
|
49f8aa209e | ||
|
|
8d26195d4d | ||
|
|
4dfc90a462 | ||
|
|
20747046bd | ||
|
|
124af9ad61 | ||
|
|
24527b8a59 | ||
|
|
9f4bf49945 | ||
|
|
7c4986546b | ||
|
|
84a2de8dec | ||
|
|
8ba39f2976 | ||
|
|
a8aca346a2 | ||
|
|
eec9f7dd86 | ||
|
|
b34d2c0d8d | ||
|
|
55dbbf5dad | ||
|
|
a068a86210 | ||
|
|
d3d0f92b83 | ||
|
|
9a2f460d17 | ||
|
|
00f7b1b9a6 | ||
|
|
0232930c8c | ||
|
|
a05009f387 | ||
|
|
1ac3d6e674 | ||
|
|
84bfa01f0f | ||
|
|
c679e7412f | ||
|
|
8b954e93ff | ||
|
|
11a6b81af2 | ||
|
|
35f1c1a4ed | ||
|
|
3e4b36d0e1 | ||
|
|
e9a11836bb | ||
|
|
c7100ca6e7 | ||
|
|
45a1b19426 | ||
|
|
e4c76ed57e | ||
|
|
b2d011bfb6 | ||
|
|
e1c3e701a8 | ||
|
|
a32f106d89 | ||
|
|
12645a3942 | ||
|
|
9a3300bc3f | ||
|
|
5dfc439f32 | ||
|
|
54f34f9ff1 | ||
|
|
0bc0814235 | ||
|
|
dccb44ad35 | ||
|
|
2c81fdc849 | ||
|
|
c5726ea7a9 | ||
|
|
a5d4a999fa | ||
|
|
d1e9849dfa | ||
|
|
f204a664c0 | ||
|
|
86043d6f87 | ||
|
|
66036bf6a3 | ||
|
|
9e0970016f | ||
|
|
c4336e8c6c | ||
|
|
228e4e5564 | ||
|
|
4794f058cf | ||
|
|
041310858e | ||
|
|
5a494f1bbf | ||
|
|
9067e0b5ce | ||
|
|
311accf5eb | ||
|
|
ad61527aff | ||
|
|
661f6a1268 | ||
|
|
e75f24ff76 | ||
|
|
72a1d09920 | ||
|
|
03be75de97 | ||
|
|
ec77e3988a | ||
|
|
ccadddc9f5 | ||
|
|
9f875b317e | ||
|
|
eb06c855b5 | ||
|
|
26a242252d | ||
|
|
87981b9e37 | ||
|
|
c9aae953f0 | ||
|
|
31cbe9beed | ||
|
|
29ecee103b | ||
|
|
eda2e7b798 | ||
|
|
594528e224 | ||
|
|
c3572785df | ||
|
|
43a6e4c059 | ||
|
|
0800b05355 | ||
|
|
789255ed1e | ||
|
|
b4c0a9aa6d | ||
|
|
6fc1871d63 | ||
|
|
2a29eb3d2d | ||
|
|
81e3a246de | ||
|
|
629eb3a3d7 | ||
|
|
fbd8279072 | ||
|
|
cf24c2aa83 | ||
|
|
a3aa9cf16f | ||
|
|
c2b8a82f80 | ||
|
|
b297b3a9de | ||
|
|
9a2ea3696e | ||
|
|
53deb75f8b | ||
|
|
f565bf1713 | ||
|
|
14db96ad56 | ||
|
|
a0fc494c8d | ||
|
|
66290dcc0b | ||
|
|
f10fa85cb7 | ||
|
|
ae42201eb8 | ||
|
|
c9a57881d2 | ||
|
|
db3114f372 | ||
|
|
9255047c9c | ||
|
|
8db4ef625b | ||
|
|
5594a32678 | ||
|
|
f40c4ae90d | ||
|
|
8672527898 | ||
|
|
8d66b1732f | ||
|
|
bbd9db5e53 | ||
|
|
6d5a451f09 | ||
|
|
398c060d4f | ||
|
|
59543bd226 | ||
|
|
0d3d2954a0 | ||
|
|
3c7f68e231 | ||
|
|
0f390f131b | ||
|
|
d78c9eb624 | ||
|
|
94d401b0b2 | ||
|
|
f24c43c396 | ||
|
|
605ed8b8a2 | ||
|
|
de4c7baa4d | ||
|
|
83a6c88345 | ||
|
|
0560039149 | ||
|
|
bf7194ec2b | ||
|
|
6e1204897a | ||
|
|
e58f42e0b9 | ||
|
|
4b1ca0b0f2 | ||
|
|
21fe9724d5 | ||
|
|
7f17342db3 | ||
|
|
2a54d86f7b | ||
|
|
1414918b17 | ||
|
|
8facb48485 | ||
|
|
ea655cb10a | ||
|
|
2d46bbd94f | ||
|
|
7e8812bc07 | ||
|
|
30f8b1d876 | ||
|
|
7c6b6cc6b7 | ||
|
|
2b89bfb934 | ||
|
|
abdb76f9a5 | ||
|
|
2efb0f4933 | ||
|
|
523bb28c54 | ||
|
|
7c913a1672 | ||
|
|
04debcf761 | ||
|
|
01d6b73b7c | ||
|
|
ba68679bee | ||
|
|
71822e6469 | ||
|
|
09302f4cb0 | ||
|
|
d234f822b8 | ||
|
|
39570992ee | ||
|
|
c60d0934ca | ||
|
|
73c91489de | ||
|
|
5845a45d5b | ||
|
|
f09e08bb8f | ||
|
|
4b1709a418 | ||
|
|
5429f7af4a | ||
|
|
c9accc9abe | ||
|
|
331111c3d3 | ||
|
|
d93891f6c1 |
@@ -1,7 +1,6 @@
|
||||
name: "Docker"
|
||||
|
||||
on:
|
||||
|
||||
# Always have a base image ready to go - this is a nightly build
|
||||
schedule:
|
||||
- cron: 0 3 * * *
|
||||
@@ -26,7 +25,6 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
|
||||
# Dockerfiles to build, a matrix supports future expanded builds
|
||||
container: [["config/docker/Dockerfile.base", "ghcr.io/mfem/mfem-ubuntu-base"],
|
||||
["config/docker/Dockerfile", "ghcr.io/mfem/mfem-ubuntu"]]
|
||||
@@ -34,15 +32,20 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
name: Build
|
||||
steps:
|
||||
- name: Run Actions Cleaner
|
||||
uses: easimon/maximize-build-space@v8
|
||||
with:
|
||||
overprovision-lvm: 'true'
|
||||
remove-dotnet: 'true'
|
||||
remove-android: 'true'
|
||||
remove-haskell: 'true'
|
||||
remove-codeql: 'true'
|
||||
remove-docker-images: 'true'
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Make Space For Build
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf /opt/ghc
|
||||
|
||||
# It's easier to reference named variables than indexes of the matrix
|
||||
# It's easier to reference named variables than indexes of the matrix
|
||||
- name: Set Environment
|
||||
env:
|
||||
dockerfile: ${{ matrix.container[0] }}
|
||||
@@ -65,13 +65,16 @@ jobs:
|
||||
# - Add a new combination.
|
||||
# 'build-system: cmake' and 'hypre-target: int64'
|
||||
#
|
||||
# note: we will gather coverage info for any non-debug run except the
|
||||
# Note: we will gather coverage info for any non-debug run except the
|
||||
# CMake build.
|
||||
include:
|
||||
- target: dbg
|
||||
codecov: NO
|
||||
- target: opt
|
||||
codecov: YES
|
||||
- os: ubuntu-latest
|
||||
target: dbg
|
||||
config-opts: 'CPPFLAGS+=-Og'
|
||||
- os: windows-latest
|
||||
codecov: NO
|
||||
- os: windows-latest
|
||||
@@ -98,181 +101,189 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
# This external action allows to interrupt a workflow already running on
|
||||
# the same branch to save resource
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
# This external action allows to interrupt a workflow already running on
|
||||
# the same branch to save resources.
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
# Checkout MFEM in "mfem" subdirectory. Final path:
|
||||
# /home/runner/work/mfem/mfem/mfem
|
||||
# Note: Done now to access "install-hypre" and "install-metis" actions.
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: ${{ env.MFEM_TOP_DIR }}
|
||||
# Fetch the complete history for codecov to access commits ID
|
||||
fetch-depth: 0
|
||||
# Fix 'No space left on device' errors for Ubuntu builds.
|
||||
- name: Run Actions Cleaner
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
uses: easimon/maximize-build-space@v8
|
||||
with:
|
||||
overprovision-lvm: 'true'
|
||||
remove-android: 'true'
|
||||
|
||||
# Only get MPI if defined for the job.
|
||||
# TODO: It would be nice to have only one step, e.g. with a dedicated
|
||||
# action, but I (@adrienbernede) don't see how at the moment.
|
||||
- name: get MPI (Linux)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install mpich libmpich-dev
|
||||
# Checkout MFEM in "mfem" subdirectory. Final path:
|
||||
# /home/runner/work/mfem/mfem/mfem
|
||||
# Note: Done now to access "install-hypre" and "install-metis" actions.
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: ${{ env.MFEM_TOP_DIR }}
|
||||
# Fetch the complete history for codecov to access commits ID
|
||||
fetch-depth: 0
|
||||
|
||||
- name: get lcov (Linux)
|
||||
if: matrix.codecov == 'YES' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install lcov
|
||||
# Only get MPI if defined for the job.
|
||||
# TODO: It would be nice to have only one step, e.g. with a dedicated
|
||||
# action, but I (@adrienbernede) don't see how at the moment.
|
||||
- name: get MPI (Linux)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install mpich libmpich-dev
|
||||
|
||||
# Keep the following section in case we need it again in the future,
|
||||
# see: https://github.com/mfem/mfem/pull/3385#discussion_r1058013032
|
||||
# - name: Set up Homebrew
|
||||
# if: ( matrix.mpi == 'par' || matrix.codecov == 'YES' ) && matrix.os == 'macos-latest'
|
||||
# uses: Homebrew/actions/setup-homebrew@master
|
||||
- name: get lcov (Linux)
|
||||
if: matrix.codecov == 'YES' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get install lcov
|
||||
|
||||
- name: get MPI (MacOS)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'macos-latest'
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install openmpi
|
||||
# Keep the following section in case we need it again in the future,
|
||||
# see: https://github.com/mfem/mfem/pull/3385#discussion_r1058013032
|
||||
# - name: Set up Homebrew
|
||||
# if: ( matrix.mpi == 'par' || matrix.codecov == 'YES' ) && matrix.os == 'macos-latest'
|
||||
# uses: Homebrew/actions/setup-homebrew@master
|
||||
|
||||
- name: get lcov (MacOS)
|
||||
if: matrix.codecov == 'YES' && matrix.os == 'macos-latest'
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install lcov
|
||||
- name: get MPI (MacOS)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'macos-latest'
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install openmpi
|
||||
|
||||
- name: get MPI (Windows)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
|
||||
uses: mpi4py/setup-mpi@v1.1.4
|
||||
- name: get lcov (MacOS)
|
||||
if: matrix.codecov == 'YES' && matrix.os == 'macos-latest'
|
||||
run: |
|
||||
export HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||
brew install lcov
|
||||
|
||||
# Get Hypre through cache, or build it.
|
||||
# Install will only run on cache miss.
|
||||
- name: cache hypre
|
||||
id: hypre-cache
|
||||
if: matrix.mpi == 'par'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-${{ matrix.hypre-target }}-v2.2
|
||||
- name: get MPI (Windows)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
|
||||
uses: mpi4py/setup-mpi@v1.1.4
|
||||
|
||||
- name: get hypre
|
||||
if: matrix.mpi == 'par' && steps.hypre-cache.outputs.cache-hit != 'true' && matrix.os != 'windows-latest'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: ${{ matrix.hypre-target }}
|
||||
build-system: make
|
||||
# Get Hypre through cache, or build it.
|
||||
# Install will only run on cache miss.
|
||||
- name: cache hypre
|
||||
id: hypre-cache
|
||||
if: matrix.mpi == 'par'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-${{ matrix.hypre-target }}-v2.2
|
||||
|
||||
- name: get hypre (Windows)
|
||||
if: matrix.mpi == 'par' && steps.hypre-cache.outputs.cache-hit != 'true' && matrix.os == 'windows-latest'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: ${{ matrix.hypre-target }}
|
||||
build-system: cmake
|
||||
- name: get hypre
|
||||
if: matrix.mpi == 'par' && steps.hypre-cache.outputs.cache-hit != 'true' && matrix.os != 'windows-latest'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: ${{ matrix.hypre-target }}
|
||||
build-system: make
|
||||
|
||||
# Get Metis through cache, or build it.
|
||||
# Install will only run on cache miss.
|
||||
- name: cache metis
|
||||
id: metis-cache
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
|
||||
- name: get hypre (Windows)
|
||||
if: matrix.mpi == 'par' && steps.hypre-cache.outputs.cache-hit != 'true' && matrix.os == 'windows-latest'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: ${{ matrix.hypre-target }}
|
||||
build-system: cmake
|
||||
|
||||
- name: install metis
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest' && steps.metis-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-metis@v2.4
|
||||
with:
|
||||
archive: ${{ env.METIS_ARCHIVE }}
|
||||
dir: ${{ env.METIS_TOP_DIR }}
|
||||
# Get Metis through cache, or build it.
|
||||
# Install will only run on cache miss.
|
||||
- name: cache metis
|
||||
id: metis-cache
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
|
||||
|
||||
- name: cache vcpkg (Windows)
|
||||
id: vcpkg-cache
|
||||
if: matrix.os == 'windows-latest'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vcpkg_cache
|
||||
key: ${{ runner.os }}-${{ matrix.mpi }}-vcpkg-v1
|
||||
- name: install metis
|
||||
if: matrix.mpi == 'par' && matrix.os != 'windows-latest' && steps.metis-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-metis@v2.4
|
||||
with:
|
||||
archive: ${{ env.METIS_ARCHIVE }}
|
||||
dir: ${{ env.METIS_TOP_DIR }}
|
||||
|
||||
- name: prepare vcpkg binary cache location (Windows)
|
||||
if: matrix.os == 'windows-latest' && steps.vcpkg-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
mkdir -p vcpkg_cache
|
||||
- name: cache vcpkg (Windows)
|
||||
id: vcpkg-cache
|
||||
if: matrix.os == 'windows-latest'
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: vcpkg_cache
|
||||
key: ${{ runner.os }}-${{ matrix.mpi }}-vcpkg-v1
|
||||
|
||||
- name: install metis (Windows)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
|
||||
env:
|
||||
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache
|
||||
run: |
|
||||
vcpkg install metis-mfem --triplet=x64-windows-static --overlay-ports=${{ env.MFEM_TOP_DIR }}/config/vcpkg/ports
|
||||
- name: prepare vcpkg binary cache location (Windows)
|
||||
if: matrix.os == 'windows-latest' && steps.vcpkg-cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
mkdir -p vcpkg_cache
|
||||
|
||||
# MFEM build and test
|
||||
- name: build
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
env:
|
||||
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
target: ${{ matrix.target }}
|
||||
codecov: ${{ matrix.codecov }}
|
||||
mpi: ${{ matrix.mpi }}
|
||||
build-system: ${{ matrix.build-system }}
|
||||
hypre-dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
metis-dir: ${{ env.METIS_TOP_DIR }}
|
||||
mfem-dir: ${{ env.MFEM_TOP_DIR }}
|
||||
config-options: ${{ matrix.config-opts }}
|
||||
library-only: ${{ matrix.target == 'dbg' }}
|
||||
- name: install metis (Windows)
|
||||
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
|
||||
env:
|
||||
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache
|
||||
run: |
|
||||
vcpkg install metis-mfem --triplet=x64-windows-static --overlay-ports=${{ env.MFEM_TOP_DIR }}/config/vcpkg/ports
|
||||
|
||||
# Run checks (and only checks) on debug targets
|
||||
- name: checks
|
||||
if: matrix.build-system == 'make' && matrix.target == 'dbg'
|
||||
run: |
|
||||
cd ${{ env.MFEM_TOP_DIR }} && make check
|
||||
# MFEM build and test
|
||||
- name: build
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
env:
|
||||
VCPKG_DEFAULT_BINARY_CACHE: ${{ github.workspace }}/vcpkg_cache
|
||||
with:
|
||||
os: ${{ matrix.os }}
|
||||
target: ${{ matrix.target }}
|
||||
codecov: ${{ matrix.codecov }}
|
||||
mpi: ${{ matrix.mpi }}
|
||||
build-system: ${{ matrix.build-system }}
|
||||
hypre-dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
metis-dir: ${{ env.METIS_TOP_DIR }}
|
||||
mfem-dir: ${{ env.MFEM_TOP_DIR }}
|
||||
config-options: ${{ matrix.config-opts }}
|
||||
library-only: ${{ matrix.target == 'dbg' && matrix.os != 'ubuntu-latest' }}
|
||||
|
||||
# Note: 'tests' include the unit tests
|
||||
- name: tests
|
||||
if: matrix.build-system == 'make' && matrix.target == 'opt'
|
||||
run: |
|
||||
cd ${{ env.MFEM_TOP_DIR }} && make test
|
||||
# Run checks (and only checks) on debug targets
|
||||
- name: checks
|
||||
if: matrix.build-system == 'make' && matrix.target == 'dbg'
|
||||
run: |
|
||||
cd ${{ env.MFEM_TOP_DIR }} && make check
|
||||
|
||||
- name: cmake checks
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'dbg'
|
||||
run: |
|
||||
CTEST_CONFIG="Debug"
|
||||
cd ${{ env.MFEM_TOP_DIR }} && cmake --build build --target check --config ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
# Note: 'tests' include the unit tests
|
||||
- name: tests
|
||||
if: matrix.build-system == 'make' && (matrix.target == 'opt' || matrix.os == 'ubuntu-latest')
|
||||
run: |
|
||||
cd ${{ env.MFEM_TOP_DIR }} && make test
|
||||
|
||||
- name: cmake unit tests (Ubuntu)
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
CTEST_CONFIG="Release"
|
||||
[[ ${{ matrix.target }} == 'dbg' ]] && CTEST_CONFIG="Debug"
|
||||
cd ${{ env.MFEM_TOP_DIR }}/build/tests/unit && ctest --output-on-failure -C ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
- name: cmake checks
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'dbg'
|
||||
run: |
|
||||
CTEST_CONFIG="Debug"
|
||||
cd ${{ env.MFEM_TOP_DIR }} && cmake --build build --target check --config ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
|
||||
- name: cmake tests
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os != 'ubuntu-latest'
|
||||
run: |
|
||||
CTEST_CONFIG="Release"
|
||||
cd ${{ env.MFEM_TOP_DIR }}/build && \
|
||||
ctest --output-on-failure -C ${CTEST_CONFIG} || \
|
||||
ctest --rerun-failed --output-on-failure -C ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
- name: cmake unit tests (Ubuntu)
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
CTEST_CONFIG="Release"
|
||||
[[ ${{ matrix.target }} == 'dbg' ]] && CTEST_CONFIG="Debug"
|
||||
cd ${{ env.MFEM_TOP_DIR }}/build/tests/unit && ctest --output-on-failure -C ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
|
||||
# Code coverage (process and upload reports)
|
||||
- name: codecov
|
||||
if: matrix.codecov == 'YES'
|
||||
uses: mfem/github-actions/upload-coverage@v2.4
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{ matrix.build-system }}-${{ matrix.target }}-${{ matrix.mpi }}-${{ matrix.hypre-target }}
|
||||
project_dir: ${{ env.MFEM_TOP_DIR }}
|
||||
directories: "fem general linalg mesh"
|
||||
- name: cmake tests
|
||||
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os != 'ubuntu-latest'
|
||||
run: |
|
||||
CTEST_CONFIG="Release"
|
||||
cd ${{ env.MFEM_TOP_DIR }}/build && \
|
||||
ctest --output-on-failure -C ${CTEST_CONFIG} || \
|
||||
ctest --rerun-failed --output-on-failure -C ${CTEST_CONFIG}
|
||||
shell: bash
|
||||
|
||||
# Code coverage (process and upload reports)
|
||||
- name: codecov
|
||||
if: matrix.codecov == 'YES'
|
||||
uses: mfem/github-actions/upload-coverage@v2.4
|
||||
with:
|
||||
name: ${{ matrix.os }}-${{ matrix.build-system }}-${{ matrix.target }}-${{ matrix.mpi }}-${{ matrix.hypre-target }}
|
||||
project_dir: ${{ env.MFEM_TOP_DIR }}
|
||||
directories: "fem general linalg mesh"
|
||||
|
||||
@@ -13,10 +13,10 @@ name: "Static Analysis"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master", "next"]
|
||||
branches: ["master", "next"]
|
||||
pull_request:
|
||||
# The branches below must be a subset of the branches above
|
||||
branches: [ "master" ]
|
||||
branches: ["master"]
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
@@ -35,36 +35,35 @@ jobs:
|
||||
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
|
||||
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
# - run: |
|
||||
# echo "Run, Build Application using script"
|
||||
# ./location_of_script_within_repo/buildscript.sh
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
@@ -34,67 +34,67 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: checkout MFEM
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: mfem
|
||||
- name: checkout MFEM
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: mfem
|
||||
|
||||
- name: Get MPI (Linux)
|
||||
run: |
|
||||
sudo apt-get install mpich libmpich-dev
|
||||
- name: Get MPI (Linux)
|
||||
run: |
|
||||
sudo apt-get install mpich libmpich-dev
|
||||
|
||||
- name: Cache Hypre Install
|
||||
id: hypre-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-v2.2
|
||||
- name: Cache Hypre Install
|
||||
id: hypre-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.HYPRE_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-v2.2
|
||||
|
||||
- name: Get Hypre
|
||||
if: steps.hypre-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: int32
|
||||
- name: Get Hypre
|
||||
if: steps.hypre-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-hypre@v2.4
|
||||
with:
|
||||
archive: ${{ env.HYPRE_ARCHIVE }}
|
||||
dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
target: int32
|
||||
|
||||
- name: Cache Metis Install
|
||||
id: metis-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
|
||||
- name: Cache Metis Install
|
||||
id: metis-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.METIS_TOP_DIR }}
|
||||
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
|
||||
|
||||
- name: Install Metis
|
||||
if: steps.metis-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-metis@v2.4
|
||||
with:
|
||||
archive: ${{ env.METIS_ARCHIVE }}
|
||||
dir: ${{ env.METIS_TOP_DIR }}
|
||||
- name: Install Metis
|
||||
if: steps.metis-cache.outputs.cache-hit != 'true'
|
||||
uses: mfem/github-actions/build-metis@v2.4
|
||||
with:
|
||||
archive: ${{ env.METIS_ARCHIVE }}
|
||||
dir: ${{ env.METIS_TOP_DIR }}
|
||||
|
||||
# MFEM build and test
|
||||
- name: build-mfem
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
with:
|
||||
os: ${{ runner.os }}
|
||||
target: opt
|
||||
codecov: NO
|
||||
mpi: par
|
||||
build-system: make
|
||||
hypre-dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
metis-dir: ${{ env.METIS_TOP_DIR }}
|
||||
mfem-dir: mfem
|
||||
# MFEM build and test
|
||||
- name: build-mfem
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
with:
|
||||
os: ${{ runner.os }}
|
||||
target: opt
|
||||
codecov: NO
|
||||
mpi: par
|
||||
build-system: make
|
||||
hypre-dir: ${{ env.HYPRE_TOP_DIR }}
|
||||
metis-dir: ${{ env.METIS_TOP_DIR }}
|
||||
mfem-dir: mfem
|
||||
|
||||
- name: test (no clean)
|
||||
run: |
|
||||
cd mfem && make test-noclean
|
||||
- name: test (no clean)
|
||||
run: |
|
||||
cd mfem && make test-noclean
|
||||
|
||||
- name: gitignore
|
||||
run: |
|
||||
cd mfem/tests/scripts
|
||||
./runtest gitignore
|
||||
- name: gitignore
|
||||
run: |
|
||||
cd mfem/tests/scripts
|
||||
./runtest gitignore
|
||||
|
||||
@@ -27,44 +27,44 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: MFEM Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: mfem
|
||||
- name: MFEM Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: mfem
|
||||
|
||||
- name: MFEM Build
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
with:
|
||||
os: ${{ runner.os }}
|
||||
target: opt
|
||||
mpi: seq
|
||||
hypre-dir: unused-hypre-dir
|
||||
metis-dir: unused-metis-dir
|
||||
mfem-dir: mfem
|
||||
build-system: make
|
||||
library-only: false
|
||||
config-options:
|
||||
CXX="clang++-14"
|
||||
CXXFLAGS="-g -O1 -std=c++11
|
||||
-fsanitize=address
|
||||
-fno-omit-frame-pointer
|
||||
-fsanitize-address-use-after-scope"
|
||||
- name: MFEM Build
|
||||
uses: mfem/github-actions/build-mfem@v2.4
|
||||
with:
|
||||
os: ${{ runner.os }}
|
||||
target: opt
|
||||
mpi: seq
|
||||
hypre-dir: unused-hypre-dir
|
||||
metis-dir: unused-metis-dir
|
||||
mfem-dir: mfem
|
||||
build-system: make
|
||||
library-only: false
|
||||
config-options:
|
||||
CXX="clang++-14"
|
||||
CXXFLAGS="-g -O1 -std=c++11
|
||||
-fsanitize=address
|
||||
-fno-omit-frame-pointer
|
||||
-fsanitize-address-use-after-scope"
|
||||
|
||||
- name: MFEM Info
|
||||
working-directory: mfem
|
||||
run: make info
|
||||
- name: MFEM Info
|
||||
working-directory: mfem
|
||||
run: make info
|
||||
|
||||
- name: MFEM Sanitize
|
||||
working-directory: mfem
|
||||
run:
|
||||
ASAN_OPTIONS="detect_leaks=1,
|
||||
strict_init_order=1,
|
||||
strict_string_checks=1,
|
||||
check_initialization_order=1,
|
||||
detect_stack_use_after_return=1"
|
||||
make test
|
||||
- name: MFEM Sanitize
|
||||
working-directory: mfem
|
||||
run:
|
||||
ASAN_OPTIONS="detect_leaks=1,
|
||||
strict_init_order=1,
|
||||
strict_string_checks=1,
|
||||
check_initialization_order=1,
|
||||
detect_stack_use_after_return=1"
|
||||
make test
|
||||
|
||||
@@ -33,49 +33,49 @@ jobs:
|
||||
(github.event_name == 'push' ||
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
- name: Cancel Previous Runs
|
||||
uses: styfle/cancel-workflow-action@0.11.0
|
||||
with:
|
||||
access_token: ${{ github.token }}
|
||||
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: copyright check
|
||||
id: copyright
|
||||
run: |
|
||||
./config/githooks/pre-push --copyright
|
||||
- name: copyright check
|
||||
id: copyright
|
||||
run: |
|
||||
./config/githooks/pre-push --copyright
|
||||
|
||||
continue-on-error: true
|
||||
continue-on-error: true
|
||||
|
||||
- name: license check
|
||||
id: license
|
||||
run: |
|
||||
./config/githooks/pre-push --license
|
||||
continue-on-error: true
|
||||
- name: license check
|
||||
id: license
|
||||
run: |
|
||||
./config/githooks/pre-push --license
|
||||
continue-on-error: true
|
||||
|
||||
- name: release check
|
||||
id: release
|
||||
run: |
|
||||
./config/githooks/pre-push --release
|
||||
continue-on-error: true
|
||||
- name: release check
|
||||
id: release
|
||||
run: |
|
||||
./config/githooks/pre-push --release
|
||||
continue-on-error: true
|
||||
|
||||
- name: wrap-up
|
||||
if: |
|
||||
steps.copyright.outcome != 'success' ||
|
||||
steps.license.outcome != 'success' ||
|
||||
steps.release.outcome != 'success'
|
||||
run: |
|
||||
if [[ "${{ steps.copyright.outcome }}" != "success" ]]; then
|
||||
echo "copyright check failed, unroll log for details"
|
||||
fi
|
||||
if [[ "${{ steps.license.outcome }}" != "success" ]]; then
|
||||
echo "license check failed, unroll log for details"
|
||||
fi
|
||||
if [[ "${{ steps.release.outcome }}" != "success" ]]; then
|
||||
echo "release check failed, unroll log for details"
|
||||
fi
|
||||
exit 1
|
||||
- name: wrap-up
|
||||
if: |
|
||||
steps.copyright.outcome != 'success' ||
|
||||
steps.license.outcome != 'success' ||
|
||||
steps.release.outcome != 'success'
|
||||
run: |
|
||||
if [[ "${{ steps.copyright.outcome }}" != "success" ]]; then
|
||||
echo "copyright check failed, unroll log for details"
|
||||
fi
|
||||
if [[ "${{ steps.license.outcome }}" != "success" ]]; then
|
||||
echo "license check failed, unroll log for details"
|
||||
fi
|
||||
if [[ "${{ steps.release.outcome }}" != "success" ]]; then
|
||||
echo "release check failed, unroll log for details"
|
||||
fi
|
||||
exit 1
|
||||
|
||||
code-style:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -83,16 +83,16 @@ jobs:
|
||||
(github.event_name == 'push' ||
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: get astyle
|
||||
run: |
|
||||
sudo apt-get install astyle
|
||||
- name: get astyle
|
||||
run: |
|
||||
sudo apt-get install astyle
|
||||
|
||||
- name: style check
|
||||
run: |
|
||||
./config/githooks/pre-push --style
|
||||
- name: style check
|
||||
run: |
|
||||
./config/githooks/pre-push --style
|
||||
|
||||
documentation:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -100,22 +100,22 @@ jobs:
|
||||
(github.event_name == 'push' ||
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: get doxygen and graphviz
|
||||
run: |
|
||||
sudo apt-get install doxygen graphviz
|
||||
- name: get doxygen and graphviz
|
||||
run: |
|
||||
sudo apt-get install doxygen graphviz
|
||||
|
||||
- name: update doxygen config file
|
||||
run: |
|
||||
cd doc
|
||||
doxygen -u CodeDocumentation.conf.in
|
||||
- name: update doxygen config file
|
||||
run: |
|
||||
cd doc
|
||||
doxygen -u CodeDocumentation.conf.in
|
||||
|
||||
- name: build documentation
|
||||
run: |
|
||||
cd tests/scripts
|
||||
./runtest documentation
|
||||
- name: build documentation
|
||||
run: |
|
||||
cd tests/scripts
|
||||
./runtest documentation
|
||||
|
||||
branch-history:
|
||||
if: |
|
||||
@@ -125,16 +125,16 @@ jobs:
|
||||
github.event.pull_request.head.repo.full_name != github.repository)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: checkout mfem
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: branch-history
|
||||
run: |
|
||||
# We override origin to make sure we point to the main repo.
|
||||
# This is to have consistent test results on PRs from forks.
|
||||
git remote remove origin
|
||||
git remote add origin https://github.com/mfem/mfem.git
|
||||
git checkout -b gh-actions-branch-history
|
||||
./config/githooks/pre-push --history
|
||||
- name: branch-history
|
||||
run: |
|
||||
# We override origin to make sure we point to the main repo.
|
||||
# This is to have consistent test results on PRs from forks.
|
||||
git remote remove origin
|
||||
git remote add origin https://github.com/mfem/mfem.git
|
||||
git checkout -b gh-actions-branch-history
|
||||
./config/githooks/pre-push --history
|
||||
|
||||
@@ -213,6 +213,7 @@ miniapps/meshing/twist
|
||||
miniapps/meshing/mesh-explorer
|
||||
miniapps/meshing/shaper
|
||||
miniapps/meshing/extruder
|
||||
miniapps/meshing/fit-node-position
|
||||
miniapps/meshing/trimmer
|
||||
miniapps/meshing/reflector
|
||||
miniapps/meshing/mesh-optimizer
|
||||
@@ -265,6 +266,7 @@ miniapps/navier/*_output
|
||||
miniapps/nurbs/nurbs_ex1
|
||||
miniapps/nurbs/nurbs_ex1p
|
||||
miniapps/nurbs/nurbs_ex11p
|
||||
miniapps/nurbs/nurbs_printfunc
|
||||
miniapps/nurbs/nurbs_patch_ex1
|
||||
miniapps/nurbs/nurbs_curveint
|
||||
miniapps/nurbs/refined.mesh
|
||||
@@ -300,6 +302,10 @@ miniapps/tools/plor-transfer
|
||||
miniapps/tools/get-values
|
||||
miniapps/tools/check-tmop-metric
|
||||
miniapps/tools/tmop-metric-magnitude
|
||||
miniapps/tools/nodal-transfer
|
||||
miniapps/tools/ParaView
|
||||
miniapps/tools/gridfunc_*
|
||||
miniapps/tools/mesh_*
|
||||
|
||||
miniapps/toys/automata
|
||||
miniapps/toys/life
|
||||
|
||||
@@ -8,111 +8,148 @@
|
||||
https://mfem.org
|
||||
|
||||
|
||||
Version 4.5.3 (development)
|
||||
Version 4.6.1 (development)
|
||||
===========================
|
||||
- Added curve interpolation method for NURBS.
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- Introduced support for higher order non conformal Nedelec elements on
|
||||
simplices in ParMesh.
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
- The ReadCubit Genesis mesh importer has been rewritten to improve readability.
|
||||
|
||||
|
||||
Version 4.6, released on September 27, 2023
|
||||
===========================================
|
||||
|
||||
- MFEM is now available in Homebrew and can be installed on a Mac with just
|
||||
"brew install mfem". See https://formulae.brew.sh/formula/mfem.
|
||||
|
||||
Meshing improvements
|
||||
--------------------
|
||||
- Added asymptotically-balanced TMOP compound metrics 90, 94, 328, 338. A new
|
||||
tool, tmop-metric-magnitude, can be used to track how metrics change under
|
||||
geometric perturbations. See miniapps/tools.
|
||||
|
||||
- Several NURBS meshing improvements:
|
||||
* Support for free connectivity of NURBS patches allowing for more complex
|
||||
patch configurations such as C-meshes.
|
||||
* New methods to set and get attributes on NURBS patches and patch boundaries.
|
||||
* The edge to knot map for NURBS meshes can be determined automatically. It is
|
||||
no longer needed to specify this in the NURBS mesh.
|
||||
* Added curve interpolation method for NURBS.
|
||||
* Added new small miniapp for printing of shape functions of a KnotVector
|
||||
* See miniapps/nurbs for example meshes and miniapps.
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- SubMesh and ParSubMesh have been extended to support the transfer of
|
||||
Nedelec and Raviart-Thomas finite element spaces.
|
||||
|
||||
- Added support for partial assembly on NURBS patches, and NURBS-patch sparse
|
||||
matrix assembly. Patch matrix assembly includes the option to use reduced
|
||||
approximate integration rules, computed by the newly implemented non-negative
|
||||
least-squares (NNLS) solver.
|
||||
|
||||
- Support for parallel transfer of H1 fields using the low-order refined (LOR)
|
||||
transfer operators in L2ProjectionGridTransfer
|
||||
|
||||
- Added KDTree class for 2D/3D set of points, which is then utilized in the new
|
||||
KDTreeNodalProjection class to project a function defined on an arbitrary set
|
||||
of points onto an MFEM grid function. This functionality is demonstrated in
|
||||
the nodal-transfer miniapp. The current implementation is serial only. Further
|
||||
extensions can include search in arbitrary dimensional spaces.
|
||||
|
||||
- Added support for p-refined meshes in GSLIB-FindPoints.
|
||||
|
||||
- Device kernels can now access device-specific DOF and quadrature limits using
|
||||
the DofQuadLimits structure, allowing increased limits when executing on CPU.
|
||||
The limits for the runtime selected device can be accessed in host code using
|
||||
DeviceDofQuadLimits::Get(). The global constants MAX_D1D and MAX_Q1D are no
|
||||
longer available.
|
||||
|
||||
- Face restriction operators for Nedelec and Raviart-Thomas finite element
|
||||
spaces are now supported through the ConformingFaceRestriction class.
|
||||
|
||||
- VectorFEBoundaryFluxLFIntegrator is now supported on device/GPU.
|
||||
|
||||
Linear and nonlinear solvers
|
||||
----------------------------
|
||||
- Updated the MUMPS interface to support multiple right-hand sides, block
|
||||
low-rank compression, builds using 64-bit integers, and other improvements.
|
||||
|
||||
- Added an interface to the MKL Pardiso sparse direct solver developed by Intel.
|
||||
The interface provides a serial (OpenMP shared memory) version of Pardiso for
|
||||
use with SparseMatrix. This complements the existing parallel (MPI distributed
|
||||
memory) version already available through the CPardiso MFEM integration.
|
||||
|
||||
- Added HIP support to the PETSc and SUNDIALS interfaces.
|
||||
|
||||
New and updated examples and miniapps
|
||||
-------------------------------------
|
||||
- Added a new example code, Example 36/36p, to demonstrate the solution of
|
||||
the obstacle problem with a new finite element method.
|
||||
|
||||
- Added a new miniapp, Mesh Quality, for evaluating mesh quality using size,
|
||||
skewness, and aspect-ratio computed from the Jacobian of the transformation.
|
||||
|
||||
- Added a new miniapp for interface and boundary fitting to implicit domains
|
||||
defined using level-set functions. See miniapps/meshing/pmesh-fitting.cpp
|
||||
- Added a new H(div) solver miniapp demonstrating the use of a matrix-free
|
||||
saddle-point solver methodology, suitable for high-order discretizations and
|
||||
for GPU acceleration. Examples illustrating the solution of Darcy and grad-div
|
||||
problems are included. See miniapps/hdiv-linear-solver.
|
||||
|
||||
- Added new Discontinuous Petrov-Galerkin (DPG) miniapp which includes serial
|
||||
and parallel examples for diffusion, convection-diffusion, acoustics and
|
||||
Maxwell equations. The miniapp includes new classes such as (Par)DPGWeakForm,
|
||||
(Par)ComplexDPGWeakForm and (Complex)BlockStaticCondensation. Three new
|
||||
integrators are added in support of DPG systems: TraceIntegrator,
|
||||
NormalTraceIntegrator and TangentTraceIntegrator.
|
||||
NormalTraceIntegrator and TangentTraceIntegrator. See miniapps/dpg.
|
||||
|
||||
- Added new SubMesh examples demonstrating source terms and boundary conditions
|
||||
transferred from SubMesh objects.
|
||||
- Added a new miniapp that implements the SPDE method for generating Gaussian
|
||||
random fields of Matern covariance. The resulting random field can be used,
|
||||
e.g., to model material uncertainties. See miniapps/spde.
|
||||
|
||||
- Added a miniapp for interpolation of NURBS.
|
||||
- Added a new parallel LOR transfer miniapp, plor-transfer, which mirrors the
|
||||
functionality of the serial LOR transfer miniapp. See miniapps/tools.
|
||||
|
||||
- Added a new H(div) solvers miniapp in miniapps/hdiv-linear-solver,
|
||||
demonstrating the use of a matrix-free saddle-point solver methodology,
|
||||
suitable for high-order discretizations and for GPU acceleration. Examples
|
||||
illustrating the solution of Darcy and grad-div problems are included.
|
||||
- New serial miniapp, nodal-transfer, demonstrating the use of KDTree to map a
|
||||
parallel grid function to a different parallel partitioning of the same mesh.
|
||||
|
||||
- Added 3 additional TMOP miniapps in miniapps/meshing:
|
||||
* Mesh-Quality evaluates quality using size, skewness, and aspect-ratio
|
||||
computed from the Jacobian of the transformation.
|
||||
* Mesh-Fitting can be used for interface and boundary fitting to implicit
|
||||
domains defined using level-set functions.
|
||||
* Fit-Node-Position fits selected mesh nodes to specified positions, while
|
||||
maintaining overall mesh quality.
|
||||
|
||||
- Added 4 new example codes:
|
||||
* Example 34/34p solves a simple magnetostatic problem where source terms and
|
||||
boundary conditions are transferred with SubMesh objects.
|
||||
* Example 35p implements H1, H(curl) and H(div) variants of a damped harmonic
|
||||
oscillator with field transfer using SubMesh objects.
|
||||
* Example 36/36p demonstrates the solution of the obstacle problem with a new
|
||||
finite element method (proximal Galerkin).
|
||||
* Example 37/37p demonstrates topology optimization with MFEM.
|
||||
|
||||
- Added a random refinement option to the mesh-explorer miniapp to assist users
|
||||
in experimenting with nonconforming meshes.
|
||||
|
||||
- Moved the distance solver methods from miniapps/shifted to miniapps/common.
|
||||
|
||||
- Added a new parallel LOR transfer miniapp, miniapps/tools/plor-transfer, which
|
||||
mirrors the functionality of the serial LOR transfer miniapp,
|
||||
miniapps/tools/lor-transfer
|
||||
|
||||
Meshing improvements
|
||||
--------------------
|
||||
- Added support for free connectivity of NURBS patches allowing for more complex
|
||||
patch configurations such as C-meshes. This is demonstrated in a new NURBS
|
||||
miniapp.
|
||||
|
||||
- The edge to knot map for NURBS meshes can be determined automatically. It is no
|
||||
longer needed to specify this in the NURBS mesh. A mesh in the NURBS miniapp
|
||||
demonstrates this.
|
||||
|
||||
- Added new methods in the Mesh class to set and get attributes on NURBS patches
|
||||
and patch boundaries.
|
||||
|
||||
- Added HIP support to the SUNDIALS interface.
|
||||
|
||||
- TMOP improvement: added asymptotically-balanced compound metrics 90, 94, 328,
|
||||
338. Added the tmop-metric-magnitude tool for tracking how metrics change
|
||||
under geometric perturbations.
|
||||
|
||||
Discretization improvements
|
||||
---------------------------
|
||||
- Face restriction operators for Nedelec and Raviart-Thomas finite element
|
||||
spaces are now supported through the ConformingFaceRestriction class.
|
||||
|
||||
- SubMesh and ParSubMesh have been extended to support the transfer of
|
||||
Nedelec and Raviart-Thomas finite element spaces.
|
||||
|
||||
- VectorFEBoundaryFluxLFIntegrator is now supported on device/GPU.
|
||||
|
||||
- Added support for partial assembly on NURBS patches and NURBS patch sparse
|
||||
matrix assembly. Patch matrix assembly includes the option to use reduced
|
||||
approximate integration rules, computed by the newly implemented non-negative
|
||||
least-squares (NNLS) solver.
|
||||
|
||||
- Added support for p-refined meshes in FindPointsGSLIB.
|
||||
|
||||
- Support for parallel transfer of H1 fields using the low-order refined (LOR)
|
||||
transfer operators in L2ProjectionGridTransfer
|
||||
|
||||
Linear and nonlinear solvers
|
||||
----------------------------
|
||||
- Updated interface to MUMPS direct solver to support multiple right-hand
|
||||
sides, block low-rank compression, builds using 64-bit integers, and other
|
||||
improvements.
|
||||
|
||||
- Added an interface to the MKL Pardiso sparse direct solver developed by Intel.
|
||||
This interface provides a serial (OpenMP shared memory) version of Pardiso for
|
||||
use with SparseMatrix. This complements the existing parallel (MPI distributed
|
||||
memory) version already available through the CPardiso MFEM integration.
|
||||
|
||||
Integrations, testing and documentation
|
||||
---------------------------------------
|
||||
- Added an address sanitizer GitHub action for a serial build/test on Ubuntu,
|
||||
based on Clang/LLVM (https://clang.llvm.org/docs/AddressSanitizer.html).
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
- Improved lambda body debugging with the addition of mfem::forall functions.
|
||||
These functions can take the place of the MFEM_FORALL macros, which have been
|
||||
preserved for backwards compatibility.
|
||||
|
||||
- Added an address sanitizer GitHub action for a serial build/test on Ubuntu,
|
||||
based on Clang/LLVM (https://clang.llvm.org/docs/AddressSanitizer.html).
|
||||
|
||||
- Reorganized files for bilinear form, linear form, and nonlinear form integrators
|
||||
in the fem/integ/ subdirectory.
|
||||
|
||||
- FiniteElementSpace::GetFE has been updated to abort instead of returning NULL for
|
||||
an empty partition.
|
||||
|
||||
- Various other simplifications, extensions, and bugfixes in the code.
|
||||
|
||||
|
||||
Version 4.5.2, released on March 23, 2023
|
||||
=========================================
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ project(mfem NONE)
|
||||
# Current version of MFEM, see also `makefile`.
|
||||
# mfem_VERSION = (string)
|
||||
# MFEM_VERSION = (int) [automatically derived from mfem_VERSION]
|
||||
set(${PROJECT_NAME}_VERSION 4.5.3)
|
||||
set(${PROJECT_NAME}_VERSION 4.6.1)
|
||||
|
||||
# Prohibit in-source build
|
||||
if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
|
||||
@@ -138,7 +138,7 @@ if (MFEM_USE_CUDA)
|
||||
set(CUDA_FLAGS "-ccbin=${CMAKE_CXX_COMPILER} ${CUDA_FLAGS}")
|
||||
set(CMAKE_CUDA_HOST_LINK_LAUNCHER ${CMAKE_CXX_COMPILER})
|
||||
endif()
|
||||
set(CMAKE_CUDA_FLAGS ${CMAKE_CUDA_FLAGS} ${CUDA_FLAGS})
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} ${CUDA_FLAGS}")
|
||||
set(CUSPARSE_FOUND TRUE)
|
||||
set(CUSPARSE_LIBRARIES "cusparse")
|
||||
set(CUBLAS_FOUND TRUE)
|
||||
|
||||
@@ -135,6 +135,7 @@ The MFEM source code has the following structure:
|
||||
│ ├── adjoint
|
||||
│ ├── autodiff
|
||||
│ ├── common
|
||||
│ ├── dpg
|
||||
│ ├── electromagnetics
|
||||
│ ├── gslib
|
||||
│ ├── hdiv-linear-solver
|
||||
@@ -148,6 +149,7 @@ The MFEM source code has the following structure:
|
||||
│ ├── performance
|
||||
│ ├── shifted
|
||||
│ ├── solvers
|
||||
│ ├── spde
|
||||
│ ├── tools
|
||||
│ └── toys
|
||||
└── tests
|
||||
|
||||
@@ -699,12 +699,15 @@ The specific libraries and their options are:
|
||||
PETSc has been cloned on the same level as mfem and hypre:
|
||||
./configure --download-fblaslapack=yes --download-scalapack=yes \
|
||||
--download-mumps=yes --download-suitesparse=yes \
|
||||
--with-hypre-dir=../hypre-2.10.0b/src/hypre \
|
||||
--with-hypre-dir=../hypre/src/hypre \
|
||||
--with-shared-libraries=0
|
||||
When building PETSc with HIP, one may need to add a flag like -std=c2x to
|
||||
CFLAGS to allow proper parsing of the hipsparse header under C.
|
||||
URL: https://www.mcs.anl.gov/petsc
|
||||
Options: PETSC_OPT, PETSC_LIB.
|
||||
Versions: PETSc >= 3.8.0 (PETSc build without CUDA)
|
||||
Versions: PETSc >= 3.8.0 (PETSc build without CUDA/HIP)
|
||||
PETSc >= 3.15.0 (PETSc built with CUDA)
|
||||
PETSc >= 3.19.0 (PETSc built with HIP, older versions may work too)
|
||||
|
||||
- SLEPc (optional), used when MFEM_USE_SLEPC = YES. SLEPc depends on PETSc and
|
||||
uses some of the PETSc options when compiled.
|
||||
|
||||
+20
-5
@@ -331,16 +331,30 @@ STRUMPACK_OPT = -I$(STRUMPACK_DIR)/include $(SCOTCH_OPT)
|
||||
STRUMPACK_LIB = -L$(STRUMPACK_DIR)/lib -lstrumpack $(MPI_FORTRAN_LIB)\
|
||||
$(SCOTCH_LIB) $(SCALAPACK_LIB)
|
||||
|
||||
# Ginkgo library configuration (currently not needed)
|
||||
# Ginkgo library configuration
|
||||
GINKGO_DIR = @MFEM_DIR@/../ginkgo/install
|
||||
GINKGO_SEARCH_DIR = $(subst @MFEM_DIR@,$(MFEM_DIR),$(GINKGO_DIR))
|
||||
GINKGO_BUILD_TYPE=Release
|
||||
ifeq ($(MFEM_USE_GINKGO),YES)
|
||||
BASE_FLAGS = -std=c++14
|
||||
endif
|
||||
GINKGO_OPT = -isystem $(GINKGO_DIR)/include
|
||||
GINKGO_LIB_DIR = $(sort $(dir $(wildcard $(GINKGO_DIR)/lib*/libginkgo*.a $(GINKGO_DIR)/lib*/libginkgo*.so $(GINKGO_DIR)/lib*/libginkgo*.dylib $(GINKGO_DIR)/lib*/libginkgo*.dll)))
|
||||
ALL_GINKGO_LIBS_DEBUG = $(notdir $(basename $(wildcard $(GINKGO_DIR)/lib*/libginkgo*d.a $(GINKGO_DIR)/lib*/libginkgo*d.so $(GINKGO_DIR)/lib*/libginkgo*d.dylib $(GINKGO_DIR)/lib*/libginkgo*d.dll)))
|
||||
ALL_GINKGO_LIBS = $(notdir $(basename $(wildcard $(GINKGO_DIR)/lib*/libginkgo*.a $(GINKGO_DIR)/lib*/libginkgo*.so $(GINKGO_DIR)/lib*/libginkgo*.dylib $(GINKGO_DIR)/lib*/libginkgo*.dll)))
|
||||
GINKGO_LIB_DIR = $(sort $(dir $(wildcard\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.a\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.so\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.dylib\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.dll)))
|
||||
GINKGO_LINK_LIB_DIR = $(GINKGO_DIR)$(subst $(GINKGO_SEARCH_DIR),,$(GINKGO_LIB_DIR))
|
||||
ALL_GINKGO_LIBS_DEBUG = $(notdir $(basename $(wildcard\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*d.a\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*d.so\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*d.dylib\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*d.dll)))
|
||||
ALL_GINKGO_LIBS = $(notdir $(basename $(wildcard\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.a\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.so\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.dylib\
|
||||
$(GINKGO_SEARCH_DIR)/lib*/libginkgo*.dll)))
|
||||
ALL_GINKGO_LIBS_RELEASE = $(filter-out $(ALL_GINKGO_LIBS_DEBUG),$(ALL_GINKGO_LIBS))
|
||||
GINKGO_LINK = $(subst libginkgo,-lginkgo,$(ALL_GINKGO_LIBS_RELEASE))
|
||||
ifeq ($(GINKGO_BUILD_TYPE),Debug)
|
||||
@@ -349,7 +363,8 @@ ifeq ($(GINKGO_BUILD_TYPE),Debug)
|
||||
endif
|
||||
else
|
||||
endif
|
||||
GINKGO_LIB = $(XLINKER)-rpath,$(GINKGO_LIB_DIR) -L$(GINKGO_LIB_DIR) $(GINKGO_LINK)
|
||||
GINKGO_LIB = $(XLINKER)-rpath,$(GINKGO_LINK_LIB_DIR) -L$(GINKGO_LINK_LIB_DIR)\
|
||||
$(GINKGO_LINK)
|
||||
|
||||
# AmgX library configuration
|
||||
AMGX_DIR = @MFEM_DIR@/../amgx
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
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
|
||||
1
|
||||
|
||||
elements
|
||||
4
|
||||
1 1 0 1
|
||||
1 1 1 2
|
||||
1 1 2 3
|
||||
1 1 3 4
|
||||
|
||||
boundary
|
||||
2
|
||||
1 0 0
|
||||
2 0 4
|
||||
|
||||
vertices
|
||||
5
|
||||
2
|
||||
0 0
|
||||
0.25 0.25
|
||||
0.50 0.50
|
||||
0.75 0.75
|
||||
1 1
|
||||
@@ -0,0 +1,37 @@
|
||||
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
|
||||
1
|
||||
|
||||
elements
|
||||
4
|
||||
1 1 0 1
|
||||
1 1 1 2
|
||||
1 1 2 3
|
||||
1 1 3 4
|
||||
|
||||
boundary
|
||||
2
|
||||
1 0 0
|
||||
2 0 4
|
||||
|
||||
vertices
|
||||
5
|
||||
3
|
||||
0 0 0
|
||||
0.25 0.25 0.25
|
||||
0.50 0.50 0.50
|
||||
0.75 0.75 0.75
|
||||
1 1 1
|
||||
@@ -38,7 +38,7 @@ PROJECT_NAME = "MFEM"
|
||||
# could be handy for archiving the generated documentation or if some version
|
||||
# control system is used.
|
||||
|
||||
PROJECT_NUMBER = v4.5.3
|
||||
PROJECT_NUMBER = v4.6.1
|
||||
|
||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
|
||||
@@ -105,8 +105,13 @@ namespace mfem {
|
||||
* - <a class="el" href="ex32p_8cpp_source.html">Example 32p</a>: parallel anisotropic Maxwell eigensolver
|
||||
* - <a class="el" href="ex33_8cpp_source.html">Example 33</a>: nodal H1 FEM for the fractional Laplacian problem
|
||||
* - <a class="el" href="ex33p_8cpp_source.html">Example 33p</a>: parallel nodal H1 FEM for the fractional Laplacian problem
|
||||
* - <a class="el" href="ex34_8cpp_source.html">Example 34</a>: multi-domain magnetostatics
|
||||
* - <a class="el" href="ex34p_8cpp_source.html">Example 34p</a>: parallel multi-domain magnetostatics
|
||||
* - <a class="el" href="ex35p_8cpp_source.html">Example 35p</a>: parallel multi-domain damped harmonic oscillators
|
||||
* - <a class="el" href="ex36_8cpp_source.html">Example 36</a>: Proximal Galerkin FEM for the obstacle problem
|
||||
* - <a class="el" href="ex36p_8cpp_source.html">Example 36p</a>: parallel Proximal Galerkin FEM for the obstacle problem
|
||||
* - <a class="el" href="ex37_8cpp_source.html">Example 37</a>: Topology optimization
|
||||
* - <a class="el" href="ex37p_8cpp_source.html">Example 37p</a>: parallel topology optimization
|
||||
*
|
||||
* <H4>AmgX Examples</H4>
|
||||
* - Variants of Examples
|
||||
|
||||
@@ -42,6 +42,7 @@ list(APPEND ALL_EXE_SRCS
|
||||
ex33.cpp
|
||||
ex34.cpp
|
||||
ex36.cpp
|
||||
ex37.cpp
|
||||
)
|
||||
|
||||
if (MFEM_USE_MPI)
|
||||
@@ -82,6 +83,7 @@ if (MFEM_USE_MPI)
|
||||
ex34p.cpp
|
||||
ex35p.cpp
|
||||
ex36p.cpp
|
||||
ex37p.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -107,6 +109,8 @@ if (MFEM_ENABLE_TESTING)
|
||||
list(APPEND THIS_TEST_OPTIONS "-e" "1")
|
||||
elseif(${TEST_NAME} MATCHES "ex27p*")
|
||||
list(APPEND THIS_TEST_OPTIONS "-dg")
|
||||
elseif(${TEST_NAME} MATCHES "ex37p*")
|
||||
list(APPEND THIS_TEST_OPTIONS "-mi" "3")
|
||||
endif()
|
||||
|
||||
if (NOT (${TEST_NAME} MATCHES ".*p$"))
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// Sample runs: mpirun -np 4 ex13p -m ../data/star.mesh
|
||||
// mpirun -np 4 ex13p -m ../data/square-disc.mesh -o 2 -n 4
|
||||
// mpirun -np 4 ex13p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 4 ex13p -m ../data/beam-tet.mesh -nc -o 2 -rs 1
|
||||
// mpirun -np 4 ex13p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 4 ex13p -m ../data/escher.mesh
|
||||
// mpirun -np 4 ex13p -m ../data/fichera.mesh
|
||||
@@ -54,6 +55,7 @@ int main(int argc, char *argv[])
|
||||
int par_ref_levels = 1;
|
||||
int order = 1;
|
||||
int nev = 5;
|
||||
bool nc = false;
|
||||
bool visualization = 1;
|
||||
const char *device_config = "cpu";
|
||||
|
||||
@@ -69,6 +71,9 @@ int main(int argc, char *argv[])
|
||||
" isoparametric space.");
|
||||
args.AddOption(&nev, "-n", "--num-eigs",
|
||||
"Number of desired eigenmodes.");
|
||||
args.AddOption(&nc, "-nc", "--non-conforming", "-c",
|
||||
"--conforming",
|
||||
"Mark the mesh as nonconforming before partitioning.");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
@@ -98,6 +103,10 @@ int main(int argc, char *argv[])
|
||||
// and volume meshes with the same code.
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
int dim = mesh->Dimension();
|
||||
if (nc)
|
||||
{
|
||||
mesh->EnsureNCMesh(true);
|
||||
}
|
||||
|
||||
// 5. Refine the serial mesh on all processors to increase the resolution. In
|
||||
// this example we do 'ref_levels' of uniform refinement (2 by default, or
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
// mpirun -np 4 ex15p -m ../data/square-disc-nurbs.mesh
|
||||
// mpirun -np 4 ex15p -m ../data/disc-nurbs.mesh
|
||||
// mpirun -np 4 ex15p -m ../data/fichera.mesh -tf 0.5
|
||||
// mpirun -np 4 ex15p -m ../data/fichera-mixed.mesh -tf 0.5
|
||||
// mpirun -np 4 ex15p -m ../data/ball-nurbs.mesh -tf 0.5
|
||||
// mpirun -np 4 ex15p -m ../data/mobius-strip.mesh
|
||||
// mpirun -np 4 ex15p -m ../data/amr-quad.mesh
|
||||
|
||||
@@ -63,6 +63,7 @@ int main(int argc, char *argv[])
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool pa = false;
|
||||
bool nc = false;
|
||||
const char *device_config = "cpu";
|
||||
bool visualization = 1;
|
||||
|
||||
@@ -77,6 +78,9 @@ int main(int argc, char *argv[])
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
|
||||
"--no-partial-assembly", "Enable Partial Assembly.");
|
||||
args.AddOption(&nc, "-nc", "--non-conforming", "-c",
|
||||
"--conforming",
|
||||
"Mark the mesh as nonconforming before partitioning.");
|
||||
args.AddOption(&device_config, "-d", "--device",
|
||||
"Device configuration string, see Device::Configure().");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
@@ -102,6 +106,11 @@ int main(int argc, char *argv[])
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
dim = mesh->Dimension();
|
||||
int sdim = mesh->SpaceDimension();
|
||||
if (nc)
|
||||
{
|
||||
// Can set to false to use conformal refinement for simplices.
|
||||
mesh->EnsureNCMesh(true);
|
||||
}
|
||||
|
||||
// 4. Refine the mesh to increase the resolution. In this example we do
|
||||
// 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
|
||||
|
||||
+24
-25
@@ -267,9 +267,9 @@ int main(int argc, char *argv[])
|
||||
<< "window_geometry 400 0 400 350" << flush;
|
||||
}
|
||||
|
||||
// 7. Define a parallel finite element space on the full mesh. Here we
|
||||
// use the H(curl) finite elements for the vector potential and H(div)
|
||||
// for the current density.
|
||||
// 7. Define a parallel finite element space on the full mesh. Here we use
|
||||
// the H(curl) finite elements for the vector potential and H(div) for the
|
||||
// current density.
|
||||
ND_FECollection fec_nd(order, dim);
|
||||
RT_FECollection fec_rt(order - 1, dim);
|
||||
FiniteElementSpace fespace_nd(&mesh, &fec_nd);
|
||||
@@ -292,10 +292,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
// 8. Determine the list of true (i.e. parallel conforming) essential
|
||||
// boundary dofs. In this example, the boundary conditions are defined
|
||||
// by marking all the boundary attributes except for those on a symmetry
|
||||
// plane as essential (Dirichlet) and converting them to a list of
|
||||
// true dofs.
|
||||
// boundary dofs. In this example, the boundary conditions are defined by
|
||||
// marking all the boundary attributes except for those on a symmetry
|
||||
// plane as essential (Dirichlet) and converting them to a list of true
|
||||
// dofs.
|
||||
Array<int> ess_tdof_list;
|
||||
Array<int> ess_bdr;
|
||||
if (mesh.bdr_attributes.Size())
|
||||
@@ -324,14 +324,13 @@ int main(int argc, char *argv[])
|
||||
GridFunction x(&fespace_nd);
|
||||
x = 0.0;
|
||||
|
||||
// 11. Set up the parallel bilinear form corresponding to the EM
|
||||
// diffusion operator curl muinv curl + delta I, by adding the
|
||||
// curl-curl and the mass domain integrators. For standard
|
||||
// magnetostatics equations choose delta << 1. Larger values of
|
||||
// delta should make the linear system easier to solve at the
|
||||
// expense of resembling a diffusive quasistatic magnetic field.
|
||||
// A reasonable balance must be found whenever the mesh or problem
|
||||
// setup is altered.
|
||||
// 11. Set up the parallel bilinear form corresponding to the EM diffusion
|
||||
// operator curl muinv curl + delta I, by adding the curl-curl and the
|
||||
// mass domain integrators. For standard magnetostatics equations choose
|
||||
// delta << 1. Larger values of delta should make the linear system
|
||||
// easier to solve at the expense of resembling a diffusive quasistatic
|
||||
// magnetic field. A reasonable balance must be found whenever the mesh
|
||||
// or problem setup is altered.
|
||||
ConstantCoefficient muinv(1.0);
|
||||
ConstantCoefficient delta(delta_const);
|
||||
BilinearForm a(&fespace_nd);
|
||||
@@ -423,8 +422,8 @@ int main(int argc, char *argv[])
|
||||
GridFunction dx(&fespace_rt);
|
||||
curl.Mult(x, dx);
|
||||
|
||||
// 18. Save the curl of the solution in parallel. This output can
|
||||
// be viewed later using GLVis: "glvis -np <np> -m mesh -g dsol".
|
||||
// 18. Save the curl of the solution in parallel. This output can be viewed
|
||||
// later using GLVis: "glvis -np <np> -m mesh -g dsol".
|
||||
{
|
||||
ostringstream dsol_name;
|
||||
dsol_name << "dsol.gf";
|
||||
@@ -456,18 +455,18 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
const Array<int> &jn_zero_attr,
|
||||
GridFunction &j_cond)
|
||||
{
|
||||
// Exract the finite element space and mesh on which j_cond is defined
|
||||
// Extract the finite element space and mesh on which j_cond is defined
|
||||
FiniteElementSpace &fes_cond_rt = *j_cond.FESpace();
|
||||
Mesh &mesh_cond = *fes_cond_rt.GetMesh();
|
||||
int dim = mesh_cond.Dimension();
|
||||
|
||||
// Define a parallel finite element space on the SubMesh. Here we use the
|
||||
// H1 finite elements for the electrostatic potential.
|
||||
// Define a parallel finite element space on the SubMesh. Here we use the H1
|
||||
// finite elements for the electrostatic potential.
|
||||
H1_FECollection fec_h1(order, dim);
|
||||
FiniteElementSpace fes_cond_h1(&mesh_cond, &fec_h1);
|
||||
|
||||
// Define the conductivity coefficient and the boundaries associated with
|
||||
// the fixed potentials phi0 and phi1 which will drive the current.
|
||||
// Define the conductivity coefficient and the boundaries associated with the
|
||||
// fixed potentials phi0 and phi1 which will drive the current.
|
||||
ConstantCoefficient sigmaCoef(1.0);
|
||||
Array<int> ess_bdr_phi(mesh_cond.bdr_attributes.Max());
|
||||
Array<int> ess_bdr_j(mesh_cond.bdr_attributes.Max());
|
||||
@@ -578,9 +577,9 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
<< "window_geometry 0 0 400 350" << flush;
|
||||
}
|
||||
|
||||
// Solve for the current density J = -sigma Grad phi with boundary
|
||||
// conditions J.n = 0 on the walls of the conductor but not on the
|
||||
// ports where phi=0 and phi=1.
|
||||
// Solve for the current density J = -sigma Grad phi with boundary conditions
|
||||
// J.n = 0 on the walls of the conductor but not on the ports where phi=0 and
|
||||
// phi=1.
|
||||
|
||||
// J will be computed in H(div) so we need an RT mass matrix
|
||||
BilinearForm m_rt(&fes_cond_rt);
|
||||
|
||||
+16
-17
@@ -302,9 +302,9 @@ int main(int argc, char *argv[])
|
||||
<< "window_geometry 400 0 400 350" << flush;
|
||||
}
|
||||
|
||||
// 8. Define a parallel finite element space on the full mesh. Here we
|
||||
// use the H(curl) finite elements for the vector potential and H(div)
|
||||
// for the current density.
|
||||
// 8. Define a parallel finite element space on the full mesh. Here we use
|
||||
// the H(curl) finite elements for the vector potential and H(div) for the
|
||||
// current density.
|
||||
ND_FECollection fec_nd(order, dim);
|
||||
RT_FECollection fec_rt(order - 1, dim);
|
||||
ParFiniteElementSpace fespace_nd(&pmesh, &fec_nd);
|
||||
@@ -360,14 +360,13 @@ int main(int argc, char *argv[])
|
||||
ParGridFunction x(&fespace_nd);
|
||||
x = 0.0;
|
||||
|
||||
// 12. Set up the parallel bilinear form corresponding to the EM
|
||||
// diffusion operator curl muinv curl + delta I, by adding the
|
||||
// curl-curl and the mass domain integrators. For standard
|
||||
// magnetostatics equations choose delta << 1. Larger values of
|
||||
// delta should make the linear system easier to solve at the
|
||||
// expense of resembling a diffusive quasistatic magnetic field.
|
||||
// A reasonable balance must be found whenever the mesh or problem
|
||||
// setup is altered.
|
||||
// 12. Set up the parallel bilinear form corresponding to the EM diffusion
|
||||
// operator curl muinv curl + delta I, by adding the curl-curl and the
|
||||
// mass domain integrators. For standard magnetostatics equations choose
|
||||
// delta << 1. Larger values of delta should make the linear system
|
||||
// easier to solve at the expense of resembling a diffusive quasistatic
|
||||
// magnetic field. A reasonable balance must be found whenever the mesh
|
||||
// or problem setup is altered.
|
||||
ConstantCoefficient muinv(1.0);
|
||||
ConstantCoefficient delta(delta_const);
|
||||
ParBilinearForm a(&fespace_nd);
|
||||
@@ -504,7 +503,7 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
const Array<int> &jn_zero_attr,
|
||||
ParGridFunction &j_cond)
|
||||
{
|
||||
// Exract the finite element space and mesh on which j_cond is defined
|
||||
// Extract the finite element space and mesh on which j_cond is defined
|
||||
ParFiniteElementSpace &fes_cond_rt = *j_cond.ParFESpace();
|
||||
ParMesh &pmesh_cond = *fes_cond_rt.GetParMesh();
|
||||
int myid = fes_cond_rt.GetMyRank();
|
||||
@@ -515,8 +514,8 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
H1_FECollection fec_h1(order, dim);
|
||||
ParFiniteElementSpace fes_cond_h1(&pmesh_cond, &fec_h1);
|
||||
|
||||
// Define the conductivity coefficient and the boundaries associated with
|
||||
// the fixed potentials phi0 and phi1 which will drive the current.
|
||||
// Define the conductivity coefficient and the boundaries associated with the
|
||||
// fixed potentials phi0 and phi1 which will drive the current.
|
||||
ConstantCoefficient sigmaCoef(1.0);
|
||||
Array<int> ess_bdr_phi(pmesh_cond.bdr_attributes.Max());
|
||||
Array<int> ess_bdr_j(pmesh_cond.bdr_attributes.Max());
|
||||
@@ -599,9 +598,9 @@ void ComputeCurrentDensityOnSubMesh(int order,
|
||||
<< "window_geometry 0 0 400 350" << flush;
|
||||
}
|
||||
|
||||
// Solve for the current density J = -sigma Grad phi with boundary
|
||||
// conditions J.n = 0 on the walls of the conductor but not on the
|
||||
// ports where phi=0 and phi=1.
|
||||
// Solve for the current density J = -sigma Grad phi with boundary conditions
|
||||
// J.n = 0 on the walls of the conductor but not on the ports where phi=0 and
|
||||
// phi=1.
|
||||
|
||||
// J will be computed in H(div) so we need an RT mass matrix
|
||||
ParBilinearForm m_rt(&fes_cond_rt);
|
||||
|
||||
+22
-25
@@ -35,10 +35,10 @@
|
||||
// conductivity, sigma = c. The user can specify these constants
|
||||
// using either set of names.
|
||||
//
|
||||
// This example demonstrates how to transfer fields computed on
|
||||
// a boundary generated SubMesh to the full mesh and apply them
|
||||
// as boundary conditions. The default mesh and corresponding
|
||||
// boundary attriburtes were chosen to verify proper behavior on
|
||||
// This example demonstrates how to transfer fields computed on a
|
||||
// boundary generated SubMesh to the full mesh and apply them as
|
||||
// boundary conditions. The default mesh and corresponding
|
||||
// boundary attributes were chosen to verify proper behavior on
|
||||
// both triangular and quadrilateral faces of tetrahedral,
|
||||
// wedge-shaped, and hexahedral elements.
|
||||
//
|
||||
@@ -420,7 +420,6 @@ int main(int argc, char *argv[])
|
||||
//
|
||||
// 2) A vector H(Div) field
|
||||
// -Grad(a Div) - omega^2 b + i omega c
|
||||
//
|
||||
ParBilinearForm pcOp(&fespace);
|
||||
if (pa) { pcOp.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
|
||||
switch (prob)
|
||||
@@ -445,8 +444,8 @@ int main(int argc, char *argv[])
|
||||
pcOp.Assemble();
|
||||
|
||||
// 14b. Define and apply a parallel FGMRES solver for AU=B with a block
|
||||
// diagonal preconditioner based on the appropriate multigrid
|
||||
// preconditioner from hypre.
|
||||
// diagonal preconditioner based on the appropriate multigrid
|
||||
// preconditioner from hypre.
|
||||
Array<int> blockTrueOffsets;
|
||||
blockTrueOffsets.SetSize(3);
|
||||
blockTrueOffsets[0] = 0;
|
||||
@@ -609,10 +608,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
/**
|
||||
Solves the eigenvalue problem -Div(Grad x) = lambda x with
|
||||
homogeneous Dirichlet boundary conditions on the boundary of the
|
||||
domain. Returns mode number "mode" (counting from zero) in the
|
||||
ParGridFunction "x".
|
||||
Solves the eigenvalue problem -Div(Grad x) = lambda x with homogeneous
|
||||
Dirichlet boundary conditions on the boundary of the domain. Returns mode
|
||||
number "mode" (counting from zero) in the ParGridFunction "x".
|
||||
*/
|
||||
void ScalarWaveGuide(int mode, ParGridFunction &x)
|
||||
{
|
||||
@@ -667,10 +665,10 @@ void ScalarWaveGuide(int mode, ParGridFunction &x)
|
||||
}
|
||||
|
||||
/**
|
||||
Solves the eigenvalue problem -Curl(Curl x) = lambda x with
|
||||
homogeneous Dirichlet boundary conditions, on the tangential
|
||||
component of x, on the boundary of the domain. Returns mode number
|
||||
"mode" (counting from zero) in the ParGridFunction "x".
|
||||
Solves the eigenvalue problem -Curl(Curl x) = lambda x with homogeneous
|
||||
Dirichlet boundary conditions, on the tangential component of x, on the
|
||||
boundary of the domain. Returns mode number "mode" (counting from zero) in
|
||||
the ParGridFunction "x".
|
||||
*/
|
||||
void VectorWaveGuide(int mode, ParGridFunction &x)
|
||||
{
|
||||
@@ -723,13 +721,12 @@ void VectorWaveGuide(int mode, ParGridFunction &x)
|
||||
}
|
||||
|
||||
/**
|
||||
Solves the eigenvalue problem -Div(Grad x) = lambda x with
|
||||
homogeneous Neumann boundary conditions on the boundary of the
|
||||
domain. Returns mode number "mode" (counting from zero) in the
|
||||
ParGridFunction "x_l2". Note that mode 0 is a constant field so
|
||||
higher mode numbers are often more interesting. The eigenmode is
|
||||
solved using continuous H1 basis of the appropriate order and then
|
||||
projected onto the L2 basis and returned.
|
||||
Solves the eigenvalue problem -Div(Grad x) = lambda x with homogeneous
|
||||
Neumann boundary conditions on the boundary of the domain. Returns mode
|
||||
number "mode" (counting from zero) in the ParGridFunction "x_l2". Note that
|
||||
mode 0 is a constant field so higher mode numbers are often more
|
||||
interesting. The eigenmode is solved using continuous H1 basis of the
|
||||
appropriate order and then projected onto the L2 basis and returned.
|
||||
*/
|
||||
void PseudoScalarWaveGuide(int mode, ParGridFunction &x_l2)
|
||||
{
|
||||
@@ -791,9 +788,9 @@ void PseudoScalarWaveGuide(int mode, ParGridFunction &x_l2)
|
||||
delete M;
|
||||
}
|
||||
|
||||
// Compute eigenmode "mode" of either a Dirichlet or Neumann Laplacian
|
||||
// or of a Dirichlet curl curl operator based on the problem type and
|
||||
// dimension of the domain.
|
||||
// Compute eigenmode "mode" of either a Dirichlet or Neumann Laplacian or of a
|
||||
// Dirichlet curl curl operator based on the problem type and dimension of the
|
||||
// domain.
|
||||
void SetPortBC(int prob, int dim, int mode, ParGridFunction &port_bc)
|
||||
{
|
||||
switch (prob)
|
||||
|
||||
+3
-7
@@ -1,12 +1,10 @@
|
||||
// MFEM Example 36
|
||||
//
|
||||
//
|
||||
// Compile with: make ex36
|
||||
//
|
||||
// Sample runs: ex36 -o 2
|
||||
// ex36 -o 2 -r 4
|
||||
//
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to solve the
|
||||
// bound-constrained energy minimization problem
|
||||
//
|
||||
@@ -28,12 +26,10 @@
|
||||
// order solutions to variation inequality problems and
|
||||
// showcases how to set up and solve nonlinear mixed methods.
|
||||
//
|
||||
//
|
||||
// [1] Keith, B. and Surowiec, T. (2023) Proximal Galerkin: A structure-
|
||||
// preserving finite element method for pointwise bound constraints.
|
||||
// arXiv:2307.12444 [math.NA]
|
||||
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -63,7 +59,7 @@ public:
|
||||
class ExponentialGridFunctionCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *u; // grid function
|
||||
GridFunction *u;
|
||||
Coefficient *obstacle;
|
||||
double min_val;
|
||||
double max_val;
|
||||
@@ -88,7 +84,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Finite element order (polynomial degree)");
|
||||
"Finite element order (polynomial degree).");
|
||||
args.AddOption(&ref_levels, "-r", "--refs",
|
||||
"Number of h-refinements.");
|
||||
args.AddOption(&max_it, "-mi", "--max-it",
|
||||
@@ -198,7 +194,7 @@ int main(int argc, char *argv[])
|
||||
u_gf.ProjectCoefficient(IC_coef);
|
||||
u_old_gf = u_gf;
|
||||
|
||||
// 9. Initialize the slack variable ψₕ = exp(uₕ)
|
||||
// 9. Initialize the slack variable ψₕ = ln(uₕ)
|
||||
LogarithmGridFunctionCoefficient ln_u(u_gf, obstacle);
|
||||
psi_gf.ProjectCoefficient(ln_u);
|
||||
psi_old_gf = psi_gf;
|
||||
|
||||
+3
-8
@@ -1,12 +1,10 @@
|
||||
// MFEM Example 36 - Parallel Version
|
||||
//
|
||||
// MFEM Example 36 - Parallel Version
|
||||
//
|
||||
// Compile with: make ex36p
|
||||
//
|
||||
// Sample runs: mpirun -np 4 ex36p -o 2
|
||||
// mpirun -np 4 ex36p -o 2 -r 4
|
||||
//
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to solve the
|
||||
// bound-constrained energy minimization problem
|
||||
//
|
||||
@@ -28,12 +26,10 @@
|
||||
// order solutions to variation inequality problems and
|
||||
// showcases how to set up and solve nonlinear mixed methods.
|
||||
//
|
||||
//
|
||||
// [1] Keith, B. and Surowiec, T. (2023) Proximal Galerkin: A structure-
|
||||
// preserving finite element method for pointwise bound constraints.
|
||||
// arXiv:2307.12444 [math.NA]
|
||||
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
@@ -63,7 +59,7 @@ public:
|
||||
class ExponentialGridFunctionCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *u; // grid function
|
||||
GridFunction *u;
|
||||
Coefficient *obstacle;
|
||||
double min_val;
|
||||
double max_val;
|
||||
@@ -220,7 +216,6 @@ int main(int argc, char *argv[])
|
||||
u_old_gf = 0.0;
|
||||
psi_old_gf = 0.0;
|
||||
|
||||
|
||||
// 8. Define the function coefficients for the solution and use them to
|
||||
// initialize the initial guess
|
||||
FunctionCoefficient exact_coef(exact_solution_obstacle);
|
||||
@@ -231,7 +226,7 @@ int main(int argc, char *argv[])
|
||||
u_gf.ProjectCoefficient(IC_coef);
|
||||
u_old_gf = u_gf;
|
||||
|
||||
// 9. Initialize the slack variable ψₕ = exp(uₕ)
|
||||
// 9. Initialize the slack variable ψₕ = ln(uₕ)
|
||||
LogarithmGridFunctionCoefficient ln_u(u_gf, obstacle);
|
||||
psi_gf.ProjectCoefficient(ln_u);
|
||||
psi_old_gf = psi_gf;
|
||||
|
||||
+414
-454
@@ -2,505 +2,465 @@
|
||||
//
|
||||
// Compile with: make ex37
|
||||
//
|
||||
// Sample runs: ex37
|
||||
// ex37 -i surface
|
||||
// ex37 -i surface -o 0
|
||||
// ex37 -i surface -r 1
|
||||
// ex37 -i surface -o 4
|
||||
// ex37 -i surface -o 4 -r 5
|
||||
// ex37 -i volumetric
|
||||
// ex37 -i volumetric -o 0
|
||||
// ex37 -i volumetric -r 1
|
||||
// ex37 -i volumetric -o 4
|
||||
// ex37 -i volumetric -o 4 -r 5
|
||||
// ex37 -i surface3d
|
||||
// ex37 -i surface3d -o 0
|
||||
// ex37 -i surface3d -r 1
|
||||
// ex37 -i surface3d -o 4
|
||||
// ex37 -i surface3d -o 4 -r 5
|
||||
// ex37 -i volumetric3d
|
||||
// ex37 -i volumetric3d -o 0
|
||||
// ex37 -i volumetric3d -r 1
|
||||
// ex37 -i volumetric3d -o 4
|
||||
// ex37 -i volumetric3d -o 4 -r 5
|
||||
// Sample runs:
|
||||
// ex37 -alpha 10
|
||||
// ex37 -alpha 10 -pv
|
||||
// ex37 -lambda 0.1 -mu 0.1
|
||||
// ex37 -o 2 -alpha 5.0 -mi 50 -vf 0.4 -ntol 1e-5
|
||||
// ex37 -r 6 -o 1 -alpha 25.0 -epsilon 0.02 -mi 50 -ntol 1e-5
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to integrate
|
||||
// functions over implicit interfaces and subdomains bounded by
|
||||
// implicit interfaces.
|
||||
// Description: This example code demonstrates the use of MFEM to solve a
|
||||
// density-filtered [3] topology optimization problem. The
|
||||
// objective is to minimize the compliance
|
||||
//
|
||||
// The quadrature rules are constructed by means of moment-fitting.
|
||||
// The interface is given by the zero iso line of a level-set
|
||||
// function ϕ and the subdomain is given as the domain where ϕ>0
|
||||
// holds. The algorithm for construction of the quadrature rules
|
||||
// was introduced by Mueller, Kummer and Oberlack [1].
|
||||
// minimize ∫_Ω f⋅u dx over u ∈ [H¹(Ω)]² and ρ ∈ L¹(Ω)
|
||||
//
|
||||
// There is an example for the integration of a quadratic function
|
||||
// over the sphere in 2 dimensions and an example computong the
|
||||
// arclength and area of an ellipse in 2 dimensions.
|
||||
// subject to
|
||||
//
|
||||
// This example showcases how to set up integrators using the
|
||||
// integration rules on surfaces and subdomains.
|
||||
// -Div(r(ρ̃)Cε(u)) = f in Ω + BCs
|
||||
// -ϵ²Δρ̃ + ρ̃ = ρ in Ω + Neumann BCs
|
||||
// 0 ≤ ρ ≤ 1 in Ω
|
||||
// ∫_Ω ρ dx = θ vol(Ω)
|
||||
//
|
||||
// [1] Mueller, B., Kummer, F. and Oberlack, M. (2013) Highly accurate surface
|
||||
// and volume integration on implicit domains by means of moment-fitting.
|
||||
// Int. J. Numer. Meth. Engng. (96) 512-528. DOI:10.1002/nme.4569
|
||||
// Here, r(ρ̃) = ρ₀ + ρ̃³ (1-ρ₀) is the solid isotropic material
|
||||
// penalization (SIMP) law, C is the elasticity tensor for an
|
||||
// isotropic linearly elastic material, ϵ > 0 is the design
|
||||
// length scale, and 0 < θ < 1 is the volume fraction.
|
||||
//
|
||||
// The problem is discretized and gradients are computing using
|
||||
// finite elements [1]. The design is optimized using an entropic
|
||||
// mirror descent algorithm introduced by Keith and Surowiec [2]
|
||||
// that is tailored to the bound constraint 0 ≤ ρ ≤ 1.
|
||||
//
|
||||
// This example highlights the ability of MFEM to deliver high-
|
||||
// order solutions to inverse design problems and showcases how
|
||||
// to set up and solve PDE-constrained optimization problems
|
||||
// using the so-called reduced space approach.
|
||||
//
|
||||
// [1] Andreassen, E., Clausen, A., Schevenels, M., Lazarov, B. S., & Sigmund, O.
|
||||
// (2011). Efficient topology optimization in MATLAB using 88 lines of
|
||||
// code. Structural and Multidisciplinary Optimization, 43(1), 1-16.
|
||||
// [2] Keith, B. and Surowiec, T. (2023) Proximal Galerkin: A structure-
|
||||
// preserving finite element method for pointwise bound constraints.
|
||||
// arXiv:2307.12444 [math.NA]
|
||||
// [3] Lazarov, B. S., & Sigmund, O. (2011). Filters in topology optimization
|
||||
// based on Helmholtz‐type differential equations. International Journal
|
||||
// for Numerical Methods in Engineering, 86(6), 765-781.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "ex37.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
/// @brief Integration rule the example should demonstrate
|
||||
enum class IntegrationType { Volumetric1D, Surface2D, Volumetric2D,
|
||||
Surface3D, Volumetric3D
|
||||
};
|
||||
IntegrationType itype;
|
||||
|
||||
/// @brief Level-set function defining the implicit interface
|
||||
double lvlset(const Vector& X)
|
||||
{
|
||||
switch (itype)
|
||||
{
|
||||
case IntegrationType::Volumetric1D:
|
||||
return .55 - X(0);
|
||||
case IntegrationType::Surface2D:
|
||||
return 1. - (pow(X(0), 2.) + pow(X(1), 2.));
|
||||
case IntegrationType::Volumetric2D:
|
||||
return 1. - (pow(X(0) / 1.5, 2.) + pow(X(1) / .75, 2.));
|
||||
case IntegrationType::Surface3D:
|
||||
return 1. - (pow(X(0), 2.) + pow(X(1), 2.) + pow(X(2), 2.));
|
||||
case IntegrationType::Volumetric3D:
|
||||
return 1. - (pow(X(0) / 1.5, 2.) + pow(X(1) / .75, 2.) + pow(X(2) / .5, 2.));
|
||||
default:
|
||||
return 1.;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Function that should be integrated
|
||||
double integrand(const Vector& X)
|
||||
{
|
||||
switch (itype)
|
||||
{
|
||||
case IntegrationType::Volumetric1D:
|
||||
return 1.;
|
||||
case IntegrationType::Surface2D:
|
||||
return 3. * pow(X(0), 2.) - pow(X(1), 2.);
|
||||
case IntegrationType::Volumetric2D:
|
||||
return 1.;
|
||||
case IntegrationType::Surface3D:
|
||||
return 4. - 3. * pow(X(0), 2.) + 2. * pow(X(1), 2.) - pow(X(2), 2.);
|
||||
case IntegrationType::Volumetric3D:
|
||||
return 1.;
|
||||
default:
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Analytic surface integral
|
||||
double Surface()
|
||||
{
|
||||
switch (itype)
|
||||
{
|
||||
case IntegrationType::Volumetric1D:
|
||||
return 1.;
|
||||
case IntegrationType::Surface2D:
|
||||
return 2. * M_PI;
|
||||
case IntegrationType::Volumetric2D:
|
||||
return 7.26633616541076;
|
||||
case IntegrationType::Surface3D:
|
||||
return 40. / 3. * M_PI;
|
||||
case IntegrationType::Volumetric3D:
|
||||
return 9.90182151329315;
|
||||
default:
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Analyitc volume integral over subdomain with positiv level-set
|
||||
double Volume()
|
||||
{
|
||||
switch (itype)
|
||||
{
|
||||
case IntegrationType::Volumetric1D:
|
||||
return .55;
|
||||
case IntegrationType::Surface2D:
|
||||
return NAN;
|
||||
case IntegrationType::Volumetric2D:
|
||||
return 9. / 8. * M_PI;
|
||||
case IntegrationType::Surface3D:
|
||||
return NAN;
|
||||
case IntegrationType::Volumetric3D:
|
||||
return 3. / 4. * M_PI;
|
||||
default:
|
||||
return 0.;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MFEM_USE_LAPACK
|
||||
/**
|
||||
@brief Class for surface linearform integrator
|
||||
|
||||
Integrator to demonstrate the use of the surface integration rule on an
|
||||
implicit surface defined by a level-set.
|
||||
* @brief Bregman projection of ρ = sigmoid(ψ) onto the subspace
|
||||
* ∫_Ω ρ dx = θ vol(Ω) as follows:
|
||||
*
|
||||
* 1. Compute the root of the R → R function
|
||||
* f(c) = ∫_Ω sigmoid(ψ + c) dx - θ vol(Ω)
|
||||
* 2. Set ψ ← ψ + c.
|
||||
*
|
||||
* @param psi a GridFunction to be updated
|
||||
* @param target_volume θ vol(Ω)
|
||||
* @param tol Newton iteration tolerance
|
||||
* @param max_its Newton maximum iteration number
|
||||
* @return double Final volume, ∫_Ω sigmoid(ψ)
|
||||
*/
|
||||
class SurfaceLFIntegrator : public LinearFormIntegrator
|
||||
double proj(GridFunction &psi, double target_volume, double tol=1e-12,
|
||||
int max_its=10)
|
||||
{
|
||||
protected:
|
||||
/// @brief vector to evaluate the basis functions
|
||||
Vector shape;
|
||||
MappedGridFunctionCoefficient sigmoid_psi(&psi, sigmoid);
|
||||
MappedGridFunctionCoefficient der_sigmoid_psi(&psi, der_sigmoid);
|
||||
|
||||
/// @brief surface integration rule
|
||||
SIntegrationRule* SIntRule;
|
||||
|
||||
/// @brief coefficient representing the level-set defining the interface
|
||||
Coefficient &LevelSet;
|
||||
|
||||
/// @brief coefficient representing the integrand
|
||||
Coefficient &Q;
|
||||
|
||||
public:
|
||||
/**
|
||||
@brief Constructor for the surface linear form integrator
|
||||
|
||||
Constructor for the surface linear form integrator to demonstrate the use
|
||||
of the surface integration rule by means of moment-fitting.
|
||||
|
||||
@param [in] q coefficient representing the inegrand
|
||||
@param [in] levelset level-set defining the implicit interfac
|
||||
@param [in] ir surface integrtion rule to be used
|
||||
*/
|
||||
SurfaceLFIntegrator(Coefficient &q, Coefficient &levelset,
|
||||
SIntegrationRule* ir)
|
||||
: LinearFormIntegrator(), Q(q), LevelSet(levelset), SIntRule(ir) {}
|
||||
|
||||
/**
|
||||
@brief Constructor for the surface linear form integrator
|
||||
|
||||
Constructor for the surface linear form integrator to demonstrate the use
|
||||
of the surface integration rule by means of moment-fitting.
|
||||
|
||||
@param [in] q coefficient representing the inegrand
|
||||
@param [in] levelset level-set defining the implicit interfac
|
||||
*/
|
||||
SurfaceLFIntegrator(Coefficient &q, Coefficient &levelset)
|
||||
: LinearFormIntegrator(), Q(q), LevelSet(levelset), SIntRule(NULL) {}
|
||||
|
||||
/**
|
||||
@brief Assembly of the element vector
|
||||
|
||||
Assemble the element vector of for the right hand side on the element given
|
||||
by the FiniteElement and ElementTransformation.
|
||||
|
||||
@param [in] el finite Element the vector belongs to
|
||||
@param [in] Tr transformation of finite element
|
||||
@param [out] elvect vector containing the
|
||||
*/
|
||||
virtual void AssembleRHSElementVect(const FiniteElement &el,
|
||||
ElementTransformation &Tr,
|
||||
Vector &elvect) override
|
||||
LinearForm int_sigmoid_psi(psi.FESpace());
|
||||
int_sigmoid_psi.AddDomainIntegrator(new DomainLFIntegrator(sigmoid_psi));
|
||||
LinearForm int_der_sigmoid_psi(psi.FESpace());
|
||||
int_der_sigmoid_psi.AddDomainIntegrator(new DomainLFIntegrator(
|
||||
der_sigmoid_psi));
|
||||
bool done = false;
|
||||
for (int k=0; k<max_its; k++) // Newton iteration
|
||||
{
|
||||
int dof = el.GetDof();
|
||||
shape.SetSize(dof);
|
||||
elvect.SetSize(dof);
|
||||
elvect = 0.;
|
||||
int_sigmoid_psi.Assemble(); // Recompute f(c) with updated ψ
|
||||
const double f = int_sigmoid_psi.Sum() - target_volume;
|
||||
|
||||
// Update the surface integration rule for the current element
|
||||
SIntRule->SetElementWithSurfaceWeights(Tr.ElementNo);
|
||||
int_der_sigmoid_psi.Assemble(); // Recompute df(c) with updated ψ
|
||||
const double df = int_der_sigmoid_psi.Sum();
|
||||
|
||||
for (int ip = 0; ip < SIntRule->GetNPoints(); ip++)
|
||||
{
|
||||
Tr.SetIntPoint((&(SIntRule->IntPoint(ip))));
|
||||
double val = Tr.Weight() * Q.Eval(Tr, SIntRule->IntPoint(ip));
|
||||
el.CalcShape(SIntRule->IntPoint(ip), shape);
|
||||
add(elvect, SIntRule->IntPoint(ip).weight * val, shape, elvect);
|
||||
}
|
||||
const double dc = -f/df;
|
||||
psi += dc;
|
||||
if (abs(dc) < tol) { done = true; break; }
|
||||
}
|
||||
|
||||
/// @brief Get the level-set defining the implicit interface
|
||||
void SetSurface(Coefficient &levelset) { LevelSet = levelset; }
|
||||
|
||||
/// @brief Set the surface integration rule
|
||||
void SetSIntRule(SIntegrationRule *ir) { SIntRule = ir; }
|
||||
|
||||
/// @brief Get the surface integration rule
|
||||
const SIntegrationRule* GetSIntRule() { return SIntRule; }
|
||||
};
|
||||
if (!done)
|
||||
{
|
||||
mfem_warning("Projection reached maximum iteration without converging. "
|
||||
"Result may not be accurate.");
|
||||
}
|
||||
int_sigmoid_psi.Assemble();
|
||||
return int_sigmoid_psi.Sum();
|
||||
}
|
||||
|
||||
/**
|
||||
@brief Class for subdomain linearform integrator
|
||||
|
||||
Integrator to demonstrate the use of the subdomain integration rule within
|
||||
an area defined by an implicit surface defined by a level-set.
|
||||
* ---------------------------------------------------------------
|
||||
* ALGORITHM PREAMBLE
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* The Lagrangian for this problem is
|
||||
*
|
||||
* L(u,ρ,ρ̃,w,w̃) = (f,u) - (r(ρ̃) C ε(u),ε(w)) + (f,w)
|
||||
* - (ϵ² ∇ρ̃,∇w̃) - (ρ̃,w̃) + (ρ,w̃)
|
||||
*
|
||||
* where
|
||||
*
|
||||
* r(ρ̃) = ρ₀ + ρ̃³ (1 - ρ₀) (SIMP rule)
|
||||
*
|
||||
* ε(u) = (∇u + ∇uᵀ)/2 (symmetric gradient)
|
||||
*
|
||||
* C e = λtr(e)I + 2μe (isotropic material)
|
||||
*
|
||||
* NOTE: The Lame parameters can be computed from Young's modulus E
|
||||
* and Poisson's ratio ν as follows:
|
||||
*
|
||||
* λ = E ν/((1+ν)(1-2ν)), μ = E/(2(1+ν))
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* Discretization choices:
|
||||
*
|
||||
* u ∈ V ⊂ (H¹)ᵈ (order p)
|
||||
* ψ ∈ L² (order p - 1), ρ = sigmoid(ψ)
|
||||
* ρ̃ ∈ H¹ (order p)
|
||||
* w ∈ V (order p)
|
||||
* w̃ ∈ H¹ (order p)
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
* ALGORITHM
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* Update ρ with projected mirror descent via the following algorithm.
|
||||
*
|
||||
* 1. Initialize ψ = inv_sigmoid(vol_fraction) so that ∫ sigmoid(ψ) = θ vol(Ω)
|
||||
*
|
||||
* While not converged:
|
||||
*
|
||||
* 2. Solve filter equation ∂_w̃ L = 0; i.e.,
|
||||
*
|
||||
* (ϵ² ∇ ρ̃, ∇ v ) + (ρ̃,v) = (ρ,v) ∀ v ∈ H¹.
|
||||
*
|
||||
* 3. Solve primal problem ∂_w L = 0; i.e.,
|
||||
*
|
||||
* (λ r(ρ̃) ∇⋅u, ∇⋅v) + (2 μ r(ρ̃) ε(u), ε(v)) = (f,v) ∀ v ∈ V.
|
||||
*
|
||||
* NB. The dual problem ∂_u L = 0 is the negative of the primal problem due to symmetry.
|
||||
*
|
||||
* 4. Solve for filtered gradient ∂_ρ̃ L = 0; i.e.,
|
||||
*
|
||||
* (ϵ² ∇ w̃ , ∇ v ) + (w̃ ,v) = (-r'(ρ̃) ( λ |∇⋅u|² + 2 μ |ε(u)|²),v) ∀ v ∈ H¹.
|
||||
*
|
||||
* 5. Project the gradient onto the discrete latent space; i.e., solve
|
||||
*
|
||||
* (G,v) = (w̃,v) ∀ v ∈ L².
|
||||
*
|
||||
* 6. Bregman proximal gradient update; i.e.,
|
||||
*
|
||||
* ψ ← ψ - αG + c,
|
||||
*
|
||||
* where α > 0 is a step size parameter and c ∈ R is a constant ensuring
|
||||
*
|
||||
* ∫_Ω sigmoid(ψ - αG + c) dx = θ vol(Ω).
|
||||
*
|
||||
* end
|
||||
*/
|
||||
class SubdomainLFIntegrator : public LinearFormIntegrator
|
||||
{
|
||||
protected:
|
||||
/// @brief vector to evaluate the basis functions
|
||||
Vector shape;
|
||||
|
||||
/// @brief surface integration rule
|
||||
CutIntegrationRule* CutIntRule;
|
||||
|
||||
/// @brief coefficient representing the level-set defining the interface
|
||||
Coefficient &LevelSet;
|
||||
|
||||
/// @brief coefficient representing the integrand
|
||||
Coefficient &Q;
|
||||
|
||||
public:
|
||||
/**
|
||||
@brief Constructor for the volumetric subdomain linear form integrator
|
||||
|
||||
Constructor for the subdomain linear form integrator to demonstrate the use
|
||||
of the volumeric subdomain integration rule by means of moment-fitting.
|
||||
|
||||
@param [in] q coefficient representing the inegrand
|
||||
@param [in] levelset level-set defining the implicit interfac
|
||||
@param [in] ir subdomain integrtion rule to be used
|
||||
*/
|
||||
SubdomainLFIntegrator(Coefficient &q, Coefficient &levelset,
|
||||
CutIntegrationRule* ir)
|
||||
: LinearFormIntegrator(), Q(q), LevelSet(levelset), CutIntRule(ir) {}
|
||||
|
||||
/**
|
||||
@brief Constructor for the volumetric subdomain linear form integrator
|
||||
|
||||
Constructor for the subdomain linear form integrator to demonstrate the use
|
||||
of the volumeric subdomain integration rule by means of moment-fitting.
|
||||
|
||||
@param [in] q coefficient representing the inegrand
|
||||
@param [in] levelset level-set defining the implicit interfac
|
||||
*/
|
||||
SubdomainLFIntegrator(Coefficient &q, Coefficient &levelset)
|
||||
: LinearFormIntegrator(), Q(q), LevelSet(levelset), CutIntRule(NULL) {}
|
||||
|
||||
/**
|
||||
@brief Assembly of the element vector
|
||||
|
||||
Assemble the element vector of for the right hand side on the element given
|
||||
by the FiniteElement and ElementTransformation.
|
||||
|
||||
@param [in] el finite Element the vector belongs to
|
||||
@param [in] Tr transformation of finite element
|
||||
@param [out] elvect vector containing the
|
||||
*/
|
||||
virtual void AssembleRHSElementVect(const FiniteElement &el,
|
||||
ElementTransformation &Tr,
|
||||
Vector &elvect) override
|
||||
{
|
||||
int dof = el.GetDof();
|
||||
shape.SetSize(dof);
|
||||
elvect.SetSize(dof);
|
||||
elvect = 0.;
|
||||
|
||||
// Update the subdomain integration rule
|
||||
CutIntRule->SetElement(Tr.ElementNo);
|
||||
|
||||
for (int ip = 0; ip < CutIntRule->GetNPoints(); ip++)
|
||||
{
|
||||
Tr.SetIntPoint((&(CutIntRule->IntPoint(ip))));
|
||||
double val = Tr.Weight()
|
||||
* Q.Eval(Tr, CutIntRule->IntPoint(ip));
|
||||
el.CalcPhysShape(Tr, shape);
|
||||
add(elvect, CutIntRule->IntPoint(ip).weight * val, shape, elvect);
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Get the level-set defining the implicit interface
|
||||
void SetSurface(Coefficient &levelset) { LevelSet = levelset; }
|
||||
|
||||
/// @brief Set the volumetric subdomain integration rule
|
||||
void SetCutIntRule(CutIntegrationRule *ir) { CutIntRule = ir; }
|
||||
|
||||
/// @brief Get the volumetricsubdomain integration
|
||||
const CutIntegrationRule* GetCutIntRule() { return CutIntRule; }
|
||||
};
|
||||
#endif //MFEM_USE_LAPACK
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifndef MFEM_USE_LAPACK
|
||||
cout << "MFEM must be build with LAPACK for this example." << endl;
|
||||
return EXIT_FAILURE;
|
||||
#else
|
||||
// 1. Parse he command-line options.
|
||||
int ref_levels = 3;
|
||||
// 1. Parse command-line options.
|
||||
int ref_levels = 5;
|
||||
int order = 2;
|
||||
const char *inttype = "surface2d";
|
||||
itype = IntegrationType::Surface2D;
|
||||
double alpha = 1.0;
|
||||
double epsilon = 0.01;
|
||||
double vol_fraction = 0.5;
|
||||
int max_it = 1e3;
|
||||
double itol = 1e-1;
|
||||
double ntol = 1e-4;
|
||||
double rho_min = 1e-6;
|
||||
double lambda = 1.0;
|
||||
double mu = 1.0;
|
||||
bool glvis_visualization = true;
|
||||
bool paraview_output = false;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&order, "-o", "--order", "Order of quadrature rule");
|
||||
args.AddOption(&ref_levels, "-r", "--refine", "Number of meh refinements");
|
||||
args.AddOption(&inttype, "-i", "--integrationtype",
|
||||
"IntegrationType to demonstrate");
|
||||
args.ParseCheck();
|
||||
args.AddOption(&ref_levels, "-r", "--refine",
|
||||
"Number of times to refine the mesh uniformly.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Order (degree) of the finite elements.");
|
||||
args.AddOption(&alpha, "-alpha", "--alpha-step-length",
|
||||
"Step length for gradient descent.");
|
||||
args.AddOption(&epsilon, "-epsilon", "--epsilon-thickness",
|
||||
"Length scale for ρ.");
|
||||
args.AddOption(&max_it, "-mi", "--max-it",
|
||||
"Maximum number of gradient descent iterations.");
|
||||
args.AddOption(&ntol, "-ntol", "--rel-tol",
|
||||
"Normalized exit tolerance.");
|
||||
args.AddOption(&itol, "-itol", "--abs-tol",
|
||||
"Increment exit tolerance.");
|
||||
args.AddOption(&vol_fraction, "-vf", "--volume-fraction",
|
||||
"Volume fraction for the material density.");
|
||||
args.AddOption(&lambda, "-lambda", "--lambda",
|
||||
"Lamé constant λ.");
|
||||
args.AddOption(&mu, "-mu", "--mu",
|
||||
"Lamé constant μ.");
|
||||
args.AddOption(&rho_min, "-rmin", "--psi-min",
|
||||
"Minimum of density coefficient.");
|
||||
args.AddOption(&glvis_visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(¶view_output, "-pv", "--paraview", "-no-pv",
|
||||
"--no-paraview",
|
||||
"Enable or disable ParaView output.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
args.PrintUsage(mfem::out);
|
||||
return 1;
|
||||
}
|
||||
args.PrintOptions(mfem::out);
|
||||
|
||||
if (strcmp(inttype, "volumetric1d") == 0
|
||||
|| strcmp(inttype, "Volumetric1D") == 0)
|
||||
{
|
||||
itype = IntegrationType::Volumetric1D;
|
||||
}
|
||||
else if (strcmp(inttype, "surface2d") == 0
|
||||
|| strcmp(inttype, "Surface2D") == 0)
|
||||
{
|
||||
itype = IntegrationType::Surface2D;
|
||||
}
|
||||
else if (strcmp(inttype, "volumetric2d") == 0
|
||||
|| strcmp(inttype, "Volumetric2D") == 0)
|
||||
{
|
||||
itype = IntegrationType::Volumetric2D;
|
||||
}
|
||||
else if (strcmp(inttype, "surface3d") == 0
|
||||
|| strcmp(inttype, "Surface3d") == 0)
|
||||
{
|
||||
itype = IntegrationType::Surface3D;
|
||||
}
|
||||
else if (strcmp(inttype, "volumetric3d") == 0
|
||||
|| strcmp(inttype, "Volumetric3d") == 0)
|
||||
{
|
||||
itype = IntegrationType::Volumetric3D;
|
||||
}
|
||||
Mesh mesh = Mesh::MakeCartesian2D(3, 1, mfem::Element::Type::QUADRILATERAL,
|
||||
true, 3.0, 1.0);
|
||||
int dim = mesh.Dimension();
|
||||
|
||||
// 2. Construct and refine the mesh.
|
||||
Mesh *mesh;
|
||||
if (itype == IntegrationType::Volumetric1D)
|
||||
// 2. Set BCs.
|
||||
for (int i = 0; i<mesh.GetNBE(); i++)
|
||||
{
|
||||
mesh = new Mesh("../data/inline-segment.mesh");
|
||||
}
|
||||
if (itype == IntegrationType::Surface2D
|
||||
|| itype == IntegrationType::Volumetric2D)
|
||||
{
|
||||
mesh = new Mesh(2, 4, 1, 0, 2);
|
||||
mesh->AddVertex(-1.6,-1.6);
|
||||
mesh->AddVertex(1.6,-1.6);
|
||||
mesh->AddVertex(1.6,1.6);
|
||||
mesh->AddVertex(-1.6,1.6);
|
||||
mesh->AddQuad(0,1,2,3);
|
||||
mesh->FinalizeQuadMesh(1, 0, 1);
|
||||
}
|
||||
else if (itype == IntegrationType::Surface3D
|
||||
|| itype == IntegrationType::Volumetric3D)
|
||||
{
|
||||
mesh = new Mesh(3, 8, 1, 0, 3);
|
||||
mesh->AddVertex(-1.6,-1.6,-1.6);
|
||||
mesh->AddVertex(1.6,-1.6,-1.6);
|
||||
mesh->AddVertex(1.6,1.6,-1.6);
|
||||
mesh->AddVertex(-1.6,1.6,-1.6);
|
||||
mesh->AddVertex(-1.6,-1.6,1.6);
|
||||
mesh->AddVertex(1.6,-1.6,1.6);
|
||||
mesh->AddVertex(1.6,1.6,1.6);
|
||||
mesh->AddVertex(-1.6,1.6,1.6);
|
||||
mesh->AddHex(0,1,2,3,4,5,6,7);
|
||||
mesh->FinalizeHexMesh(1, 0, 1);
|
||||
}
|
||||
Element * be = mesh.GetBdrElement(i);
|
||||
Array<int> vertices;
|
||||
be->GetVertices(vertices);
|
||||
|
||||
double * coords1 = mesh.GetVertex(vertices[0]);
|
||||
double * coords2 = mesh.GetVertex(vertices[1]);
|
||||
|
||||
Vector center(2);
|
||||
center(0) = 0.5*(coords1[0] + coords2[0]);
|
||||
center(1) = 0.5*(coords1[1] + coords2[1]);
|
||||
|
||||
if (abs(center(0) - 0.0) < 1e-10)
|
||||
{
|
||||
// the left edge
|
||||
be->SetAttribute(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other boundaries
|
||||
be->SetAttribute(2);
|
||||
}
|
||||
}
|
||||
mesh.SetAttributes();
|
||||
|
||||
// 3. Refine the mesh.
|
||||
for (int lev = 0; lev < ref_levels; lev++)
|
||||
{
|
||||
mesh->UniformRefinement();
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
|
||||
// 3. Define the necessary finite element space on the mesh.
|
||||
H1_FECollection fe_coll(1, mesh->Dimension());
|
||||
FiniteElementSpace *fespace = new FiniteElementSpace(mesh, &fe_coll);
|
||||
// 4. Define the necessary finite element spaces on the mesh.
|
||||
H1_FECollection state_fec(order, dim); // space for u
|
||||
H1_FECollection filter_fec(order, dim); // space for ρ̃
|
||||
L2_FECollection control_fec(order-1, dim,
|
||||
BasisType::GaussLobatto); // space for ψ
|
||||
FiniteElementSpace state_fes(&mesh, &state_fec,dim);
|
||||
FiniteElementSpace filter_fes(&mesh, &filter_fec);
|
||||
FiniteElementSpace control_fes(&mesh, &control_fec);
|
||||
|
||||
// 4.
|
||||
FunctionCoefficient levelset(lvlset);
|
||||
FunctionCoefficient u(integrand);
|
||||
int state_size = state_fes.GetTrueVSize();
|
||||
int control_size = control_fes.GetTrueVSize();
|
||||
int filter_size = filter_fes.GetTrueVSize();
|
||||
mfem::out << "Number of state unknowns: " << state_size << std::endl;
|
||||
mfem::out << "Number of filter unknowns: " << filter_size << std::endl;
|
||||
mfem::out << "Number of control unknowns: " << control_size << std::endl;
|
||||
|
||||
// 5. Define the necessary Integration rules on element 0.
|
||||
IsoparametricTransformation Tr;
|
||||
mesh->GetElementTransformation(0, &Tr);
|
||||
SIntegrationRule* sir = new SIntegrationRule(order, Tr, levelset);
|
||||
CutIntegrationRule* cir = NULL;
|
||||
if (itype == IntegrationType::Volumetric1D
|
||||
|| itype == IntegrationType::Volumetric2D
|
||||
|| itype == IntegrationType::Volumetric3D)
|
||||
// 5. Set the initial guess for ρ.
|
||||
GridFunction u(&state_fes);
|
||||
GridFunction psi(&control_fes);
|
||||
GridFunction psi_old(&control_fes);
|
||||
GridFunction rho_filter(&filter_fes);
|
||||
u = 0.0;
|
||||
rho_filter = vol_fraction;
|
||||
psi = inv_sigmoid(vol_fraction);
|
||||
psi_old = inv_sigmoid(vol_fraction);
|
||||
|
||||
// ρ = sigmoid(ψ)
|
||||
MappedGridFunctionCoefficient rho(&psi, sigmoid);
|
||||
// Interpolation of ρ = sigmoid(ψ) in control fes (for ParaView output)
|
||||
GridFunction rho_gf(&control_fes);
|
||||
// ρ - ρ_old = sigmoid(ψ) - sigmoid(ψ_old)
|
||||
DiffMappedGridFunctionCoefficient succ_diff_rho(&psi, &psi_old, sigmoid);
|
||||
|
||||
// 6. Set-up the physics solver.
|
||||
int maxat = mesh.bdr_attributes.Max();
|
||||
Array<int> ess_bdr(maxat);
|
||||
ess_bdr = 0;
|
||||
ess_bdr[0] = 1;
|
||||
ConstantCoefficient one(1.0);
|
||||
ConstantCoefficient lambda_cf(lambda);
|
||||
ConstantCoefficient mu_cf(mu);
|
||||
LinearElasticitySolver * ElasticitySolver = new LinearElasticitySolver();
|
||||
ElasticitySolver->SetMesh(&mesh);
|
||||
ElasticitySolver->SetOrder(state_fec.GetOrder());
|
||||
ElasticitySolver->SetupFEM();
|
||||
Vector center(2); center(0) = 2.9; center(1) = 0.5;
|
||||
Vector force(2); force(0) = 0.0; force(1) = -1.0;
|
||||
double r = 0.05;
|
||||
VolumeForceCoefficient vforce_cf(r,center,force);
|
||||
ElasticitySolver->SetRHSCoefficient(&vforce_cf);
|
||||
ElasticitySolver->SetEssentialBoundary(ess_bdr);
|
||||
|
||||
// 7. Set-up the filter solver.
|
||||
ConstantCoefficient eps2_cf(epsilon*epsilon);
|
||||
DiffusionSolver * FilterSolver = new DiffusionSolver();
|
||||
FilterSolver->SetMesh(&mesh);
|
||||
FilterSolver->SetOrder(filter_fec.GetOrder());
|
||||
FilterSolver->SetDiffusionCoefficient(&eps2_cf);
|
||||
FilterSolver->SetMassCoefficient(&one);
|
||||
Array<int> ess_bdr_filter;
|
||||
if (mesh.bdr_attributes.Size())
|
||||
{
|
||||
cir = new CutIntegrationRule(order, Tr, levelset);
|
||||
ess_bdr_filter.SetSize(mesh.bdr_attributes.Max());
|
||||
ess_bdr_filter = 0;
|
||||
}
|
||||
FilterSolver->SetEssentialBoundary(ess_bdr_filter);
|
||||
FilterSolver->SetupFEM();
|
||||
|
||||
// 6. Define and assemble the linar forms on the finite element space.
|
||||
LinearForm surface(fespace);
|
||||
LinearForm volume(fespace);
|
||||
BilinearForm mass(&control_fes);
|
||||
mass.AddDomainIntegrator(new InverseIntegrator(new MassIntegrator(one)));
|
||||
mass.Assemble();
|
||||
SparseMatrix M;
|
||||
Array<int> empty;
|
||||
mass.FormSystemMatrix(empty,M);
|
||||
|
||||
surface.AddDomainIntegrator(new SurfaceLFIntegrator(u, levelset, sir));
|
||||
surface.Assemble();
|
||||
// 8. Define the Lagrange multiplier and gradient functions.
|
||||
GridFunction grad(&control_fes);
|
||||
GridFunction w_filter(&filter_fes);
|
||||
|
||||
if (itype == IntegrationType::Volumetric1D
|
||||
|| itype == IntegrationType::Volumetric2D
|
||||
|| itype == IntegrationType::Volumetric3D)
|
||||
{
|
||||
volume.AddDomainIntegrator(new SubdomainLFIntegrator(u, levelset, cir));
|
||||
volume.Assemble();
|
||||
}
|
||||
// 9. Define some tools for later.
|
||||
ConstantCoefficient zero(0.0);
|
||||
GridFunction onegf(&control_fes);
|
||||
onegf = 1.0;
|
||||
GridFunction zerogf(&control_fes);
|
||||
zerogf = 0.0;
|
||||
LinearForm vol_form(&control_fes);
|
||||
vol_form.AddDomainIntegrator(new DomainLFIntegrator(one));
|
||||
vol_form.Assemble();
|
||||
double domain_volume = vol_form(onegf);
|
||||
const double target_volume = domain_volume * vol_fraction;
|
||||
|
||||
// 7. Print information, computed values and errors to the console.
|
||||
int qorder = 0;
|
||||
int nbasis = 2 * (order + 1) + (int)(order * (order + 1) / 2);
|
||||
IntegrationRules irs(0, Quadrature1D::GaussLegendre);
|
||||
IntegrationRule ir = irs.Get(Geometry::SQUARE, qorder);
|
||||
for (; ir.GetNPoints() <= nbasis; qorder++)
|
||||
{
|
||||
ir = irs.Get(Geometry::SQUARE, qorder);
|
||||
}
|
||||
cout << "============================================" << endl;
|
||||
cout << "Mesh size dx: ";
|
||||
if (itype != IntegrationType::Volumetric1D)
|
||||
{
|
||||
cout << 3.2 / pow(2., (double)ref_levels) << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
cout << .25 / pow(2., (double)ref_levels) << endl;
|
||||
}
|
||||
if (itype == IntegrationType::Surface2D
|
||||
|| itype == IntegrationType::Volumetric2D)
|
||||
{
|
||||
cout << "Number of div free basis functions: " << nbasis << endl;
|
||||
cout << "Number of quadrature points: " << ir.GetNPoints() << endl;
|
||||
}
|
||||
cout << scientific << setprecision(2);
|
||||
cout << "============================================" << endl;
|
||||
cout << "Computed value of surface integral: " << surface.Sum() << endl;
|
||||
cout << "True value of surface integral: " << Surface() << endl;
|
||||
cout << "Absolut Error (Surface): ";
|
||||
cout << abs(surface.Sum() - Surface()) << endl;
|
||||
cout << "Relative Error (Surface): ";
|
||||
cout << abs(surface.Sum() - Surface()) / Surface() << endl;
|
||||
if (itype == IntegrationType::Volumetric1D
|
||||
|| itype == IntegrationType::Volumetric2D
|
||||
|| itype == IntegrationType::Volumetric3D)
|
||||
{
|
||||
cout << "--------------------------------------------" << endl;
|
||||
cout << "Computed value of volume integral: " << volume.Sum() << endl;
|
||||
cout << "True value of volume integral: " << Volume() << endl;
|
||||
cout << "Absolut Error (Volume): ";
|
||||
cout << abs(volume.Sum() - Volume()) << endl;
|
||||
cout << "Relative Error (Volume): ";
|
||||
cout << abs(volume.Sum() - Volume()) / Volume() << endl;
|
||||
}
|
||||
cout << "============================================" << endl;
|
||||
|
||||
// 8. Plot the level-set function on a high order finite element space.
|
||||
H1_FECollection fe_coll2(5, mesh->Dimension());
|
||||
FiniteElementSpace fespace2(mesh, &fe_coll2);
|
||||
FunctionCoefficient levelset_coeff(levelset);
|
||||
GridFunction lgf(&fespace2);
|
||||
lgf.ProjectCoefficient(levelset_coeff);
|
||||
// 10. Connect to GLVis. Prepare for VisIt output.
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sol_sock(vishost, visport);
|
||||
sol_sock.precision(8);
|
||||
sol_sock << "solution\n" << *mesh << lgf << flush;
|
||||
sol_sock << "keys pppppppppppppppppppppppppppcmmlRj\n";
|
||||
sol_sock << "levellines " << 0. << " " << 0. << " " << 1 << "\n" << flush;
|
||||
socketstream sout_r;
|
||||
if (glvis_visualization)
|
||||
{
|
||||
sout_r.open(vishost, visport);
|
||||
sout_r.precision(8);
|
||||
}
|
||||
|
||||
delete sir;
|
||||
delete cir;
|
||||
delete fespace;
|
||||
delete mesh;
|
||||
return EXIT_SUCCESS;
|
||||
#endif //MFEM_USE_LAPACK
|
||||
}
|
||||
mfem::ParaViewDataCollection paraview_dc("ex37", &mesh);
|
||||
if (paraview_output)
|
||||
{
|
||||
rho_gf.ProjectCoefficient(rho);
|
||||
paraview_dc.SetPrefixPath("ParaView");
|
||||
paraview_dc.SetLevelsOfDetail(order);
|
||||
paraview_dc.SetDataFormat(VTKFormat::BINARY);
|
||||
paraview_dc.SetHighOrderOutput(true);
|
||||
paraview_dc.SetCycle(0);
|
||||
paraview_dc.SetTime(0.0);
|
||||
paraview_dc.RegisterField("displacement",&u);
|
||||
paraview_dc.RegisterField("density",&rho_gf);
|
||||
paraview_dc.RegisterField("filtered_density",&rho_filter);
|
||||
paraview_dc.Save();
|
||||
}
|
||||
|
||||
// 11. Iterate:
|
||||
for (int k = 1; k <= max_it; k++)
|
||||
{
|
||||
if (k > 1) { alpha *= ((double) k) / ((double) k-1); }
|
||||
|
||||
mfem::out << "\nStep = " << k << std::endl;
|
||||
|
||||
// Step 1 - Filter solve
|
||||
// Solve (ϵ^2 ∇ ρ̃, ∇ v ) + (ρ̃,v) = (ρ,v)
|
||||
FilterSolver->SetRHSCoefficient(&rho);
|
||||
FilterSolver->Solve();
|
||||
rho_filter = *FilterSolver->GetFEMSolution();
|
||||
|
||||
// Step 2 - State solve
|
||||
// Solve (λ r(ρ̃) ∇⋅u, ∇⋅v) + (2 μ r(ρ̃) ε(u), ε(v)) = (f,v)
|
||||
SIMPInterpolationCoefficient SIMP_cf(&rho_filter,rho_min, 1.0);
|
||||
ProductCoefficient lambda_SIMP_cf(lambda_cf,SIMP_cf);
|
||||
ProductCoefficient mu_SIMP_cf(mu_cf,SIMP_cf);
|
||||
ElasticitySolver->SetLameCoefficients(&lambda_SIMP_cf,&mu_SIMP_cf);
|
||||
ElasticitySolver->Solve();
|
||||
u = *ElasticitySolver->GetFEMSolution();
|
||||
|
||||
// Step 3 - Adjoint filter solve
|
||||
// Solve (ϵ² ∇ w̃, ∇ v) + (w̃ ,v) = (-r'(ρ̃) ( λ |∇⋅u|² + 2 μ |ε(u)|²),v)
|
||||
StrainEnergyDensityCoefficient rhs_cf(&lambda_cf,&mu_cf,&u, &rho_filter,
|
||||
rho_min);
|
||||
FilterSolver->SetRHSCoefficient(&rhs_cf);
|
||||
FilterSolver->Solve();
|
||||
w_filter = *FilterSolver->GetFEMSolution();
|
||||
|
||||
// Step 4 - Compute gradient
|
||||
// Solve G = M⁻¹w̃
|
||||
GridFunctionCoefficient w_cf(&w_filter);
|
||||
LinearForm w_rhs(&control_fes);
|
||||
w_rhs.AddDomainIntegrator(new DomainLFIntegrator(w_cf));
|
||||
w_rhs.Assemble();
|
||||
M.Mult(w_rhs,grad);
|
||||
|
||||
// Step 5 - Update design variable ψ ← proj(ψ - αG)
|
||||
psi.Add(-alpha, grad);
|
||||
const double material_volume = proj(psi, target_volume);
|
||||
|
||||
// Compute ||ρ - ρ_old|| in control fes.
|
||||
double norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
|
||||
double norm_reduced_gradient = norm_increment/alpha;
|
||||
psi_old = psi;
|
||||
|
||||
double compliance = (*(ElasticitySolver->GetLinearForm()))(u);
|
||||
mfem::out << "norm of the reduced gradient = " << norm_reduced_gradient <<
|
||||
std::endl;
|
||||
mfem::out << "norm of the increment = " << norm_increment << endl;
|
||||
mfem::out << "compliance = " << compliance << std::endl;
|
||||
mfem::out << "volume fraction = " << material_volume / domain_volume <<
|
||||
std::endl;
|
||||
|
||||
if (glvis_visualization)
|
||||
{
|
||||
GridFunction r_gf(&filter_fes);
|
||||
r_gf.ProjectCoefficient(SIMP_cf);
|
||||
sout_r << "solution\n" << mesh << r_gf
|
||||
<< "window_title 'Design density r(ρ̃)'" << flush;
|
||||
}
|
||||
|
||||
if (paraview_output)
|
||||
{
|
||||
rho_gf.ProjectCoefficient(rho);
|
||||
paraview_dc.SetCycle(k);
|
||||
paraview_dc.SetTime((double)k);
|
||||
paraview_dc.Save();
|
||||
}
|
||||
|
||||
if (norm_reduced_gradient < ntol && norm_increment < itol)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete ElasticitySolver;
|
||||
delete FilterSolver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,748 @@
|
||||
// MFEM Example 37 - Serial/Parallel Shared Code
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
/// @brief Inverse sigmoid function
|
||||
double inv_sigmoid(double x)
|
||||
{
|
||||
double tol = 1e-12;
|
||||
x = std::min(std::max(tol,x),1.0-tol);
|
||||
return std::log(x/(1.0-x));
|
||||
}
|
||||
|
||||
/// @brief Sigmoid function
|
||||
double sigmoid(double x)
|
||||
{
|
||||
if (x >= 0)
|
||||
{
|
||||
return 1.0/(1.0+std::exp(-x));
|
||||
}
|
||||
else
|
||||
{
|
||||
return std::exp(x)/(1.0+std::exp(x));
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Derivative of sigmoid function
|
||||
double der_sigmoid(double x)
|
||||
{
|
||||
double tmp = sigmoid(-x);
|
||||
return tmp - std::pow(tmp,2);
|
||||
}
|
||||
|
||||
/// @brief Returns f(u(x)) where u is a scalar GridFunction and f:R → R
|
||||
class MappedGridFunctionCoefficient : public GridFunctionCoefficient
|
||||
{
|
||||
protected:
|
||||
std::function<double(const double)> fun; // f:R → R
|
||||
public:
|
||||
MappedGridFunctionCoefficient()
|
||||
:GridFunctionCoefficient(),
|
||||
fun([](double x) {return x;}) {}
|
||||
MappedGridFunctionCoefficient(const GridFunction *gf,
|
||||
std::function<double(const double)> fun_,
|
||||
int comp=1)
|
||||
:GridFunctionCoefficient(gf, comp),
|
||||
fun(fun_) {}
|
||||
|
||||
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
return fun(GridFunctionCoefficient::Eval(T, ip));
|
||||
}
|
||||
void SetFunction(std::function<double(const double)> fun_) { fun = fun_; }
|
||||
};
|
||||
|
||||
|
||||
/// @brief Returns f(u(x)) - f(v(x)) where u, v are scalar GridFunctions and f:R → R
|
||||
class DiffMappedGridFunctionCoefficient : public GridFunctionCoefficient
|
||||
{
|
||||
protected:
|
||||
const GridFunction *OtherGridF;
|
||||
GridFunctionCoefficient OtherGridF_cf;
|
||||
std::function<double(const double)> fun; // f:R → R
|
||||
public:
|
||||
DiffMappedGridFunctionCoefficient()
|
||||
:GridFunctionCoefficient(),
|
||||
OtherGridF(nullptr),
|
||||
OtherGridF_cf(),
|
||||
fun([](double x) {return x;}) {}
|
||||
DiffMappedGridFunctionCoefficient(const GridFunction *gf,
|
||||
const GridFunction *other_gf,
|
||||
std::function<double(const double)> fun_,
|
||||
int comp=1)
|
||||
:GridFunctionCoefficient(gf, comp),
|
||||
OtherGridF(other_gf),
|
||||
OtherGridF_cf(OtherGridF),
|
||||
fun(fun_) {}
|
||||
|
||||
virtual double Eval(ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
const double value1 = fun(GridFunctionCoefficient::Eval(T, ip));
|
||||
const double value2 = fun(OtherGridF_cf.Eval(T, ip));
|
||||
return value1 - value2;
|
||||
}
|
||||
void SetFunction(std::function<double(const double)> fun_) { fun = fun_; }
|
||||
};
|
||||
|
||||
/// @brief Solid isotropic material penalization (SIMP) coefficient
|
||||
class SIMPInterpolationCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
GridFunction *rho_filter;
|
||||
double min_val;
|
||||
double max_val;
|
||||
double exponent;
|
||||
|
||||
public:
|
||||
SIMPInterpolationCoefficient(GridFunction *rho_filter_, double min_val_= 1e-6,
|
||||
double max_val_ = 1.0, double exponent_ = 3)
|
||||
: rho_filter(rho_filter_), min_val(min_val_), max_val(max_val_),
|
||||
exponent(exponent_) { }
|
||||
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
|
||||
{
|
||||
double val = rho_filter->GetValue(T, ip);
|
||||
double coeff = min_val + pow(val,exponent)*(max_val-min_val);
|
||||
return coeff;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/// @brief Strain energy density coefficient
|
||||
class StrainEnergyDensityCoefficient : public Coefficient
|
||||
{
|
||||
protected:
|
||||
Coefficient * lambda=nullptr;
|
||||
Coefficient * mu=nullptr;
|
||||
GridFunction *u = nullptr; // displacement
|
||||
GridFunction *rho_filter = nullptr; // filter density
|
||||
DenseMatrix grad; // auxiliary matrix, used in Eval
|
||||
double exponent;
|
||||
double rho_min;
|
||||
|
||||
public:
|
||||
StrainEnergyDensityCoefficient(Coefficient *lambda_, Coefficient *mu_,
|
||||
GridFunction * u_, GridFunction * rho_filter_, double rho_min_=1e-6,
|
||||
double exponent_ = 3.0)
|
||||
: lambda(lambda_), mu(mu_), u(u_), rho_filter(rho_filter_),
|
||||
exponent(exponent_), rho_min(rho_min_)
|
||||
{
|
||||
MFEM_ASSERT(rho_min_ >= 0.0, "rho_min must be >= 0");
|
||||
MFEM_ASSERT(rho_min_ < 1.0, "rho_min must be > 1");
|
||||
MFEM_ASSERT(u, "displacement field is not set");
|
||||
MFEM_ASSERT(rho_filter, "density field is not set");
|
||||
}
|
||||
|
||||
virtual double Eval(ElementTransformation &T, const IntegrationPoint &ip)
|
||||
{
|
||||
double L = lambda->Eval(T, ip);
|
||||
double M = mu->Eval(T, ip);
|
||||
u->GetVectorGradient(T, grad);
|
||||
double div_u = grad.Trace();
|
||||
double density = L*div_u*div_u;
|
||||
int dim = T.GetSpaceDim();
|
||||
for (int i=0; i<dim; i++)
|
||||
{
|
||||
for (int j=0; j<dim; j++)
|
||||
{
|
||||
density += M*grad(i,j)*(grad(i,j)+grad(j,i));
|
||||
}
|
||||
}
|
||||
double val = rho_filter->GetValue(T,ip);
|
||||
|
||||
return -exponent * pow(val, exponent-1.0) * (1-rho_min) * density;
|
||||
}
|
||||
};
|
||||
|
||||
/// @brief Volumetric force for linear elasticity
|
||||
class VolumeForceCoefficient : public VectorCoefficient
|
||||
{
|
||||
private:
|
||||
double r;
|
||||
Vector center;
|
||||
Vector force;
|
||||
public:
|
||||
VolumeForceCoefficient(double r_,Vector & center_, Vector & force_) :
|
||||
VectorCoefficient(center_.Size()), r(r_), center(center_), force(force_) { }
|
||||
|
||||
using VectorCoefficient::Eval;
|
||||
|
||||
virtual void Eval(Vector &V, ElementTransformation &T,
|
||||
const IntegrationPoint &ip)
|
||||
{
|
||||
Vector xx; xx.SetSize(T.GetDimension());
|
||||
T.Transform(ip,xx);
|
||||
for (int i=0; i<xx.Size(); i++)
|
||||
{
|
||||
xx[i]=xx[i]-center[i];
|
||||
}
|
||||
|
||||
double cr=xx.Norml2();
|
||||
V.SetSize(T.GetDimension());
|
||||
if (cr <= r)
|
||||
{
|
||||
V = force;
|
||||
}
|
||||
else
|
||||
{
|
||||
V = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
void Set(double r_,Vector & center_, Vector & force_)
|
||||
{
|
||||
r=r_;
|
||||
center = center_;
|
||||
force = force_;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class for solving Poisson's equation:
|
||||
*
|
||||
* - ∇ ⋅(κ ∇ u) = f in Ω
|
||||
*
|
||||
*/
|
||||
class DiffusionSolver
|
||||
{
|
||||
private:
|
||||
Mesh * mesh = nullptr;
|
||||
int order = 1;
|
||||
// diffusion coefficient
|
||||
Coefficient * diffcf = nullptr;
|
||||
// mass coefficient
|
||||
Coefficient * masscf = nullptr;
|
||||
Coefficient * rhscf = nullptr;
|
||||
Coefficient * essbdr_cf = nullptr;
|
||||
Coefficient * neumann_cf = nullptr;
|
||||
VectorCoefficient * gradient_cf = nullptr;
|
||||
|
||||
// FEM solver
|
||||
int dim;
|
||||
FiniteElementCollection * fec = nullptr;
|
||||
FiniteElementSpace * fes = nullptr;
|
||||
Array<int> ess_bdr;
|
||||
Array<int> neumann_bdr;
|
||||
GridFunction * u = nullptr;
|
||||
LinearForm * b = nullptr;
|
||||
bool parallel;
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParMesh * pmesh = nullptr;
|
||||
ParFiniteElementSpace * pfes = nullptr;
|
||||
#endif
|
||||
|
||||
public:
|
||||
DiffusionSolver() { }
|
||||
DiffusionSolver(Mesh * mesh_, int order_, Coefficient * diffcf_,
|
||||
Coefficient * cf_);
|
||||
|
||||
void SetMesh(Mesh * mesh_)
|
||||
{
|
||||
mesh = mesh_;
|
||||
parallel = false;
|
||||
#ifdef MFEM_USE_MPI
|
||||
pmesh = dynamic_cast<ParMesh *>(mesh);
|
||||
if (pmesh) { parallel = true; }
|
||||
#endif
|
||||
}
|
||||
void SetOrder(int order_) { order = order_ ; }
|
||||
void SetDiffusionCoefficient(Coefficient * diffcf_) { diffcf = diffcf_; }
|
||||
void SetMassCoefficient(Coefficient * masscf_) { masscf = masscf_; }
|
||||
void SetRHSCoefficient(Coefficient * rhscf_) { rhscf = rhscf_; }
|
||||
void SetEssentialBoundary(const Array<int> & ess_bdr_) { ess_bdr = ess_bdr_;};
|
||||
void SetNeumannBoundary(const Array<int> & neumann_bdr_) { neumann_bdr = neumann_bdr_;};
|
||||
void SetNeumannData(Coefficient * neumann_cf_) {neumann_cf = neumann_cf_;}
|
||||
void SetEssBdrData(Coefficient * essbdr_cf_) {essbdr_cf = essbdr_cf_;}
|
||||
void SetGradientData(VectorCoefficient * gradient_cf_) {gradient_cf = gradient_cf_;}
|
||||
|
||||
void ResetFEM();
|
||||
void SetupFEM();
|
||||
|
||||
void Solve();
|
||||
GridFunction * GetFEMSolution();
|
||||
LinearForm * GetLinearForm() {return b;}
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParGridFunction * GetParFEMSolution();
|
||||
ParLinearForm * GetParLinearForm()
|
||||
{
|
||||
if (parallel)
|
||||
{
|
||||
return dynamic_cast<ParLinearForm *>(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Wrong code path. Call GetLinearForm");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
~DiffusionSolver();
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Class for solving linear elasticity:
|
||||
*
|
||||
* -∇ ⋅ σ(u) = f in Ω + BCs
|
||||
*
|
||||
* where
|
||||
*
|
||||
* σ(u) = λ ∇⋅u I + μ (∇ u + ∇uᵀ)
|
||||
*
|
||||
*/
|
||||
class LinearElasticitySolver
|
||||
{
|
||||
private:
|
||||
Mesh * mesh = nullptr;
|
||||
int order = 1;
|
||||
Coefficient * lambda_cf = nullptr;
|
||||
Coefficient * mu_cf = nullptr;
|
||||
VectorCoefficient * essbdr_cf = nullptr;
|
||||
VectorCoefficient * rhs_cf = nullptr;
|
||||
|
||||
// FEM solver
|
||||
int dim;
|
||||
FiniteElementCollection * fec = nullptr;
|
||||
FiniteElementSpace * fes = nullptr;
|
||||
Array<int> ess_bdr;
|
||||
Array<int> neumann_bdr;
|
||||
GridFunction * u = nullptr;
|
||||
LinearForm * b = nullptr;
|
||||
bool parallel;
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParMesh * pmesh = nullptr;
|
||||
ParFiniteElementSpace * pfes = nullptr;
|
||||
#endif
|
||||
|
||||
public:
|
||||
LinearElasticitySolver() { }
|
||||
LinearElasticitySolver(Mesh * mesh_, int order_,
|
||||
Coefficient * lambda_cf_, Coefficient * mu_cf_);
|
||||
|
||||
void SetMesh(Mesh * mesh_)
|
||||
{
|
||||
mesh = mesh_;
|
||||
parallel = false;
|
||||
#ifdef MFEM_USE_MPI
|
||||
pmesh = dynamic_cast<ParMesh *>(mesh);
|
||||
if (pmesh) { parallel = true; }
|
||||
#endif
|
||||
}
|
||||
void SetOrder(int order_) { order = order_ ; }
|
||||
void SetLameCoefficients(Coefficient * lambda_cf_, Coefficient * mu_cf_) { lambda_cf = lambda_cf_; mu_cf = mu_cf_; }
|
||||
void SetRHSCoefficient(VectorCoefficient * rhs_cf_) { rhs_cf = rhs_cf_; }
|
||||
void SetEssentialBoundary(const Array<int> & ess_bdr_) { ess_bdr = ess_bdr_;};
|
||||
void SetNeumannBoundary(const Array<int> & neumann_bdr_) { neumann_bdr = neumann_bdr_;};
|
||||
void SetEssBdrData(VectorCoefficient * essbdr_cf_) {essbdr_cf = essbdr_cf_;}
|
||||
|
||||
void ResetFEM();
|
||||
void SetupFEM();
|
||||
|
||||
void Solve();
|
||||
GridFunction * GetFEMSolution();
|
||||
LinearForm * GetLinearForm() {return b;}
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParGridFunction * GetParFEMSolution();
|
||||
ParLinearForm * GetParLinearForm()
|
||||
{
|
||||
if (parallel)
|
||||
{
|
||||
return dynamic_cast<ParLinearForm *>(b);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Wrong code path. Call GetLinearForm");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
~LinearElasticitySolver();
|
||||
|
||||
};
|
||||
|
||||
|
||||
// Poisson solver
|
||||
|
||||
DiffusionSolver::DiffusionSolver(Mesh * mesh_, int order_,
|
||||
Coefficient * diffcf_, Coefficient * rhscf_)
|
||||
: mesh(mesh_), order(order_), diffcf(diffcf_), rhscf(rhscf_)
|
||||
{
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
pmesh = dynamic_cast<ParMesh *>(mesh);
|
||||
if (pmesh) { parallel = true; }
|
||||
#endif
|
||||
|
||||
SetupFEM();
|
||||
}
|
||||
|
||||
void DiffusionSolver::SetupFEM()
|
||||
{
|
||||
dim = mesh->Dimension();
|
||||
fec = new H1_FECollection(order, dim);
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
pfes = new ParFiniteElementSpace(pmesh, fec);
|
||||
u = new ParGridFunction(pfes);
|
||||
b = new ParLinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
fes = new FiniteElementSpace(mesh, fec);
|
||||
u = new GridFunction(fes);
|
||||
b = new LinearForm(fes);
|
||||
}
|
||||
#else
|
||||
fes = new FiniteElementSpace(mesh, fec);
|
||||
u = new GridFunction(fes);
|
||||
b = new LinearForm(fes);
|
||||
#endif
|
||||
*u=0.0;
|
||||
|
||||
if (!ess_bdr.Size())
|
||||
{
|
||||
if (mesh->bdr_attributes.Size())
|
||||
{
|
||||
ess_bdr.SetSize(mesh->bdr_attributes.Max());
|
||||
ess_bdr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DiffusionSolver::Solve()
|
||||
{
|
||||
OperatorPtr A;
|
||||
Vector B, X;
|
||||
Array<int> ess_tdof_list;
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
pfes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
}
|
||||
#else
|
||||
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
#endif
|
||||
*u=0.0;
|
||||
if (b)
|
||||
{
|
||||
delete b;
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
b = new ParLinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = new LinearForm(fes);
|
||||
}
|
||||
#else
|
||||
b = new LinearForm(fes);
|
||||
#endif
|
||||
}
|
||||
if (rhscf)
|
||||
{
|
||||
b->AddDomainIntegrator(new DomainLFIntegrator(*rhscf));
|
||||
}
|
||||
if (neumann_cf)
|
||||
{
|
||||
MFEM_VERIFY(neumann_bdr.Size(), "neumann_bdr attributes not provided");
|
||||
b->AddBoundaryIntegrator(new BoundaryLFIntegrator(*neumann_cf),neumann_bdr);
|
||||
}
|
||||
else if (gradient_cf)
|
||||
{
|
||||
MFEM_VERIFY(neumann_bdr.Size(), "neumann_bdr attributes not provided");
|
||||
b->AddBoundaryIntegrator(new BoundaryNormalLFIntegrator(*gradient_cf),
|
||||
neumann_bdr);
|
||||
}
|
||||
|
||||
b->Assemble();
|
||||
|
||||
BilinearForm * a = nullptr;
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
a = new ParBilinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = new BilinearForm(fes);
|
||||
}
|
||||
#else
|
||||
a = new BilinearForm(fes);
|
||||
#endif
|
||||
a->AddDomainIntegrator(new DiffusionIntegrator(*diffcf));
|
||||
if (masscf)
|
||||
{
|
||||
a->AddDomainIntegrator(new MassIntegrator(*masscf));
|
||||
}
|
||||
a->Assemble();
|
||||
if (essbdr_cf)
|
||||
{
|
||||
u->ProjectBdrCoefficient(*essbdr_cf,ess_bdr);
|
||||
}
|
||||
a->FormLinearSystem(ess_tdof_list, *u, *b, A, X, B);
|
||||
|
||||
CGSolver * cg = nullptr;
|
||||
Solver * M = nullptr;
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
M = new HypreBoomerAMG;
|
||||
dynamic_cast<HypreBoomerAMG*>(M)->SetPrintLevel(0);
|
||||
cg = new CGSolver(pmesh->GetComm());
|
||||
}
|
||||
else
|
||||
{
|
||||
M = new GSSmoother((SparseMatrix&)(*A));
|
||||
cg = new CGSolver;
|
||||
}
|
||||
#else
|
||||
M = new GSSmoother((SparseMatrix&)(*A));
|
||||
cg = new CGSolver;
|
||||
#endif
|
||||
cg->SetRelTol(1e-12);
|
||||
cg->SetMaxIter(10000);
|
||||
cg->SetPrintLevel(0);
|
||||
cg->SetPreconditioner(*M);
|
||||
cg->SetOperator(*A);
|
||||
cg->Mult(B, X);
|
||||
delete M;
|
||||
delete cg;
|
||||
a->RecoverFEMSolution(X, *b, *u);
|
||||
delete a;
|
||||
}
|
||||
|
||||
GridFunction * DiffusionSolver::GetFEMSolution()
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParGridFunction * DiffusionSolver::GetParFEMSolution()
|
||||
{
|
||||
if (parallel)
|
||||
{
|
||||
return dynamic_cast<ParGridFunction*>(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Wrong code path. Call GetFEMSolution");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
DiffusionSolver::~DiffusionSolver()
|
||||
{
|
||||
delete u; u = nullptr;
|
||||
delete fes; fes = nullptr;
|
||||
#ifdef MFEM_USE_MPI
|
||||
delete pfes; pfes=nullptr;
|
||||
#endif
|
||||
delete fec; fec = nullptr;
|
||||
delete b;
|
||||
}
|
||||
|
||||
|
||||
// Elasticity solver
|
||||
|
||||
LinearElasticitySolver::LinearElasticitySolver(Mesh * mesh_, int order_,
|
||||
Coefficient * lambda_cf_, Coefficient * mu_cf_)
|
||||
: mesh(mesh_), order(order_), lambda_cf(lambda_cf_), mu_cf(mu_cf_)
|
||||
{
|
||||
#ifdef MFEM_USE_MPI
|
||||
pmesh = dynamic_cast<ParMesh *>(mesh);
|
||||
if (pmesh) { parallel = true; }
|
||||
#endif
|
||||
SetupFEM();
|
||||
}
|
||||
|
||||
void LinearElasticitySolver::SetupFEM()
|
||||
{
|
||||
dim = mesh->Dimension();
|
||||
fec = new H1_FECollection(order, dim,BasisType::Positive);
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
pfes = new ParFiniteElementSpace(pmesh, fec, dim);
|
||||
u = new ParGridFunction(pfes);
|
||||
b = new ParLinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
fes = new FiniteElementSpace(mesh, fec,dim);
|
||||
u = new GridFunction(fes);
|
||||
b = new LinearForm(fes);
|
||||
}
|
||||
#else
|
||||
fes = new FiniteElementSpace(mesh, fec, dim);
|
||||
u = new GridFunction(fes);
|
||||
b = new LinearForm(fes);
|
||||
#endif
|
||||
*u=0.0;
|
||||
|
||||
if (!ess_bdr.Size())
|
||||
{
|
||||
if (mesh->bdr_attributes.Size())
|
||||
{
|
||||
ess_bdr.SetSize(mesh->bdr_attributes.Max());
|
||||
ess_bdr = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LinearElasticitySolver::Solve()
|
||||
{
|
||||
GridFunction * x = nullptr;
|
||||
OperatorPtr A;
|
||||
Vector B, X;
|
||||
Array<int> ess_tdof_list;
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
x = new ParGridFunction(pfes);
|
||||
pfes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
}
|
||||
else
|
||||
{
|
||||
x = new GridFunction(fes);
|
||||
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
}
|
||||
#else
|
||||
x = new GridFunction(fes);
|
||||
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
|
||||
#endif
|
||||
*u=0.0;
|
||||
if (b)
|
||||
{
|
||||
delete b;
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
b = new ParLinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
b = new LinearForm(fes);
|
||||
}
|
||||
#else
|
||||
b = new LinearForm(fes);
|
||||
#endif
|
||||
}
|
||||
if (rhs_cf)
|
||||
{
|
||||
b->AddDomainIntegrator(new VectorDomainLFIntegrator(*rhs_cf));
|
||||
}
|
||||
|
||||
b->Assemble();
|
||||
|
||||
*x = 0.0;
|
||||
|
||||
BilinearForm * a = nullptr;
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
a = new ParBilinearForm(pfes);
|
||||
}
|
||||
else
|
||||
{
|
||||
a = new BilinearForm(fes);
|
||||
}
|
||||
#else
|
||||
a = new BilinearForm(fes);
|
||||
#endif
|
||||
a->AddDomainIntegrator(new ElasticityIntegrator(*lambda_cf, *mu_cf));
|
||||
a->Assemble();
|
||||
if (essbdr_cf)
|
||||
{
|
||||
u->ProjectBdrCoefficient(*essbdr_cf,ess_bdr);
|
||||
}
|
||||
a->FormLinearSystem(ess_tdof_list, *x, *b, A, X, B);
|
||||
|
||||
CGSolver * cg = nullptr;
|
||||
Solver * M = nullptr;
|
||||
#ifdef MFEM_USE_MPI
|
||||
if (parallel)
|
||||
{
|
||||
M = new HypreBoomerAMG;
|
||||
dynamic_cast<HypreBoomerAMG*>(M)->SetPrintLevel(0);
|
||||
cg = new CGSolver(pmesh->GetComm());
|
||||
}
|
||||
else
|
||||
{
|
||||
M = new GSSmoother((SparseMatrix&)(*A));
|
||||
cg = new CGSolver;
|
||||
}
|
||||
#else
|
||||
M = new GSSmoother((SparseMatrix&)(*A));
|
||||
cg = new CGSolver;
|
||||
#endif
|
||||
cg->SetRelTol(1e-10);
|
||||
cg->SetMaxIter(10000);
|
||||
cg->SetPrintLevel(0);
|
||||
cg->SetPreconditioner(*M);
|
||||
cg->SetOperator(*A);
|
||||
cg->Mult(B, X);
|
||||
delete M;
|
||||
delete cg;
|
||||
a->RecoverFEMSolution(X, *b, *x);
|
||||
*u+=*x;
|
||||
delete a;
|
||||
delete x;
|
||||
}
|
||||
|
||||
GridFunction * LinearElasticitySolver::GetFEMSolution()
|
||||
{
|
||||
return u;
|
||||
}
|
||||
|
||||
#ifdef MFEM_USE_MPI
|
||||
ParGridFunction * LinearElasticitySolver::GetParFEMSolution()
|
||||
{
|
||||
if (parallel)
|
||||
{
|
||||
return dynamic_cast<ParGridFunction*>(u);
|
||||
}
|
||||
else
|
||||
{
|
||||
MFEM_ABORT("Wrong code path. Call GetFEMSolution");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
LinearElasticitySolver::~LinearElasticitySolver()
|
||||
{
|
||||
delete u; u = nullptr;
|
||||
delete fes; fes = nullptr;
|
||||
#ifdef MFEM_USE_MPI
|
||||
delete pfes; pfes=nullptr;
|
||||
#endif
|
||||
delete fec; fec = nullptr;
|
||||
delete b;
|
||||
}
|
||||
|
||||
} // namespace mfem
|
||||
|
||||
@@ -0,0 +1,497 @@
|
||||
// MFEM Example 37 - Parallel Version
|
||||
//
|
||||
// Compile with: make ex37p
|
||||
//
|
||||
// Sample runs:
|
||||
// mpirun -np 4 ex37p -alpha 10 -pv
|
||||
// mpirun -np 4 ex37p -lambda 0.1 -mu 0.1
|
||||
// mpirun -np 4 ex37p -o 2 -alpha 5.0 -mi 50 -vf 0.4 -ntol 1e-5
|
||||
// mpirun -np 4 ex37p -r 6 -o 2 -alpha 10.0 -epsilon 0.02 -mi 50 -ntol 1e-5
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to solve a
|
||||
// density-filtered [3] topology optimization problem. The
|
||||
// objective is to minimize the compliance
|
||||
//
|
||||
// minimize ∫_Ω f⋅u dx over u ∈ [H¹(Ω)]² and ρ ∈ L¹(Ω)
|
||||
//
|
||||
// subject to
|
||||
//
|
||||
// -Div(r(ρ̃)Cε(u)) = f in Ω + BCs
|
||||
// -ϵ²Δρ̃ + ρ̃ = ρ in Ω + Neumann BCs
|
||||
// 0 ≤ ρ ≤ 1 in Ω
|
||||
// ∫_Ω ρ dx = θ vol(Ω)
|
||||
//
|
||||
// Here, r(ρ̃) = ρ₀ + ρ̃³ (1-ρ₀) is the solid isotropic material
|
||||
// penalization (SIMP) law, C is the elasticity tensor for an
|
||||
// isotropic linearly elastic material, ϵ > 0 is the design
|
||||
// length scale, and 0 < θ < 1 is the volume fraction.
|
||||
//
|
||||
// The problem is discretized and gradients are computing using
|
||||
// finite elements [1]. The design is optimized using an entropic
|
||||
// mirror descent algorithm introduced by Keith and Surowiec [2]
|
||||
// that is tailored to the bound constraint 0 ≤ ρ ≤ 1.
|
||||
//
|
||||
// This example highlights the ability of MFEM to deliver high-
|
||||
// order solutions to inverse design problems and showcases how
|
||||
// to set up and solve PDE-constrained optimization problems
|
||||
// using the so-called reduced space approach.
|
||||
//
|
||||
// [1] Andreassen, E., Clausen, A., Schevenels, M., Lazarov, B. S., & Sigmund, O.
|
||||
// (2011). Efficient topology optimization in MATLAB using 88 lines of
|
||||
// code. Structural and Multidisciplinary Optimization, 43(1), 1-16.
|
||||
// [2] Keith, B. and Surowiec, T. (2023) Proximal Galerkin: A structure-
|
||||
// preserving finite element method for pointwise bound constraints.
|
||||
// arXiv:2307.12444 [math.NA]
|
||||
// [3] Lazarov, B. S., & Sigmund, O. (2011). Filters in topology optimization
|
||||
// based on Helmholtz‐type differential equations. International Journal
|
||||
// for Numerical Methods in Engineering, 86(6), 765-781.
|
||||
|
||||
#include "mfem.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "ex37.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace mfem;
|
||||
|
||||
/**
|
||||
* @brief Bregman projection of ρ = sigmoid(ψ) onto the subspace
|
||||
* ∫_Ω ρ dx = θ vol(Ω) as follows:
|
||||
*
|
||||
* 1. Compute the root of the R → R function
|
||||
* f(c) = ∫_Ω sigmoid(ψ + c) dx - θ vol(Ω)
|
||||
* 2. Set ψ ← ψ + c.
|
||||
*
|
||||
* @param psi a GridFunction to be updated
|
||||
* @param target_volume θ vol(Ω)
|
||||
* @param tol Newton iteration tolerance
|
||||
* @param max_its Newton maximum iteration number
|
||||
* @return double Final volume, ∫_Ω sigmoid(ψ)
|
||||
*/
|
||||
double proj(ParGridFunction &psi, double target_volume, double tol=1e-12,
|
||||
int max_its=10)
|
||||
{
|
||||
MappedGridFunctionCoefficient sigmoid_psi(&psi, sigmoid);
|
||||
MappedGridFunctionCoefficient der_sigmoid_psi(&psi, der_sigmoid);
|
||||
|
||||
ParLinearForm int_sigmoid_psi(psi.ParFESpace());
|
||||
int_sigmoid_psi.AddDomainIntegrator(new DomainLFIntegrator(sigmoid_psi));
|
||||
ParLinearForm int_der_sigmoid_psi(psi.ParFESpace());
|
||||
int_der_sigmoid_psi.AddDomainIntegrator(new DomainLFIntegrator(
|
||||
der_sigmoid_psi));
|
||||
bool done = false;
|
||||
for (int k=0; k<max_its; k++) // Newton iteration
|
||||
{
|
||||
int_sigmoid_psi.Assemble(); // Recompute f(c) with updated ψ
|
||||
double f = int_sigmoid_psi.Sum();
|
||||
MPI_Allreduce(MPI_IN_PLACE, &f, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
|
||||
f -= target_volume;
|
||||
|
||||
int_der_sigmoid_psi.Assemble(); // Recompute df(c) with updated ψ
|
||||
double df = int_der_sigmoid_psi.Sum();
|
||||
MPI_Allreduce(MPI_IN_PLACE, &df, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
|
||||
|
||||
const double dc = -f/df;
|
||||
psi += dc;
|
||||
if (abs(dc) < tol) { done = true; break; }
|
||||
}
|
||||
if (!done)
|
||||
{
|
||||
mfem_warning("Projection reached maximum iteration without converging. "
|
||||
"Result may not be accurate.");
|
||||
}
|
||||
int_sigmoid_psi.Assemble();
|
||||
double material_volume = int_sigmoid_psi.Sum();
|
||||
MPI_Allreduce(MPI_IN_PLACE, &material_volume, 1, MPI_DOUBLE, MPI_SUM,
|
||||
MPI_COMM_WORLD);
|
||||
return material_volume;
|
||||
}
|
||||
|
||||
/**
|
||||
* ---------------------------------------------------------------
|
||||
* ALGORITHM PREAMBLE
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* The Lagrangian for this problem is
|
||||
*
|
||||
* L(u,ρ,ρ̃,w,w̃) = (f,u) - (r(ρ̃) C ε(u),ε(w)) + (f,w)
|
||||
* - (ϵ² ∇ρ̃,∇w̃) - (ρ̃,w̃) + (ρ,w̃)
|
||||
*
|
||||
* where
|
||||
*
|
||||
* r(ρ̃) = ρ₀ + ρ̃³ (1 - ρ₀) (SIMP rule)
|
||||
*
|
||||
* ε(u) = (∇u + ∇uᵀ)/2 (symmetric gradient)
|
||||
*
|
||||
* C e = λtr(e)I + 2μe (isotropic material)
|
||||
*
|
||||
* NOTE: The Lame parameters can be computed from Young's modulus E
|
||||
* and Poisson's ratio ν as follows:
|
||||
*
|
||||
* λ = E ν/((1+ν)(1-2ν)), μ = E/(2(1+ν))
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* Discretization choices:
|
||||
*
|
||||
* u ∈ V ⊂ (H¹)ᵈ (order p)
|
||||
* ψ ∈ L² (order p - 1), ρ = sigmoid(ψ)
|
||||
* ρ̃ ∈ H¹ (order p)
|
||||
* w ∈ V (order p)
|
||||
* w̃ ∈ H¹ (order p)
|
||||
*
|
||||
* ---------------------------------------------------------------
|
||||
* ALGORITHM
|
||||
* ---------------------------------------------------------------
|
||||
*
|
||||
* Update ρ with projected mirror descent via the following algorithm.
|
||||
*
|
||||
* 1. Initialize ψ = inv_sigmoid(vol_fraction) so that ∫ sigmoid(ψ) = θ vol(Ω)
|
||||
*
|
||||
* While not converged:
|
||||
*
|
||||
* 2. Solve filter equation ∂_w̃ L = 0; i.e.,
|
||||
*
|
||||
* (ϵ² ∇ ρ̃, ∇ v ) + (ρ̃,v) = (ρ,v) ∀ v ∈ H¹.
|
||||
*
|
||||
* 3. Solve primal problem ∂_w L = 0; i.e.,
|
||||
*
|
||||
* (λ r(ρ̃) ∇⋅u, ∇⋅v) + (2 μ r(ρ̃) ε(u), ε(v)) = (f,v) ∀ v ∈ V.
|
||||
*
|
||||
* NB. The dual problem ∂_u L = 0 is the negative of the primal problem due to symmetry.
|
||||
*
|
||||
* 4. Solve for filtered gradient ∂_ρ̃ L = 0; i.e.,
|
||||
*
|
||||
* (ϵ² ∇ w̃ , ∇ v ) + (w̃ ,v) = (-r'(ρ̃) ( λ |∇⋅u|² + 2 μ |ε(u)|²),v) ∀ v ∈ H¹.
|
||||
*
|
||||
* 5. Project the gradient onto the discrete latent space; i.e., solve
|
||||
*
|
||||
* (G,v) = (w̃,v) ∀ v ∈ L².
|
||||
*
|
||||
* 6. Bregman proximal gradient update; i.e.,
|
||||
*
|
||||
* ψ ← ψ - αG + c,
|
||||
*
|
||||
* where α > 0 is a step size parameter and c ∈ R is a constant ensuring
|
||||
*
|
||||
* ∫_Ω sigmoid(ψ - αG + c) dx = θ vol(Ω).
|
||||
*
|
||||
* end
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// 0. Initialize MPI and HYPRE.
|
||||
Mpi::Init();
|
||||
int num_procs = Mpi::WorldSize();
|
||||
int myid = Mpi::WorldRank();
|
||||
Hypre::Init();
|
||||
|
||||
// 1. Parse command-line options.
|
||||
int ref_levels = 5;
|
||||
int order = 2;
|
||||
double alpha = 1.0;
|
||||
double epsilon = 0.01;
|
||||
double vol_fraction = 0.5;
|
||||
int max_it = 1e3;
|
||||
double itol = 1e-1;
|
||||
double ntol = 1e-4;
|
||||
double rho_min = 1e-6;
|
||||
double lambda = 1.0;
|
||||
double mu = 1.0;
|
||||
bool glvis_visualization = true;
|
||||
bool paraview_output = false;
|
||||
|
||||
OptionsParser args(argc, argv);
|
||||
args.AddOption(&ref_levels, "-r", "--refine",
|
||||
"Number of times to refine the mesh uniformly.");
|
||||
args.AddOption(&order, "-o", "--order",
|
||||
"Order (degree) of the finite elements.");
|
||||
args.AddOption(&alpha, "-alpha", "--alpha-step-length",
|
||||
"Step length for gradient descent.");
|
||||
args.AddOption(&epsilon, "-epsilon", "--epsilon-thickness",
|
||||
"Length scale for ρ.");
|
||||
args.AddOption(&max_it, "-mi", "--max-it",
|
||||
"Maximum number of gradient descent iterations.");
|
||||
args.AddOption(&ntol, "-ntol", "--rel-tol",
|
||||
"Normalized exit tolerance.");
|
||||
args.AddOption(&itol, "-itol", "--abs-tol",
|
||||
"Increment exit tolerance.");
|
||||
args.AddOption(&vol_fraction, "-vf", "--volume-fraction",
|
||||
"Volume fraction for the material density.");
|
||||
args.AddOption(&lambda, "-lambda", "--lambda",
|
||||
"Lamé constant λ.");
|
||||
args.AddOption(&mu, "-mu", "--mu",
|
||||
"Lamé constant μ.");
|
||||
args.AddOption(&rho_min, "-rmin", "--psi-min",
|
||||
"Minimum of density coefficient.");
|
||||
args.AddOption(&glvis_visualization, "-vis", "--visualization", "-no-vis",
|
||||
"--no-visualization",
|
||||
"Enable or disable GLVis visualization.");
|
||||
args.AddOption(¶view_output, "-pv", "--paraview", "-no-pv",
|
||||
"--no-paraview",
|
||||
"Enable or disable ParaView output.");
|
||||
args.Parse();
|
||||
if (!args.Good())
|
||||
{
|
||||
if (myid == 0)
|
||||
{
|
||||
args.PrintUsage(cout);
|
||||
}
|
||||
MPI_Finalize();
|
||||
return 1;
|
||||
}
|
||||
if (myid == 0)
|
||||
{
|
||||
mfem::out << num_procs << " number of process created.\n";
|
||||
args.PrintOptions(cout);
|
||||
}
|
||||
|
||||
Mesh mesh = Mesh::MakeCartesian2D(3, 1, mfem::Element::Type::QUADRILATERAL,
|
||||
true, 3.0, 1.0);
|
||||
int dim = mesh.Dimension();
|
||||
|
||||
// 2. Set BCs.
|
||||
for (int i = 0; i<mesh.GetNBE(); i++)
|
||||
{
|
||||
Element * be = mesh.GetBdrElement(i);
|
||||
Array<int> vertices;
|
||||
be->GetVertices(vertices);
|
||||
|
||||
double * coords1 = mesh.GetVertex(vertices[0]);
|
||||
double * coords2 = mesh.GetVertex(vertices[1]);
|
||||
|
||||
Vector center(2);
|
||||
center(0) = 0.5*(coords1[0] + coords2[0]);
|
||||
center(1) = 0.5*(coords1[1] + coords2[1]);
|
||||
|
||||
if (abs(center(0) - 0.0) < 1e-10)
|
||||
{
|
||||
// the left edge
|
||||
be->SetAttribute(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other boundaries
|
||||
be->SetAttribute(2);
|
||||
}
|
||||
}
|
||||
mesh.SetAttributes();
|
||||
|
||||
// 3. Refine the mesh.
|
||||
for (int lev = 0; lev < ref_levels; lev++)
|
||||
{
|
||||
mesh.UniformRefinement();
|
||||
}
|
||||
|
||||
ParMesh pmesh(MPI_COMM_WORLD, mesh);
|
||||
mesh.Clear();
|
||||
|
||||
// 4. Define the necessary finite element spaces on the mesh.
|
||||
H1_FECollection state_fec(order, dim); // space for u
|
||||
H1_FECollection filter_fec(order, dim); // space for ρ̃
|
||||
L2_FECollection control_fec(order-1, dim,
|
||||
BasisType::GaussLobatto); // space for ψ
|
||||
ParFiniteElementSpace state_fes(&pmesh, &state_fec,dim);
|
||||
ParFiniteElementSpace filter_fes(&pmesh, &filter_fec);
|
||||
ParFiniteElementSpace control_fes(&pmesh, &control_fec);
|
||||
|
||||
HYPRE_BigInt state_size = state_fes.GlobalTrueVSize();
|
||||
HYPRE_BigInt control_size = control_fes.GlobalTrueVSize();
|
||||
HYPRE_BigInt filter_size = filter_fes.GlobalTrueVSize();
|
||||
if (myid==0)
|
||||
{
|
||||
cout << "Number of state unknowns: " << state_size << endl;
|
||||
cout << "Number of filter unknowns: " << filter_size << endl;
|
||||
cout << "Number of control unknowns: " << control_size << endl;
|
||||
}
|
||||
|
||||
// 5. Set the initial guess for ρ.
|
||||
ParGridFunction u(&state_fes);
|
||||
ParGridFunction psi(&control_fes);
|
||||
ParGridFunction psi_old(&control_fes);
|
||||
ParGridFunction rho_filter(&filter_fes);
|
||||
u = 0.0;
|
||||
rho_filter = vol_fraction;
|
||||
psi = inv_sigmoid(vol_fraction);
|
||||
psi_old = inv_sigmoid(vol_fraction);
|
||||
|
||||
// ρ = sigmoid(ψ)
|
||||
MappedGridFunctionCoefficient rho(&psi, sigmoid);
|
||||
// Interpolation of ρ = sigmoid(ψ) in control fes (for ParaView output)
|
||||
ParGridFunction rho_gf(&control_fes);
|
||||
// ρ - ρ_old = sigmoid(ψ) - sigmoid(ψ_old)
|
||||
DiffMappedGridFunctionCoefficient succ_diff_rho(&psi, &psi_old, sigmoid);
|
||||
|
||||
// 6. Set-up the physics solver.
|
||||
int maxat = pmesh.bdr_attributes.Max();
|
||||
Array<int> ess_bdr(maxat);
|
||||
ess_bdr = 0;
|
||||
ess_bdr[0] = 1;
|
||||
ConstantCoefficient one(1.0);
|
||||
ConstantCoefficient lambda_cf(lambda);
|
||||
ConstantCoefficient mu_cf(mu);
|
||||
LinearElasticitySolver * ElasticitySolver = new LinearElasticitySolver();
|
||||
ElasticitySolver->SetMesh(&pmesh);
|
||||
ElasticitySolver->SetOrder(state_fec.GetOrder());
|
||||
ElasticitySolver->SetupFEM();
|
||||
Vector center(2); center(0) = 2.9; center(1) = 0.5;
|
||||
Vector force(2); force(0) = 0.0; force(1) = -1.0;
|
||||
double r = 0.05;
|
||||
VolumeForceCoefficient vforce_cf(r,center,force);
|
||||
ElasticitySolver->SetRHSCoefficient(&vforce_cf);
|
||||
ElasticitySolver->SetEssentialBoundary(ess_bdr);
|
||||
|
||||
// 7. Set-up the filter solver.
|
||||
ConstantCoefficient eps2_cf(epsilon*epsilon);
|
||||
DiffusionSolver * FilterSolver = new DiffusionSolver();
|
||||
FilterSolver->SetMesh(&pmesh);
|
||||
FilterSolver->SetOrder(filter_fec.GetOrder());
|
||||
FilterSolver->SetDiffusionCoefficient(&eps2_cf);
|
||||
FilterSolver->SetMassCoefficient(&one);
|
||||
Array<int> ess_bdr_filter;
|
||||
if (pmesh.bdr_attributes.Size())
|
||||
{
|
||||
ess_bdr_filter.SetSize(pmesh.bdr_attributes.Max());
|
||||
ess_bdr_filter = 0;
|
||||
}
|
||||
FilterSolver->SetEssentialBoundary(ess_bdr_filter);
|
||||
FilterSolver->SetupFEM();
|
||||
|
||||
ParBilinearForm mass(&control_fes);
|
||||
mass.AddDomainIntegrator(new InverseIntegrator(new MassIntegrator(one)));
|
||||
mass.Assemble();
|
||||
HypreParMatrix M;
|
||||
Array<int> empty;
|
||||
mass.FormSystemMatrix(empty,M);
|
||||
|
||||
// 8. Define the Lagrange multiplier and gradient functions.
|
||||
ParGridFunction grad(&control_fes);
|
||||
ParGridFunction w_filter(&filter_fes);
|
||||
|
||||
// 9. Define some tools for later.
|
||||
ConstantCoefficient zero(0.0);
|
||||
ParGridFunction onegf(&control_fes);
|
||||
onegf = 1.0;
|
||||
ParGridFunction zerogf(&control_fes);
|
||||
zerogf = 0.0;
|
||||
ParLinearForm vol_form(&control_fes);
|
||||
vol_form.AddDomainIntegrator(new DomainLFIntegrator(one));
|
||||
vol_form.Assemble();
|
||||
double domain_volume = vol_form(onegf);
|
||||
const double target_volume = domain_volume * vol_fraction;
|
||||
|
||||
// 10. Connect to GLVis. Prepare for VisIt output.
|
||||
char vishost[] = "localhost";
|
||||
int visport = 19916;
|
||||
socketstream sout_r;
|
||||
if (glvis_visualization)
|
||||
{
|
||||
sout_r.open(vishost, visport);
|
||||
sout_r.precision(8);
|
||||
}
|
||||
|
||||
mfem::ParaViewDataCollection paraview_dc("ex37p", &pmesh);
|
||||
if (paraview_output)
|
||||
{
|
||||
rho_gf.ProjectCoefficient(rho);
|
||||
paraview_dc.SetPrefixPath("ParaView");
|
||||
paraview_dc.SetLevelsOfDetail(order);
|
||||
paraview_dc.SetDataFormat(VTKFormat::BINARY);
|
||||
paraview_dc.SetHighOrderOutput(true);
|
||||
paraview_dc.SetCycle(0);
|
||||
paraview_dc.SetTime(0.0);
|
||||
paraview_dc.RegisterField("displacement",&u);
|
||||
paraview_dc.RegisterField("density",&rho_gf);
|
||||
paraview_dc.RegisterField("filtered_density",&rho_filter);
|
||||
paraview_dc.Save();
|
||||
}
|
||||
|
||||
// 11. Iterate:
|
||||
for (int k = 1; k <= max_it; k++)
|
||||
{
|
||||
if (k > 1) { alpha *= ((double) k) / ((double) k-1); }
|
||||
|
||||
if (myid == 0)
|
||||
{
|
||||
cout << "\nStep = " << k << endl;
|
||||
}
|
||||
|
||||
// Step 1 - Filter solve
|
||||
// Solve (ϵ^2 ∇ ρ̃, ∇ v ) + (ρ̃,v) = (ρ,v)
|
||||
FilterSolver->SetRHSCoefficient(&rho);
|
||||
FilterSolver->Solve();
|
||||
rho_filter = *FilterSolver->GetFEMSolution();
|
||||
|
||||
// Step 2 - State solve
|
||||
// Solve (λ r(ρ̃) ∇⋅u, ∇⋅v) + (2 μ r(ρ̃) ε(u), ε(v)) = (f,v)
|
||||
SIMPInterpolationCoefficient SIMP_cf(&rho_filter,rho_min, 1.0);
|
||||
ProductCoefficient lambda_SIMP_cf(lambda_cf,SIMP_cf);
|
||||
ProductCoefficient mu_SIMP_cf(mu_cf,SIMP_cf);
|
||||
ElasticitySolver->SetLameCoefficients(&lambda_SIMP_cf,&mu_SIMP_cf);
|
||||
ElasticitySolver->Solve();
|
||||
u = *ElasticitySolver->GetFEMSolution();
|
||||
|
||||
// Step 3 - Adjoint filter solve
|
||||
// Solve (ϵ² ∇ w̃, ∇ v) + (w̃ ,v) = (-r'(ρ̃) ( λ |∇⋅u|² + 2 μ |ε(u)|²),v)
|
||||
StrainEnergyDensityCoefficient rhs_cf(&lambda_cf,&mu_cf,&u, &rho_filter,
|
||||
rho_min);
|
||||
FilterSolver->SetRHSCoefficient(&rhs_cf);
|
||||
FilterSolver->Solve();
|
||||
w_filter = *FilterSolver->GetFEMSolution();
|
||||
|
||||
// Step 4 - Compute gradient
|
||||
// Solve G = M⁻¹w̃
|
||||
GridFunctionCoefficient w_cf(&w_filter);
|
||||
ParLinearForm w_rhs(&control_fes);
|
||||
w_rhs.AddDomainIntegrator(new DomainLFIntegrator(w_cf));
|
||||
w_rhs.Assemble();
|
||||
M.Mult(w_rhs,grad);
|
||||
|
||||
// Step 5 - Update design variable ψ ← proj(ψ - αG)
|
||||
psi.Add(-alpha, grad);
|
||||
const double material_volume = proj(psi, target_volume);
|
||||
|
||||
// Compute ||ρ - ρ_old|| in control fes.
|
||||
double norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
|
||||
double norm_reduced_gradient = norm_increment/alpha;
|
||||
psi_old = psi;
|
||||
|
||||
double compliance = (*(ElasticitySolver->GetLinearForm()))(u);
|
||||
MPI_Allreduce(MPI_IN_PLACE,&compliance,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD);
|
||||
if (myid == 0)
|
||||
{
|
||||
mfem::out << "norm of the reduced gradient = " << norm_reduced_gradient << endl;
|
||||
mfem::out << "norm of the increment = " << norm_increment << endl;
|
||||
mfem::out << "compliance = " << compliance << endl;
|
||||
mfem::out << "volume fraction = " << material_volume / domain_volume << endl;
|
||||
}
|
||||
|
||||
if (glvis_visualization)
|
||||
{
|
||||
ParGridFunction r_gf(&filter_fes);
|
||||
r_gf.ProjectCoefficient(SIMP_cf);
|
||||
sout_r << "parallel " << num_procs << " " << myid << "\n";
|
||||
sout_r << "solution\n" << pmesh << r_gf
|
||||
<< "window_title 'Design density r(ρ̃)'" << flush;
|
||||
}
|
||||
|
||||
if (paraview_output)
|
||||
{
|
||||
rho_gf.ProjectCoefficient(rho);
|
||||
paraview_dc.SetCycle(k);
|
||||
paraview_dc.SetTime((double)k);
|
||||
paraview_dc.Save();
|
||||
}
|
||||
|
||||
if (norm_reduced_gradient < ntol && norm_increment < itol)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete ElasticitySolver;
|
||||
delete FilterSolver;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
// Sample runs: mpirun -np 4 ex3p -m ../data/star.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/square-disc.mesh -o 2
|
||||
// mpirun -np 4 ex3p -m ../data/beam-tet.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/beam-tet.mesh -nc -o 2
|
||||
// mpirun -np 4 ex3p -m ../data/beam-hex.mesh
|
||||
// mpirun -np 4 ex3p -m ../data/beam-hex.mesh -o 2 -pa
|
||||
// mpirun -np 4 ex3p -m ../data/escher.mesh
|
||||
@@ -70,6 +71,7 @@ int main(int argc, char *argv[])
|
||||
int order = 1;
|
||||
bool static_cond = false;
|
||||
bool pa = false;
|
||||
bool nc = false;
|
||||
const char *device_config = "cpu";
|
||||
bool visualization = true;
|
||||
#ifdef MFEM_USE_AMGX
|
||||
@@ -87,6 +89,9 @@ int main(int argc, char *argv[])
|
||||
"--no-static-condensation", "Enable static condensation.");
|
||||
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
|
||||
"--no-partial-assembly", "Enable Partial Assembly.");
|
||||
args.AddOption(&nc, "-nc", "--non-conforming", "-c",
|
||||
"--conforming",
|
||||
"Mark the mesh as nonconforming before partitioning.");
|
||||
args.AddOption(&device_config, "-d", "--device",
|
||||
"Device configuration string, see Device::Configure().");
|
||||
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
|
||||
@@ -124,6 +129,11 @@ int main(int argc, char *argv[])
|
||||
Mesh *mesh = new Mesh(mesh_file, 1, 1);
|
||||
dim = mesh->Dimension();
|
||||
int sdim = mesh->SpaceDimension();
|
||||
if (nc)
|
||||
{
|
||||
// Can set to false to use conformal refinement for simplices.
|
||||
mesh->EnsureNCMesh(true);
|
||||
}
|
||||
|
||||
// 5. Refine the serial mesh on all processors to increase the resolution. In
|
||||
// this example we do 'ref_levels' of uniform refinement. We choose
|
||||
|
||||
+2
-1
@@ -450,7 +450,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(BilinearForm &M_, BilinearForm &K_, const Vector &b_)
|
||||
: TimeDependentOperator(M_.Height()), M(M_), K(K_), b(b_), z(M_.Height())
|
||||
: TimeDependentOperator(M_.FESpace()->GetTrueVSize()),
|
||||
M(M_), K(K_), b(b_), z(height)
|
||||
{
|
||||
Array<int> ess_tdof_list;
|
||||
if (M.GetAssemblyLevel() == AssemblyLevel::LEGACY)
|
||||
|
||||
+2
-2
@@ -659,9 +659,9 @@ int main(int argc, char *argv[])
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
|
||||
const Vector &b_, PrecType prec_type)
|
||||
: TimeDependentOperator(M_.Height()), b(b_),
|
||||
: TimeDependentOperator(M_.ParFESpace()->GetTrueVSize()), b(b_),
|
||||
M_solver(M_.ParFESpace()->GetComm()),
|
||||
z(M_.Height())
|
||||
z(height)
|
||||
{
|
||||
if (M_.GetAssemblyLevel()==AssemblyLevel::LEGACY)
|
||||
{
|
||||
|
||||
+9
-5
@@ -23,17 +23,15 @@ MFEM_LIB_FILE = mfem_is_not_built
|
||||
|
||||
SEQ_EXAMPLES = ex0 ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 \
|
||||
ex17 ex18 ex19 ex20 ex21 ex22 ex23 ex24 ex25 ex26 ex27 ex28 ex29 ex30 \
|
||||
ex31 ex33 ex34 ex36
|
||||
ex31 ex33 ex34 ex36 ex37
|
||||
PAR_EXAMPLES = ex0p ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex8p ex9p ex10p ex11p \
|
||||
ex12p ex13p ex14p ex15p ex16p ex17p ex18p ex19p ex20p ex21p ex22p ex24p \
|
||||
ex25p ex26p ex27p ex28p ex29p ex30p ex31p ex32p ex33p ex34p ex35p ex36p
|
||||
ex25p ex26p ex27p ex28p ex29p ex30p ex31p ex32p ex33p ex34p ex35p ex36p \
|
||||
ex37p
|
||||
SEQ_DEVICE_EXAMPLES = ex1 ex3 ex4 ex5 ex6 ex9 ex22 ex24 ex25 ex26 ex34
|
||||
PAR_DEVICE_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex9p ex13p ex22p \
|
||||
ex24p ex25p ex26p ex34p ex35p
|
||||
|
||||
ifeq ($(MFEM_USE_LAPACK),YES)
|
||||
SEQ_EXAMPLES += ex37
|
||||
endif
|
||||
ifeq ($(MFEM_USE_MPI),NO)
|
||||
EXAMPLES = $(SEQ_EXAMPLES)
|
||||
else
|
||||
@@ -95,10 +93,12 @@ $(SUBDIRS_TPRINT):
|
||||
# Additional dependencies
|
||||
ex18: $(SRC)ex18.hpp
|
||||
ex33: $(SRC)ex33.hpp
|
||||
ex37: $(SRC)ex37.hpp
|
||||
|
||||
ifeq ($(MFEM_USE_MPI),YES)
|
||||
ex18p: $(SRC)ex18.hpp
|
||||
ex33p: $(SRC)ex33.hpp
|
||||
ex37p: $(SRC)ex37.hpp
|
||||
endif
|
||||
|
||||
MFEM_TESTS = EXAMPLES
|
||||
@@ -142,6 +142,10 @@ ex27-test-seq: ex27
|
||||
@$(call mfem-test,$<,, Serial example,-dg)
|
||||
ex27p-test-par: ex27p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), Parallel example,-dg)
|
||||
ex37-test-seq: ex37
|
||||
@$(call mfem-test,$<,, Serial example,-mi 3)
|
||||
ex37p-test-par: ex37p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), Parallel example,-mi 3)
|
||||
# Testing: optional tests
|
||||
ifeq ($(MFEM_USE_STRUMPACK),YES)
|
||||
ex11p-test-strumpack: ex11p
|
||||
|
||||
@@ -24,13 +24,13 @@ if (MFEM_USE_MPI)
|
||||
ex10p.cpp
|
||||
)
|
||||
list(APPEND PETSC_RC_FILES
|
||||
rc_ex1p
|
||||
rc_ex2p
|
||||
rc_ex1p rc_ex1p_device rc_ex1p_deviceamg
|
||||
rc_ex2p rc_ex2p_bddc rc_ex2p_asm
|
||||
rc_ex3p rc_ex3p_bddc
|
||||
rc_ex4p rc_ex4p_bddc
|
||||
rc_ex5p_bddc rc_ex5p_fieldsplit
|
||||
rc_ex9p_expl rc_ex9p_impl
|
||||
rc_ex10p
|
||||
rc_ex9p_expl rc_ex9p_expl_device rc_ex9p_impl
|
||||
rc_ex10p rc_ex10p_mf rc_ex10p_mfop rc_ex10p_jfnk
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -39,7 +39,7 @@ if (MFEM_USE_SLEPC)
|
||||
ex11p.cpp
|
||||
)
|
||||
list(APPEND PETSC_RC_FILES
|
||||
rc_ex11p_lobpcg rc_ex11p_gd
|
||||
rc_ex11p_lobpcg rc_ex11p_lobpcg_device rc_ex11p_gd
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -74,7 +74,13 @@ add_mfem_examples(PETSC_EXAMPLES_SRCS ${PFX} copy_petsc_rc_files test_petsc)
|
||||
# Command line options for the tests.
|
||||
set(EX1_ARGS_W -m ../../data/amr-quad.mesh --usepetsc)
|
||||
set(EX1_ARGS_P -m ../../data/amr-quad.mesh --usepetsc --petscopts rc_ex1p)
|
||||
set(EX1_ARGS_CUDA -m ../../data/star.mesh --usepetsc --partial-assembly --device cuda --petscopts rc_ex1p_device)
|
||||
set(EX1_ARGS_CUDAAMG -m ../../data/star.mesh --usepetsc --device cuda --petscopts rc_ex1p_deviceamg)
|
||||
set(EX1_ARGS_HIP -m ../../data/star.mesh --usepetsc --partial-assembly --device hip --petscopts rc_ex1p_device)
|
||||
set(EX1_ARGS_HIPAMG -m ../../data/star.mesh --usepetsc --device hip --petscopts rc_ex1p_deviceamg)
|
||||
set(EX2_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p)
|
||||
set(EX2_ARGS_BDDC -m ../../data/beam-tri.mesh --usepetsc --nonoverlapping --petscopts rc_ex2p_bddc)
|
||||
set(EX2_ARGS_ASM -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p_asm)
|
||||
set(EX3_ARGS -m ../../data/klein-bottle.mesh -o 2 -f 0.1 --usepetsc --petscopts rc_ex3p_bddc --nonoverlapping)
|
||||
set(EX4_ARGS -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping)
|
||||
set(EX4_HYB_ARGS -m ../../data/klein-bottle.mesh -o 2 --usepetsc --petscopts rc_ex4p_bddc --nonoverlapping --hybridization)
|
||||
@@ -85,22 +91,46 @@ set(EX6_ARGS -m ../../data/amr-quad.mesh --usepetsc)
|
||||
set(EX6_NONOVL_ARGS -m ../../data/amr-quad.mesh --usepetsc --nonoverlapping)
|
||||
set(EX9_E_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl -dt 0.1)
|
||||
set(EX9_ES_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl --no-step)
|
||||
set(EX9_ES_ARGS_CUDA -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_device --no-step --partial-assembly --device cuda)
|
||||
set(EX9_ES_ARGS_HIP -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_device --no-step --partial-assembly --device hip)
|
||||
set(EX9_IS_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_impl --implicit -tf 0.5)
|
||||
set(EX10_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p -tf 30 -s 3 -rs 2 -dt 3)
|
||||
set(EX10_MF_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_mf -tf 6 -s 3 -rs 0 -dt 3)
|
||||
set(EX10_MFOP_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_mfop -tf 6 -s 3 -rs 0 -dt 3)
|
||||
set(EX10_JFNK_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_jfnk --jfnk -tf 6 -s 3 -rs 0 -dt 3)
|
||||
if (MFEM_USE_SLEPC)
|
||||
set(EX11_ARGS_SINV -m ../../data/star.mesh --useslepc)
|
||||
set(EX11_ARGS_LOBPCG -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg)
|
||||
set(EX11_ARGS_LOBPCG_CUDA -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_device --device cuda)
|
||||
set(EX11_ARGS_LOBPCG_HIP -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_device --device hip)
|
||||
set(EX11_ARGS_GD -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_gd)
|
||||
endif()
|
||||
|
||||
# Add the tests: one test per command-line-variable.
|
||||
if (MFEM_ENABLE_TESTING)
|
||||
set(TEST_OPTIONS_VARS
|
||||
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX3_ARGS EX4_ARGS EX4_HYB_ARGS
|
||||
EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS EX5_FSPL_ARGS EX6_ARGS EX6_NONOVL_ARGS
|
||||
EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS EX10_ARGS)
|
||||
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX2_ARGS_BDDC EX2_ARGS_ASM EX3_ARGS
|
||||
EX4_ARGS EX4_HYB_ARGS EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS EX5_FSPL_ARGS
|
||||
EX6_ARGS EX6_NONOVL_ARGS EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS EX10_ARGS
|
||||
EX10_MF_ARGS EX10_MFOP_ARGS EX10_JFNK_ARGS)
|
||||
if (MFEM_USE_SLEPC)
|
||||
list(APPEND TEST_OPTIONS_VARS EX11_ARGS_SINV EX11_ARGS_LOBPCG EX11_ARGS_GD)
|
||||
list(APPEND TEST_OPTIONS_VARS
|
||||
EX11_ARGS_SINV EX11_ARGS_LOBPCG EX11_ARGS_GD)
|
||||
endif()
|
||||
# CUDA/HIP tests
|
||||
if (MFEM_USE_CUDA)
|
||||
list(APPEND TEST_OPTIONS_VARS
|
||||
EX1_ARGS_CUDA EX1_ARGS_CUDAAMG EX9_ES_ARGS_CUDA)
|
||||
if (MFEM_USE_SLEPC)
|
||||
list(APPEND TEST_OPTIONS_VARS EX11_ARGS_LOBPCG_CUDA)
|
||||
endif()
|
||||
elseif (MFEM_USE_HIP)
|
||||
list(APPEND TEST_OPTIONS_VARS
|
||||
EX1_ARGS_HIP EX1_ARGS_HIPAMG EX9_ES_ARGS_HIP)
|
||||
if (MFEM_USE_SLEPC)
|
||||
# SLEPc does not support BVSVEC with HIP
|
||||
# list(APPEND TEST_OPTIONS_VARS EX11_ARGS_LOBPCG_HIP)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
foreach(TEST_OPTIONS_VAR ${TEST_OPTIONS_VARS})
|
||||
@@ -115,7 +145,7 @@ if (MFEM_ENABLE_TESTING)
|
||||
|
||||
# All PETSC tests are parallel.
|
||||
if (MFEM_USE_MPI)
|
||||
add_test(NAME ${TEST_NAME_FULL}_np=4
|
||||
add_test(NAME ${TEST_NAME_FULL}_np=${MFEM_MPI_NP}
|
||||
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
|
||||
${MPIEXEC_PREFLAGS}
|
||||
$<TARGET_FILE:${TEST_NAME}> ${TEST_OPTIONS}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
// mpirun -np 4 ex1p -m ../../data/amr-quad.mesh --petscopts rc_ex1p
|
||||
//
|
||||
// Device sample runs:
|
||||
// mpirun -np 4 ex1p -pa -d cuda --petscopts rc_ex1p_cuda
|
||||
// mpirun -np 4 ex1p -pa -d cuda --petscopts rc_ex1p_device
|
||||
//
|
||||
// Description: This example code demonstrates the use of MFEM to define a
|
||||
// simple finite element discretization of the Laplace problem
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
// finite elements (velocity u) and piecewise discontinuous
|
||||
// polynomials (pressure p).
|
||||
//
|
||||
// The example demonstrates the use of the BlockMatrix class, as
|
||||
// The example demonstrates the use of the BlockOperator class, as
|
||||
// well as the collective saving of several grid functions in a
|
||||
// VisIt (visit.llnl.gov) visualization format.
|
||||
//
|
||||
|
||||
@@ -520,10 +520,10 @@ int main(int argc, char *argv[])
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
|
||||
const Vector &b_,bool M_in_lhs)
|
||||
: TimeDependentOperator(M_.Height(), 0.0,
|
||||
: TimeDependentOperator(M_.ParFESpace()->GetTrueVSize(), 0.0,
|
||||
M_in_lhs ? TimeDependentOperator::IMPLICIT
|
||||
: TimeDependentOperator::EXPLICIT),
|
||||
b(b_), comm(M_.ParFESpace()->GetComm()), M_solver(comm), z(M_.Height()),
|
||||
b(b_), comm(M_.ParFESpace()->GetComm()), M_solver(comm), z(height),
|
||||
iJacobian(NULL), rJacobian(NULL)
|
||||
{
|
||||
MAlev = M_.GetAssemblyLevel();
|
||||
|
||||
+29
-9
@@ -66,7 +66,9 @@ include $(MFEM_TEST_MK)
|
||||
|
||||
# Testing: Parallel runs
|
||||
RUN_MPI = $(MFEM_MPIEXEC) $(MFEM_MPIEXEC_NP) $(MFEM_MPI_NP)
|
||||
TESTNAME = Parallel PETSc example
|
||||
TESTNAME = Parallel PETSc example
|
||||
TESTNAME_CUDA = Parallel CUDA PETSc example
|
||||
TESTNAME_HIP = Parallel HIP PETSc example
|
||||
%-test-par: %
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME))
|
||||
|
||||
@@ -74,8 +76,10 @@ TESTNAME = Parallel PETSc example
|
||||
# Testing PETSc execution options.
|
||||
EX1_ARGS_W := -m ../../data/amr-quad.mesh --usepetsc
|
||||
EX1_ARGS_P := -m ../../data/amr-quad.mesh --usepetsc --petscopts rc_ex1p
|
||||
EX1_ARGS_CUDA := -m ../../data/star.mesh --usepetsc --partial-assembly --device cuda --petscopts rc_ex1p_cuda
|
||||
EX1_ARGS_CUDAAMG := -m ../../data/star.mesh --usepetsc --device cuda --petscopts rc_ex1p_cudaamg
|
||||
EX1_ARGS_CUDA := -m ../../data/star.mesh --usepetsc --partial-assembly --device cuda --petscopts rc_ex1p_device
|
||||
EX1_ARGS_CUDAAMG := -m ../../data/star.mesh --usepetsc --device cuda --petscopts rc_ex1p_deviceamg
|
||||
EX1_ARGS_HIP := -m ../../data/star.mesh --usepetsc --partial-assembly --device hip --petscopts rc_ex1p_device
|
||||
EX1_ARGS_HIPAMG := -m ../../data/star.mesh --usepetsc --device hip --petscopts rc_ex1p_deviceamg
|
||||
EX2_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p
|
||||
EX2_ARGS_BDDC := -m ../../data/beam-tri.mesh --usepetsc --nonoverlapping --petscopts rc_ex2p_bddc
|
||||
EX2_ARGS_ASM := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex2p_asm
|
||||
@@ -89,7 +93,8 @@ EX6_ARGS := -m ../../data/amr-quad.mesh --usepetsc
|
||||
EX6_NONOVL_ARGS := -m ../../data/amr-quad.mesh --usepetsc --nonoverlapping
|
||||
EX9_E_ARGS := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl -dt 0.1
|
||||
EX9_ES_ARGS := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl --no-step
|
||||
EX9_ES_ARGS_CUDA := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_cuda --no-step --partial-assembly --device cuda
|
||||
EX9_ES_ARGS_CUDA := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_device --no-step --partial-assembly --device cuda
|
||||
EX9_ES_ARGS_HIP := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl_device --no-step --partial-assembly --device hip
|
||||
EX9_IS_ARGS := -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_impl --implicit -tf 0.5
|
||||
EX10_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p -tf 30 -s 3 -rs 2 -dt 3
|
||||
EX10_MF_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_mf -tf 6 -s 3 -rs 0 -dt 3
|
||||
@@ -97,15 +102,20 @@ EX10_MFOP_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_
|
||||
EX10_JFNK_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_jfnk --jfnk -tf 6 -s 3 -rs 0 -dt 3
|
||||
EX11_ARGS_SINV := -m ../../data/star.mesh --useslepc
|
||||
EX11_ARGS_LOBPCG := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg
|
||||
EX11_ARGS_LOBPCG_CUDA := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_cuda --device cuda
|
||||
EX11_ARGS_LOBPCG_CUDA := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_device --device cuda
|
||||
EX11_ARGS_LOBPCG_HIP := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg_device --device hip
|
||||
EX11_ARGS_GD := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_gd
|
||||
|
||||
ex1p-test-par: ex1p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_W))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_P))
|
||||
ifeq ($(MFEM_USE_CUDA),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_CUDA))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_CUDAAMG))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_CUDA),$(EX1_ARGS_CUDA))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_CUDA),$(EX1_ARGS_CUDAAMG))
|
||||
endif
|
||||
ifeq ($(MFEM_USE_HIP),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_HIP),$(EX1_ARGS_HIP))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_HIP),$(EX1_ARGS_HIPAMG))
|
||||
endif
|
||||
ex2p-test-par: ex2p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX2_ARGS))
|
||||
@@ -128,7 +138,10 @@ ex9p-test-par: ex9p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_ES_ARGS))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_IS_ARGS))
|
||||
ifeq ($(MFEM_USE_CUDA),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX9_ES_ARGS_CUDA))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_CUDA),$(EX9_ES_ARGS_CUDA))
|
||||
endif
|
||||
ifeq ($(MFEM_USE_HIP),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_HIP),$(EX9_ES_ARGS_HIP))
|
||||
endif
|
||||
ex10p-test-par: ex10p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX10_ARGS))
|
||||
@@ -140,8 +153,12 @@ ex11p-test-par: ex11p
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_SINV))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_LOBPCG))
|
||||
ifeq ($(MFEM_USE_CUDA),YES)
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_LOBPCG_CUDA))
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_CUDA),$(EX11_ARGS_LOBPCG_CUDA))
|
||||
endif
|
||||
# SLEPc does not support BVSVEC with HIP
|
||||
#ifeq ($(MFEM_USE_HIP),YES)
|
||||
# @$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME_HIP),$(EX11_ARGS_LOBPCG_HIP))
|
||||
#endif
|
||||
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_GD))
|
||||
endif
|
||||
|
||||
@@ -156,6 +173,9 @@ clean: clean-build clean-exec
|
||||
clean-build:
|
||||
rm -f *.o *~ $(SEQ_EXAMPLES) $(PAR_EXAMPLES)
|
||||
rm -rf *.dSYM *.TVD.*breakpoints
|
||||
ifneq ($(SRC),)
|
||||
rm -f $(RC_FILES)
|
||||
endif
|
||||
|
||||
clean-exec:
|
||||
@rm -rf mesh.* sol.* sol_p.* sol_u.* Example5*
|
||||
|
||||
@@ -476,7 +476,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(BilinearForm &M_, BilinearForm &K_, const Vector &b_)
|
||||
: TimeDependentOperator(M_.Height()), M(M_), K(K_), b(b_), z(M_.Height())
|
||||
: TimeDependentOperator(M_.FESpace()->GetTrueVSize()),
|
||||
M(M_), K(K_), b(b_), z(height)
|
||||
{
|
||||
Array<int> ess_tdof_list;
|
||||
if (M.GetAssemblyLevel() == AssemblyLevel::LEGACY)
|
||||
|
||||
@@ -679,10 +679,10 @@ int main(int argc, char *argv[])
|
||||
// Implementation of class FE_Evolution
|
||||
FE_Evolution::FE_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
|
||||
const Vector &b_, PrecType prec_type)
|
||||
: TimeDependentOperator(M_.Height()),
|
||||
: TimeDependentOperator(M_.ParFESpace()->GetTrueVSize()),
|
||||
b(b_),
|
||||
M_solver(M_.ParFESpace()->GetComm()),
|
||||
z(M_.Height())
|
||||
z(height)
|
||||
{
|
||||
if (M_.GetAssemblyLevel()==AssemblyLevel::LEGACY)
|
||||
{
|
||||
|
||||
@@ -88,6 +88,7 @@ set(SRCS
|
||||
ceed/solvers/algebraic.cpp
|
||||
ceed/solvers/full-assembly.cpp
|
||||
ceed/solvers/solvers-atpmg.cpp
|
||||
kdtree.cpp
|
||||
linearform.cpp
|
||||
linearform_ext.cpp
|
||||
lininteg.cpp
|
||||
@@ -199,6 +200,7 @@ set(HDRS
|
||||
ceed/solvers/algebraic.hpp
|
||||
ceed/solvers/full-assembly.hpp
|
||||
ceed/solvers/solvers-atpmg.hpp
|
||||
kdtree.hpp
|
||||
linearform.hpp
|
||||
linearform_ext.hpp
|
||||
lininteg.hpp
|
||||
|
||||
@@ -433,6 +433,7 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
// Element-wise integration
|
||||
for (int i = 0; i < fes -> GetNE(); i++)
|
||||
{
|
||||
doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
if (element_matrices)
|
||||
{
|
||||
elmat_p = &(*element_matrices)(i);
|
||||
@@ -468,7 +469,6 @@ void BilinearForm::Assemble(int skip_zeros)
|
||||
{
|
||||
elmat_p = &elmat;
|
||||
}
|
||||
doftrans = fes->GetElementVDofs(i, vdofs);
|
||||
if (doftrans)
|
||||
{
|
||||
doftrans->TransformDual(elmat);
|
||||
|
||||
@@ -254,6 +254,12 @@ public:
|
||||
/// Access all the integrators added with AddDomainIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetDBFI() { return &domain_integs; }
|
||||
|
||||
/// @brief Access all boundary markers added with AddDomainIntegrator().
|
||||
///
|
||||
/// If no marker was specified when the integrator was added, the
|
||||
/// corresponding pointer (to Array<int>) will be NULL. */
|
||||
Array<Array<int>*> *GetDBFI_Marker() { return &domain_integs_marker; }
|
||||
|
||||
/// Access all the integrators added with AddBoundaryIntegrator().
|
||||
Array<BilinearFormIntegrator*> *GetBBFI() { return &boundary_integs; }
|
||||
/** @brief Access all boundary markers added with AddBoundaryIntegrator().
|
||||
@@ -452,7 +458,7 @@ public:
|
||||
practice it is convenient to have it in transposed form for
|
||||
construction of RAP operators in matrix-free methods. */
|
||||
virtual const Operator *GetOutputRestrictionTranspose() const
|
||||
{ return GetOutputProlongation(); }
|
||||
{ return fes->GetRestrictionTransposeOperator(); }
|
||||
/// Get the output finite element space restriction matrix
|
||||
virtual const Operator *GetOutputRestriction() const
|
||||
{ return GetRestriction(); }
|
||||
|
||||
+128
-10
@@ -264,6 +264,14 @@ void PABilinearFormExtension::SetupRestrictionOperators(const L2FaceValues m)
|
||||
localX.SetSize(elem_restrict->Height(), Device::GetDeviceMemoryType());
|
||||
localY.SetSize(elem_restrict->Height(), Device::GetDeviceMemoryType());
|
||||
localY.UseDevice(true); // ensure 'localY = 0.0' is done on device
|
||||
|
||||
// Gather the attributes on the host from all the elements
|
||||
const Mesh &mesh = *trial_fes->GetMesh();
|
||||
elem_attributes.SetSize(mesh.GetNE());
|
||||
for (int i = 0; i < mesh.GetNE(); ++i)
|
||||
{
|
||||
elem_attributes[i] = mesh.GetAttribute(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Construct face restriction operators only if the bilinear form has
|
||||
@@ -289,6 +297,46 @@ void PABilinearFormExtension::SetupRestrictionOperators(const L2FaceValues m)
|
||||
bdr_face_X.SetSize(bdr_face_restrict_lex->Height(), Device::GetMemoryType());
|
||||
bdr_face_Y.SetSize(bdr_face_restrict_lex->Height(), Device::GetMemoryType());
|
||||
bdr_face_Y.UseDevice(true); // ensure 'faceBoundY = 0.0' is done on device
|
||||
|
||||
const Mesh &mesh = *trial_fes->GetMesh();
|
||||
// See LinearFormExtension::Update for explanation of f_to_be logic.
|
||||
std::unordered_map<int,int> f_to_be;
|
||||
for (int i = 0; i < mesh.GetNBE(); ++i)
|
||||
{
|
||||
const int f = mesh.GetBdrElementEdgeIndex(i);
|
||||
f_to_be[f] = i;
|
||||
}
|
||||
const int nf_bdr = trial_fes->GetNFbyType(FaceType::Boundary);
|
||||
bdr_attributes.SetSize(nf_bdr);
|
||||
int f_ind = 0;
|
||||
int missing_bdr_elems = 0;
|
||||
for (int f = 0; f < mesh.GetNumFaces(); ++f)
|
||||
{
|
||||
if (!mesh.GetFaceInformation(f).IsOfFaceType(FaceType::Boundary))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int attribute = 1; // default value
|
||||
if (f_to_be.find(f) != f_to_be.end())
|
||||
{
|
||||
const int be = f_to_be[f];
|
||||
attribute = mesh.GetBdrAttribute(be);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If a boundary face does not correspond to the a boundary element,
|
||||
// we assign it the default attribute of 1. We also generate a
|
||||
// warning at runtime with the number of such missing elements.
|
||||
++missing_bdr_elems;
|
||||
}
|
||||
bdr_attributes[f_ind] = attribute;
|
||||
++f_ind;
|
||||
}
|
||||
if (missing_bdr_elems)
|
||||
{
|
||||
MFEM_WARNING("Missing " << missing_bdr_elems << " boundary elements "
|
||||
"for boundary faces.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -458,11 +506,13 @@ void PABilinearFormExtension::Mult(const Vector &x, Vector &y) const
|
||||
{
|
||||
if (iSz)
|
||||
{
|
||||
Array<Array<int>*> &elem_markers = *a->GetDBFI_Marker();
|
||||
elem_restrict->Mult(x, localX);
|
||||
localY = 0.0;
|
||||
for (int i = 0; i < iSz; ++i)
|
||||
{
|
||||
integrators[i]->AddMultPA(localX, localY);
|
||||
AddMultWithMarkers(*integrators[i], localX, elem_markers[i], elem_attributes,
|
||||
false, localY);
|
||||
}
|
||||
elem_restrict->MultTranspose(localY, y);
|
||||
}
|
||||
@@ -495,17 +545,21 @@ void PABilinearFormExtension::Mult(const Vector &x, Vector &y) const
|
||||
const bool has_bdr_integs = (n_bdr_face_integs > 0 || n_bdr_integs > 0);
|
||||
if (bdr_face_restrict_lex && has_bdr_integs)
|
||||
{
|
||||
Array<Array<int>*> &bdr_markers = *a->GetBBFI_Marker();
|
||||
Array<Array<int>*> &bdr_face_markers = *a->GetBFBFI_Marker();
|
||||
bdr_face_restrict_lex->Mult(x, bdr_face_X);
|
||||
if (bdr_face_X.Size()>0)
|
||||
{
|
||||
bdr_face_Y = 0.0;
|
||||
for (int i = 0; i < n_bdr_integs; ++i)
|
||||
{
|
||||
bdr_integs[i]->AddMultPA(bdr_face_X, bdr_face_Y);
|
||||
AddMultWithMarkers(*bdr_integs[i], bdr_face_X, bdr_markers[i], bdr_attributes,
|
||||
false, bdr_face_Y);
|
||||
}
|
||||
for (int i = 0; i < n_bdr_face_integs; ++i)
|
||||
{
|
||||
bdr_face_integs[i]->AddMultPA(bdr_face_X, bdr_face_Y);
|
||||
AddMultWithMarkers(*bdr_face_integs[i], bdr_face_X, bdr_face_markers[i],
|
||||
bdr_attributes, false, bdr_face_Y);
|
||||
}
|
||||
bdr_face_restrict_lex->AddMultTransposeInPlace(bdr_face_Y, y);
|
||||
}
|
||||
@@ -518,11 +572,13 @@ void PABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
|
||||
const int iSz = integrators.Size();
|
||||
if (elem_restrict)
|
||||
{
|
||||
Array<Array<int>*> &elem_markers = *a->GetDBFI_Marker();
|
||||
elem_restrict->Mult(x, localX);
|
||||
localY = 0.0;
|
||||
for (int i = 0; i < iSz; ++i)
|
||||
{
|
||||
integrators[i]->AddMultTransposePA(localX, localY);
|
||||
AddMultWithMarkers(*integrators[i], localX, elem_markers[i], elem_attributes,
|
||||
true, localY);
|
||||
}
|
||||
elem_restrict->MultTranspose(localY, y);
|
||||
}
|
||||
@@ -552,23 +608,85 @@ void PABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
|
||||
}
|
||||
}
|
||||
|
||||
Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
|
||||
const int bFISz = bdrFaceIntegrators.Size();
|
||||
if (bdr_face_restrict_lex && bFISz>0)
|
||||
Array<BilinearFormIntegrator*> &bdr_integs = *a->GetBBFI();
|
||||
Array<BilinearFormIntegrator*> &bdr_face_integs = *a->GetBFBFI();
|
||||
const int n_bdr_integs = bdr_integs.Size();
|
||||
const int n_bdr_face_integs = bdr_face_integs.Size();
|
||||
const bool has_bdr_integs = (n_bdr_face_integs > 0 || n_bdr_integs > 0);
|
||||
if (bdr_face_restrict_lex && has_bdr_integs)
|
||||
{
|
||||
Array<Array<int>*> &bdr_markers = *a->GetBBFI_Marker();
|
||||
Array<Array<int>*> &bdr_face_markers = *a->GetBFBFI_Marker();
|
||||
|
||||
bdr_face_restrict_lex->Mult(x, bdr_face_X);
|
||||
if (bdr_face_X.Size()>0)
|
||||
if (bdr_face_X.Size() > 0)
|
||||
{
|
||||
bdr_face_Y = 0.0;
|
||||
for (int i = 0; i < bFISz; ++i)
|
||||
for (int i = 0; i < n_bdr_integs; ++i)
|
||||
{
|
||||
bdrFaceIntegrators[i]->AddMultTransposePA(bdr_face_X, bdr_face_Y);
|
||||
AddMultWithMarkers(*bdr_integs[i], bdr_face_X, bdr_markers[i], bdr_attributes,
|
||||
true, bdr_face_Y);
|
||||
}
|
||||
for (int i = 0; i < n_bdr_face_integs; ++i)
|
||||
{
|
||||
AddMultWithMarkers(*bdr_face_integs[i], bdr_face_X, bdr_face_markers[i],
|
||||
bdr_attributes, true, bdr_face_Y);
|
||||
}
|
||||
bdr_face_restrict_lex->AddMultTransposeInPlace(bdr_face_Y, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute kernels for PABilinearFormExtension::AddMultWithMarkers.
|
||||
// Cannot be in member function with non-public visibility.
|
||||
static void AddWithMarkers_(
|
||||
const int ne,
|
||||
const int nd,
|
||||
const Vector &x,
|
||||
const Array<int> &markers,
|
||||
const Array<int> &attributes,
|
||||
Vector &y)
|
||||
{
|
||||
const auto d_x = Reshape(x.Read(), nd, ne);
|
||||
const auto d_m = Reshape(markers.Read(), markers.Size());
|
||||
const auto d_attr = Reshape(attributes.Read(), ne);
|
||||
auto d_y = Reshape(y.ReadWrite(), nd, ne);
|
||||
mfem::forall(ne, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
const int attr = d_attr[e];
|
||||
if (d_m[attr - 1] == 0) { return; }
|
||||
for (int i = 0; i < nd; ++i)
|
||||
{
|
||||
d_y(i, e) += d_x(i, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PABilinearFormExtension::AddMultWithMarkers(
|
||||
const BilinearFormIntegrator &integ,
|
||||
const Vector &x,
|
||||
const Array<int> *markers,
|
||||
const Array<int> &attributes,
|
||||
const bool transpose,
|
||||
Vector &y) const
|
||||
{
|
||||
if (markers)
|
||||
{
|
||||
tmp_evec.SetSize(y.Size());
|
||||
tmp_evec = 0.0;
|
||||
if (transpose) { integ.AddMultTransposePA(x, tmp_evec); }
|
||||
else { integ.AddMultPA(x, tmp_evec); }
|
||||
const int ne = attributes.Size();
|
||||
const int nd = x.Size() / ne;
|
||||
AddWithMarkers_(ne, nd, tmp_evec, *markers, attributes, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (transpose) { integ.AddMultTransposePA(x, y); }
|
||||
else { integ.AddMultPA(x, y); }
|
||||
}
|
||||
}
|
||||
|
||||
// Data and methods for element-assembled bilinear forms
|
||||
EABilinearFormExtension::EABilinearFormExtension(BilinearForm *form)
|
||||
: PABilinearFormExtension(form),
|
||||
|
||||
@@ -68,6 +68,9 @@ class PABilinearFormExtension : public BilinearFormExtension
|
||||
{
|
||||
protected:
|
||||
const FiniteElementSpace *trial_fes, *test_fes; // Not owned
|
||||
/// Attributes of all mesh elements.
|
||||
Array<int> elem_attributes, bdr_attributes;
|
||||
mutable Vector tmp_evec; // Work array
|
||||
mutable Vector localX, localY;
|
||||
mutable Vector int_face_X, int_face_Y;
|
||||
mutable Vector bdr_face_X, bdr_face_Y;
|
||||
@@ -91,6 +94,25 @@ public:
|
||||
|
||||
protected:
|
||||
void SetupRestrictionOperators(const L2FaceValues m);
|
||||
|
||||
/// @brief Accumulate the action (or transpose) of the integrator on @a x
|
||||
/// into @a y, taking into account the (possibly null) @a markers array.
|
||||
///
|
||||
/// If @a markers is non-null, then only those elements or boundary elements
|
||||
/// whose attribute is marked in the markers array will be added to @a y.
|
||||
///
|
||||
/// @param integ The integrator (domain, boundary, or boundary face).
|
||||
/// @param x Input E-vector.
|
||||
/// @param markers Marked attributes (possibly null, meaning all attributes).
|
||||
/// @param attributes Array of element or boundary element attributes.
|
||||
/// @param transpose Compute the action or transpose of the integrator .
|
||||
/// @param y Output E-vector
|
||||
void AddMultWithMarkers(const BilinearFormIntegrator &integ,
|
||||
const Vector &x,
|
||||
const Array<int> *markers,
|
||||
const Array<int> &attributes,
|
||||
const bool transpose,
|
||||
Vector &y) const;
|
||||
};
|
||||
|
||||
/// Data and methods for element-assembled bilinear forms
|
||||
|
||||
+4
-4
@@ -2456,7 +2456,7 @@ void VectorFEMassIntegrator::AssembleElementMatrix(
|
||||
{
|
||||
int dof = el.GetDof();
|
||||
int spaceDim = Trans.GetSpaceDim();
|
||||
int vdim = std::max(spaceDim, el.GetVDim());
|
||||
int vdim = std::max(spaceDim, el.GetRangeDim());
|
||||
|
||||
double w;
|
||||
|
||||
@@ -2524,7 +2524,7 @@ void VectorFEMassIntegrator::AssembleElementMatrix2(
|
||||
{
|
||||
// assume test_fe is scalar FE and trial_fe is vector FE
|
||||
int spaceDim = Trans.GetSpaceDim();
|
||||
int vdim = std::max(spaceDim, trial_fe.GetVDim());
|
||||
int vdim = std::max(spaceDim, trial_fe.GetRangeDim());
|
||||
int trial_dof = trial_fe.GetDof();
|
||||
int test_dof = test_fe.GetDof();
|
||||
double w;
|
||||
@@ -2622,8 +2622,8 @@ void VectorFEMassIntegrator::AssembleElementMatrix2(
|
||||
{
|
||||
// assume both test_fe and trial_fe are vector FE
|
||||
int spaceDim = Trans.GetSpaceDim();
|
||||
int trial_vdim = std::max(spaceDim, trial_fe.GetVDim());
|
||||
int test_vdim = std::max(spaceDim, test_fe.GetVDim());
|
||||
int trial_vdim = std::max(spaceDim, trial_fe.GetRangeDim());
|
||||
int test_vdim = std::max(spaceDim, test_fe.GetRangeDim());
|
||||
int trial_dof = trial_fe.GetDof();
|
||||
int test_dof = test_fe.GetDof();
|
||||
double w;
|
||||
|
||||
+12
-23
@@ -20,17 +20,6 @@
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
// Local maximum size of dofs and quads in 1D
|
||||
constexpr int HCURL_MAX_D1D = 5;
|
||||
#ifdef MFEM_USE_HIP
|
||||
constexpr int HCURL_MAX_Q1D = 5;
|
||||
#else
|
||||
constexpr int HCURL_MAX_Q1D = 6;
|
||||
#endif
|
||||
|
||||
constexpr int HDIV_MAX_D1D = 5;
|
||||
constexpr int HDIV_MAX_Q1D = 6;
|
||||
|
||||
/// Abstract base class BilinearFormIntegrator
|
||||
class BilinearFormIntegrator : public NonlinearFormIntegrator
|
||||
{
|
||||
@@ -591,7 +580,7 @@ protected:
|
||||
|
||||
|
||||
inline virtual int GetTestVDim(const FiniteElement & test_fe)
|
||||
{ return std::max(space_dim, test_fe.GetVDim()); }
|
||||
{ return std::max(space_dim, test_fe.GetRangeDim()); }
|
||||
|
||||
inline virtual void CalcTestShape(const FiniteElement & test_fe,
|
||||
ElementTransformation &Trans,
|
||||
@@ -599,7 +588,7 @@ protected:
|
||||
{ test_fe.CalcVShape(Trans, shape); }
|
||||
|
||||
inline virtual int GetTrialVDim(const FiniteElement & trial_fe)
|
||||
{ return std::max(space_dim, trial_fe.GetVDim()); }
|
||||
{ return std::max(space_dim, trial_fe.GetRangeDim()); }
|
||||
|
||||
inline virtual void CalcTrialShape(const FiniteElement & trial_fe,
|
||||
ElementTransformation &Trans,
|
||||
@@ -689,7 +678,7 @@ protected:
|
||||
|
||||
|
||||
inline virtual int GetVDim(const FiniteElement & vector_fe)
|
||||
{ return std::max(space_dim, vector_fe.GetVDim()); }
|
||||
{ return std::max(space_dim, vector_fe.GetRangeDim()); }
|
||||
|
||||
inline virtual void CalcVShape(const FiniteElement & vector_fe,
|
||||
ElementTransformation &Trans,
|
||||
@@ -1116,7 +1105,7 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetVDim() == 3 &&
|
||||
return (trial_fe.GetRangeDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
|
||||
test_fe.GetDerivType() == mfem::FiniteElement::GRAD );
|
||||
@@ -1299,8 +1288,8 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetCurlDim() == 3 && trial_fe.GetVDim() == 3 &&
|
||||
test_fe.GetCurlDim() == 3 && test_fe.GetVDim() == 3 &&
|
||||
return (trial_fe.GetCurlDim() == 3 && trial_fe.GetRangeDim() == 3 &&
|
||||
test_fe.GetCurlDim() == 3 && test_fe.GetRangeDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
@@ -1430,7 +1419,7 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetVDim() == 3 && test_fe.GetCurlDim() == 3 &&
|
||||
return (trial_fe.GetRangeDim() == 3 && test_fe.GetCurlDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
test_fe.GetDerivType() == mfem::FiniteElement::CURL );
|
||||
@@ -1500,7 +1489,7 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (test_fe.GetVDim() == 3 &&
|
||||
return (test_fe.GetRangeDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
|
||||
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
|
||||
@@ -1540,7 +1529,7 @@ public:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetCurlDim() == 3 && test_fe.GetVDim() == 3 &&
|
||||
return (trial_fe.GetCurlDim() == 3 && test_fe.GetRangeDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
|
||||
@@ -1911,7 +1900,7 @@ protected:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetCurlDim() == 3 && test_fe.GetVDim() == 3 &&
|
||||
return (trial_fe.GetCurlDim() == 3 && test_fe.GetRangeDim() == 3 &&
|
||||
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
|
||||
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
|
||||
}
|
||||
@@ -1970,7 +1959,7 @@ protected:
|
||||
const FiniteElement & trial_fe,
|
||||
const FiniteElement & test_fe) const
|
||||
{
|
||||
return (trial_fe.GetVDim() == 3 && test_fe.GetCurlDim() == 3 &&
|
||||
return (trial_fe.GetRangeDim() == 3 && test_fe.GetCurlDim() == 3 &&
|
||||
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
|
||||
test_fe.GetDerivType() == mfem::FiniteElement::CURL );
|
||||
}
|
||||
@@ -3451,7 +3440,7 @@ private:
|
||||
void cross_product(const Vector & x, const DenseMatrix & Y, DenseMatrix & Z)
|
||||
{
|
||||
int dim = x.Size();
|
||||
MFEM_VERIFY(Y.Width() == dim, "Size missmatch");
|
||||
MFEM_VERIFY(Y.Width() == dim, "Size mismatch");
|
||||
int dimc = dim == 3 ? dim : 1;
|
||||
int h = Y.Height();
|
||||
Z.SetSize(h,dimc);
|
||||
|
||||
+18
-6
@@ -220,12 +220,12 @@ double TransformedCoefficient::Eval(ElementTransformation &T,
|
||||
{
|
||||
if (Q2)
|
||||
{
|
||||
return (*Transform2)(Q1->Eval(T, ip, GetTime()),
|
||||
Q2->Eval(T, ip, GetTime()));
|
||||
return Transform2(Q1->Eval(T, ip, GetTime()),
|
||||
Q2->Eval(T, ip, GetTime()));
|
||||
}
|
||||
else
|
||||
{
|
||||
return (*Transform1)(Q1->Eval(T, ip, GetTime()));
|
||||
return Transform1(Q1->Eval(T, ip, GetTime()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1591,14 +1591,21 @@ void VectorQuadratureFunctionCoefficient::Eval(Vector &V,
|
||||
{
|
||||
QuadF.HostRead();
|
||||
|
||||
const int el_idx = QuadF.GetSpace()->GetEntityIndex(T);
|
||||
// Handle the case of "interior boundary elements" and FaceQuadratureSpace
|
||||
// with FaceType::Boundary.
|
||||
if (el_idx < 0) { V = 0.0; return; }
|
||||
|
||||
const int ip_idx = QuadF.GetSpace()->GetPermutedIndex(el_idx, ip.index);
|
||||
|
||||
if (index == 0 && vdim == QuadF.GetVDim())
|
||||
{
|
||||
QuadF.GetValues(T.ElementNo, ip.index, V);
|
||||
QuadF.GetValues(el_idx, ip_idx, V);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector temp;
|
||||
QuadF.GetValues(T.ElementNo, ip.index, temp);
|
||||
QuadF.GetValues(el_idx, ip_idx, temp);
|
||||
V.SetSize(vdim);
|
||||
for (int i = 0; i < vdim; i++)
|
||||
{
|
||||
@@ -1625,7 +1632,12 @@ double QuadratureFunctionCoefficient::Eval(ElementTransformation &T,
|
||||
{
|
||||
QuadF.HostRead();
|
||||
Vector temp(1);
|
||||
QuadF.GetValues(T.ElementNo, ip.index, temp);
|
||||
const int el_idx = QuadF.GetSpace()->GetEntityIndex(T);
|
||||
// Handle the case of "interior boundary elements" and FaceQuadratureSpace
|
||||
// with FaceType::Boundary.
|
||||
if (el_idx < 0) { return 0.0; }
|
||||
const int ip_idx = QuadF.GetSpace()->GetPermutedIndex(el_idx, ip.index);
|
||||
QuadF.GetValues(el_idx, ip_idx, temp);
|
||||
return temp[0];
|
||||
}
|
||||
|
||||
|
||||
+6
-6
@@ -422,15 +422,15 @@ class TransformedCoefficient : public Coefficient
|
||||
private:
|
||||
Coefficient * Q1;
|
||||
Coefficient * Q2;
|
||||
double (*Transform1)(double);
|
||||
double (*Transform2)(double,double);
|
||||
std::function<double(double)> Transform1;
|
||||
std::function<double(double, double)> Transform2;
|
||||
|
||||
public:
|
||||
TransformedCoefficient (Coefficient * q,double (*F)(double))
|
||||
: Q1(q), Transform1(F) { Q2 = 0; Transform2 = 0; }
|
||||
TransformedCoefficient (Coefficient * q, std::function<double(double)> F)
|
||||
: Q1(q), Transform1(std::move(F)) { Q2 = 0; Transform2 = 0; }
|
||||
TransformedCoefficient (Coefficient * q1,Coefficient * q2,
|
||||
double (*F)(double,double))
|
||||
: Q1(q1), Q2(q2), Transform2(F) { Transform1 = 0; }
|
||||
std::function<double(double, double)> F)
|
||||
: Q1(q1), Q2(q2), Transform2(std::move(F)) { Transform1 = 0; }
|
||||
|
||||
/// Set the time for internally stored coefficients
|
||||
void SetTime(double t);
|
||||
|
||||
+4
-6
@@ -166,21 +166,19 @@ void DGMassInverse::DGMassCGIteration(const Vector &b_, Vector &u_) const
|
||||
b = b_.Read();
|
||||
}
|
||||
|
||||
constexpr int NB = Q1D ? Q1D : 1; // block size
|
||||
static constexpr int NB = Q1D ? Q1D : 1; // block size
|
||||
|
||||
mfem::forall_2D(NE, NB, NB, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr int NB = Q1D ? Q1D : 1; // redefine here for some compilers
|
||||
|
||||
// Perform change of basis if needed
|
||||
if (CHANGE_BASIS)
|
||||
{
|
||||
// Transform RHS
|
||||
DGMassBasis<DIM,D1D,MAX_D1D>(e, NE, q2d_Bt, b_orig, b2, d1d);
|
||||
DGMassBasis<DIM,D1D>(e, NE, q2d_Bt, b_orig, b2, d1d);
|
||||
if (IT_MODE)
|
||||
{
|
||||
// Transform initial guess
|
||||
DGMassBasis<DIM,D1D,MAX_D1D>(e, NE, d2q_B, u, u, d1d);
|
||||
DGMassBasis<DIM,D1D>(e, NE, d2q_B, u, u, d1d);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +255,7 @@ void DGMassInverse::DGMassCGIteration(const Vector &b_, Vector &u_) const
|
||||
|
||||
if (CHANGE_BASIS)
|
||||
{
|
||||
DGMassBasis<DIM,D1D,MAX_D1D>(e, NE, q2d_B, u, u, d1d);
|
||||
DGMassBasis<DIM,D1D>(e, NE, q2d_B, u, u, d1d);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ double DGMassDot(const int e,
|
||||
return s_dot[0];
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int MAX_D1D = 0>
|
||||
template<int T_D1D = 0>
|
||||
MFEM_HOST_DEVICE inline
|
||||
void DGMassBasis2D(const int e,
|
||||
const int NE,
|
||||
@@ -181,7 +181,7 @@ void DGMassBasis2D(const int e,
|
||||
double *y_,
|
||||
const int d1d = 0)
|
||||
{
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
|
||||
const auto b = Reshape(b_, D1D, D1D);
|
||||
@@ -213,7 +213,7 @@ void DGMassBasis2D(const int e,
|
||||
MFEM_SYNC_THREAD;
|
||||
}
|
||||
|
||||
template<int T_D1D = 0, int MAX_D1D = 0>
|
||||
template<int T_D1D = 0>
|
||||
MFEM_HOST_DEVICE inline
|
||||
void DGMassBasis3D(const int e,
|
||||
const int NE,
|
||||
@@ -228,7 +228,7 @@ void DGMassBasis3D(const int e,
|
||||
const auto x = Reshape(x_, D1D, D1D, D1D, NE);
|
||||
auto y = Reshape(y_, D1D, D1D, D1D, NE);
|
||||
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sB[MD1*MD1];
|
||||
MFEM_SHARED double sm0[MD1*MD1*MD1];
|
||||
@@ -260,7 +260,7 @@ void DGMassBasis3D(const int e,
|
||||
MFEM_SYNC_THREAD;
|
||||
}
|
||||
|
||||
template<int DIM, int T_D1D = 0, int MAX_D1D = 0>
|
||||
template<int DIM, int T_D1D = 0>
|
||||
MFEM_HOST_DEVICE inline
|
||||
void DGMassBasis(const int e,
|
||||
const int NE,
|
||||
@@ -271,11 +271,11 @@ void DGMassBasis(const int e,
|
||||
{
|
||||
if (DIM == 2)
|
||||
{
|
||||
DGMassBasis2D<T_D1D, MAX_D1D>(e, NE, b_, x_, y_, d1d);
|
||||
DGMassBasis2D<T_D1D>(e, NE, b_, x_, y_, d1d);
|
||||
}
|
||||
else if (DIM == 3)
|
||||
{
|
||||
DGMassBasis3D<T_D1D, MAX_D1D>(e, NE, b_, x_, y_, d1d);
|
||||
DGMassBasis3D<T_D1D>(e, NE, b_, x_, y_, d1d);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+1
-1
@@ -125,7 +125,7 @@ public:
|
||||
DofTransformation objects are provided by the FiniteElementSpace which has
|
||||
access to the mesh and can therefore provide the face orientations. This is
|
||||
convenient when working with GridFunction, LinearForm, or BilinearForm
|
||||
obejcts or their parallel counterparts.
|
||||
objects or their parallel counterparts.
|
||||
|
||||
StatelessDofTransformation objects are provided by FiniteElement or
|
||||
FiniteElementCollection objects which do not have access to face
|
||||
|
||||
@@ -492,6 +492,7 @@ int IsoparametricTransformation::OrderGrad(const FiniteElement *fe) const
|
||||
void IsoparametricTransformation::Transform (const IntegrationPoint &ip,
|
||||
Vector &trans)
|
||||
{
|
||||
MFEM_ASSERT(FElem != nullptr, "Must provide a valid FiniteElement object!");
|
||||
shape.SetSize(FElem->GetDof());
|
||||
trans.SetSize(PointMat.Height());
|
||||
|
||||
|
||||
+1
-1
@@ -807,7 +807,7 @@ void NodalFiniteElement::Project(
|
||||
else
|
||||
{
|
||||
DenseMatrix vshape(fe.GetDof(), std::max(Trans.GetSpaceDim(),
|
||||
fe.GetVDim()));
|
||||
fe.GetRangeDim()));
|
||||
|
||||
I.SetSize(vshape.Width()*dof, fe.GetDof());
|
||||
for (int k = 0; k < dof; k++)
|
||||
|
||||
+7
-6
@@ -307,19 +307,20 @@ public:
|
||||
FiniteElement(int D, Geometry::Type G, int Do, int O,
|
||||
int F = FunctionSpace::Pk);
|
||||
|
||||
/// Returns the reference space dimension for the finite element
|
||||
/// Returns the reference space dimension for the finite element.
|
||||
int GetDim() const { return dim; }
|
||||
|
||||
/// Returns the vector dimension for vector-valued finite elements
|
||||
int GetVDim() const { return vdim; }
|
||||
/** @brief Returns the vector dimension for vector-valued finite elements,
|
||||
which is also the dimension of the interpolation operatrion. */
|
||||
int GetRangeDim() const { return vdim; }
|
||||
|
||||
/// Returns the dimension of the curl for vector-valued finite elements
|
||||
/// Returns the dimension of the curl for vector-valued finite elements.
|
||||
int GetCurlDim() const { return cdim; }
|
||||
|
||||
/// Returns the Geometry::Type of the reference element
|
||||
/// Returns the Geometry::Type of the reference element.
|
||||
Geometry::Type GetGeomType() const { return geom_type; }
|
||||
|
||||
/// Returns the number of degrees of freedom in the finite element
|
||||
/// Returns the number of degrees of freedom in the finite element.
|
||||
int GetDof() const { return dof; }
|
||||
|
||||
/** @brief Returns the order of the finite element. In the case of
|
||||
|
||||
+2
-2
@@ -1852,7 +1852,7 @@ void ND_R1D_SegmentElement::Project(const FiniteElement &fe,
|
||||
else
|
||||
{
|
||||
double vk[Geometry::MaxDim];
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetVDim());
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetRangeDim());
|
||||
|
||||
double * tk_ptr = const_cast<double*>(tk);
|
||||
|
||||
@@ -2293,7 +2293,7 @@ void ND_R2D_FiniteElement::Project(const FiniteElement &fe,
|
||||
else
|
||||
{
|
||||
double vk[Geometry::MaxDim];
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetVDim());
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetRangeDim());
|
||||
|
||||
double * tk_ptr = const_cast<double*>(tk);
|
||||
|
||||
|
||||
+4
-4
@@ -1486,7 +1486,7 @@ void RT_R1D_SegmentElement::Project(const FiniteElement &fe,
|
||||
else
|
||||
{
|
||||
double vk[Geometry::MaxDim];
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetVDim());
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetRangeDim());
|
||||
|
||||
double * nk_ptr = const_cast<double*>(nk);
|
||||
|
||||
@@ -1523,7 +1523,7 @@ void RT_R1D_SegmentElement::ProjectCurl(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &curl) const
|
||||
{
|
||||
DenseMatrix curl_shape(fe.GetDof(), fe.GetVDim());
|
||||
DenseMatrix curl_shape(fe.GetDof(), fe.GetRangeDim());
|
||||
Vector curl_k(fe.GetDof());
|
||||
|
||||
double * nk_ptr = const_cast<double*>(nk);
|
||||
@@ -1849,7 +1849,7 @@ void RT_R2D_FiniteElement::Project(const FiniteElement &fe,
|
||||
else
|
||||
{
|
||||
double vk[Geometry::MaxDim];
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetVDim());
|
||||
DenseMatrix vshape(fe.GetDof(), fe.GetRangeDim());
|
||||
|
||||
double * nk_ptr = const_cast<double*>(nk);
|
||||
|
||||
@@ -1888,7 +1888,7 @@ void RT_R2D_FiniteElement::ProjectCurl(const FiniteElement &fe,
|
||||
ElementTransformation &Trans,
|
||||
DenseMatrix &curl) const
|
||||
{
|
||||
DenseMatrix curl_shape(fe.GetDof(), fe.GetVDim());
|
||||
DenseMatrix curl_shape(fe.GetDof(), fe.GetRangeDim());
|
||||
Vector curl_k(fe.GetDof());
|
||||
|
||||
double * nk_ptr = const_cast<double*>(nk);
|
||||
|
||||
@@ -87,6 +87,16 @@ int FiniteElementCollection::GetDerivMapType(int dim) const
|
||||
return FiniteElement::UNKNOWN_MAP_TYPE;
|
||||
}
|
||||
|
||||
int FiniteElementCollection::GetRangeDim(int dim) const
|
||||
{
|
||||
const FiniteElement *fe = FiniteElementForDim(dim);
|
||||
if (fe)
|
||||
{
|
||||
return fe->GetRangeDim();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FiniteElementCollection::HasFaceDofs(Geometry::Type geom, int p) const
|
||||
{
|
||||
switch (geom)
|
||||
|
||||
+347
-293
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -13,7 +13,6 @@
|
||||
#define MFEM_FEM_HPP
|
||||
|
||||
#include "intrules.hpp"
|
||||
#include "intrules_cut.hpp"
|
||||
#include "geom.hpp"
|
||||
#include "fe.hpp"
|
||||
#include "fe_coll.hpp"
|
||||
@@ -27,6 +26,7 @@
|
||||
#include "bilininteg.hpp"
|
||||
#include "fespace.hpp"
|
||||
#include "gridfunc.hpp"
|
||||
#include "kdtree.hpp"
|
||||
#include "linearform.hpp"
|
||||
#include "nonlinearform.hpp"
|
||||
#include "bilinearform.hpp"
|
||||
|
||||
+67
-28
@@ -64,7 +64,7 @@ FiniteElementSpace::FiniteElementSpace()
|
||||
face_dof(NULL),
|
||||
NURBSext(NULL), own_ext(false),
|
||||
DoFTrans(0), VDoFTrans(vdim, ordering),
|
||||
cP(NULL), cR(NULL), cR_hp(NULL), cP_is_set(false),
|
||||
cP_is_set(false),
|
||||
Th(Operator::ANY_TYPE),
|
||||
sequence(0), mesh_sequence(0), orders_changed(false), relaxed_hp(false)
|
||||
{ }
|
||||
@@ -123,24 +123,24 @@ void FiniteElementSpace::CopyProlongationAndRestriction(
|
||||
|
||||
if (fes.GetConformingProlongation() != NULL)
|
||||
{
|
||||
if (perm) { cP = Mult(*perm_mat, *fes.GetConformingProlongation()); }
|
||||
else { cP = new SparseMatrix(*fes.GetConformingProlongation()); }
|
||||
if (perm) { cP.reset(Mult(*perm_mat, *fes.GetConformingProlongation())); }
|
||||
else { cP.reset(new SparseMatrix(*fes.GetConformingProlongation())); }
|
||||
cP_is_set = true;
|
||||
}
|
||||
else if (perm != NULL)
|
||||
{
|
||||
cP = perm_mat;
|
||||
cP.reset(perm_mat);
|
||||
cP_is_set = true;
|
||||
perm_mat = NULL;
|
||||
}
|
||||
if (fes.GetConformingRestriction() != NULL)
|
||||
{
|
||||
if (perm) { cR = Mult(*fes.GetConformingRestriction(), *perm_mat_tr); }
|
||||
else { cR = new SparseMatrix(*fes.GetConformingRestriction()); }
|
||||
if (perm) { cR.reset(Mult(*fes.GetConformingRestriction(), *perm_mat_tr)); }
|
||||
else { cR.reset(new SparseMatrix(*fes.GetConformingRestriction())); }
|
||||
}
|
||||
else if (perm != NULL)
|
||||
{
|
||||
cR = perm_mat_tr;
|
||||
cR.reset(perm_mat_tr);
|
||||
perm_mat_tr = NULL;
|
||||
}
|
||||
|
||||
@@ -960,7 +960,10 @@ void FiniteElementSpace::BuildConformingInterpolation() const
|
||||
|
||||
if (FEColl()->GetContType() == FiniteElementCollection::DISCONTINUOUS)
|
||||
{
|
||||
cP = cR = cR_hp = NULL; // will be treated as identities
|
||||
cP.reset();
|
||||
cR.reset();
|
||||
cR_hp.reset();
|
||||
R_transpose.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1114,12 +1117,15 @@ void FiniteElementSpace::BuildConformingInterpolation() const
|
||||
// if all dofs are true dofs leave cP and cR NULL
|
||||
if (n_true_dofs == ndofs)
|
||||
{
|
||||
cP = cR = cR_hp = NULL; // will be treated as identities
|
||||
cP.reset();
|
||||
cR.reset();
|
||||
cR_hp.reset();
|
||||
R_transpose.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
// create the conforming prolongation matrix cP
|
||||
cP = new SparseMatrix(ndofs, n_true_dofs);
|
||||
cP.reset(new SparseMatrix(ndofs, n_true_dofs));
|
||||
|
||||
// create the conforming restriction matrix cR
|
||||
int *cR_J;
|
||||
@@ -1133,12 +1139,19 @@ void FiniteElementSpace::BuildConformingInterpolation() const
|
||||
cR_A[i] = 1.0;
|
||||
}
|
||||
cR_I[n_true_dofs] = n_true_dofs;
|
||||
cR = new SparseMatrix(cR_I, cR_J, cR_A, n_true_dofs, ndofs);
|
||||
cR.reset(new SparseMatrix(cR_I, cR_J, cR_A, n_true_dofs, ndofs));
|
||||
}
|
||||
|
||||
// In var. order spaces, create the restriction matrix cR_hp which is similar
|
||||
// to cR, but has interpolation in the extra master edge/face DOFs.
|
||||
cR_hp = IsVariableOrder() ? new SparseMatrix(n_true_dofs, ndofs) : NULL;
|
||||
if (IsVariableOrder())
|
||||
{
|
||||
cR_hp.reset(new SparseMatrix(n_true_dofs, ndofs));
|
||||
}
|
||||
else
|
||||
{
|
||||
cR_hp.reset();
|
||||
}
|
||||
|
||||
Array<bool> finalized(ndofs);
|
||||
finalized = false;
|
||||
@@ -1256,21 +1269,28 @@ const SparseMatrix* FiniteElementSpace::GetConformingProlongation() const
|
||||
{
|
||||
if (Conforming()) { return NULL; }
|
||||
if (!cP_is_set) { BuildConformingInterpolation(); }
|
||||
return cP;
|
||||
return cP.get();
|
||||
}
|
||||
|
||||
const SparseMatrix* FiniteElementSpace::GetConformingRestriction() const
|
||||
{
|
||||
if (Conforming()) { return NULL; }
|
||||
if (!cP_is_set) { BuildConformingInterpolation(); }
|
||||
return cR;
|
||||
if (cR && !R_transpose) { R_transpose.reset(new TransposeOperator(*cR)); }
|
||||
return cR.get();
|
||||
}
|
||||
|
||||
const SparseMatrix* FiniteElementSpace::GetHpConformingRestriction() const
|
||||
{
|
||||
if (Conforming()) { return NULL; }
|
||||
if (!cP_is_set) { BuildConformingInterpolation(); }
|
||||
return IsVariableOrder() ? cR_hp : cR;
|
||||
return IsVariableOrder() ? cR_hp.get() : cR.get();
|
||||
}
|
||||
|
||||
const Operator *FiniteElementSpace::GetRestrictionTransposeOperator() const
|
||||
{
|
||||
GetRestrictionOperator(); // Ensure that R_transpose is built
|
||||
return R_transpose.get();
|
||||
}
|
||||
|
||||
int FiniteElementSpace::GetNConformingDofs() const
|
||||
@@ -2201,7 +2221,10 @@ void FiniteElementSpace::Constructor(Mesh *mesh_, NURBSExtension *NURBSext_,
|
||||
own_ext = 1;
|
||||
}
|
||||
UpdateNURBS();
|
||||
cP = cR = cR_hp = NULL;
|
||||
cP.reset();
|
||||
cR.reset();
|
||||
cR_hp.reset();
|
||||
R_transpose.reset();
|
||||
cP_is_set = false;
|
||||
|
||||
ConstructDoFTrans();
|
||||
@@ -2363,6 +2386,7 @@ void FiniteElementSpace::Construct()
|
||||
cR = NULL;
|
||||
cR_hp = NULL;
|
||||
cP_is_set = false;
|
||||
R_transpose = NULL;
|
||||
// 'Th' is initialized/destroyed before this method is called.
|
||||
|
||||
int dim = mesh->Dimension();
|
||||
@@ -2404,6 +2428,7 @@ void FiniteElementSpace::Construct()
|
||||
{
|
||||
// the simple case: all edges are of the same order
|
||||
nedofs = mesh->GetNEdges() * fec->GetNumDof(Geometry::SEGMENT, order);
|
||||
var_edge_dofs.Clear(); // ensure any old var_edge_dof table is dumped.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2422,6 +2447,7 @@ void FiniteElementSpace::Construct()
|
||||
// the simple case: all faces are of the same geometry and order
|
||||
uni_fdof = fec->GetNumDof(mesh->GetFaceGeometry(0), order);
|
||||
nfdofs = mesh->GetNFaces() * uni_fdof;
|
||||
var_face_dofs.Clear(); // ensure any old var_face_dof table is dumped.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2632,7 +2658,6 @@ int FiniteElementSpace::MakeDofTable(int ent_dim,
|
||||
int dofs = fec->GetNumDof(geom, order);
|
||||
list.Append(Connection(i, total_dofs));
|
||||
total_dofs += dofs;
|
||||
|
||||
if (var_ent_order) { var_ent_order->Append(order); }
|
||||
}
|
||||
}
|
||||
@@ -2643,7 +2668,6 @@ int FiniteElementSpace::MakeDofTable(int ent_dim,
|
||||
|
||||
// build the table
|
||||
entity_dofs.MakeFromList(num_ent+1, list);
|
||||
|
||||
return total_dofs;
|
||||
}
|
||||
|
||||
@@ -2816,9 +2840,15 @@ void FiniteElementSpace::GetPatchDofs(int patch, Array<int> &dofs) const
|
||||
|
||||
const FiniteElement *FiniteElementSpace::GetFE(int i) const
|
||||
{
|
||||
if (i < 0 || !mesh->GetNE()) { return NULL; }
|
||||
MFEM_VERIFY(i < mesh->GetNE(),
|
||||
"Invalid element id " << i << ", maximum allowed " << mesh->GetNE()-1);
|
||||
if (i < 0 || i >= mesh->GetNE())
|
||||
{
|
||||
if (mesh->GetNE() == 0)
|
||||
{
|
||||
MFEM_ABORT("Empty MPI partitions are not permitted!");
|
||||
}
|
||||
MFEM_ABORT("Invalid element id:" << i << "; minimum allowed:" << 0 <<
|
||||
", maximum allowed:" << mesh->GetNE()-1);
|
||||
}
|
||||
|
||||
const FiniteElement *FE =
|
||||
fec->GetFE(mesh->GetElementGeometry(i), GetElementOrderImpl(i));
|
||||
@@ -2966,7 +2996,14 @@ int FiniteElementSpace::GetFaceDofs(int face, Array<int> &dofs,
|
||||
|
||||
order = !IsVariableOrder() ? fec->GetOrder() :
|
||||
var_face_orders[var_face_dofs.GetI()[face] + variant];
|
||||
MFEM_ASSERT(fec->GetNumDof(fgeom, order) == nf, "");
|
||||
MFEM_ASSERT(fec->GetNumDof(fgeom, order) == nf, [&]()
|
||||
{
|
||||
std::stringstream msg;
|
||||
msg << "fec->GetNumDof(" << (fgeom == Geometry::SQUARE ? "square" : "triangle")
|
||||
<< ", " << order << ") = " << fec->GetNumDof(fgeom, order) << " nf " << nf;
|
||||
msg << " face " << face << " variant " << variant << std::endl;
|
||||
return msg.str();
|
||||
}());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3218,9 +3255,10 @@ FiniteElementSpace::~FiniteElementSpace()
|
||||
|
||||
void FiniteElementSpace::Destroy()
|
||||
{
|
||||
delete cR;
|
||||
delete cR_hp;
|
||||
delete cP;
|
||||
R_transpose.reset();
|
||||
cR.reset();
|
||||
cR_hp.reset();
|
||||
cP.reset();
|
||||
Th.Clear();
|
||||
L2E_nat.Clear();
|
||||
L2E_lex.Clear();
|
||||
@@ -3233,6 +3271,7 @@ void FiniteElementSpace::Destroy()
|
||||
{
|
||||
delete x.second;
|
||||
}
|
||||
L2F.clear();
|
||||
for (int i = 0; i < E2IFQ_array.Size(); i++)
|
||||
{
|
||||
delete E2IFQ_array[i];
|
||||
@@ -3332,14 +3371,14 @@ void FiniteElementSpace::GetTrueTransferOperator(
|
||||
switch (RP_case)
|
||||
{
|
||||
case 1:
|
||||
T.Reset(new ProductOperator(cR, T.Ptr(), false, owner));
|
||||
T.Reset(new ProductOperator(cR.get(), T.Ptr(), false, owner));
|
||||
break;
|
||||
case 2:
|
||||
T.Reset(new ProductOperator(T.Ptr(), coarse_P, owner, false));
|
||||
break;
|
||||
case 3:
|
||||
T.Reset(new TripleProductOperator(
|
||||
cR, T.Ptr(), coarse_P, false, owner, false));
|
||||
cR.get(), T.Ptr(), coarse_P, false, owner, false));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3457,7 +3496,7 @@ void FiniteElementSpace::Update(bool want_transform)
|
||||
if (cP && cR)
|
||||
{
|
||||
Th.SetOperatorOwner(false);
|
||||
Th.Reset(new TripleProductOperator(cP, cR, Th.Ptr(),
|
||||
Th.Reset(new TripleProductOperator(cP.get(), cR.get(), Th.Ptr(),
|
||||
false, false, true));
|
||||
}
|
||||
break;
|
||||
|
||||
+21
-10
@@ -214,7 +214,7 @@ class FaceQuadratureInterpolator;
|
||||
@par
|
||||
Clearly the notion of a @b vdof is relevant in each of the three contexts
|
||||
mentioned above so extra care must be taken whenever @b vdim != 1 to ensure
|
||||
that the @b edof, @b ldof, or @b tdof is being interpretted correctly.
|
||||
that the @b edof, @b ldof, or @b tdof is being interpreted correctly.
|
||||
*/
|
||||
class FiniteElementSpace
|
||||
{
|
||||
@@ -277,12 +277,14 @@ protected:
|
||||
/** Matrix representing the prolongation from the global conforming dofs to
|
||||
a set of intermediate partially conforming dofs, e.g. the dofs associated
|
||||
with a "cut" space on a non-conforming mesh. */
|
||||
mutable SparseMatrix *cP; // owned
|
||||
mutable std::unique_ptr<SparseMatrix> cP;
|
||||
/// Conforming restriction matrix such that cR.cP=I.
|
||||
mutable SparseMatrix *cR; // owned
|
||||
mutable std::unique_ptr<SparseMatrix> cR;
|
||||
/// A version of the conforming restriction matrix for variable-order spaces.
|
||||
mutable SparseMatrix *cR_hp; // owned
|
||||
mutable std::unique_ptr<SparseMatrix> cR_hp;
|
||||
mutable bool cP_is_set;
|
||||
/// Operator computing the action of the transpose of the restriction.
|
||||
mutable std::unique_ptr<Operator> R_transpose;
|
||||
|
||||
/// Transformation to apply to GridFunctions after space Update().
|
||||
OperatorHandle Th;
|
||||
@@ -592,10 +594,17 @@ public:
|
||||
{ return GetConformingProlongation(); }
|
||||
|
||||
/// Return an operator that performs the transpose of GetRestrictionOperator
|
||||
/** The returned operator is owned by the FiniteElementSpace. In serial this
|
||||
is the same as GetProlongationMatrix() */
|
||||
virtual const Operator *GetRestrictionTransposeOperator() const
|
||||
{ return GetConformingProlongation(); }
|
||||
/** The returned operator is owned by the FiniteElementSpace.
|
||||
|
||||
For a serial conforming space, this returns NULL, indicating the identity
|
||||
operator.
|
||||
|
||||
For a parallel conforming space, this will return a matrix-free
|
||||
(Device)ConformingProlongationOperator.
|
||||
|
||||
For a non-conforming mesh this will return a TransposeOperator wrapping
|
||||
the restriction matrix. */
|
||||
const Operator *GetRestrictionTransposeOperator() const;
|
||||
|
||||
/// An abstract operator that performs the same action as GetRestrictionMatrix
|
||||
/** In some cases this is an optimized matrix-free implementation. The
|
||||
@@ -898,7 +907,7 @@ public:
|
||||
/// changed in the forward mappings by passing a value for @a ndofs which
|
||||
/// differs from that returned by GetNDofs().
|
||||
///
|
||||
/// @note Thse methods, with the exception of VDofToDof(), are designed to
|
||||
/// @note These methods, with the exception of VDofToDof(), are designed to
|
||||
/// produce the correctly encoded values when dof entries are negative,
|
||||
/// see @ref ldof for more on negative dof indices.
|
||||
///
|
||||
@@ -1115,7 +1124,9 @@ public:
|
||||
int GetLocalDofForDof(int i) const { return dof_ldof_array[i]; }
|
||||
|
||||
/** @brief Returns pointer to the FiniteElement in the FiniteElementCollection
|
||||
associated with i'th element in the mesh object. */
|
||||
associated with i'th element in the mesh object.
|
||||
Note: The method has been updated to abort instead of returning NULL for
|
||||
an empty partition. */
|
||||
virtual const FiniteElement *GetFE(int i) const;
|
||||
|
||||
/** @brief Returns pointer to the FiniteElement in the FiniteElementCollection
|
||||
|
||||
+56
-127
@@ -27,7 +27,6 @@
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
namespace mfem
|
||||
{
|
||||
|
||||
@@ -39,8 +38,9 @@ GridFunction::GridFunction(Mesh *m, std::istream &input)
|
||||
// Grid functions are stored on the device
|
||||
UseDevice(true);
|
||||
|
||||
fes = new FiniteElementSpace;
|
||||
fec = fes->Load(m, input);
|
||||
owned_fes.reset(new FiniteElementSpace);
|
||||
fes = owned_fes.get();
|
||||
fec.reset(fes->Load(m, input));
|
||||
|
||||
skip_comment_lines(input, '#');
|
||||
istream::int_type next_char = input.peek();
|
||||
@@ -82,10 +82,11 @@ GridFunction::GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces)
|
||||
int vdim, ordering;
|
||||
|
||||
fes = gf_array[0]->FESpace();
|
||||
fec = FiniteElementCollection::New(fes->FEColl()->Name());
|
||||
fec.reset(FiniteElementCollection::New(fes->FEColl()->Name()));
|
||||
vdim = fes->GetVDim();
|
||||
ordering = fes->GetOrdering();
|
||||
fes = new FiniteElementSpace(m, fec, vdim, ordering);
|
||||
owned_fes.reset(new FiniteElementSpace(m, fec.get(), vdim, ordering));
|
||||
fes = owned_fes.get();
|
||||
SetSize(fes->GetVSize());
|
||||
|
||||
if (m->NURBSext)
|
||||
@@ -154,12 +155,9 @@ GridFunction::GridFunction(Mesh *m, GridFunction *gf_array[], int num_pieces)
|
||||
|
||||
void GridFunction::Destroy()
|
||||
{
|
||||
if (fec)
|
||||
{
|
||||
delete fes;
|
||||
delete fec;
|
||||
fec = NULL;
|
||||
}
|
||||
owned_fes.reset();
|
||||
fec.reset();
|
||||
fes = nullptr;
|
||||
}
|
||||
|
||||
void GridFunction::Update()
|
||||
@@ -341,7 +339,7 @@ int GridFunction::VectorDim() const
|
||||
return fes->GetVDim();
|
||||
}
|
||||
return fes->GetVDim()*std::max(fes->GetMesh()->SpaceDimension(),
|
||||
fe->GetVDim());
|
||||
fe->GetRangeDim());
|
||||
}
|
||||
|
||||
int GridFunction::CurlDim() const
|
||||
@@ -721,56 +719,6 @@ void GridFunction::GetVectorValues(int i, const IntegrationRule &ir,
|
||||
GetVectorValues(*Tr, ir, vals);
|
||||
}
|
||||
|
||||
void be_to_bfe(Geometry::Type geom, int o, const IntegrationPoint &ip,
|
||||
IntegrationPoint &fip)
|
||||
{
|
||||
if (geom == Geometry::TRIANGLE)
|
||||
{
|
||||
if (o == 2)
|
||||
{
|
||||
fip.x = 1.0 - ip.x - ip.y;
|
||||
fip.y = ip.x;
|
||||
}
|
||||
else if (o == 4)
|
||||
{
|
||||
fip.x = ip.y;
|
||||
fip.y = 1.0 - ip.x - ip.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
fip.x = ip.x;
|
||||
fip.y = ip.y;
|
||||
}
|
||||
fip.z = ip.z;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (o == 2)
|
||||
{
|
||||
fip.x = ip.y;
|
||||
fip.y = 1.0 - ip.x;
|
||||
}
|
||||
else if (o == 4)
|
||||
{
|
||||
fip.x = 1.0 - ip.x;
|
||||
fip.y = 1.0 - ip.y;
|
||||
}
|
||||
else if (o == 6)
|
||||
{
|
||||
fip.x = 1.0 - ip.y;
|
||||
fip.y = ip.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
fip.x = ip.x;
|
||||
fip.y = ip.y;
|
||||
}
|
||||
fip.z = ip.z;
|
||||
}
|
||||
fip.weight = ip.weight;
|
||||
fip.index = ip.index;
|
||||
}
|
||||
|
||||
double GridFunction::GetValue(ElementTransformation &T,
|
||||
const IntegrationPoint &ip,
|
||||
int comp, Vector *tr) const
|
||||
@@ -835,18 +783,15 @@ double GridFunction::GetValue(ElementTransformation &T,
|
||||
// boundary so we'll evaluate it in the neighboring element.
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
MFEM_ASSERT(FET != nullptr,
|
||||
"FaceElementTransformation must be valid for a boundary element");
|
||||
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// Boundary elements and boundary faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, ip, fip);
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o, ip);
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -974,18 +919,15 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
|
||||
// the boundary so we'll evaluate it in the neighboring element.
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
MFEM_ASSERT(FET != nullptr,
|
||||
"FaceElementTransformation must be valid for a boundary element");
|
||||
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// Boundary elements and boundary faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, ip, fip);
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o, ip);
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -998,6 +940,8 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
|
||||
{
|
||||
FaceElementTransformations * FET =
|
||||
dynamic_cast<FaceElementTransformations *>(&T);
|
||||
MFEM_ASSERT(FET != nullptr,
|
||||
"FaceElementTransformation must be valid for a boundary element");
|
||||
|
||||
// Evaluate in neighboring element for both continuous and
|
||||
// discontinuous fields (the integration point in T1 should have
|
||||
@@ -1042,7 +986,7 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
|
||||
else
|
||||
{
|
||||
int spaceDim = fes->GetMesh()->SpaceDimension();
|
||||
int vdim = std::max(spaceDim, fe->GetVDim());
|
||||
int vdim = std::max(spaceDim, fe->GetRangeDim());
|
||||
DenseMatrix vshape(dof, vdim);
|
||||
fe->CalcVShape(T, vshape);
|
||||
val.SetSize(vdim);
|
||||
@@ -1094,7 +1038,7 @@ void GridFunction::GetVectorValues(ElementTransformation &T,
|
||||
else
|
||||
{
|
||||
int spaceDim = fes->GetMesh()->SpaceDimension();
|
||||
int vdim = std::max(spaceDim, FElem->GetVDim());
|
||||
int vdim = std::max(spaceDim, FElem->GetRangeDim());
|
||||
DenseMatrix vshape(dof, vdim);
|
||||
|
||||
vals.SetSize(vdim, nip);
|
||||
@@ -1116,11 +1060,10 @@ int GridFunction::GetFaceVectorValues(
|
||||
int i, int side, const IntegrationRule &ir,
|
||||
DenseMatrix &vals, DenseMatrix &tr) const
|
||||
{
|
||||
int n, di;
|
||||
int di;
|
||||
FaceElementTransformations *Transf;
|
||||
|
||||
n = ir.GetNPoints();
|
||||
IntegrationRule eir(n); // ---
|
||||
IntegrationRule eir(ir.GetNPoints()); // ---
|
||||
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 0);
|
||||
if (side == 2)
|
||||
{
|
||||
@@ -1142,12 +1085,14 @@ int GridFunction::GetFaceVectorValues(
|
||||
if (di == 0)
|
||||
{
|
||||
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 5);
|
||||
MFEM_ASSERT(Transf != nullptr, "FaceElementTransformation cannot be null!");
|
||||
Transf->Loc1.Transform(ir, eir);
|
||||
GetVectorValues(*Transf->Elem1, eir, vals, &tr);
|
||||
}
|
||||
else
|
||||
{
|
||||
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 10);
|
||||
MFEM_ASSERT(Transf != nullptr, "FaceElementTransformation cannot be null!");
|
||||
Transf->Loc2.Transform(ir, eir);
|
||||
GetVectorValues(*Transf->Elem2, eir, vals, &tr);
|
||||
}
|
||||
@@ -1505,17 +1450,13 @@ double GridFunction::GetDivergence(ElementTransformation &T) const
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// Boundary elements and boundary faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o,
|
||||
T.GetIntPoint());
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -1602,17 +1543,13 @@ void GridFunction::GetCurl(ElementTransformation &T, Vector &curl) const
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// Boundary elements and boundary faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o,
|
||||
T.GetIntPoint());
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -1671,17 +1608,13 @@ void GridFunction::GetGradient(ElementTransformation &T, Vector &grad) const
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// Boundary elements and boundary faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o,
|
||||
T.GetIntPoint());
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
@@ -1757,17 +1690,13 @@ void GridFunction::GetVectorGradient(
|
||||
FaceElementTransformations * FET =
|
||||
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
|
||||
|
||||
// Boundary elements and Boundary Faces may have different
|
||||
// Boundary elements and boundary faces may have different
|
||||
// orientations so adjust the integration point if necessary.
|
||||
int o = 0;
|
||||
if (fes->GetMesh()->Dimension() == 3)
|
||||
{
|
||||
int f;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
}
|
||||
|
||||
IntegrationPoint fip;
|
||||
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
|
||||
int f, o;
|
||||
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
|
||||
IntegrationPoint fip =
|
||||
Mesh::TransformBdrElementToFace(FET->GetGeometryType(), o,
|
||||
T.GetIntPoint());
|
||||
|
||||
// Compute and set the point in element 1 from fip
|
||||
FET->SetAllIntPoints(&fip);
|
||||
|
||||
+7
-24
@@ -20,6 +20,7 @@
|
||||
#include "../general/adios2stream.hpp"
|
||||
#endif
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
@@ -30,14 +31,13 @@ namespace mfem
|
||||
class GridFunction : public Vector
|
||||
{
|
||||
protected:
|
||||
/// FE space on which the grid function lives. Owned if #fec is not NULL.
|
||||
/// FE space on which the grid function lives.
|
||||
FiniteElementSpace *fes;
|
||||
|
||||
/** @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;
|
||||
set explicitly, see MakeOwner(). */
|
||||
std::shared_ptr<FiniteElementCollection> fec;
|
||||
std::shared_ptr<FiniteElementSpace> owned_fes;
|
||||
|
||||
long fes_sequence; // see FiniteElementSpace::sequence, Mesh::sequence
|
||||
|
||||
@@ -74,11 +74,6 @@ public:
|
||||
|
||||
GridFunction() { fes = NULL; fec = NULL; fes_sequence = 0; UseDevice(true); }
|
||||
|
||||
/// Copy constructor. The internal true-dof vector #t_vec is not copied.
|
||||
GridFunction(const GridFunction &orig)
|
||||
: Vector(orig), fes(orig.fes), fec(NULL), fes_sequence(orig.fes_sequence)
|
||||
{ UseDevice(true); }
|
||||
|
||||
/// Construct a GridFunction associated with the FiniteElementSpace @a *f.
|
||||
GridFunction(FiniteElementSpace *f) : Vector(f->GetVSize())
|
||||
{ fes = f; fec = NULL; fes_sequence = f->GetSequence(); UseDevice(true); }
|
||||
@@ -107,21 +102,12 @@ 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
|
||||
assignment operator. */
|
||||
GridFunction &operator=(const GridFunction &rhs)
|
||||
{ return operator=((const Vector &)rhs); }
|
||||
|
||||
/// Make the GridFunction the owner of #fec and #fes.
|
||||
/** If the new FiniteElementCollection, @a fec_, is NULL, ownership of #fec
|
||||
and #fes is taken away. */
|
||||
void MakeOwner(FiniteElementCollection *fec_) { fec = fec_; }
|
||||
void MakeOwner(FiniteElementCollection *fec_) { fec.reset(fec_); }
|
||||
|
||||
FiniteElementCollection *OwnFEC() { return fec; }
|
||||
FiniteElementCollection *OwnFEC() { return fec.get(); }
|
||||
|
||||
int VectorDim() const;
|
||||
int CurlDim() const;
|
||||
@@ -754,9 +740,6 @@ public:
|
||||
/** @brief Write the GridFunction in STL format. Note that the mesh dimension
|
||||
must be 2 and that quad elements will be broken into two triangles.*/
|
||||
void SaveSTL(std::ostream &out, int TimesToRefine = 1);
|
||||
|
||||
/// Destroys grid function.
|
||||
virtual ~GridFunction() { Destroy(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
+35
-8
@@ -10,6 +10,7 @@
|
||||
// CONTRIBUTING.md for details.
|
||||
|
||||
#include "gslib.hpp"
|
||||
#include "geom.hpp"
|
||||
|
||||
#ifdef MFEM_USE_GSLIB
|
||||
|
||||
@@ -238,7 +239,8 @@ void FindPointsGSLIB::FindPoints(const Vector &point_pos,
|
||||
}
|
||||
|
||||
// Map element number for simplices, and ref_pos from [-1,1] to [0,1] for
|
||||
// both simplices and quads.
|
||||
// both simplices and quads. Also sets code to 1 for points found on element
|
||||
// faces/edges.
|
||||
MapRefPosAndElemIndices();
|
||||
}
|
||||
|
||||
@@ -681,6 +683,9 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
int nptorig = points_cnt,
|
||||
npt = points_cnt;
|
||||
|
||||
// tolerance for point to be marked as on element edge/face
|
||||
double btol = 1e-12;
|
||||
|
||||
GridFunction *gf_rst_map_temp = NULL;
|
||||
int nptsend = 0;
|
||||
|
||||
@@ -694,7 +699,7 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
|
||||
// Pack data to send via crystal router
|
||||
struct gslib::array *outpt = new gslib::array;
|
||||
struct out_pt { double r[3]; uint index, el, proc; };
|
||||
struct out_pt { double r[3]; uint index, el, proc, code; };
|
||||
struct out_pt *pt;
|
||||
array_init(struct out_pt, outpt, nptsend);
|
||||
outpt->n=nptsend;
|
||||
@@ -712,12 +717,12 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
pt->index = index;
|
||||
pt->proc = gsl_proc[index];
|
||||
pt->el = gsl_elem[index];
|
||||
pt->code = gsl_code[index];
|
||||
++pt;
|
||||
}
|
||||
|
||||
// Transfer data to target MPI ranks
|
||||
sarray_transfer(struct out_pt, outpt, proc, 1, cr);
|
||||
|
||||
// Map received points
|
||||
npt = outpt->n;
|
||||
pt = (struct out_pt *)outpt->ptr;
|
||||
@@ -731,7 +736,13 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
const Geometry::Type gt = fe->GetGeomType();
|
||||
pt->el = mesh_elem;
|
||||
|
||||
if (gt == Geometry::SQUARE || gt == Geometry::CUBE) { ++pt; continue; }
|
||||
if (gt == Geometry::SQUARE || gt == Geometry::CUBE)
|
||||
{
|
||||
// check if it is on element boundary
|
||||
pt->code = Geometry::CheckPoint(gt, ip, -btol) ? 0 : 1;
|
||||
++pt;
|
||||
continue;
|
||||
}
|
||||
else if (gt == Geometry::TRIANGLE)
|
||||
{
|
||||
gf_rst_map_temp = gf_rst_map[0];
|
||||
@@ -758,6 +769,10 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
{
|
||||
pt->r[d] = mfem_ref(d);
|
||||
}
|
||||
|
||||
// check if point is on element boundary
|
||||
ip.Set3(&pt->r[0]);
|
||||
pt->code = Geometry::CheckPoint(gt, ip, -btol) ? 0 : 1;
|
||||
++pt;
|
||||
}
|
||||
|
||||
@@ -774,6 +789,7 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
{
|
||||
gsl_mfem_ref(d + pt->index*dim) = pt->r[d];
|
||||
}
|
||||
gsl_code[pt->index] = pt->code;
|
||||
++pt;
|
||||
}
|
||||
array_free(outpt);
|
||||
@@ -784,12 +800,22 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
{
|
||||
if (gsl_code[index] != 2 && gsl_proc[index] == gsl_comm->id)
|
||||
{
|
||||
|
||||
IntegrationPoint ip;
|
||||
Vector mfem_ref(gsl_mfem_ref.GetData()+index*dim, dim);
|
||||
ip.Set2(mfem_ref.GetData());
|
||||
if (dim == 3) { ip.z = mfem_ref(2); }
|
||||
|
||||
const int elem = gsl_elem[index];
|
||||
const int mesh_elem = split_element_map[elem];
|
||||
const FiniteElement *fe = mesh->GetNodalFESpace()->GetFE(mesh_elem);
|
||||
const Geometry::Type gt = fe->GetGeomType();
|
||||
gsl_mfem_elem[index] = mesh_elem;
|
||||
if (gt == Geometry::SQUARE || gt == Geometry::CUBE) { continue; }
|
||||
if (gt == Geometry::SQUARE || gt == Geometry::CUBE)
|
||||
{
|
||||
gsl_code[index] = Geometry::CheckPoint(gt, ip, -btol) ? 0 : 1;
|
||||
continue;
|
||||
}
|
||||
else if (gt == Geometry::TRIANGLE)
|
||||
{
|
||||
gf_rst_map_temp = gf_rst_map[0];
|
||||
@@ -808,11 +834,12 @@ void FindPointsGSLIB::MapRefPosAndElemIndices()
|
||||
}
|
||||
|
||||
int local_elem = split_element_index[elem];
|
||||
IntegrationPoint ip;
|
||||
Vector mfem_ref(gsl_mfem_ref.GetData()+index*dim, dim);
|
||||
gf_rst_map_temp->GetVectorValue(local_elem, ip, mfem_ref);
|
||||
|
||||
// Check if the point is on element boundary
|
||||
ip.Set2(mfem_ref.GetData());
|
||||
if (dim == 3) { ip.z = mfem_ref(2); }
|
||||
gf_rst_map_temp->GetVectorValue(local_elem, ip, mfem_ref);
|
||||
gsl_code[index] = Geometry::CheckPoint(gt, ip, -btol) ? 0 : 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,8 @@ static void EAConvectionAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, NE);
|
||||
@@ -38,7 +38,7 @@ static void EAConvectionAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_Gi[MQ1];
|
||||
double r_Bj[MQ1];
|
||||
for (int q = 0; q < Q1D; q++)
|
||||
@@ -80,8 +80,8 @@ static void EAConvectionAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, 2, NE);
|
||||
@@ -90,8 +90,8 @@ static void EAConvectionAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
double r_G[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
@@ -157,8 +157,8 @@ static void EAConvectionAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, 3, NE);
|
||||
@@ -167,8 +167,8 @@ static void EAConvectionAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
double r_G[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
|
||||
@@ -203,8 +203,8 @@ void PAConvectionApply2D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -216,8 +216,8 @@ void PAConvectionApply2D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double u[max_D1D][max_D1D];
|
||||
for (int dy = 0; dy < D1D; ++dy)
|
||||
@@ -323,8 +323,8 @@ void SmemPAConvectionApply2D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -338,8 +338,8 @@ void SmemPAConvectionApply2D(const int ne,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
// constexpr int MDQ = (max_Q1D > max_D1D) ? max_Q1D : max_D1D;
|
||||
MFEM_SHARED double u[NBZ][max_D1D][max_D1D];
|
||||
MFEM_FOREACH_THREAD(dy,y,D1D)
|
||||
@@ -450,8 +450,8 @@ void PAConvectionApply3D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -463,8 +463,8 @@ void PAConvectionApply3D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double u[max_D1D][max_D1D][max_D1D];
|
||||
for (int dz = 0; dz < D1D; ++dz)
|
||||
@@ -631,8 +631,8 @@ void SmemPAConvectionApply3D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -644,8 +644,8 @@ void SmemPAConvectionApply3D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_DQ = (max_Q1D > max_D1D) ? max_Q1D : max_D1D;
|
||||
MFEM_SHARED double sm0[max_DQ*max_DQ*max_DQ];
|
||||
MFEM_SHARED double sm1[max_DQ*max_DQ*max_DQ];
|
||||
@@ -835,8 +835,8 @@ void PAConvectionApplyT2D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), D1D, Q1D);
|
||||
@@ -848,8 +848,8 @@ void PAConvectionApplyT2D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double u[max_D1D][max_D1D];
|
||||
for (int dy = 0; dy < D1D; ++dy)
|
||||
@@ -951,8 +951,8 @@ void SmemPAConvectionApplyT2D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), D1D, Q1D);
|
||||
@@ -966,8 +966,8 @@ void SmemPAConvectionApplyT2D(const int ne,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
MFEM_SHARED double u[NBZ][max_D1D][max_D1D];
|
||||
MFEM_FOREACH_THREAD(dy,y,D1D)
|
||||
{
|
||||
@@ -1073,8 +1073,8 @@ void PAConvectionApplyT3D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), D1D, Q1D);
|
||||
@@ -1086,8 +1086,8 @@ void PAConvectionApplyT3D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double u[max_D1D][max_D1D][max_D1D];
|
||||
for (int dz = 0; dz < D1D; ++dz)
|
||||
@@ -1249,8 +1249,8 @@ void SmemPAConvectionApplyT3D(const int ne,
|
||||
const int NE = ne;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), D1D, Q1D);
|
||||
@@ -1262,8 +1262,8 @@ void SmemPAConvectionApplyT3D(const int ne,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int max_DQ = (max_Q1D > max_D1D) ? max_Q1D : max_D1D;
|
||||
MFEM_SHARED double sm0[3*max_DQ*max_DQ*max_DQ];
|
||||
MFEM_SHARED double sm1[3*max_DQ*max_DQ*max_DQ];
|
||||
|
||||
@@ -83,8 +83,8 @@ static void EADGTraceAssemble2DInt(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, 2, 2, NF);
|
||||
auto A_int = Reshape(eadata_int.ReadWrite(), D1D, D1D, 2, NF);
|
||||
@@ -138,8 +138,8 @@ static void EADGTraceAssemble2DBdr(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, 2, 2, NF);
|
||||
auto A_bdr = Reshape(eadata_bdr.ReadWrite(), D1D, D1D, NF);
|
||||
@@ -181,8 +181,8 @@ static void EADGTraceAssemble3DInt(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
auto A_int = Reshape(eadata_int.ReadWrite(), D1D, D1D, D1D, D1D, 2, NF);
|
||||
@@ -191,8 +191,8 @@ static void EADGTraceAssemble3DInt(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
{
|
||||
@@ -278,8 +278,8 @@ static void EADGTraceAssemble3DBdr(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
auto A_bdr = Reshape(eadata_bdr.ReadWrite(), D1D, D1D, D1D, D1D, NF);
|
||||
@@ -287,8 +287,8 @@ static void EADGTraceAssemble3DBdr(const int NF,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
{
|
||||
|
||||
@@ -258,8 +258,8 @@ void PADGTraceApply2D(const int NF,
|
||||
const int VDIM = 1;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, 2, 2, NF);
|
||||
@@ -272,8 +272,8 @@ void PADGTraceApply2D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double u0[max_D1D][VDIM];
|
||||
double u1[max_D1D][VDIM];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
@@ -349,8 +349,8 @@ void PADGTraceApply3D(const int NF,
|
||||
const int VDIM = 1;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
@@ -363,8 +363,8 @@ void PADGTraceApply3D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double u0[max_D1D][max_D1D][VDIM];
|
||||
double u1[max_D1D][max_D1D][VDIM];
|
||||
for (int d1 = 0; d1 < D1D; d1++)
|
||||
@@ -494,8 +494,8 @@ void SmemPADGTraceApply3D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
@@ -509,8 +509,8 @@ void SmemPADGTraceApply3D(const int NF,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
MFEM_SHARED double u0[NBZ][max_D1D][max_D1D];
|
||||
MFEM_SHARED double u1[NBZ][max_D1D][max_D1D];
|
||||
MFEM_FOREACH_THREAD(d1,x,D1D)
|
||||
@@ -659,8 +659,8 @@ void PADGTraceApplyTranspose2D(const int NF,
|
||||
const int VDIM = 1;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, 2, 2, NF);
|
||||
@@ -673,8 +673,8 @@ void PADGTraceApplyTranspose2D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double u0[max_D1D][VDIM];
|
||||
double u1[max_D1D][VDIM];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
@@ -755,8 +755,8 @@ void PADGTraceApplyTranspose3D(const int NF,
|
||||
const int VDIM = 1;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
@@ -769,8 +769,8 @@ void PADGTraceApplyTranspose3D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double u0[max_D1D][max_D1D][VDIM];
|
||||
double u1[max_D1D][max_D1D][VDIM];
|
||||
for (int d1 = 0; d1 < D1D; d1++)
|
||||
@@ -911,8 +911,8 @@ void SmemPADGTraceApplyTranspose3D(const int NF,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, 2, 2, NF);
|
||||
@@ -926,8 +926,8 @@ void SmemPADGTraceApplyTranspose3D(const int NF,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
MFEM_SHARED double u0[NBZ][max_D1D][max_D1D];
|
||||
MFEM_SHARED double u1[NBZ][max_D1D][max_D1D];
|
||||
MFEM_FOREACH_THREAD(d1,x,D1D)
|
||||
|
||||
@@ -28,8 +28,8 @@ static void EADiffusionAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, NE);
|
||||
auto A = Reshape(eadata.ReadWrite(), D1D, D1D, NE);
|
||||
@@ -37,7 +37,7 @@ static void EADiffusionAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_Gi[MQ1];
|
||||
double r_Gj[MQ1];
|
||||
for (int q = 0; q < Q1D; q++)
|
||||
@@ -79,8 +79,8 @@ static void EADiffusionAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, 3, NE);
|
||||
@@ -89,8 +89,8 @@ static void EADiffusionAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
double r_G[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
@@ -156,8 +156,8 @@ static void EADiffusionAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, 6, NE);
|
||||
@@ -166,8 +166,8 @@ static void EADiffusionAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
double r_G[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
|
||||
@@ -98,8 +98,8 @@ inline void PADiffusionDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
// note the different shape for D, if this is a symmetric matrix we only
|
||||
@@ -110,8 +110,8 @@ inline void PADiffusionDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
// gradphi \cdot Q \gradphi has four terms
|
||||
double QD0[MQ1][MD1];
|
||||
double QD1[MQ1][MD1];
|
||||
@@ -165,10 +165,10 @@ inline void SmemPADiffusionDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D*Q1D, symmetric ? 3 : 4, NE);
|
||||
@@ -179,8 +179,8 @@ inline void SmemPADiffusionDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
MFEM_SHARED double BG[2][MQ1*MD1];
|
||||
double (*B)[MD1] = (double (*)[MD1]) (BG+0);
|
||||
double (*G)[MD1] = (double (*)[MD1]) (BG+1);
|
||||
@@ -260,10 +260,10 @@ inline void PADiffusionDiagonal3D(const int NE,
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Q = Reshape(d.Read(), Q1D*Q1D*Q1D, symmetric ? 6 : 9, NE);
|
||||
@@ -272,8 +272,8 @@ inline void PADiffusionDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double QQD[MQ1][MQ1][MD1];
|
||||
double QDD[MQ1][MD1][MD1];
|
||||
for (int i = 0; i < DIM; ++i)
|
||||
@@ -361,10 +361,10 @@ inline void SmemPADiffusionDiagonal3D(const int NE,
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D*Q1D*Q1D, symmetric ? 6 : 9, NE);
|
||||
@@ -374,8 +374,8 @@ inline void SmemPADiffusionDiagonal3D(const int NE,
|
||||
const int tidz = MFEM_THREAD_ID(z);
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
MFEM_SHARED double BG[2][MQ1*MD1];
|
||||
double (*B)[MD1] = (double (*)[MD1]) (BG+0);
|
||||
double (*G)[MD1] = (double (*)[MD1]) (BG+1);
|
||||
@@ -521,8 +521,8 @@ inline void PADiffusionApply2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt_.Read(), D1D, Q1D);
|
||||
@@ -535,8 +535,8 @@ inline void PADiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][2];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -642,10 +642,10 @@ inline void SmemPADiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D*Q1D, symmetric ? 3 : 4, NE);
|
||||
@@ -657,8 +657,8 @@ inline void SmemPADiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
MFEM_SHARED double sBG[2][MQ1*MD1];
|
||||
double (*B)[MD1] = (double (*)[MD1]) (sBG+0);
|
||||
double (*G)[MD1] = (double (*)[MD1]) (sBG+1);
|
||||
@@ -800,8 +800,8 @@ inline void PADiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -813,8 +813,8 @@ inline void PADiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][3];
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -992,10 +992,10 @@ inline void SmemPADiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int M1Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int M1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= M1D, "");
|
||||
MFEM_VERIFY(Q1D <= M1Q, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, D1D);
|
||||
auto d = Reshape(d_.Read(), Q1D, Q1D, Q1D, symmetric ? 6 : 9, NE);
|
||||
@@ -1005,8 +1005,8 @@ inline void SmemPADiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
MFEM_SHARED double sBG[2][MQ1*MD1];
|
||||
double (*B)[MD1] = (double (*)[MD1]) (sBG+0);
|
||||
|
||||
@@ -229,9 +229,9 @@ static void PAGradientApply2D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, TR_D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, TR_D1D);
|
||||
auto Bt = Reshape(bt.Read(), TE_D1D, Q1D);
|
||||
@@ -245,8 +245,8 @@ static void PAGradientApply2D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 2;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][VDIM];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -359,9 +359,9 @@ static void PAGradientApply3D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, TR_D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, TR_D1D);
|
||||
auto Bt = Reshape(bt.Read(), TE_D1D, Q1D);
|
||||
@@ -375,8 +375,8 @@ static void PAGradientApply3D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 3;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][VDIM];
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
@@ -555,11 +555,11 @@ static void SmemPAGradientApply3D(const int NE,
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= Q1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= Q1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
|
||||
auto b = Reshape(b_.Read(), Q1D, TR_D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, TR_D1D);
|
||||
@@ -575,9 +575,9 @@ static void SmemPAGradientApply3D(const int NE,
|
||||
const int D1DR = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int D1DE = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1R = T_TR_D1D ? T_TR_D1D : MAX_D1D;
|
||||
constexpr int MD1E = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1R = T_TR_D1D ? T_TR_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MD1E = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MD1 = MD1E > MD1R ? MD1E : MD1R;
|
||||
constexpr int MDQ = MQ1 > MD1 ? MQ1 : MD1;
|
||||
MFEM_SHARED double sBG[2][MQ1*MD1];
|
||||
|
||||
@@ -26,9 +26,6 @@ void PAHcurlMassAssembleDiagonal2D(const int D1D,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Bc = Reshape(bc.Read(), Q1D, D1D);
|
||||
auto op = Reshape(pa_data.Read(), Q1D, Q1D, symmetric ? 3 : 4, NE);
|
||||
@@ -36,6 +33,9 @@ void PAHcurlMassAssembleDiagonal2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y components
|
||||
@@ -83,11 +83,10 @@ void PAHcurlMassAssembleDiagonal3D(const int D1D,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
@@ -97,6 +96,8 @@ void PAHcurlMassAssembleDiagonal3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
|
||||
@@ -158,10 +159,6 @@ void PAHcurlMassApply2D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Bc = Reshape(bc.Read(), Q1D, D1D);
|
||||
auto Bot = Reshape(bot.Read(), D1D-1, Q1D);
|
||||
@@ -172,6 +169,10 @@ void PAHcurlMassApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -288,11 +289,10 @@ void PAHcurlMassApply3D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
@@ -305,6 +305,9 @@ void PAHcurlMassApply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
@@ -604,9 +607,6 @@ void PACurlCurlAssembleDiagonal2D(const int D1D,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Gc = Reshape(gc.Read(), Q1D, D1D);
|
||||
auto op = Reshape(pa_data.Read(), Q1D, Q1D, NE);
|
||||
@@ -614,6 +614,9 @@ void PACurlCurlAssembleDiagonal2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y components
|
||||
@@ -661,9 +664,6 @@ void PACurlCurlApply2D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Bot = Reshape(bot.Read(), D1D-1, Q1D);
|
||||
@@ -675,6 +675,10 @@ void PACurlCurlApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double curl[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
// curl[qy][qx] will be computed as du_y/dx - du_x/dy
|
||||
@@ -824,9 +828,6 @@ void PAHcurlL2Apply2D(const int D1D,
|
||||
const Vector &x, // trial = H(curl)
|
||||
Vector &y) // test = L2 or H1
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
const int H1 = (D1Dtest == D1D);
|
||||
|
||||
MFEM_VERIFY(y.Size() == NE*D1Dtest*D1Dtest, "Test vector of wrong dimension");
|
||||
@@ -841,6 +842,10 @@ void PAHcurlL2Apply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double curl[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
// curl[qy][qx] will be computed as du_y/dx - du_x/dy
|
||||
@@ -939,9 +944,6 @@ void PAHcurlL2ApplyTranspose2D(const int D1D,
|
||||
const Vector &x, // trial = H(curl)
|
||||
Vector &y) // test = L2 or H1
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
const int H1 = (D1Dtest == D1D);
|
||||
|
||||
MFEM_VERIFY(x.Size() == NE*D1Dtest*D1Dtest, "Test vector of wrong dimension");
|
||||
@@ -956,6 +958,10 @@ void PAHcurlL2ApplyTranspose2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
// Zero-order term in L2 or H1 test space
|
||||
|
||||
@@ -59,8 +59,10 @@ inline void SmemPAHcurlMassAssembleDiagonal3D(const int d1d,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -72,8 +74,8 @@ inline void SmemPAHcurlMassAssembleDiagonal3D(const int d1d,
|
||||
mfem::forall_3D(NE, Q1D, Q1D, Q1D, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -218,8 +220,10 @@ inline void SmemPAHcurlMassApply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -234,8 +238,8 @@ inline void SmemPAHcurlMassApply3D(const int d1d,
|
||||
mfem::forall_3D(NE, Q1D, Q1D, Q1D, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -441,8 +445,10 @@ inline void PACurlCurlAssembleDiagonal3D(const int d1d,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -476,8 +482,8 @@ inline void PACurlCurlAssembleDiagonal3D(const int d1d,
|
||||
// which may be non-symmetric depending on a possibly non-symmetric matrix coefficient.
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -635,8 +641,10 @@ inline void SmemPACurlCurlAssembleDiagonal3D(const int d1d,
|
||||
const Vector &pa_data,
|
||||
Vector &diag)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -667,8 +675,8 @@ inline void SmemPACurlCurlAssembleDiagonal3D(const int d1d,
|
||||
// If c = 2, \hat{\nabla}\times\hat{u} reduces to [(u_2)_{x_1}, -(u_2)_{x_0}, 0]
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -848,8 +856,10 @@ inline void PACurlCurlApply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -874,8 +884,8 @@ inline void PACurlCurlApply3D(const int d1d,
|
||||
// If c = 2, \hat{\nabla}\times\hat{u} reduces to [(u_2)_{x_1}, -(u_2)_{x_0}, 0]
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -1369,8 +1379,10 @@ inline void SmemPACurlCurlApply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -1392,8 +1404,8 @@ inline void SmemPACurlCurlApply3D(const int d1d,
|
||||
auto device_kernel = [=] MFEM_DEVICE (int e)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -1738,8 +1750,10 @@ inline void PAHcurlL2Apply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -1764,8 +1778,8 @@ inline void PAHcurlL2Apply3D(const int d1d,
|
||||
// If c = 2, \hat{\nabla}\times\hat{u} reduces to [(u_2)_{x_1}, -(u_2)_{x_0}, 0]
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2107,8 +2121,10 @@ inline void SmemPAHcurlL2Apply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2123,8 +2139,8 @@ inline void SmemPAHcurlL2Apply3D(const int d1d,
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int maxCoeffDim = 9;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2425,8 +2441,10 @@ inline void PAHcurlL2ApplyTranspose3D(const int d1d,
|
||||
Vector &y)
|
||||
{
|
||||
// See PAHcurlL2Apply3D for comments.
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2442,8 +2460,8 @@ inline void PAHcurlL2ApplyTranspose3D(const int d1d,
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2791,8 +2809,10 @@ inline void SmemPAHcurlL2ApplyTranspose3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -2807,8 +2827,8 @@ inline void SmemPAHcurlL2ApplyTranspose3D(const int d1d,
|
||||
{
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int maxCoeffDim = 9;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
constexpr int MD1D = T_D1D ? T_D1D : DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
|
||||
@@ -224,11 +224,10 @@ void PAHcurlHdivMassApply2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int VDIM = 2;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -244,6 +243,8 @@ void PAHcurlHdivMassApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -323,7 +324,7 @@ void PAHcurlHdivMassApply2D(const int D1D,
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double massX[HDIV_MAX_D1D];
|
||||
double massX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
massX[dx] = 0.0;
|
||||
@@ -370,11 +371,10 @@ void PAHcurlHdivMassApply3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -395,6 +395,8 @@ void PAHcurlHdivMassApply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
@@ -507,7 +509,7 @@ void PAHcurlHdivMassApply3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double massXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
double massXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
|
||||
osc = 0;
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y, z test components
|
||||
@@ -528,7 +530,7 @@ void PAHcurlHdivMassApply3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double massX[HDIV_MAX_D1D];
|
||||
double massX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
massX[dx] = 0.0;
|
||||
|
||||
@@ -92,10 +92,12 @@ inline void PAHcurlHdivApply3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_D1D_TEST ||
|
||||
d1dtest <= HCURL_MAX_D1D, "Error: d1dtest > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_D1D_TEST || d1dtest <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1dtest > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -120,8 +122,8 @@ inline void PAHcurlHdivApply3D(const int d1d,
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D :
|
||||
HCURL_MAX_D1D; // Assuming HDIV_MAX_D1D <= HCURL_MAX_D1D
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
DofQuadLimits::HCURL_MAX_D1D; // Assuming HDIV_MAX_D1D <= HCURL_MAX_D1D
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -459,10 +461,12 @@ inline void PAHcurlHdivApplyTranspose3D(const int d1d,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d1d <= HCURL_MAX_D1D, "Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_D1D_TEST ||
|
||||
d1dtest <= HCURL_MAX_D1D, "Error: d1dtest > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= HCURL_MAX_Q1D, "Error: q1d > HCURL_MAX_Q1D");
|
||||
MFEM_VERIFY(T_D1D || d1d <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1d > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_D1D_TEST || d1dtest <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: d1dtest > HCURL_MAX_D1D");
|
||||
MFEM_VERIFY(T_Q1D || q1d <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: q1d > HCURL_MAX_Q1D");
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
@@ -487,8 +491,8 @@ inline void PAHcurlHdivApplyTranspose3D(const int d1d,
|
||||
|
||||
constexpr int VDIM = 3;
|
||||
constexpr int MD1D = T_D1D ? T_D1D :
|
||||
HCURL_MAX_D1D; // Assuming HDIV_MAX_D1D <= HCURL_MAX_D1D
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : HCURL_MAX_Q1D;
|
||||
DofQuadLimits::HCURL_MAX_D1D; // Assuming HDIV_MAX_D1D <= HCURL_MAX_D1D
|
||||
constexpr int MQ1D = T_Q1D ? T_Q1D : DofQuadLimits::HCURL_MAX_Q1D;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int D1Dtest = T_D1D_TEST ? T_D1D_TEST : d1dtest;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
@@ -176,9 +176,6 @@ void PAHdivMassAssembleDiagonal2D(const int D1D,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Bc = Reshape(Bc_.Read(), Q1D, D1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, symmetric ? 3 : 4, NE);
|
||||
@@ -186,6 +183,9 @@ void PAHdivMassAssembleDiagonal2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y components
|
||||
@@ -232,8 +232,10 @@ void PAHdivMassAssembleDiagonal3D(const int D1D,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -254,7 +256,7 @@ void PAHdivMassAssembleDiagonal3D(const int D1D,
|
||||
const int opc = (c == 0) ? 0 : ((c == 1) ? (symmetric ? 3 : 4) :
|
||||
(symmetric ? 5 : 8));
|
||||
|
||||
double mass[HDIV_MAX_Q1D];
|
||||
double mass[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
|
||||
for (int dz = 0; dz < D1Dz; ++dz)
|
||||
{
|
||||
@@ -347,10 +349,6 @@ void PAHdivMassApply2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Bc = Reshape(Bc_.Read(), Q1D, D1D);
|
||||
auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
|
||||
@@ -361,6 +359,10 @@ void PAHdivMassApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -478,8 +480,10 @@ void PAHdivMassApply3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -492,7 +496,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
double mass[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D][VDIM];
|
||||
double mass[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -518,7 +522,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
for (int dz = 0; dz < D1Dz; ++dz)
|
||||
{
|
||||
double massXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double massXY[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -529,7 +533,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
for (int dy = 0; dy < D1Dy; ++dy)
|
||||
{
|
||||
double massX[HDIV_MAX_Q1D];
|
||||
double massX[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
massX[qx] = 0.0;
|
||||
@@ -600,7 +604,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double massXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
double massXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
|
||||
osc = 0;
|
||||
|
||||
@@ -619,7 +623,7 @@ void PAHdivMassApply3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double massX[HDIV_MAX_D1D];
|
||||
double massX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
massX[dx] = 0;
|
||||
@@ -730,9 +734,6 @@ void PADivDivAssembleDiagonal2D(const int D1D,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
|
||||
@@ -740,6 +741,9 @@ void PADivDivAssembleDiagonal2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
int osc = 0;
|
||||
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y components
|
||||
@@ -786,8 +790,10 @@ void PADivDivAssembleDiagonal3D(const int D1D,
|
||||
const Vector &op_,
|
||||
Vector &diag_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -809,7 +815,7 @@ void PADivDivAssembleDiagonal3D(const int D1D,
|
||||
{
|
||||
for (int dy = 0; dy < D1Dy; ++dy)
|
||||
{
|
||||
double a[HDIV_MAX_Q1D];
|
||||
double a[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
@@ -855,10 +861,6 @@ void PADivDivApply2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
|
||||
auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
|
||||
@@ -869,6 +871,10 @@ void PADivDivApply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
double div[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
// div[qy][qx] will be computed as du_x/dx + du_y/dy
|
||||
@@ -974,8 +980,10 @@ void PADivDivApply3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -988,7 +996,7 @@ void PADivDivApply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -1011,7 +1019,7 @@ void PADivDivApply3D(const int D1D,
|
||||
|
||||
for (int dz = 0; dz < D1Dz; ++dz)
|
||||
{
|
||||
double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double aXY[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -1022,7 +1030,7 @@ void PADivDivApply3D(const int D1D,
|
||||
|
||||
for (int dy = 0; dy < D1Dy; ++dy)
|
||||
{
|
||||
double aX[HDIV_MAX_Q1D];
|
||||
double aX[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
aX[qx] = 0.0;
|
||||
@@ -1078,7 +1086,7 @@ void PADivDivApply3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
double aXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
|
||||
osc = 0;
|
||||
|
||||
@@ -1097,7 +1105,7 @@ void PADivDivApply3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double aX[HDIV_MAX_D1D];
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
@@ -1207,8 +1215,8 @@ void PAHdivL2AssembleDiagonal_ADAt_2D(const int D1D,
|
||||
// Compute row (rx,ry), assuming all contributions are from
|
||||
// a single element.
|
||||
|
||||
double row[2*HDIV_MAX_D1D*(HDIV_MAX_D1D-1)];
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double row[2*DofQuadLimits::HDIV_MAX_D1D*(DofQuadLimits::HDIV_MAX_D1D-1)];
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
|
||||
for (int i=0; i<2*D1D*(D1D - 1); ++i)
|
||||
{
|
||||
@@ -1231,7 +1239,7 @@ void PAHdivL2AssembleDiagonal_ADAt_2D(const int D1D,
|
||||
const int D1Dy = (c == 1) ? D1D : D1D - 1;
|
||||
const int D1Dx = (c == 0) ? D1D : D1D - 1;
|
||||
|
||||
double aX[HDIV_MAX_D1D];
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
@@ -1281,8 +1289,10 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
const Vector &D_,
|
||||
Vector &diag_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
|
||||
@@ -1303,8 +1313,9 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
// Compute row (rx,ry,rz), assuming all contributions are from
|
||||
// a single element.
|
||||
|
||||
double row[3*HDIV_MAX_D1D*(HDIV_MAX_D1D-1)*(HDIV_MAX_D1D-1)];
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double row[3*DofQuadLimits::HDIV_MAX_D1D*(DofQuadLimits::HDIV_MAX_D1D-1)*
|
||||
(DofQuadLimits::HDIV_MAX_D1D-1)];
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
|
||||
for (int i=0; i<3*D1D*(D1D - 1)*(D1D - 1); ++i)
|
||||
{
|
||||
@@ -1325,7 +1336,7 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
double aXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
|
||||
int osc = 0;
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
|
||||
@@ -1343,7 +1354,7 @@ void PAHdivL2AssembleDiagonal_ADAt_3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double aX[HDIV_MAX_D1D];
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
@@ -1408,10 +1419,6 @@ void PAHdivL2Apply2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
auto Gc = Reshape(Gc_.Read(), Q1D, D1D);
|
||||
auto L2Bot = Reshape(L2Bot_.Read(), L2D1D, Q1D);
|
||||
@@ -1421,6 +1428,10 @@ void PAHdivL2Apply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
double div[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -1514,10 +1525,6 @@ void PAHdivL2ApplyTranspose2D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
|
||||
|
||||
auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
|
||||
auto Gct = Reshape(Gct_.Read(), D1D, Q1D);
|
||||
auto Bot = Reshape(Bot_.Read(), D1D-1, Q1D);
|
||||
@@ -1527,6 +1534,10 @@ void PAHdivL2ApplyTranspose2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HDIV_MAX_Q1D;
|
||||
|
||||
double div[MAX_Q1D][MAX_Q1D];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -1622,8 +1633,10 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto Bo = Reshape(Bo_.Read(), Q1D, D1D-1);
|
||||
@@ -1635,7 +1648,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -1658,7 +1671,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
for (int dz = 0; dz < D1Dz; ++dz)
|
||||
{
|
||||
double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double aXY[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -1669,7 +1682,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
for (int dy = 0; dy < D1Dy; ++dy)
|
||||
{
|
||||
double aX[HDIV_MAX_Q1D];
|
||||
double aX[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
aX[qx] = 0.0;
|
||||
@@ -1724,7 +1737,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
double aXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
|
||||
for (int dy = 0; dy < L2D1D; ++dy)
|
||||
{
|
||||
@@ -1735,7 +1748,7 @@ void PAHdivL2Apply3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double aX[HDIV_MAX_D1D];
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < L2D1D; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
@@ -1783,8 +1796,10 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
const Vector &x_,
|
||||
Vector &y_)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= HDIV_MAX_D1D, "Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= HDIV_MAX_Q1D, "Error: Q1D > HDIV_MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Error: D1D > HDIV_MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Error: Q1D > HDIV_MAX_Q1D");
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
auto L2Bo = Reshape(L2Bo_.Read(), Q1D, L2D1D);
|
||||
@@ -1796,7 +1811,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
double div[HDIV_MAX_Q1D][HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double div[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -1811,7 +1826,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
|
||||
for (int dz = 0; dz < L2D1D; ++dz)
|
||||
{
|
||||
double aXY[HDIV_MAX_Q1D][HDIV_MAX_Q1D];
|
||||
double aXY[DofQuadLimits::HDIV_MAX_Q1D][DofQuadLimits::HDIV_MAX_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -1822,7 +1837,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
|
||||
for (int dy = 0; dy < L2D1D; ++dy)
|
||||
{
|
||||
double aX[HDIV_MAX_Q1D];
|
||||
double aX[DofQuadLimits::HDIV_MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
aX[qx] = 0.0;
|
||||
@@ -1874,7 +1889,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
double aXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
|
||||
double aXY[DofQuadLimits::HDIV_MAX_D1D][DofQuadLimits::HDIV_MAX_D1D];
|
||||
|
||||
int osc = 0;
|
||||
for (int c = 0; c < VDIM; ++c) // loop over x, y, z components
|
||||
@@ -1892,7 +1907,7 @@ void PAHdivL2ApplyTranspose3D(const int D1D,
|
||||
}
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
double aX[HDIV_MAX_D1D];
|
||||
double aX[DofQuadLimits::HDIV_MAX_D1D];
|
||||
for (int dx = 0; dx < D1Dx; ++dx)
|
||||
{
|
||||
aX[dx] = 0;
|
||||
|
||||
@@ -140,8 +140,8 @@ inline void SmemPAHdivMassApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : HDIV_MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : HDIV_MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::HDIV_MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
|
||||
MFEM_SHARED double smo[MQ1*(MD1-1)];
|
||||
@@ -310,8 +310,8 @@ inline void SmemPAHdivMassApply3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : HDIV_MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : HDIV_MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::HDIV_MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::HDIV_MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
|
||||
MFEM_SHARED double smo[MQ1*(MD1-1)];
|
||||
|
||||
@@ -34,11 +34,12 @@ static void PAHcurlApplyGradient2D(const int c_dofs1D,
|
||||
auto x = Reshape(x_.Read(), c_dofs1D, c_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), 2 * c_dofs1D * o_dofs1D, NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w[MAX_D1D][MAX_D1D];
|
||||
|
||||
// horizontal part
|
||||
@@ -110,11 +111,12 @@ static void PAHcurlApplyGradient2DBId(const int c_dofs1D,
|
||||
auto x = Reshape(x_.Read(), c_dofs1D, c_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), 2 * c_dofs1D * o_dofs1D, NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w[MAX_D1D][MAX_D1D];
|
||||
|
||||
// horizontal part
|
||||
@@ -178,11 +180,12 @@ static void PAHcurlApplyGradientTranspose2D(
|
||||
auto x = Reshape(x_.Read(), 2 * c_dofs1D * o_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w[MAX_D1D][MAX_D1D];
|
||||
|
||||
// horizontal part (open x, closed y)
|
||||
@@ -253,11 +256,12 @@ static void PAHcurlApplyGradientTranspose2DBId(
|
||||
auto x = Reshape(x_.Read(), 2 * c_dofs1D * o_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w[MAX_D1D][MAX_D1D];
|
||||
|
||||
// horizontal part (open x, closed y)
|
||||
@@ -324,11 +328,12 @@ static void PAHcurlApplyGradient3D(const int c_dofs1D,
|
||||
auto x = Reshape(x_.Read(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w1[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
|
||||
@@ -511,11 +516,13 @@ static void PAHcurlApplyGradient3DBId(const int c_dofs1D,
|
||||
auto x = Reshape(x_.Read(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
|
||||
auto y = Reshape(y_.ReadWrite(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w1[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
|
||||
@@ -678,11 +685,12 @@ static void PAHcurlApplyGradientTranspose3D(
|
||||
auto x = Reshape(x_.Read(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
|
||||
auto y = Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
double w1[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
// ---
|
||||
@@ -863,11 +871,13 @@ static void PAHcurlApplyGradientTranspose3DBId(
|
||||
auto x = Reshape(x_.Read(), (3 * c_dofs1D * c_dofs1D * o_dofs1D), NE);
|
||||
auto y = Reshape(y_.ReadWrite(), c_dofs1D, c_dofs1D, c_dofs1D, NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w1[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
// ---
|
||||
@@ -1152,12 +1162,13 @@ static void PAHcurlVecH1IdentityApply2D(const int c_dofs1D,
|
||||
|
||||
auto vk = Reshape(pa_data.Read(), 2, (2 * c_dofs1D * o_dofs1D), NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w[2][MAX_D1D][MAX_D1D];
|
||||
|
||||
// dofs that point parallel to x-axis (open in x, closed in y)
|
||||
@@ -1251,13 +1262,13 @@ static void PAHcurlVecH1IdentityApplyTranspose2D(const int c_dofs1D,
|
||||
|
||||
auto vk = Reshape(pa_data.Read(), 2, (2 * c_dofs1D * o_dofs1D), NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
//constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w[2][MAX_D1D][MAX_D1D];
|
||||
|
||||
// dofs that point parallel to x-axis (open in x, closed in y)
|
||||
@@ -1360,12 +1371,13 @@ static void PAHcurlVecH1IdentityApply3D(const int c_dofs1D,
|
||||
|
||||
auto vk = Reshape(pa_data.Read(), 3, (3 * c_dofs1D * c_dofs1D * o_dofs1D),
|
||||
NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w1[3][MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[3][MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
|
||||
@@ -1574,12 +1586,13 @@ static void PAHcurlVecH1IdentityApplyTranspose3D(const int c_dofs1D,
|
||||
auto vk = Reshape(pa_data.Read(), 3, (3 * c_dofs1D * c_dofs1D * o_dofs1D),
|
||||
NE);
|
||||
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
|
||||
MFEM_VERIFY(c_dofs1D <= MAX_D1D && o_dofs1D <= c_dofs1D, "");
|
||||
MFEM_VERIFY(c_dofs1D <= DeviceDofQuadLimits::Get().MAX_D1D &&
|
||||
o_dofs1D <= c_dofs1D, "");
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
|
||||
double w1[3][MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
double w2[3][MAX_D1D][MAX_D1D][MAX_D1D];
|
||||
|
||||
|
||||
@@ -27,8 +27,8 @@ static void EAMassAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, NE);
|
||||
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, NE);
|
||||
@@ -36,7 +36,7 @@ static void EAMassAssemble1D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_Bi[MQ1];
|
||||
double r_Bj[MQ1];
|
||||
for (int q = 0; q < Q1D; q++)
|
||||
@@ -77,8 +77,8 @@ static void EAMassAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, NE);
|
||||
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, NE);
|
||||
@@ -86,8 +86,8 @@ static void EAMassAssemble2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double r_B[MQ1][MD1];
|
||||
for (int d = 0; d < D1D; d++)
|
||||
{
|
||||
@@ -149,8 +149,8 @@ static void EAMassAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(basis.Read(), Q1D, D1D);
|
||||
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, NE);
|
||||
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, D1D, D1D, NE);
|
||||
@@ -158,8 +158,8 @@ static void EAMassAssemble3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int DQ = T_D1D * T_Q1D;
|
||||
|
||||
// For quadratic and lower it's better to use registers but for higher-order you start to
|
||||
|
||||
@@ -25,8 +25,6 @@ static void PAMassAssembleDiagonal1D(const int NE,
|
||||
const int D1D,
|
||||
const int Q1D)
|
||||
{
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d.Read(), Q1D, NE);
|
||||
auto Y = Reshape(y.ReadWrite(), D1D, NE);
|
||||
@@ -34,7 +32,6 @@ static void PAMassAssembleDiagonal1D(const int NE,
|
||||
{
|
||||
for (int dx = 0; dx < D1D; ++dx)
|
||||
{
|
||||
Y(dx, e) = 0.0;
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
Y(dx, e) += B(qx, dx) * B(qx, dx) * D(qx, e);
|
||||
@@ -198,8 +195,7 @@ void PAMassApply1D_Element(const int e,
|
||||
auto X = ConstDeviceMatrix(x_, D1D, NE);
|
||||
auto Y = DeviceMatrix(y_, D1D, NE);
|
||||
|
||||
constexpr int max_Q1D = MAX_Q1D;
|
||||
double XQ[max_Q1D];
|
||||
double XQ[DofQuadLimits::MAX_Q1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
XQ[qx] = 0.0;
|
||||
@@ -232,8 +228,8 @@ static void PAMassApply1D(const int NE,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
MFEM_VERIFY(d1d <= MAX_D1D, "");
|
||||
MFEM_VERIFY(q1d <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(d1d <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(q1d <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
|
||||
const auto B = b_.Read();
|
||||
const auto Bt = bt_.Read();
|
||||
|
||||
@@ -42,8 +42,8 @@ inline void PAMassAssembleDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d.Read(), Q1D, Q1D, NE);
|
||||
auto Y = Reshape(y.ReadWrite(), D1D, D1D, NE);
|
||||
@@ -51,8 +51,8 @@ inline void PAMassAssembleDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double QD[MQ1][MD1];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
{
|
||||
@@ -90,10 +90,10 @@ inline void SmemPAMassAssembleDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D, Q1D, NE);
|
||||
auto Y = Reshape(y_.ReadWrite(), D1D, D1D, NE);
|
||||
@@ -103,8 +103,8 @@ inline void SmemPAMassAssembleDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
MFEM_SHARED double B[MQ1][MD1];
|
||||
MFEM_SHARED double QDZ[NBZ][MQ1][MD1];
|
||||
double (*QD)[MD1] = (double (*)[MD1])(QDZ + tidz);
|
||||
@@ -156,8 +156,8 @@ inline void PAMassAssembleDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d.Read(), Q1D, Q1D, Q1D, NE);
|
||||
auto Y = Reshape(y.ReadWrite(), D1D, D1D, D1D, NE);
|
||||
@@ -165,8 +165,8 @@ inline void PAMassAssembleDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double QQD[MQ1][MQ1][MD1];
|
||||
double QDD[MQ1][MD1][MD1];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -226,10 +226,10 @@ inline void SmemPAMassAssembleDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto b = Reshape(b_.Read(), Q1D, D1D);
|
||||
auto D = Reshape(d_.Read(), Q1D, Q1D, Q1D, NE);
|
||||
auto Y = Reshape(y_.ReadWrite(), D1D, D1D, D1D, NE);
|
||||
@@ -238,8 +238,8 @@ inline void SmemPAMassAssembleDiagonal3D(const int NE,
|
||||
const int tidz = MFEM_THREAD_ID(z);
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
MFEM_SHARED double B[MQ1][MD1];
|
||||
MFEM_SHARED double QQD[MQ1][MQ1][MD1];
|
||||
MFEM_SHARED double QDD[MQ1][MD1][MD1];
|
||||
@@ -365,8 +365,8 @@ void PAMassApply2D_Element(const int e,
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int max_D1D = MAX_D1D;
|
||||
constexpr int max_Q1D = MAX_Q1D;
|
||||
constexpr int max_D1D = DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = DofQuadLimits::MAX_Q1D;
|
||||
double sol_xy[max_Q1D][max_Q1D];
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
{
|
||||
@@ -447,8 +447,8 @@ void SmemPAMassApply2D_Element(const int e,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
|
||||
auto b = ConstDeviceMatrix(b_, Q1D, D1D);
|
||||
@@ -592,8 +592,8 @@ void PAMassApply3D_Element(const int e,
|
||||
}
|
||||
}
|
||||
|
||||
constexpr int max_D1D = MAX_D1D;
|
||||
constexpr int max_Q1D = MAX_Q1D;
|
||||
constexpr int max_D1D = DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = DofQuadLimits::MAX_Q1D;
|
||||
double sol_xyz[max_Q1D][max_Q1D][max_Q1D];
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
{
|
||||
@@ -722,8 +722,8 @@ void SmemPAMassApply3D_Element(const int e,
|
||||
{
|
||||
constexpr int D1D = T_D1D ? T_D1D : d1d;
|
||||
constexpr int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
|
||||
|
||||
auto b = ConstDeviceMatrix(b_, Q1D, D1D);
|
||||
@@ -948,8 +948,8 @@ inline void PAMassApply2D(const int NE,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D ? T_D1D : d1d <= MAX_D1D, "");
|
||||
MFEM_VERIFY(T_Q1D ? T_Q1D : q1d <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(T_D1D ? T_D1D : d1d <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(T_Q1D ? T_Q1D : q1d <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
|
||||
const auto B = b_.Read();
|
||||
const auto Bt = bt_.Read();
|
||||
@@ -978,10 +978,10 @@ inline void SmemPAMassApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
const auto b = b_.Read();
|
||||
const auto D = d_.Read();
|
||||
const auto x = x_.Read();
|
||||
@@ -1004,8 +1004,8 @@ inline void PAMassApply3D(const int NE,
|
||||
const int d1d = 0,
|
||||
const int q1d = 0)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D ? T_D1D : d1d <= MAX_D1D, "");
|
||||
MFEM_VERIFY(T_Q1D ? T_Q1D : q1d <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(T_D1D ? T_D1D : d1d <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(T_Q1D ? T_Q1D : q1d <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
|
||||
const auto B = b_.Read();
|
||||
const auto Bt = bt_.Read();
|
||||
@@ -1033,10 +1033,10 @@ inline void SmemPAMassApply3D(const int NE,
|
||||
MFEM_CONTRACT_VAR(bt_);
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int M1Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int M1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= M1D, "");
|
||||
MFEM_VERIFY(Q1D <= M1Q, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto b = b_.Read();
|
||||
auto d = d_.Read();
|
||||
auto x = x_.Read();
|
||||
|
||||
@@ -128,7 +128,7 @@ void MassIntegrator::AssemblePABoundary(const FiniteElementSpace &fes)
|
||||
|
||||
int map_type = el.GetMapType();
|
||||
dim = el.GetDim(); // Dimension of the boundary element, *not* the mesh
|
||||
ne = fes.GetMesh()->GetNBE();
|
||||
ne = fes.GetMesh()->GetNFbyType(FaceType::Boundary);
|
||||
nq = ir->GetNPoints();
|
||||
face_geom = mesh->GetFaceGeometricFactors(*ir, GeometricFactors::DETERMINANTS,
|
||||
FaceType::Boundary, mt);
|
||||
|
||||
@@ -31,10 +31,6 @@ static void PAHcurlH1Apply2D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bc = Reshape(bc.Read(), Q1D, D1D);
|
||||
auto Gc = Reshape(gc.Read(), Q1D, D1D);
|
||||
auto Bot = Reshape(bot.Read(), D1D-1, Q1D);
|
||||
@@ -45,6 +41,10 @@ static void PAHcurlH1Apply2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -155,10 +155,6 @@ static void PAHcurlH1ApplyTranspose2D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
auto Bc = Reshape(bc.Read(), Q1D, D1D);
|
||||
auto Bo = Reshape(bo.Read(), Q1D, D1D-1);
|
||||
auto Bt = Reshape(bct.Read(), D1D, Q1D);
|
||||
@@ -169,6 +165,10 @@ static void PAHcurlH1ApplyTranspose2D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int VDIM = 2;
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qy = 0; qy < Q1D; ++qy)
|
||||
@@ -280,11 +280,10 @@ static void PAHcurlH1Apply3D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
@@ -298,6 +297,9 @@ static void PAHcurlH1Apply3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
@@ -470,11 +472,10 @@ static void PAHcurlH1ApplyTranspose3D(const int D1D,
|
||||
const Vector &x,
|
||||
Vector &y)
|
||||
{
|
||||
constexpr static int MAX_D1D = HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
|
||||
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().HCURL_MAX_D1D,
|
||||
"Error: D1D > MAX_D1D");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().HCURL_MAX_Q1D,
|
||||
"Error: Q1D > MAX_Q1D");
|
||||
|
||||
constexpr static int VDIM = 3;
|
||||
|
||||
@@ -488,6 +489,9 @@ static void PAHcurlH1ApplyTranspose3D(const int D1D,
|
||||
|
||||
mfem::forall(NE, [=] MFEM_HOST_DEVICE (int e)
|
||||
{
|
||||
constexpr static int MAX_D1D = DofQuadLimits::HCURL_MAX_D1D;
|
||||
constexpr static int MAX_Q1D = DofQuadLimits::HCURL_MAX_Q1D;
|
||||
|
||||
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
|
||||
|
||||
for (int qz = 0; qz < Q1D; ++qz)
|
||||
|
||||
@@ -233,8 +233,8 @@ static void PAVectorDiffusionDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
// note the different shape for D, this is a (symmetric) matrix so we only
|
||||
@@ -245,8 +245,8 @@ static void PAVectorDiffusionDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
// gradphi \cdot Q \gradphi has four terms
|
||||
double QD0[MQ1][MD1];
|
||||
double QD1[MQ1][MD1];
|
||||
@@ -301,10 +301,10 @@ static void PAVectorDiffusionDiagonal3D(const int NE,
|
||||
constexpr int DIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= MD1, "");
|
||||
MFEM_VERIFY(Q1D <= MQ1, "");
|
||||
const int max_q1d = T_Q1D ? T_Q1D : DeviceDofQuadLimits::Get().MAX_Q1D;
|
||||
const int max_d1d = T_D1D ? T_D1D : DeviceDofQuadLimits::Get().MAX_D1D;
|
||||
MFEM_VERIFY(D1D <= max_d1d, "");
|
||||
MFEM_VERIFY(Q1D <= max_q1d, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Q = Reshape(d.Read(), Q1D*Q1D*Q1D, 6, NE);
|
||||
@@ -313,8 +313,8 @@ static void PAVectorDiffusionDiagonal3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double QQD[MQ1][MQ1][MD1];
|
||||
double QDD[MQ1][MD1][MD1];
|
||||
for (int i = 0; i < DIM; ++i)
|
||||
@@ -442,8 +442,8 @@ void PAVectorDiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = T_VDIM ? T_VDIM : vdim;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -456,8 +456,8 @@ void PAVectorDiffusionApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = T_VDIM ? T_VDIM : vdim;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][2];
|
||||
for (int c = 0; c < VDIM; c++)
|
||||
@@ -563,8 +563,8 @@ void PAVectorDiffusionApply3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 3;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -576,8 +576,8 @@ void PAVectorDiffusionApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
for (int c = 0; c < VDIM; ++ c)
|
||||
{
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][3];
|
||||
|
||||
@@ -170,9 +170,9 @@ static void PADivergenceApply2D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, TR_D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, TR_D1D);
|
||||
auto Bt = Reshape(bt.Read(), TE_D1D, Q1D);
|
||||
@@ -186,8 +186,8 @@ static void PADivergenceApply2D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 2;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][VDIM];
|
||||
double div[max_Q1D][max_Q1D];
|
||||
@@ -308,9 +308,9 @@ static void PADivergenceApplyTranspose2D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto Bt = Reshape(bt.Read(), TR_D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), TR_D1D, Q1D);
|
||||
auto B = Reshape(b.Read(), Q1D, TE_D1D);
|
||||
@@ -324,8 +324,8 @@ static void PADivergenceApplyTranspose2D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 2;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TR_D1D = T_TR_D1D ? T_TR_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_TR_D1D = T_TR_D1D ? T_TR_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double quadTest[max_Q1D][max_Q1D];
|
||||
double grad[max_Q1D][max_Q1D][VDIM];
|
||||
@@ -424,9 +424,9 @@ static void PADivergenceApply3D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, TR_D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, TR_D1D);
|
||||
auto Bt = Reshape(bt.Read(), TE_D1D, Q1D);
|
||||
@@ -440,8 +440,8 @@ static void PADivergenceApply3D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 3;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_TE_D1D = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][VDIM];
|
||||
double div[max_Q1D][max_Q1D][max_Q1D];
|
||||
@@ -607,9 +607,9 @@ static void PADivergenceApplyTranspose3D(const int NE,
|
||||
const int TR_D1D = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto Bt = Reshape(bt.Read(), TR_D1D, Q1D);
|
||||
auto Gt = Reshape(gt.Read(), TR_D1D, Q1D);
|
||||
auto B = Reshape(b.Read(), Q1D, TE_D1D);
|
||||
@@ -623,8 +623,8 @@ static void PADivergenceApplyTranspose3D(const int NE,
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
const int VDIM = 3;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_TR_D1D = T_TR_D1D ? T_TR_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_TR_D1D = T_TR_D1D ? T_TR_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double quadTest[max_Q1D][max_Q1D][max_Q1D];
|
||||
double grad[max_Q1D][max_Q1D][max_Q1D][VDIM];
|
||||
@@ -786,9 +786,9 @@ static void SmemPADivergenceApply3D(const int NE,
|
||||
const int TE_D1D = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
|
||||
MFEM_VERIFY(TR_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(TR_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(TE_D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
|
||||
auto b = Reshape(b_.Read(), Q1D, TR_D1D);
|
||||
auto g = Reshape(g_.Read(), Q1D, TR_D1D);
|
||||
@@ -804,9 +804,9 @@ static void SmemPADivergenceApply3D(const int NE,
|
||||
const int D1DR = T_TR_D1D ? T_TR_D1D : tr_d1d;
|
||||
const int D1DE = T_TE_D1D ? T_TE_D1D : te_d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int MD1R = T_TR_D1D ? T_TR_D1D : MAX_D1D;
|
||||
constexpr int MD1E = T_TE_D1D ? T_TE_D1D : MAX_D1D;
|
||||
constexpr int MQ1 = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int MD1R = T_TR_D1D ? T_TR_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MD1E = T_TE_D1D ? T_TE_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MD1 = MD1E > MD1R ? MD1E : MD1R;
|
||||
constexpr int MDQ = MQ1 > MD1 ? MQ1 : MD1;
|
||||
MFEM_SHARED double sBG[2][MQ1*MD1];
|
||||
|
||||
@@ -118,8 +118,8 @@ static void PAVectorMassAssembleDiagonal2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 2;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(B_.Read(), Q1D, D1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
|
||||
auto y = Reshape(diag_.ReadWrite(), D1D, D1D, VDIM, NE);
|
||||
@@ -127,8 +127,8 @@ static void PAVectorMassAssembleDiagonal2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double temp[max_Q1D][max_D1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -170,8 +170,8 @@ static void PAVectorMassAssembleDiagonal3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 3;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(B_.Read(), Q1D, D1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
|
||||
auto y = Reshape(diag_.ReadWrite(), D1D, D1D, D1D, VDIM, NE);
|
||||
@@ -180,8 +180,8 @@ static void PAVectorMassAssembleDiagonal3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d; // nvcc workaround
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double temp[max_Q1D][max_Q1D][max_D1D];
|
||||
for (int qx = 0; qx < Q1D; ++qx)
|
||||
@@ -281,8 +281,8 @@ static void PAVectorMassApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 2;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(B_.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(Bt_.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, NE);
|
||||
@@ -293,8 +293,8 @@ static void PAVectorMassApply2D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d; // nvcc workaround
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
// the following variables are evaluated at compile time
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double sol_xy[max_Q1D][max_Q1D];
|
||||
for (int c = 0; c < VDIM; ++c)
|
||||
{
|
||||
@@ -377,8 +377,8 @@ static void PAVectorMassApply3D(const int NE,
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int VDIM = 3;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(B_.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(Bt_.Read(), D1D, Q1D);
|
||||
auto op = Reshape(op_.Read(), Q1D, Q1D, Q1D, NE);
|
||||
@@ -388,8 +388,8 @@ static void PAVectorMassApply3D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double sol_xyz[max_Q1D][max_Q1D][max_Q1D];
|
||||
for (int c = 0; c < VDIM; ++ c)
|
||||
{
|
||||
|
||||
@@ -38,7 +38,7 @@ static void BLFEvalAssemble2D(const int vdim, const int nbe, const int d,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double QQ[Q];
|
||||
|
||||
for (int c = 0; c < vdim; ++c)
|
||||
@@ -92,8 +92,8 @@ static void BLFEvalAssemble3D(const int vdim, const int nbe, const int d,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sBt[Q*D];
|
||||
MFEM_SHARED double sQQ[Q*Q];
|
||||
|
||||
@@ -33,7 +33,7 @@ void BFLFEvalAssemble2D(const int nbe, const int d, const int q,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore (in a lambda return acts as continue)
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
double QQ[Q];
|
||||
|
||||
for (int qx = 0; qx < q; ++qx)
|
||||
@@ -67,8 +67,8 @@ void BFLFEvalAssemble3D(const int nbe, const int d, const int q,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sBt[Q*D];
|
||||
MFEM_SHARED double sQQ[Q*Q];
|
||||
|
||||
@@ -36,8 +36,8 @@ static void DLFEvalAssemble2D(const int vdim, const int ne, const int d,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sBt[Q*D];
|
||||
MFEM_SHARED double sQQ[Q*Q];
|
||||
@@ -107,8 +107,8 @@ static void DLFEvalAssemble3D(const int vdim, const int ne, const int d,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQD = (Q >= D) ? Q : D;
|
||||
|
||||
double u[D];
|
||||
|
||||
@@ -36,8 +36,8 @@ void DLFGradAssemble2D(const int vdim, const int ne, const int d, const int q,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sBGt[2][Q*D];
|
||||
MFEM_SHARED double sQQ[2][Q*Q];
|
||||
@@ -130,8 +130,8 @@ void DLFGradAssemble3D(const int vdim, const int ne, const int d, const int q,
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int MQD = (Q >= D) ? Q : D;
|
||||
|
||||
MFEM_SHARED double sBGt[2][Q*D];
|
||||
|
||||
@@ -22,8 +22,10 @@ static void HdivDLFAssemble2D(
|
||||
const double *bc, const double *j, const double *weights,
|
||||
const Vector &coeff, double *y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d <= HDIV_MAX_D1D, "Problem size too large.");
|
||||
MFEM_VERIFY(T_Q1D || q <= HDIV_MAX_Q1D, "Problem size too large.");
|
||||
MFEM_VERIFY(T_D1D || d <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Problem size too large.");
|
||||
MFEM_VERIFY(T_Q1D || q <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Problem size too large.");
|
||||
|
||||
static constexpr int vdim = 2;
|
||||
const auto F = coeff.Read();
|
||||
@@ -40,8 +42,8 @@ static void HdivDLFAssemble2D(
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : HDIV_MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : HDIV_MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::HDIV_MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::HDIV_MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sBot[Q*D];
|
||||
MFEM_SHARED double sBct[Q*D];
|
||||
@@ -121,8 +123,10 @@ static void HdivDLFAssemble3D(
|
||||
const double *bc, const double *j, const double *weights,
|
||||
const Vector &coeff, double *y)
|
||||
{
|
||||
MFEM_VERIFY(T_D1D || d <= HDIV_MAX_D1D, "Problem size too large.");
|
||||
MFEM_VERIFY(T_Q1D || q <= HDIV_MAX_Q1D, "Problem size too large.");
|
||||
MFEM_VERIFY(T_D1D || d <= DeviceDofQuadLimits::Get().HDIV_MAX_D1D,
|
||||
"Problem size too large.");
|
||||
MFEM_VERIFY(T_Q1D || q <= DeviceDofQuadLimits::Get().HDIV_MAX_Q1D,
|
||||
"Problem size too large.");
|
||||
|
||||
static constexpr int vdim = 3;
|
||||
const auto F = coeff.Read();
|
||||
@@ -139,8 +143,8 @@ static void HdivDLFAssemble3D(
|
||||
{
|
||||
if (M(e) == 0) { return; } // ignore
|
||||
|
||||
constexpr int Q = T_Q1D ? T_Q1D : HDIV_MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : HDIV_MAX_D1D;
|
||||
constexpr int Q = T_Q1D ? T_Q1D : DofQuadLimits::HDIV_MAX_Q1D;
|
||||
constexpr int D = T_D1D ? T_D1D : DofQuadLimits::HDIV_MAX_D1D;
|
||||
|
||||
MFEM_SHARED double sBot[Q*D];
|
||||
MFEM_SHARED double sBct[Q*D];
|
||||
|
||||
@@ -136,8 +136,8 @@ static void PAConvectionNLApply2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
auto Bt = Reshape(bt.Read(), D1D, Q1D);
|
||||
@@ -148,8 +148,8 @@ static void PAConvectionNLApply2D(const int NE,
|
||||
{
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double data[max_Q1D][max_Q1D][2];
|
||||
double grad0[max_Q1D][max_Q1D][2];
|
||||
@@ -273,8 +273,8 @@ static void PAConvectionNLApply3D(const int NE,
|
||||
constexpr int VDIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
MFEM_VERIFY(D1D <= MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
|
||||
MFEM_VERIFY(D1D <= DeviceDofQuadLimits::Get().MAX_D1D, "");
|
||||
MFEM_VERIFY(Q1D <= DeviceDofQuadLimits::Get().MAX_Q1D, "");
|
||||
|
||||
auto B = Reshape(b.Read(), Q1D, D1D);
|
||||
auto G = Reshape(g.Read(), Q1D, D1D);
|
||||
@@ -288,8 +288,8 @@ static void PAConvectionNLApply3D(const int NE,
|
||||
constexpr int VDIM = 3;
|
||||
const int D1D = T_D1D ? T_D1D : d1d;
|
||||
const int Q1D = T_Q1D ? T_Q1D : q1d;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : MAX_Q1D;
|
||||
constexpr int max_D1D = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
|
||||
constexpr int max_Q1D = T_Q1D ? T_Q1D : DofQuadLimits::MAX_Q1D;
|
||||
|
||||
double data[max_Q1D][max_Q1D][max_Q1D][VDIM];
|
||||
double grad0[max_Q1D][max_Q1D][max_Q1D][VDIM];
|
||||
|
||||
+53
-2
@@ -36,6 +36,7 @@ IntegrationRule::IntegrationRule(IntegrationRule &irx, IntegrationRule &iry)
|
||||
ny = iry.GetNPoints();
|
||||
SetSize(nx * ny);
|
||||
SetPointIndices();
|
||||
Order = std::min(irx.GetOrder(), iry.GetOrder());
|
||||
|
||||
for (j = 0; j < ny; j++)
|
||||
{
|
||||
@@ -60,6 +61,7 @@ IntegrationRule::IntegrationRule(IntegrationRule &irx, IntegrationRule &iry,
|
||||
const int nz = irz.GetNPoints();
|
||||
SetSize(nx*ny*nz);
|
||||
SetPointIndices();
|
||||
Order = std::min({irx.GetOrder(), iry.GetOrder(), irz.GetOrder()});
|
||||
|
||||
for (int iz = 0; iz < nz; ++iz)
|
||||
{
|
||||
@@ -125,6 +127,7 @@ void IntegrationRule::GrundmannMollerSimplexRule(int s, int n)
|
||||
np /= f;
|
||||
SetSize(np);
|
||||
SetPointIndices();
|
||||
Order = 2*s + 1;
|
||||
|
||||
int pt = 0;
|
||||
for (int i = 0; i <= s; i++)
|
||||
@@ -181,6 +184,7 @@ IntegrationRule::ApplyToKnotIntervals(KnotVector const& kv) const
|
||||
const int ne = kv.GetNE();
|
||||
|
||||
IntegrationRule *kvir = new IntegrationRule(ne * np);
|
||||
kvir->SetOrder(GetOrder());
|
||||
|
||||
double x0 = kv[0];
|
||||
double x1 = x0;
|
||||
@@ -421,6 +425,7 @@ void QuadratureFunctions1D::GaussLegendre(const int np, IntegrationRule* ir)
|
||||
{
|
||||
ir->SetSize(np);
|
||||
ir->SetPointIndices();
|
||||
ir->SetOrder(2*np - 1);
|
||||
|
||||
switch (np)
|
||||
{
|
||||
@@ -527,9 +532,11 @@ void QuadratureFunctions1D::GaussLobatto(const int np, IntegrationRule* ir)
|
||||
if ( np == 1 )
|
||||
{
|
||||
ir->IntPoint(0).Set1w(0.5, 1.0);
|
||||
ir->SetOrder(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
ir->SetOrder(2*np - 3);
|
||||
|
||||
#ifndef MFEM_USE_MPFR
|
||||
|
||||
@@ -624,6 +631,7 @@ void QuadratureFunctions1D::OpenUniform(const int np, IntegrationRule* ir)
|
||||
{
|
||||
ir->SetSize(np);
|
||||
ir->SetPointIndices();
|
||||
ir->SetOrder(np - 1 + np%2);
|
||||
|
||||
// The Newton-Cotes quadrature is based on weights that integrate exactly the
|
||||
// interpolatory polynomial through the equally spaced quadrature points.
|
||||
@@ -640,6 +648,7 @@ void QuadratureFunctions1D::ClosedUniform(const int np,
|
||||
{
|
||||
ir->SetSize(np);
|
||||
ir->SetPointIndices();
|
||||
ir->SetOrder(np - 1 + np%2);
|
||||
if ( np == 1 ) // allow this case as "closed"
|
||||
{
|
||||
ir->IntPoint(0).Set1w(0.5, 1.0);
|
||||
@@ -658,6 +667,7 @@ void QuadratureFunctions1D::OpenHalfUniform(const int np, IntegrationRule* ir)
|
||||
{
|
||||
ir->SetSize(np);
|
||||
ir->SetPointIndices();
|
||||
ir->SetOrder(np - 1 + np%2);
|
||||
|
||||
// Open half points: the centers of np uniform intervals
|
||||
for (int i = 0; i < np ; ++i)
|
||||
@@ -674,6 +684,7 @@ void QuadratureFunctions1D::ClosedGL(const int np, IntegrationRule* ir)
|
||||
ir->SetPointIndices();
|
||||
ir->IntPoint(0).x = 0.0;
|
||||
ir->IntPoint(np-1).x = 1.0;
|
||||
ir->SetOrder(np - 1 + np%2); // Is this the correct order?
|
||||
|
||||
if ( np > 2 )
|
||||
{
|
||||
@@ -999,13 +1010,17 @@ const IntegrationRule &IntegrationRules::Get(int GeomType, int Order)
|
||||
if (!HaveIntRule(*ir_array, Order))
|
||||
{
|
||||
IntegrationRule *ir = GenerateIntegrationRule(GeomType, Order);
|
||||
#ifdef MFEM_DEBUG
|
||||
int RealOrder = Order;
|
||||
while (RealOrder+1 < ir_array->Size() &&
|
||||
(*ir_array)[RealOrder+1] == ir)
|
||||
{
|
||||
RealOrder++;
|
||||
}
|
||||
ir->SetOrder(RealOrder);
|
||||
MFEM_VERIFY(RealOrder == ir->GetOrder(), "internal error");
|
||||
#else
|
||||
MFEM_CONTRACT_VAR(ir);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1114,6 +1129,7 @@ IntegrationRule *IntegrationRules::PointIntegrationRule(int Order)
|
||||
IntegrationRule *ir = new IntegrationRule(1);
|
||||
ir->IntPoint(0).x = .0;
|
||||
ir->IntPoint(0).weight = 1.;
|
||||
ir->SetOrder(1);
|
||||
|
||||
PointIntRules[1] = PointIntRules[0] = ir;
|
||||
|
||||
@@ -1178,6 +1194,7 @@ IntegrationRule *IntegrationRules::SegmentIntegrationRule(int Order)
|
||||
{
|
||||
// Effectively passing memory management to SegmentIntegrationRules
|
||||
IntegrationRule *refined_ir = new IntegrationRule(2*n);
|
||||
refined_ir->SetOrder(ir->GetOrder());
|
||||
for (int j = 0; j < n; j++)
|
||||
{
|
||||
refined_ir->IntPoint(j).x = ir->IntPoint(j).x/2.0;
|
||||
@@ -1202,16 +1219,18 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
// assuming that orders <= 25 are pre-allocated
|
||||
switch (Order)
|
||||
{
|
||||
case 0: // 1 point - 0 degree
|
||||
case 0: // 1 point - degree 1
|
||||
case 1:
|
||||
ir = new IntegrationRule(1);
|
||||
ir->AddTriMidPoint(0, 0.5);
|
||||
ir->SetOrder(1);
|
||||
TriangleIntRules[0] = TriangleIntRules[1] = ir;
|
||||
return ir;
|
||||
|
||||
case 2: // 3 point - 2 degree
|
||||
ir = new IntegrationRule(3);
|
||||
ir->AddTriPoints3(0, 1./6., 1./6.);
|
||||
ir->SetOrder(2);
|
||||
TriangleIntRules[2] = ir;
|
||||
// interior points
|
||||
return ir;
|
||||
@@ -1220,6 +1239,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir = new IntegrationRule(4);
|
||||
ir->AddTriMidPoint(0, -0.28125); // -9./32.
|
||||
ir->AddTriPoints3(1, 0.2, 25./96.);
|
||||
ir->SetOrder(3);
|
||||
TriangleIntRules[3] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1227,6 +1247,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir = new IntegrationRule(6);
|
||||
ir->AddTriPoints3(0, 0.091576213509770743460, 0.054975871827660933819);
|
||||
ir->AddTriPoints3(3, 0.44594849091596488632, 0.11169079483900573285);
|
||||
ir->SetOrder(4);
|
||||
TriangleIntRules[4] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1235,6 +1256,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir->AddTriMidPoint(0, 0.1125);
|
||||
ir->AddTriPoints3(1, 0.10128650732345633880, 0.062969590272413576298);
|
||||
ir->AddTriPoints3(4, 0.47014206410511508977, 0.066197076394253090369);
|
||||
ir->SetOrder(5);
|
||||
TriangleIntRules[5] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1244,6 +1266,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir->AddTriPoints3(3, 0.24928674517091042129, 0.058393137863189683013);
|
||||
ir->AddTriPoints6(6, 0.053145049844816947353, 0.31035245103378440542,
|
||||
0.041425537809186787597);
|
||||
ir->SetOrder(6);
|
||||
TriangleIntRules[6] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1258,6 +1281,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
0.30472650086816719592, 0.028775042784981585738);
|
||||
ir->AddTriPoints3R(9, 0.51584233435359177926, 0.27771616697639178257,
|
||||
0.20644149867001643817, 0.067493187009802774463);
|
||||
ir->SetOrder(7);
|
||||
TriangleIntRules[7] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1273,6 +1297,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir->AddTriPoints6(10, 0.008394777409957605337213834539296,
|
||||
0.263112829634638113421785786284643,
|
||||
0.0136151570872174971324223450369544);
|
||||
ir->SetOrder(8);
|
||||
TriangleIntRules[8] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1290,6 +1315,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir->AddTriPoints6(13, 0.0368384120547362836348175987833851,
|
||||
0.2219629891607656956751025276931919,
|
||||
0.0216417696886446886446886446886446);
|
||||
ir->SetOrder(9);
|
||||
TriangleIntRules[9] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1309,6 +1335,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir->AddTriPoints6(19, 0.0095408154002994575801528096228873,
|
||||
0.0668032510122002657735402127620247,
|
||||
4.71083348186641172996373548344341E-03);
|
||||
ir->SetOrder(10);
|
||||
TriangleIntRules[10] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1331,6 +1358,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir->AddTriPoints6(22, 0.0448416775891304433090523914688007,
|
||||
0.2772206675282791551488214673424523,
|
||||
0.0205281577146442833208261574536469);
|
||||
ir->SetOrder(11);
|
||||
TriangleIntRules[11] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1347,6 +1375,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
1.11783866011515E-02);
|
||||
ir->AddTriPoints6(27, 2.57340505483300E-02, 1.16251915907597E-01,
|
||||
8.65811555432950E-03);
|
||||
ir->SetOrder(12);
|
||||
TriangleIntRules[12] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1374,6 +1403,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
ir->AddTriPoints6(31, 0.0897330604516053590796290561145196,
|
||||
0.2723110556841851025078181617634414,
|
||||
0.0182757511120486476280967518782978);
|
||||
ir->SetOrder(13);
|
||||
TriangleIntRules[13] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1393,6 +1423,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
7.21815405676700E-03);
|
||||
ir->AddTriPoints6(36, 1.26833093287200E-03, 1.18974497696957E-01,
|
||||
2.50511441925050E-03);
|
||||
ir->SetOrder(14);
|
||||
TriangleIntRules[14] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1416,6 +1447,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
0.012803670460631195);
|
||||
ir->AddTriPoints6(48, 0.1684044181246992, 0.281835668099084562,
|
||||
0.016544097765822835);
|
||||
ir->SetOrder(15);
|
||||
TriangleIntRules[15] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1443,6 +1475,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
9.14639838501250E-03);
|
||||
ir->AddTriPoints6 (55, 1.46631822248280E-02, 8.07113136795640E-02,
|
||||
3.33281600208250E-03);
|
||||
ir->SetOrder(17);
|
||||
TriangleIntRules[16] = TriangleIntRules[17] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1474,6 +1507,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
0.0051292818680995);
|
||||
ir->AddTriPoints6 (67, 0.065494628082938, 0.010161119296278,
|
||||
0.001899964427651);
|
||||
ir->SetOrder(19);
|
||||
TriangleIntRules[18] = TriangleIntRules[19] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1508,6 +1542,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
0.009336472951467735);
|
||||
ir->AddTriPoints6(79, 0.140710844943938733, 0.323170566536257485,
|
||||
0.01140911202919763);
|
||||
ir->SetOrder(20);
|
||||
TriangleIntRules[20] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1559,6 +1594,7 @@ IntegrationRule *IntegrationRules::TriangleIntegrationRule(int Order)
|
||||
0.00707722325261307);
|
||||
ir->AddTriPoints6(120, 0.191771865867325067, 0.325618122595983752,
|
||||
0.007440689780584005);
|
||||
ir->SetOrder(25);
|
||||
TriangleIntRules[21] =
|
||||
TriangleIntRules[22] =
|
||||
TriangleIntRules[23] =
|
||||
@@ -1609,6 +1645,7 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
case 1:
|
||||
ir = new IntegrationRule(1);
|
||||
ir->AddTetMidPoint(0, 1./6.);
|
||||
ir->SetOrder(1);
|
||||
TetrahedronIntRules[0] = TetrahedronIntRules[1] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1616,6 +1653,7 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
ir = new IntegrationRule(4);
|
||||
// ir->AddTetPoints4(0, 0.13819660112501051518, 1./24.);
|
||||
ir->AddTetPoints4b(0, 0.58541019662496845446, 1./24.);
|
||||
ir->SetOrder(2);
|
||||
TetrahedronIntRules[2] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1623,6 +1661,7 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
ir = new IntegrationRule(5);
|
||||
ir->AddTetMidPoint(0, -2./15.);
|
||||
ir->AddTetPoints4b(1, 0.5, 0.075);
|
||||
ir->SetOrder(3);
|
||||
TetrahedronIntRules[3] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1631,6 +1670,7 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
ir->AddTetPoints4(0, 1./14., 343./45000.);
|
||||
ir->AddTetMidPoint(4, -74./5625.);
|
||||
ir->AddTetPoints6(5, 0.10059642383320079500, 28./1125.);
|
||||
ir->SetOrder(4);
|
||||
TetrahedronIntRules[4] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1641,6 +1681,7 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
ir->AddTetPoints4(6, 0.092735250310891226402, 0.012248840519393658257);
|
||||
ir->AddTetPoints4b(10, 0.067342242210098170608,
|
||||
0.018781320953002641800);
|
||||
ir->SetOrder(5);
|
||||
TetrahedronIntRules[5] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1654,6 +1695,7 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
9.2261969239424536825E-03);
|
||||
ir->AddTetPoints12(12, 0.063661001875017525299, 0.26967233145831580803,
|
||||
8.0357142857142857143E-03);
|
||||
ir->SetOrder(6);
|
||||
TetrahedronIntRules[6] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1667,6 +1709,7 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
ir->AddTetPoints4b(15, 2.3825066607381275412E-03,
|
||||
4.8914252630734993858E-03);
|
||||
ir->AddTetPoints12(19, 0.1, 0.2, 0.027557319223985890653);
|
||||
ir->SetOrder(7);
|
||||
TetrahedronIntRules[7] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1684,6 +1727,7 @@ IntegrationRule *IntegrationRules::TetrahedronIntegrationRule(int Order)
|
||||
5.7044858086819185068E-03);
|
||||
ir->AddTetPoints4(38, 0.20682993161067320408, 0.014250305822866901248);
|
||||
ir->AddTetMidPoint(42, -0.020500188658639915841);
|
||||
ir->SetOrder(8);
|
||||
TetrahedronIntRules[8] = ir;
|
||||
return ir;
|
||||
|
||||
@@ -1714,6 +1758,7 @@ IntegrationRule *IntegrationRules::PyramidIntegrationRule(int Order)
|
||||
int npts = irc.GetNPoints();
|
||||
AllocIntRule(PyramidIntRules, Order);
|
||||
PyramidIntRules[Order] = new IntegrationRule(npts);
|
||||
PyramidIntRules[Order]->SetOrder(Order); // FIXME: see comment above
|
||||
|
||||
for (int k=0; k<npts; k++)
|
||||
{
|
||||
@@ -1736,6 +1781,12 @@ IntegrationRule *IntegrationRules::PrismIntegrationRule(int Order)
|
||||
int ns = irs.GetNPoints();
|
||||
AllocIntRule(PrismIntRules, Order);
|
||||
PrismIntRules[Order] = new IntegrationRule(nt * ns);
|
||||
PrismIntRules[Order]->SetOrder(std::min(irt.GetOrder(), irs.GetOrder()));
|
||||
while (Order < std::min(irt.GetOrder(), irs.GetOrder()))
|
||||
{
|
||||
AllocIntRule(PrismIntRules, ++Order);
|
||||
PrismIntRules[Order] = PrismIntRules[Order-1];
|
||||
}
|
||||
|
||||
for (int ks=0; ks<ns; ks++)
|
||||
{
|
||||
|
||||
+3
-3
@@ -97,7 +97,7 @@ class IntegrationRule : public Array<IntegrationPoint>
|
||||
{
|
||||
private:
|
||||
friend class IntegrationRules;
|
||||
int Order;
|
||||
int Order = 0;
|
||||
/** @brief The quadrature weights gathered as a contiguous array. Created
|
||||
by request with the method GetWeights(). */
|
||||
mutable Array<double> weights;
|
||||
@@ -218,11 +218,11 @@ private:
|
||||
|
||||
public:
|
||||
IntegrationRule() :
|
||||
Array<IntegrationPoint>(), Order(0) { }
|
||||
Array<IntegrationPoint>() { }
|
||||
|
||||
/// Construct an integration rule with given number of points
|
||||
explicit IntegrationRule(int NP) :
|
||||
Array<IntegrationPoint>(NP), Order(0)
|
||||
Array<IntegrationPoint>(NP)
|
||||
{
|
||||
for (int i = 0; i < this->Size(); i++)
|
||||
{
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user