Compare commits

..
Author SHA1 Message Date
camierjs 976d8d968a Use external PA data 2025-07-16 20:19:16 -07:00
camierjs 0278197710 wip tuo runs 2025-07-16 20:07:40 -07:00
camierjs d30bcb3f69 wip kernels 2025-07-16 17:18:34 -07:00
camierjs ca4fbb03c1 wip fma kernels 2025-07-16 15:58:48 -07:00
camierjs 2db473b899 Cleanup 2025-07-14 17:40:40 -07:00
camierjs 4856eaef9b WIP autopa vs. action 2025-07-14 17:39:11 -07:00
camierjs 38575c14ea Re-enable StiffnessMult 2025-07-14 11:01:49 -07:00
camierjs 5d90b86910 Fix g++ warnings 2025-07-14 10:56:25 -07:00
camierjs 4954ca0586 Tuo runs fixes 2025-07-14 10:34:02 -07:00
camierjs 73276af78e Warning fix 2025-07-14 09:45:31 -07:00
camierjs 7f7136caa9 Simplify 2025-07-13 21:02:27 -07:00
camierjs 5c17c232dd Inline pass and profiling 2025-07-13 20:45:49 -07:00
camierjs c81ebfd1dc Add exceptions handling 2025-07-13 16:23:13 -07:00
camierjs d4de7d03ab version 0: PA std
version 1: PA new
version 2: PA new (layout by vdim)
version 3: MF ∂fem
version 4: PA ∂fem
version 5: PA ∂fem new
version 6: Auto PA ∂fem
version 7: Auto PA ∂fem new
2025-07-13 12:58:05 -07:00
camierjs 67be33e4e8 NewAutoActionCallback on CPU 2025-07-12 13:36:44 -07:00
camierjs 659b4d11fa Pre outsourcing derivative_action_callbacks w/ new kernels 2025-07-11 16:12:11 -07:00
camierjs 7eb86b3929 Avoid 'Too many changes' (c884050c52) 2025-07-11 15:53:43 -07:00
camierjs c946506c5f Avoid dscalar_t case 2025-07-10 11:06:12 -07:00
camierjs 8a35f67d0b wip bench linearisation 2025-07-10 10:05:58 -07:00
camierjs b5b31514ef Merge branch 'dfem-kernels' into dfem-automatic-pa-kernels 2025-07-10 08:47:41 -07:00
camierjs 6b17032d18 Merge branch 'master' into dfem-automatic-pa-kernels 2025-07-10 08:34:03 -07:00
camierjs b639394d56 Cleanup 2025-07-10 08:26:00 -07:00
camierjs 12c2d71bd2 Merge branch 'master' into dfem-kernels 2025-07-10 08:25:18 -07:00
camierjs c6f7e9f635 Switched VDIM/DIM dimensions runs 2025-07-07 13:56:11 -07:00
camierjs 7151713d9c Try StiffnessMult with VDIM/DIM layout 2025-07-07 10:10:06 -07:00
camierjs a5379de077 Use constants, simplify & cleanup 2025-07-06 16:29:53 -07:00
camierjs 85d24f1354 Merge branch 'master' into dfem-kernels 2025-07-06 14:45:43 -07:00
camierjs b60a76f0db Cleanup 2025-07-06 14:45:06 -07:00
camierjs e0dc7659fb With specializations 2025-07-06 11:56:22 -07:00
camierjs b7b4268138 use_kernels_specialization 2025-07-05 21:11:17 -07:00
camierjs e89a61399c GPU runs 2025-07-05 15:57:31 -07:00
camierjs 6c90686880 Forced inlines w/o changes 2025-07-05 15:12:09 -07:00
camierjs 331a66c027 Cleanup 2025-07-05 14:51:59 -07:00
camierjs 6d509fa5c3 Cleanup 2025-07-05 14:40:23 -07:00
camierjs b62cf39359 Simplify 2025-07-05 14:34:58 -07:00
camierjs 49f44e65c0 Cleanup & Simplify 2025-07-05 12:04:54 -07:00
camierjs 32697fea42 cleanup 2025-07-05 11:37:11 -07:00
camierjs c80a091f56 w/o unpack_shmem 2025-07-05 10:56:43 -07:00
camierjs bbc6708976 with r2 2025-07-05 10:46:52 -07:00
camierjs 6a01f6551a Action 2025-07-05 10:17:05 -07:00
camierjs 0c663a8aa2 with process_qf_result 2025-07-05 08:28:27 -07:00
camierjs be224ed94a wip apply_kernel 2025-07-05 08:17:17 -07:00
camierjs c09da71078 wip back action_callback_new 2025-07-04 18:07:15 -07:00
camierjs cf5f0126ce Avoid double mdofs in first iteration 2025-07-04 17:15:46 -07:00
camierjs a23e8907d7 removed fqp and use directly r0 2025-07-04 17:03:04 -07:00
camierjs 4ca2805303 map_quadrature_data_to_fields 2025-07-04 14:14:08 -07:00
camierjs 1b775faa43 is_gradient_fop 2025-07-04 13:38:00 -07:00
camierjs 0edefaeae5 action_callback_new cleanup 2025-07-04 12:50:59 -07:00
camierjs a12132ccb6 MFEM_NEW_KERNELS & action_callback_new 2025-07-04 11:30:30 -07:00
camierjs 9f044d89b5 bench_dfem run with assert Grad diff 2025-07-04 09:51:07 -07:00
camierjs 191e3df84b LoadDofs3d, Grad3d 2025-07-04 09:45:34 -07:00
camierjs 6b6f8afdac wip sync 2025-07-04 09:11:58 -07:00
camierjs 25e333dbf4 Merge branch 'dfem-bench' 2025-07-04 08:12:03 -07:00
camierjs 856d13e9ff Roctx init 2025-07-04 08:00:50 -07:00
Julian Andrej 7acd8c08b4 too many changes 2025-07-03 10:47:58 -07:00
camierjs eb8f7f433c Run tests/unit/dfem/test_diffusion_q1d 2025-07-02 17:00:41 -07:00
camierjs 6a693a818f wip merge fix 2025-07-02 15:05:47 -07:00
camierjs fa7d81095a Merge branch 'master' into dfem-kernels 2025-07-02 15:05:30 -07:00
camierjs 16260082f6 wip interpolate 2025-07-02 14:52:18 -07:00
camierjs 7763785ed7 Use MFEM_FOREACH_THREAD_DIRECT 2025-07-02 10:29:40 -07:00
camierjs 2baa889917 Merge branch 'master' into dfem-bench 2025-07-02 08:38:17 -07:00
camierjs 2ed1a9eaad BP3/1/6/25 @ 40 MDof/s 2025-06-30 18:02:56 -07:00
camierjs 1545f03a94 Merge branch 'master' into dfem-bench 2025-06-30 16:19:53 -07:00
Julian Andrej c884050c52 some profiling changes 2025-06-29 14:01:25 -07:00
Julian Andrej 6d0c250a01 Merge branch 'minsurface-bugfix' into dfem-automatic-pa 2025-06-27 08:35:53 -07:00
Julian Andrej f5cb982b59 bugfix accounting for new SetSubVector behavior 2025-06-27 08:35:03 -07:00
Julian Andrej 2d80a76f17 extra tests 2025-06-26 14:44:02 -07:00
Julian Andrej 310d702702 bugfix 2025-06-26 14:43:57 -07:00
Julian Andrej 9facc437ec working pa data cache 2025-06-25 11:40:52 -07:00
Julian Andrej d9874e1134 test for nvcc 2025-06-24 16:09:35 -07:00
camierjs 59a5c9fc79 Sync with fem/kernels.hpp, still performance wip 2025-06-24 11:43:05 -07:00
camierjs c389a3c434 Use latest dFEM for benchmark 2025-06-24 11:27:34 -07:00
camierjs ec96a85f86 Merge branch 'master' into dfem-bench 2025-06-24 11:27:15 -07:00
camierjs dd99371cda dFEM diffusion test Identity vs. None fix 2025-05-19 16:48:56 -07:00
camierjs 90aa6fc544 Merge branch 'dfem-phase1-dev' into dfem-kernels 2025-05-19 16:44:02 -07:00
camierjs 7b4fcc3e52 Add qp wip header/test 2025-05-19 16:42:15 -07:00
camierjs 81b6b7eeb2 Merge branch 'master'/'dfem-phase-1' into dfem-bench 2025-05-19 16:02:46 -07:00
camierjs 4b5974f600 Fix CMake and dFEM bench 2025-05-19 16:01:16 -07:00
camierjs a6926f4ce6 Merge branch 'dfem-phase1-dev' 2025-05-19 15:54:58 -07:00
camierjs b6e972af79 Merge branch 'master' 2025-05-19 15:49:54 -07:00
Julian Andrej e76ec19775 restructure 2025-05-19 14:46:20 -07:00
Julian Andrej d797322fea path 2025-05-19 08:22:36 -07:00
Julian AndrejandJohn Camier 5a5e34a744 Update fem/dfem/doperator.hpp
Co-authored-by: John Camier <camierjs@gmail.com>
2025-05-19 08:11:13 -07:00
Julian AndrejandJohn Camier 93db7052ff Update fem/dfem/util.hpp
Co-authored-by: John Camier <camierjs@gmail.com>
2025-05-19 08:10:44 -07:00
Julian AndrejandJohn Camier f7170af7bd Update fem/dfem/tuple.hpp
Co-authored-by: John Camier <camierjs@gmail.com>
2025-05-19 08:10:12 -07:00
Julian AndrejandJohn Camier b78eef3eaa Update fem/dfem/tuple.hpp
Co-authored-by: John Camier <camierjs@gmail.com>
2025-05-19 08:10:00 -07:00
Julian Andrej d5decea85c Revert "change default location for enzyme and add instructions"
This reverts commit dea3ae3317.
2025-05-16 12:59:14 -07:00
Julian Andrej dea3ae3317 change default location for enzyme and add instructions 2025-05-16 12:55:04 -07:00
Julian Andrej 33c1e50235 astyle 2025-05-16 12:39:47 -07:00
Julian Andrej 5718ad1b53 cuda compat 2025-05-16 12:38:08 -07:00
Julian AndrejandAndrew Ho 4f3671e253 Update fem/dfem/util.hpp
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:58:50 -07:00
Julian AndrejandAndrew Ho 4e08bb1b66 Update fem/dfem/util.hpp
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:58:42 -07:00
Julian AndrejandAndrew Ho 69c5016b63 Update fem/dfem/util.hpp
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:58:20 -07:00
Julian AndrejandAndrew Ho ce1bf58dc0 Update fem/dfem/doperator.hpp
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:58:13 -07:00
Julian AndrejandAndrew Ho 5eb00c9ee6 Update fem/dfem/doperator.hpp
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:58:05 -07:00
Julian AndrejandAndrew Ho 1f3b6b95aa Update fem/dfem/util.hpp
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:57:58 -07:00
Julian AndrejandAndrew Ho 118db41049 Update fem/dfem/util.hpp
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:57:49 -07:00
Julian AndrejandAndrew Ho 8390c3e50b Update fem/dfem/doperator.hpp
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:57:40 -07:00
Julian Andrej 168b5179e6 remove findenzyme module 2025-05-16 11:57:11 -07:00
Julian AndrejandAndrew Ho 7697f6d400 Update CMakeLists.txt
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2025-05-16 11:56:11 -07:00
Julian AndrejandJan Nikl 235ebce5d5 Update examples/dfem/minimal_surface.cpp
Co-authored-by: Jan Nikl <nikl1@llnl.gov>
2025-05-16 07:58:47 -07:00
Julian AndrejandJan Nikl e8a09d6499 Update examples/dfem/minimal_surface.cpp
Co-authored-by: Jan Nikl <nikl1@llnl.gov>
2025-05-16 07:57:47 -07:00
Julian AndrejandJan Nikl edc67827d8 Update examples/dfem/minimal_surface.cpp
Co-authored-by: Jan Nikl <nikl1@llnl.gov>
2025-05-16 07:57:34 -07:00
Julian Andrej 9e5cdef2ef add host device 2025-05-14 17:39:40 -07:00
Andrew Ho c2f4a5e248 Updated makefile to work with clang as the cuda compiler 2025-05-14 11:25:59 -07:00
Julian Andrej 72d811b289 device support for fdjacobian 2025-05-14 09:57:18 -07:00
Julian Andrej 43731aa990 memory type for temporary 2025-05-14 09:46:39 -07:00
Julian Andrej 45f59fff3a device memory locations 2025-05-14 09:23:58 -07:00
Julian Andrej 58a4cfa132 cuda compat 2025-05-14 07:43:13 -07:00
Julian Andrej 333dd3f2fd rename ParametricSpace -> ParameterSpace 2025-05-13 13:29:38 -07:00
Julian Andrej c4f7dd77b1 bugs 2025-05-13 13:24:18 -07:00
Julian Andrej f442b83573 whitespace 2025-05-13 11:33:54 -07:00
Julian Andrej 768aaae25d docs 2025-05-13 11:27:36 -07:00
Julian Andrej eab997c557 typo 2025-05-13 11:26:09 -07:00
Julian Andrej 9d73dc487d docs 2025-05-13 11:24:36 -07:00
Julian Andrej 2575ac61ba more comments 2025-05-13 09:08:54 -07:00
Julian Andrej 6130144da1 comments 2025-05-13 08:46:15 -07:00
camierjs 68db31da44 SetMaxOf comments 2025-05-12 18:15:09 -07:00
Julian Andrej 1acbce733c cmake 2025-05-09 11:46:10 -07:00
Julian Andrej b44316049b cmake 2025-05-09 10:41:11 -07:00
Julian Andrej 2e133e8ecb remove serial tests from cmake 2025-05-09 10:36:37 -07:00
Julian Andrej dfb2f4d7f2 typos 2025-05-09 08:41:17 -07:00
Julian Andrej 10e9e4215f cmake 2025-05-09 08:38:46 -07:00
Julian Andrej 8125a211d3 Merge branch 'master' into dfem-phase1-dev 2025-05-08 09:40:48 -07:00
Julian Andrej 818b8db433 switch example to CG 2025-05-07 17:19:36 -07:00
Julian Andrej ad4626edfc leftover comment 2025-05-07 15:51:29 -07:00
Julian Andrej 8d7e8933cf mesh 2025-05-07 15:50:43 -07:00
Julian Andrej 3ad21a409f precision 2025-05-07 15:31:39 -07:00
Julian Andrej b16b550150 corrections 2025-05-07 15:08:11 -07:00
Julian Andrej 102dc8bd02 ifdef 2025-05-07 14:20:41 -07:00
Julian Andrej e306ba0c85 ifdef 2025-05-07 13:44:30 -07:00
Julian Andrej 4b88ad2b0a more minsurface 2025-05-07 13:19:28 -07:00
Julian Andrej d0fb4e342e example draft 2025-05-06 21:06:56 -07:00
Julian Andrej b53d0529db bug 2025-05-06 17:41:48 -07:00
Julian Andrej 8c7988b525 changes 2025-05-06 17:41:22 -07:00
Julian Andrej dfffe4b5e8 rename fops 2025-05-06 09:12:33 -07:00
Julian Andrej 538aa11904 rename fops 2025-05-06 08:56:20 -07:00
Julian Andrej 6fa978af9a rename fops 2025-05-06 08:53:31 -07:00
Julian Andrej 3f81af72f6 rename fops 2025-05-06 08:51:06 -07:00
Julian Andrej 97f1cf08fb docs 2025-05-05 13:45:03 -07:00
camierjs e047cec18a All 3 MQ1Settings working 2025-05-03 14:30:34 -07:00
camierjs bdcf59d109 make_qf_map 2025-05-03 13:48:03 -07:00
Tzanio Kolev d3f1379dc8 Merge branch 'master' into dfem-phase1-dev 2025-05-03 13:46:43 -07:00
camierjs b876d32452 Pre cleanup MQ1 on qfunction 2025-05-03 13:06:34 -07:00
camierjs 50a6be3d58 wip runtime_get 2025-05-03 10:49:25 -07:00
camierjs 5251db2278 All interpolate gradient tests 2025-05-02 17:31:40 -07:00
camierjs 92fca7cf01 Interpolate all Gradient but toroid mesh 2025-05-02 17:27:54 -07:00
camierjs e22f5bc048 Interpolate Gradient AlmostEq 2025-05-02 17:17:22 -07:00
camierjs f971d1e0bb Merge branch 'dfem-phase1-dev' 2025-05-02 15:29:05 -07:00
camierjs 752917acaa Rename Diffusion PA kernels
dFEM DOperator debug traces
2025-05-02 15:27:59 -07:00
Julian Andrej ea6fb52698 bug 2025-05-02 13:09:47 -07:00
Julian Andrej 07a87e369c style 2025-05-02 12:01:08 -07:00
camierjs 56c46e6da5 Remove MFEM_FOREACH_THREAD1 2025-05-02 11:23:27 -07:00
camierjs 2db4ca1300 Avoid MFEM recompilation with dFEM changes 2025-05-02 11:19:48 -07:00
camierjs 53bc415268 Squashed commit of the following:
commit be537728df
Merge: 8cc9eec53 4e5b98b10
Author: camierjs <camierjs@gmail.com>
Date:   Fri May 2 10:37:34 2025 -0700

    Merge branch 'dfem-phase1-dev' into dfem-bench

commit 4e5b98b10f
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 10:05:20 2025 -0700

    doc

commit d4acd906bf
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 09:01:51 2025 -0700

    update brew before enzyme install

commit d751ce66a3
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 08:43:46 2025 -0700

    ci

commit 3f0abd4dfd
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 08:40:45 2025 -0700

    ci

commit 44a423d804
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 08:39:58 2025 -0700

    ci

commit 3e61e0490e
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 08:38:47 2025 -0700

    ci

commit def4919592
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 08:33:33 2025 -0700

    ci config

commit 2d147d70e0
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 08:33:29 2025 -0700

    reintroduce tests

commit e29e64dffe
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Fri May 2 08:04:44 2025 -0700

    reintroduce macos fp64 ci target

commit a7ec259bd5
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Thu May 1 16:46:22 2025 -0700

    reintroduce macos fp64 ci target

commit 3e93e19767
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Thu May 1 14:41:25 2025 -0700

    enzyme bug notes

commit 532b065596
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Thu May 1 14:41:17 2025 -0700

    consistency

commit 82c1e2315b
Author: Julian Andrej <andrej1@llnl.gov>
Date:   Thu May 1 13:19:25 2025 -0700

    modernize

commit 8cc9eec535
Author: camierjs <camierjs@gmail.com>
Date:   Thu May 1 11:06:03 2025 -0700

    Remove unused code

commit dece65be31
Author: camierjs <camierjs@gmail.com>
Date:   Thu May 1 10:59:50 2025 -0700

    Header and style

commit 3e6d29b3dd
Author: camierjs <camierjs@gmail.com>
Date:   Thu May 1 10:53:12 2025 -0700

    Meld toward dfem

commit 487135b497
Author: camierjs <camierjs@gmail.com>
Date:   Thu May 1 10:48:02 2025 -0700

    Meld back toward dfem dev

commit 91f648aa95
Author: camierjs <camierjs@gmail.com>
Date:   Thu May 1 10:36:43 2025 -0700

    Remove examples leftovers

commit 999931ded2
Author: camierjs <camierjs@gmail.com>
Date:   Thu May 1 10:36:18 2025 -0700

    Sync dfem bench
2025-05-02 10:40:23 -07:00
camierjs be537728df Merge branch 'dfem-phase1-dev' into dfem-bench 2025-05-02 10:37:34 -07:00
Julian Andrej 4e5b98b10f doc 2025-05-02 10:05:20 -07:00
Julian Andrej d4acd906bf update brew before enzyme install 2025-05-02 09:01:51 -07:00
Julian Andrej d751ce66a3 ci 2025-05-02 08:43:46 -07:00
Julian Andrej 3f0abd4dfd ci 2025-05-02 08:40:45 -07:00
Julian Andrej 44a423d804 ci 2025-05-02 08:39:58 -07:00
Julian Andrej 3e61e0490e ci 2025-05-02 08:38:47 -07:00
Julian Andrej def4919592 ci config 2025-05-02 08:33:33 -07:00
Julian Andrej 2d147d70e0 reintroduce tests 2025-05-02 08:33:29 -07:00
Julian Andrej e29e64dffe reintroduce macos fp64 ci target 2025-05-02 08:04:44 -07:00
Julian Andrej a7ec259bd5 reintroduce macos fp64 ci target 2025-05-01 16:46:22 -07:00
Julian Andrej 3e93e19767 enzyme bug notes 2025-05-01 14:41:25 -07:00
Julian Andrej 532b065596 consistency 2025-05-01 14:41:17 -07:00
Julian Andrej 82c1e2315b modernize 2025-05-01 13:19:25 -07:00
camierjs 8cc9eec535 Remove unused code 2025-05-01 11:06:03 -07:00
camierjs dece65be31 Header and style 2025-05-01 10:59:50 -07:00
camierjs 3e6d29b3dd Meld toward dfem 2025-05-01 10:53:12 -07:00
camierjs 487135b497 Meld back toward dfem dev 2025-05-01 10:48:02 -07:00
camierjs 91f648aa95 Remove examples leftovers 2025-05-01 10:36:43 -07:00
camierjs 999931ded2 Sync dfem bench 2025-05-01 10:36:18 -07:00
camierjs 15dbcae725 Add version info 2025-05-01 10:26:49 -07:00
camierjs 01efb623da Update kernels pa to regs use 2025-05-01 10:08:01 -07:00
camierjs f854c5262d Move kernels pa to dfem regs 2025-05-01 10:07:46 -07:00
camierjs a91b754aaa Update dfem examples 2025-05-01 10:06:06 -07:00
camierjs b1623ff3d4 Sync dfem examples with latest changes 2025-05-01 10:05:54 -07:00
camierjs c2426ca45a Merge branch 'dfem-phase1-dev' 2025-05-01 09:35:22 -07:00
camierjs 276f419a3d Merge branch 'dfem-phase1-dev' of github.com:mfem/mfem into dfem-phase1-dev 2025-05-01 09:31:53 -07:00
Julian Andrej c91b8bea01 prevent possible indexing error 2025-05-01 08:42:56 -07:00
Veselin Dobrev 7bdceca6ce Windows CI debug 2025-05-01 04:48:28 -07:00
Veselin Dobrev 6f9a263435 Disable Ninja on windows -- it does not detect MSVC.
Add a debug action step to print the environment under windows.
2025-05-01 03:49:52 -07:00
Veselin Dobrev 28a7865ed1 Fix MSVC build issue.
Use the Ninja CMake generator on Windows to try to speedup the build.
2025-05-01 00:44:37 -07:00
Julian Andrej 6e7335ac52 Revert "test more captures"
This reverts commit 8115383dec.
2025-04-30 16:49:35 -07:00
Julian Andrej 8115383dec test more captures 2025-04-30 16:34:17 -07:00
Julian Andrej 3d1b017a60 Revert "test capture"
This reverts commit bf14e5b018.
2025-04-30 16:29:16 -07:00
Julian Andrej bf14e5b018 test capture 2025-04-30 16:12:23 -07:00
Julian Andrej fb3517453f correctness 2025-04-30 15:48:35 -07:00
Julian Andrej bfca6beb28 Revert "hints for mscv"
This reverts commit 78a60cc1d9.
2025-04-30 14:30:02 -07:00
Julian Andrej f51e46d3d8 changelog 2025-04-30 14:02:28 -07:00
Julian Andrej 78a60cc1d9 hints for mscv 2025-04-30 14:02:24 -07:00
Julian Andrej 935d3a9e42 namespaces 2025-04-30 10:30:44 -07:00
Julian Andrej 35866f8485 namespaces 2025-04-30 09:40:45 -07:00
Julian Andrej 6b4b644355 namespaces 2025-04-30 09:38:52 -07:00
Julian Andrej b9ec58e7a1 guards 2025-04-30 09:19:17 -07:00
Julian Andrej 4644aed322 native ad test 2025-04-30 09:18:22 -07:00
Julian Andrej 80da896859 namespaces 2025-04-30 09:18:16 -07:00
Julian Andrej b96dcb4401 namespaces 2025-04-30 08:54:57 -07:00
Julian Andrej 5054f1784d again 2025-04-29 14:13:51 -07:00
Julian Andrej 788c0efda0 sync input values 2025-04-29 14:10:42 -07:00
Julian Andrej 4d49d42702 typo 2025-04-29 13:33:16 -07:00
Julian Andrej f5192230e0 more msvc handholding 2025-04-29 11:22:24 -07:00
Tzanio Kolev 400e3eca7d Merge branch 'master' into dfem-phase1-dev 2025-04-29 09:55:18 -07:00
Julian Andrej b90c8d80fe remove problematic constexpr 2025-04-29 08:50:20 -07:00
Veselin Dobrev a0491f6bfc Fix some msvc warnings which also fixed some compilation errors 2025-04-29 01:43:41 -07:00
Julian Andrej a8df54cf5d please msvc 2025-04-28 20:39:29 -07:00
Julian Andrej 9c4e43ee12 revert 2025-04-28 19:29:23 -07:00
Julian Andrej 7a1887c525 oops 2025-04-28 17:58:40 -07:00
Julian Andrej 907783f9ca testing 2025-04-28 17:56:23 -07:00
Julian Andrej f4f68fa021 size 2025-04-28 17:08:04 -07:00
Julian Andrej b76e9e80a7 real annoying real_t 2025-04-28 17:03:59 -07:00
Julian Andrej b8f677b2fe shadows 2025-04-28 16:59:44 -07:00
Julian Andrej 6e42fbae4d guards 2025-04-28 16:51:34 -07:00
Julian Andrej b8c0008061 include orders etc 2025-04-28 16:36:44 -07:00
Julian Andrej cdce090c2a cmake 2025-04-28 15:48:25 -07:00
Julian Andrej e246c0852b c++17 2025-04-28 15:40:50 -07:00
Julian Andrej 4db86286ee unguard test 2025-04-28 14:05:55 -07:00
Julian Andrej 9308946715 guards 2025-04-28 14:05:44 -07:00
Julian Andrej d28eca6b7f renaming 2025-04-28 14:05:34 -07:00
Julian Andrej 8e26105232 temporary disable offended unit tests 2025-04-28 11:53:12 -07:00
Julian Andrej c674f9f7ad defuse test 2025-04-24 15:29:09 -07:00
Julian Andrej 537d30120a Merge branch 'master' into dfem-phase1-dev 2025-04-24 14:35:23 -07:00
Julian Andrej 519267e1cb paths 2025-04-24 14:02:09 -07:00
Julian Andrej 2c495fb70d shadow warnings 2025-04-24 13:36:05 -07:00
Julian Andrej 401d1aec7b ci 2025-04-24 13:02:10 -07:00
Julian Andrej 8299b1c036 ci 2025-04-24 12:52:18 -07:00
Julian Andrej 9dd1e4dbdb ci 2025-04-24 11:48:17 -07:00
Julian Andrej 47a3534eff ci 2025-04-24 11:44:08 -07:00
Julian Andrej 2f39ff66f3 ci 2025-04-24 11:34:36 -07:00
Julian Andrej ddca183704 ci 2025-04-24 11:20:31 -07:00
Julian Andrej 078ce6130c ci 2025-04-24 11:17:54 -07:00
Julian Andrej 6d15c2a156 ci 2025-04-24 11:11:54 -07:00
Julian Andrej 7d705c0677 ci 2025-04-24 11:09:42 -07:00
Julian Andrej c027328b91 ci 2025-04-24 11:07:27 -07:00
Julian Andrej 65cb67e1c1 ci 2025-04-24 11:04:54 -07:00
Julian Andrej 494f27c14c ci 2025-04-24 11:00:37 -07:00
Julian Andrej 3c02b72084 ci 2025-04-24 10:51:20 -07:00
Julian Andrej 75e2be35ba ci 2025-04-24 10:46:12 -07:00
Julian Andrej b0f9cbfd26 ci 2025-04-24 10:42:24 -07:00
Julian Andrej 6afea18cde ci 2025-04-24 10:39:14 -07:00
Julian Andrej 2e69ff4b97 ci 2025-04-24 10:33:08 -07:00
Julian Andrej 6c70fe9334 ci 2025-04-24 10:27:46 -07:00
Julian Andrej 4ccbd4581e ci 2025-04-24 10:19:07 -07:00
Julian Andrej 6e262f6c3f ci 2025-04-24 10:13:37 -07:00
Julian Andrej 52e10475a5 ci 2025-04-24 10:10:20 -07:00
Julian Andrej c0299a5a4b ci 2025-04-24 10:05:24 -07:00
Julian Andrej 06eecb0dce yaml lint and first enzyme ci entries 2025-04-24 10:01:07 -07:00
Julian Andrej 96261a7742 c++17 and experimental namespace 2025-04-23 18:09:12 -07:00
Julian Andrej d7c479fa1e documentation 2025-04-21 09:21:07 -07:00
Julian Andrej 8b01d8f13b std::cout -> mfem::out 2025-04-16 10:53:23 -07:00
Julian Andrej 710da275c8 add dfem folder to makefile 2025-04-16 09:02:57 -07:00
Julian Andrej fd481eb725 correct include orders 2025-04-16 09:02:43 -07:00
Julian Andrej b5bbdbbed5 vectorfe leftover 2025-04-16 09:02:31 -07:00
Julian Andrej 6a26200314 remove vectorfe crumbs 2025-04-15 11:31:14 -07:00
Julian Andrej a485121526 msvc ambiguity enable_if 2025-04-14 14:40:52 -07:00
Julian Andrej 1f9e1cf175 brackets 2025-04-14 14:03:28 -07:00
Julian Andrej ec402882da move guard 2025-04-14 13:58:10 -07:00
Julian Andrej e7633e0e2c guard tests 2025-04-14 13:49:46 -07:00
Julian Andrej 30aeb465b7 includes 2025-04-14 13:27:15 -07:00
Julian Andrej ff4993fc51 array include 2025-04-14 13:13:44 -07:00
Julian Andrej 0a42ea8021 copyright dates 2025-04-14 13:13:33 -07:00
Julian Andrej b8d024b59b remove example subdirectory 2025-04-14 10:51:57 -07:00
Julian Andrejandcamierjs 9e1ccf4543 phase 1 skeleton
Co-authored-by: camierjs <camierjs@gmail.com>
2025-04-14 09:43:43 -07:00
camierjs 075ebb255d Do one first benchmark 2025-04-09 11:35:40 -07:00
camierjs 3eb6a5b3b2 Merge branch 'dfem-phase1-dev' 2025-04-03 14:01:28 -07:00
Julian Andrej 8ba1f17f72 add nonlinear solver options to command line arguments 2025-04-03 11:01:31 -07:00
Julian Andrej e5f5a79e66 attempt to fix parametric function transfers 2025-04-03 08:19:53 -07:00
Julian Andrej 43f1b19767 switch to 2d by default 2025-04-03 08:19:32 -07:00
Julian Andrej 7bebe4528f stop printing dependency maps 2025-04-03 08:19:16 -07:00
camierjs da63657cdd GCC warning fixes 2025-04-02 18:40:57 -07:00
camierjs 2b1d271888 Merge branch 'dfem-phase1-dev' 2025-04-02 18:34:46 -07:00
camierjs 47fb8a4fda No auto for gcc 2025-04-02 18:34:30 -07:00
camierjs ee7d9726df Warnings & fixes 2025-04-02 18:34:08 -07:00
camierjs 44b560a916 Merge branch 'dfem-phase1-dev' 2025-04-02 17:56:37 -07:00
Julian Andrej 5657f6ebe8 Merge branch 'dfem-phase1-dev' of github.com:mfem/mfem into dfem-phase1-dev 2025-04-02 17:44:22 -07:00
Julian Andrej 19543b6b16 more device stuff 2025-04-02 17:41:57 -07:00
camierjs 94a832a0c6 Merge branch 'dfem-phase1-dev' 2025-04-02 17:21:09 -07:00
camierjs b56e994ecd Copyright header, includes trim & warning fixes 2025-04-02 17:20:29 -07:00
camierjs 8be11cdfdb Remove duplicate inline 2025-04-02 16:49:20 -07:00
camierjs d71a9602b5 Merge branch 'dfem-phase1-dev' 2025-04-02 16:41:06 -07:00
camierjs 1108bb7e85 Use SetMaxOf inside kernel 2025-04-02 16:40:38 -07:00
Julian Andrej ae8e5aa88d some device stuff 2025-04-02 16:21:18 -07:00
camierjs 17f4acf6b1 Merge branch 'main' of github.com:camierjs/mfem-dfem-bench into main 2025-04-02 16:03:32 -07:00
camierjs 2ce3f3037c Cleanup 2025-04-02 16:03:30 -07:00
camierjs 29189a6d4a Merge branch 'dfem-phase1-dev' 2025-04-02 16:02:10 -07:00
Julian Andrej 08f3c86b8a make attributes device compatible 2025-04-02 15:46:19 -07:00
camierjs c6eb171b5b Back to foreach treads 2025-04-02 14:33:42 -07:00
camierjs d26695cd2a Use latest AddDomainIntegrator API 2025-04-02 12:18:21 -07:00
camierjs 01ab390b06 Merge branch 'dfem-phase1-dev' 2025-04-02 12:09:57 -07:00
camierjs 43c42295d3 Few changes with clang 20.1 2025-04-02 12:09:36 -07:00
camierjs 52bc915120 Few fixes to run on device and removed warnings 2025-04-02 12:07:57 -07:00
camierjs cd9cabb955 Cleanup all hipGetLastError 2025-04-02 09:32:36 -07:00
Julian Andrej e66a61c198 add build instructions 2025-03-31 17:23:33 -07:00
Julian Andrej f8b3c78b19 tensor additions 2025-03-31 14:28:29 -07:00
Julian Andrej 4749746171 add laghos 2025-03-31 14:28:10 -07:00
camierjs 1ddd01c2a0 All dfem BP3 versions 2025-03-31 13:47:06 -07:00
camierjs 87ec3850b5 Update Diffusion class 2025-03-30 13:08:31 -07:00
camierjs 1b25a61c9e Re-order kpc benchmarks 2025-03-30 11:52:41 -07:00
camierjs 7bee8e8161 tests/benchmarks/bench_dfem 2025-03-30 11:40:41 -07:00
camierjs a545ff8264 Bring StiffnessIntegrator in bench dfem 2025-03-30 10:29:17 -07:00
camierjs 5352234aef Use SetMaxOf 2025-03-30 10:06:54 -07:00
camierjs c3732f9d86 dfem diffusion3d D1D Q1D tests 2025-03-30 09:46:08 -07:00
camierjs b95f3809fe ParametricSpace d1d/q1d 2025-03-28 17:24:29 -07:00
camierjs e6a28b7753 Merge branch 'dfem-phase1-dev' 2025-03-28 15:09:46 -07:00
camierjs 62adea8b46 WIP dfem diffusion 2025-03-28 15:09:22 -07:00
camierjs 7d11db33c0 Add dfem diffusion multi-version example and bench dfem setup 2025-03-28 12:09:52 -07:00
Julian Andrej 11fce4235b revert width determination 2025-03-28 08:16:26 -07:00
camierjs f500b4875f dfem bench check 2025-03-27 10:48:46 -07:00
camierjs ba212c583e bench dfem init with nvtx 2025-03-27 10:34:12 -07:00
Julian Andrej fd341e07da example 2025-03-21 15:54:58 -07:00
Julian Andrej d59e2a229c phase 1 skeleton 2025-03-21 15:54:18 -07:00
630 changed files with 25328 additions and 75083 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ runs:
steps:
- uses: ./.github/actions/sanitize/config
- uses: actions/cache@v5
- uses: actions/cache@v4
if: ${{env.DEBUG == 'true'}}
id: debug
with:
+1 -1
View File
@@ -36,7 +36,7 @@ runs:
steps:
- uses: ./.github/actions/sanitize/config
- uses: actions/cache@v5
- uses: actions/cache@v4
if: ${{env.DEBUG == 'true' && inputs.cache-skip != 'true'}}
id: debug
with:
+5 -5
View File
@@ -23,7 +23,7 @@ inputs:
runs:
using: 'composite'
steps:
- uses: actions/cache/restore@v5 # Cache for LLVM libcxx
- uses: actions/cache/restore@v4 # Cache for LLVM libcxx
with:
path: ${{env.LLVM_DIR}}
fail-on-cache-miss: true
@@ -32,14 +32,14 @@ runs:
- uses: ./.github/actions/sanitize/mpi
if: ${{inputs.par == 'true'}}
- uses: actions/cache/restore@v5 # Cache for Hypre
- uses: actions/cache/restore@v4 # Cache for Hypre
if: ${{inputs.par == 'true'}}
with:
path: ${{env.HYPRE_DIR}}
fail-on-cache-miss: true
key: ${{runner.os}}-ompi-build-${{env.HYPRE_DIR}}-int32-fp64-v2.5
- uses: actions/cache/restore@v5 # Cache for Metis
- uses: actions/cache/restore@v4 # Cache for Metis
if: ${{inputs.par == 'true'}}
with:
path: ${{env.METIS_DIR}}
@@ -51,13 +51,13 @@ runs:
run: ln -s -f ${{env.HYPRE_DIR}} hypre && ln -s -f ${{env.METIS_DIR}} metis-4.0
shell: bash
- uses: actions/cache/restore@v5 # Cache for LSAN suppression file
- uses: actions/cache/restore@v4 # Cache for LSAN suppression file
with:
path: ${{env.LSAN_DIR}}
fail-on-cache-miss: true
key: build-lsan-suppression-file
- uses: actions/checkout@v6 # Checkout the repository
- uses: actions/checkout@v4 # Checkout the repository
with:
path: mfem
# ref: ${{env.BRANCH}}
+1 -1
View File
@@ -43,7 +43,7 @@ jobs:
remove-docker-images: 'true'
- name: Checkout
uses: actions/checkout@v6
uses: actions/checkout@v4
# It's easier to reference named variables than indexes of the matrix
- name: Set Environment
+10 -18
View File
@@ -132,14 +132,12 @@ jobs:
hypre-target: int32
precision: fp64
enzyme: true
config-opts: MFEM_USE_ENZYME=YES ENZYME_DIR=$(brew --prefix enzyme) LDFLAGS=-L$LLVM_PREFIX/lib/c++
config-opts: MFEM_USE_ENZYME=YES ENZYME_DIR=$(brew --prefix enzyme)
name: ${{ matrix.os }}-${{ matrix.build-system }}-${{ matrix.target }}-${{ matrix.mpi }}-${{ matrix.hypre-target }}-${{ matrix.precision }}${{ matrix.enzyme && '-enzyme' || '' }}
runs-on: ${{ matrix.os }}
continue-on-error: ${{ matrix.enzyme && true || false }}
steps:
# Fix 'No space left on device' errors for Ubuntu builds.
- name: Run Actions Cleaner
@@ -153,7 +151,7 @@ jobs:
# /home/runner/work/mfem/mfem/mfem
# Note: Done now to access "install-hypre" and "install-metis" actions.
- name: checkout mfem
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
path: ${{ env.MFEM_TOP_DIR }}
# Fetch the complete history for codecov to access commits ID
@@ -170,13 +168,10 @@ jobs:
env
shell: bash
# For info on Xcode see:
# - https://github.com/actions/runner-images/issues/12541
# - https://github.com/actions/runner-images/blob/releases/macos-15-arm64/20250811/images/macos/macos-15-arm64-Readme.md#xcode
- name: Xcode version setup (MacOS)
if: matrix.os == 'macos-latest'
run: |
XCODE_PATH="/Applications/Xcode_16.4.app"
XCODE_PATH="/Applications/Xcode_15.3.app"
echo "> sudo xcode-select -s ${XCODE_PATH}"
sudo xcode-select -s ${XCODE_PATH}
echo "> g++ -v"
@@ -225,7 +220,7 @@ jobs:
- name: cache hypre
id: hypre-cache
if: matrix.mpi == 'par'
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{ env.HYPRE_TOP_DIR }}
key: ${{ runner.os }}-ompi-build-${{ env.HYPRE_TOP_DIR }}-${{ matrix.hypre-target }}-${{ matrix.precision }}-v2.5
@@ -255,7 +250,7 @@ jobs:
- name: cache metis
id: metis-cache
if: matrix.mpi == 'par' && matrix.os != 'windows-latest'
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{ env.METIS_TOP_DIR }}
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.5
@@ -270,7 +265,7 @@ jobs:
- name: cache vcpkg (Windows)
id: vcpkg-cache
if: matrix.os == 'windows-latest'
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: vcpkg_cache
key: ${{ runner.os }}-${{ matrix.mpi }}-vcpkg-v1
@@ -294,13 +289,10 @@ jobs:
run: |
export HOMEBREW_NO_INSTALL_CLEANUP=1
brew update
brew install enzyme
ENZYME_LLVM=$(brew info enzyme | sed -n 's/^Required.*:.*\(llvm[^ ]*\).*/\1/p')
echo "ENZYME_LLVM=$ENZYME_LLVM"
LLVM_PREFIX=$(brew --prefix $ENZYME_LLVM)
echo "LLVM_PREFIX=$LLVM_PREFIX" >> $GITHUB_ENV
echo "OMPI_CC=$LLVM_PREFIX/bin/clang" >> $GITHUB_ENV
echo "OMPI_CXX=$LLVM_PREFIX/bin/clang++" >> $GITHUB_ENV
brew install llvm@19 enzyme
echo "LLVM_PREFIX=$(brew --prefix llvm@19)" >> $GITHUB_ENV
echo "OMPI_CC=$(brew --prefix llvm@19)/bin/clang" >> $GITHUB_ENV
echo "OMPI_CXX=$(brew --prefix llvm@19)/bin/clang++" >> $GITHUB_ENV
# MFEM build and test
- name: build
+4 -4
View File
@@ -40,11 +40,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v6
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v4
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.
@@ -57,7 +57,7 @@ jobs:
# 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@v4
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
@@ -70,4 +70,4 @@ jobs:
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v4
uses: github/codeql-action/analyze@v2
+3 -3
View File
@@ -39,7 +39,7 @@ jobs:
steps:
- name: checkout MFEM
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
path: mfem
@@ -50,7 +50,7 @@ jobs:
- name: Cache Hypre Install
id: hypre-cache
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{ env.HYPRE_TOP_DIR }}
key: ${{ runner.os }}-ompi-build-${{ env.HYPRE_TOP_DIR }}-v2.5
@@ -65,7 +65,7 @@ jobs:
- name: Cache Metis Install
id: metis-cache
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{ env.METIS_TOP_DIR }}
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.5
+4 -4
View File
@@ -38,7 +38,7 @@ jobs:
github.event.pull_request.head.repo.full_name != github.repository)
steps:
- name: checkout mfem
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: copyright check
id: copyright
@@ -93,7 +93,7 @@ jobs:
github.event.pull_request.head.repo.full_name != github.repository)
steps:
- name: checkout mfem
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: get astyle
run: |
@@ -110,7 +110,7 @@ jobs:
github.event.pull_request.head.repo.full_name != github.repository)
steps:
- name: checkout mfem
uses: actions/checkout@v6
uses: actions/checkout@v4
- name: get doxygen and graphviz
run: |
@@ -135,7 +135,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout mfem
uses: actions/checkout@v6
uses: actions/checkout@v4
with:
fetch-depth: 0
+2 -2
View File
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest
name: 2.19.0
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/config
- name: Cache
id: cache
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{env.HYPRE_DIR}}
key: ${{runner.os}}-ompi-build-${{env.HYPRE_DIR}}-int32-fp64-v2.5
+2 -2
View File
@@ -27,13 +27,13 @@ jobs:
llvm_use_sanitizer: "Undefined"
name: ${{matrix.sanitizer}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/config
with:
NO_FLAGS: true
- name: Cache
id: cache
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{env.LLVM_DIR}}
key: build-libcxx-${{env.LLVM_VER}}-${{matrix.sanitizer}}
+2 -2
View File
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest
name: lsan.supp
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/config
- name: Cache
id: cache
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{env.LSAN_DIR}}
key: build-lsan-suppression-file
+2 -2
View File
@@ -17,11 +17,11 @@ jobs:
runs-on: ubuntu-latest
name: 4.0.3
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/config
- name: Cache
id: cache
uses: actions/cache@v5
uses: actions/cache@v4
with:
path: ${{env.METIS_DIR}}
key: ${{runner.os}}-build-${{env.METIS_DIR}}-v2.5
+7 -7
View File
@@ -28,7 +28,7 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/mfem
with:
par: ${{inputs.par}}
@@ -40,7 +40,7 @@ jobs:
env:
ex: ${{inputs.par && 'ex1p' || 'ex1'}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/restore
id: restore
with:
@@ -58,7 +58,7 @@ jobs:
env:
exclude: ${{inputs.par && '-E "_ser"' || ''}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/restore
id: restore
with:
@@ -82,7 +82,7 @@ jobs:
env:
exclude: ${{inputs.par && '-E "_ser"' || ''}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/restore
id: restore
with:
@@ -107,7 +107,7 @@ jobs:
run: ${{inputs.par && '-R "_cpu_np"' || ''}}
exclude: ${{inputs.par && '"unit_tests|debug"' || '"^unit_tests$|debug"'}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/restore
id: restore
with:
@@ -131,7 +131,7 @@ jobs:
env:
unit_tests: ${{inputs.par && 'punit_tests' || 'unit_tests'}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/restore
id: restore
with:
@@ -165,7 +165,7 @@ jobs:
unit_tests: ${{inputs.par && 'punit_tests' || 'unit_tests'}}
np: ${{inputs.par && '_np=2' || ''}}
steps:
- uses: actions/checkout@v6
- uses: actions/checkout@v4
- uses: ./.github/actions/sanitize/restore
id: restore
with:
-44
View File
@@ -29,47 +29,3 @@ jobs:
operations-per-run: 500
exempt-issue-labels: "bug,WIP,ready-for-review,in-review,in-next"
exempt-pr-labels: "bug,WIP,ready-for-review,in-review,in-next"
# Stale action for PRs with "in-review" label.
stale-in-review-pr:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
actions: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: ':warning: This PR has been automatically marked as stale because it has not had any activity in the last 150 days. *If no activity occurs in the next 30 days, it will be automatically closed.* Thank you for your contributions.'
only-pr-labels: "in-review"
days-before-pr-stale: 150
days-before-pr-close: 30
days-before-issue-stale: -1
days-before-issue-close: -1
stale-pr-label: 'stale'
operations-per-run: 500
# Stale action for PRs with "WIP" label.
stale-wip-pr:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
actions: write
steps:
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-pr-message: ':warning: This PR has been automatically marked as stale because it has not had any activity in the last 300 days. *If no activity occurs in the next 30 days, it will be automatically closed.* Thank you for your contributions.'
only-pr-labels: "WIP"
days-before-pr-stale: 300
days-before-pr-close: 30
days-before-issue-stale: -1
days-before-issue-close: -1
stale-pr-label: 'stale'
operations-per-run: 500
+18 -56
View File
@@ -19,15 +19,9 @@ CMakeFiles/
# Clangd server cache
*.cache*
#vscode settings
/.vscode/
# Backup files
*~
# clangd index
/.cache/
# Default install location
/mfem/
@@ -85,17 +79,12 @@ examples/sol_u.*
examples/sol_p.*
examples/sol_r.*
examples/sol_i.*
examples/sol_z.*
examples/ex6p-checkpoint.*
examples/order.*
examples/ex9.mesh
examples/ex9-mesh.*
examples/ex9-init.*
examples/ex9-final.*
examples/ex41.mesh
examples/ex41-mesh.*
examples/ex41-init.*
examples/ex41-final.*
examples/deformed.*
examples/velocity.*
examples/elastic_energy.*
@@ -219,16 +208,10 @@ miniapps/electromagnetics/volta
miniapps/electromagnetics/tesla
miniapps/electromagnetics/maxwell
miniapps/electromagnetics/joule
miniapps/electromagnetics/lorentz
miniapps/electromagnetics/Volta-AMR*
miniapps/electromagnetics/Tesla-AMR*
miniapps/electromagnetics/Maxwell-Parallel*
miniapps/electromagnetics/Joule_[0-9]*
miniapps/electromagnetics/Lorentz_[0-9]*
miniapps/electromagnetics/Lorentz.dat
miniapps/fluids/schrodinger-flow/schrodinger_flow
miniapps/fluids/schrodinger-flow/pschrodinger_flow
miniapps/electromagnetics/Joule_*
miniapps/gslib/field-diff
miniapps/gslib/field-interp
@@ -237,7 +220,6 @@ miniapps/gslib/pfindpts
miniapps/gslib/schwarz_ex1
miniapps/gslib/schwarz_ex1p
miniapps/gslib/interpolated.gf
miniapps/gslib/particles_redist
miniapps/meshing/mobius-strip
miniapps/meshing/klein-bottle
@@ -284,8 +266,10 @@ miniapps/meshing/refined.mesh
miniapps/meshing/bounding-box*
miniapps/meshing/jacobian-determinant*
miniapps/mtop/ParaView/
miniapps/mtop/mtop_test_iso_elasticity
miniapps/mtop/parheat
miniapps/mtop/ParHeat*
miniapps/mtop/seqheat
miniapps/mtop/SeqHeat*
miniapps/autodiff/paradiff
miniapps/autodiff/seqadiff
@@ -293,35 +277,29 @@ miniapps/autodiff/seqtest
miniapps/autodiff/par_example
miniapps/autodiff/seq_example
miniapps/autodiff/seq_test
miniapps/autodiff/Example/*
miniapps/autodiff/Exampl*
miniapps/fluids/navier/navier_mms
miniapps/fluids/navier/navier_kovasznay
miniapps/fluids/navier/navier_kovasznay_vs
miniapps/fluids/navier/navier_tgv
miniapps/fluids/navier/navier_shear
miniapps/fluids/navier/navier_3dfoc
miniapps/fluids/navier/navier_turbchan
miniapps/fluids/navier/navier_cht
miniapps/fluids/navier/navier_bifurcation
miniapps/fluids/navier/Navier_Bifurcation_[0-9]*
miniapps/fluids/navier/ParaView
miniapps/fluids/navier/tgv_out*.txt
miniapps/fluids/navier/*_output
miniapps/navier/navier_mms
miniapps/navier/navier_kovasznay
miniapps/navier/navier_kovasznay_vs
miniapps/navier/navier_tgv
miniapps/navier/navier_shear
miniapps/navier/navier_3dfoc
miniapps/navier/navier_turbchan
miniapps/navier/navier_cht
miniapps/navier/tgv_out*.txt
miniapps/navier/*_output
miniapps/nurbs/nurbs_ex1
miniapps/nurbs/nurbs_ex1p
miniapps/nurbs/nurbs_ex3
miniapps/nurbs/nurbs_ex5
miniapps/nurbs/nurbs_ex10
miniapps/nurbs/nurbs_ex10p
miniapps/nurbs/nurbs_ex11p
miniapps/nurbs/nurbs_ex24
miniapps/nurbs/nurbs_solenoidal
miniapps/nurbs/nurbs_printfunc
miniapps/nurbs/nurbs_patch_ex1
miniapps/nurbs/nurbs_curveint
miniapps/nurbs/nurbs_surface
miniapps/nurbs/refined.mesh
miniapps/nurbs/mesh.*
miniapps/nurbs/sol_?.gf
@@ -340,14 +318,6 @@ miniapps/nurbs/nurbs_naca_cmesh
miniapps/nurbs/naca-cmesh.mesh
miniapps/nurbs/glvis_naca-cmesh.mesh
miniapps/nurbs/Naca_cmesh
miniapps/nurbs/nurbs_mesh_info
miniapps/nurbs/k*_*.dat
miniapps/nurbs/*-Surface.mesh
miniapps/nurbs/*.mesh
miniapps/nurbs/*.sol
miniapps/nurbs/deformed.*
miniapps/nurbs/elastic_energy.*
miniapps/nurbs/velocity.*
miniapps/performance/ex1
miniapps/performance/ex1p
@@ -369,7 +339,6 @@ miniapps/shifted/lsf_integral
miniapps/tools/display-basis
miniapps/tools/load-dc
miniapps/tools/convert-dc
miniapps/tools/compare-dc
miniapps/tools/gridfunction-bounds
miniapps/tools/lor-transfer
miniapps/tools/plor-transfer
@@ -440,19 +409,12 @@ miniapps/tribol/contact-patch-test
miniapps/diag-smoothers/abs-l1-jacobi
miniapps/diag-smoothers/mg-abs-l1-jacobi
miniapps/contact/contact
miniapps/contact/ParaView
miniapps/plasma/pic/electrostatic-*
!miniapps/plasma/pic/electrostatic-*.cpp
miniapps/plasma/pic/*.csv
# Unit test binary and outputs
tests/unit/output_meshes
tests/unit/unit_tests
tests/unit/punit_tests
tests/unit/gpu_unit_tests
tests/unit/pgpu_unit_tests
tests/unit/cunit_tests
tests/unit/pcunit_tests
tests/unit/sedov_tests_*
tests/unit/psedov_tests_*
tests/unit/tmop_pa_tests_*
+70 -529
View File
@@ -9,550 +9,91 @@
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# DESCRIPTION:
###############################################################################
# General GitLab pipelines configurations for supercomputers and Linux clusters
# at Lawrence Livermore National Laboratory (LLNL).
# This entire pipeline is LLNL-specific
#
# Important note: This file is a template provided by llnl/radiuss-shared-ci.
# Remains to set variable values, change the reference to the radiuss-shared-ci
# repo, opt-in and out optional features. The project can then extend it with
# additional stages.
#
# In addition, each project should copy over and complete:
# - .gitlab/custom-jobs-and-variables.yml
# - .gitlab/subscribed-pipelines.yml
#
# The jobs should be specified in a file local to the project,
# - .gitlab/jobs/${CI_MACHINE}.yml
# or generated (see LLNL/Umpire for an example).
###############################################################################
# MAP OF GITLAB CI
#######################
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# File dependencies: direct, through jobs, through variables
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# .gitlab-ci.yml
# ├── .build-and-test [job]
# │ ├── .gitlab/custom-jobs-and-variables.yml
# │ │ ├── .custom_job [job]
# │ │ ├── .reproducer_vars [job]
# │ │ ├── .report_job_success [job]
# │ │ │ └── .gitlab/scripts/report_build_and_test [script]
# │ │ │ ├── .gitlab/scripts/safe_create_rundir [script]
# │ │ │ └── .gitlab/scripts/git_try_to_push [script]
# │ │ ├── .report_job_failure [job]
# │ │ │ └── .gitlab/scripts/report_build_and_test [script]
# │ │ │ ├── .gitlab/scripts/safe_create_rundir [script]
# │ │ │ └── .gitlab/scripts/git_try_to_push [script]
# │ │ └── JOB_CMD [var]
# │ │ └── tests/gitlab/build_and_test [script]
# │ │ └── tests/gitlab/get_mfem_uberenv [script]
# │ ├── <radiuss-shared-ci>/pipelines/matrix.yml [conditional]
# │ │ ├── .on_matrix [job]
# │ │ ├── .matrix_reproducer_init [job]
# │ │ ├── .matrix_reproducer_vars [job]
# │ │ ├── .matrix_reproducer_job [job]
# │ │ ├── .matrix_job_command [job]
# │ │ └── .job_on_matrix [job]
# │ ├── <radiuss-shared-ci>/pipelines/dane.yml [conditional]
# │ │ ├── .on_dane [job]
# │ │ ├── .dane_reproducer_init [job]
# │ │ ├── .dane_reproducer_vars [job]
# │ │ ├── .dane_reproducer_job [job]
# │ │ ├── .dane_job_command [job]
# │ │ ├── .job_on_dane [job]
# │ │ ├── allocate_resources [job]
# │ │ └── release_resources [job]
# │ ├── <radiuss-shared-ci>/pipelines/tioga.yml [conditional]
# │ │ ├── .on_tioga [job]
# │ │ ├── .tioga_reproducer_init [job]
# │ │ ├── .tioga_reproducer_vars [job]
# │ │ ├── .tioga_reproducer_job [job]
# │ │ ├── .tioga_job_command [job]
# │ │ ├── .job_on_tioga [job]
# │ │ ├── allocate_resources [job]
# │ │ └── release_resources [job]
# │ ├── <artifact>/matrix-jobs.yml [conditional, from 'generate-job-lists']
# │ │ ├── .gitlab/jobs/matrix.yml
# │ │ │ ├── .matrix_reproducer_vars [job]
# │ │ │ ├── setup [job]
# │ │ │ │ └── ./tests/gitlab/build_and_test_setup [script]
# │ │ │ ├── opt_mpi_cuda_gcc [job]
# │ │ │ └── opt_mpi_cuda_hypre_cuda_gcc [job]
# │ │ └── .gitlab/jobs/matrix-reports.yml [used conditionally]
# │ │ ├── report_job_success
# │ │ └── report_job_failure
# │ ├── <artifact>/dane-jobs.yml [conditional, from 'generate-job-lists']
# │ │ ├── .gitlab/jobs/dane.yml
# │ │ │ ├── .dane_reproducer_vars [job]
# │ │ │ ├── setup [job]
# │ │ │ │ └── ./tests/gitlab/build_and_test_setup [script]
# │ │ │ ├── debug_ser_gcc_10 [job]
# │ │ │ ├── debug_par_gcc_10 [job]
# │ │ │ ├── opt_ser_gcc_10 [job]
# │ │ │ ├── opt_par_gcc_10 [job]
# │ │ │ ├── opt_par_gcc_10_sundials [job]
# │ │ │ ├── opt_par_gcc_10_petsc [job]
# │ │ │ └── opt_par_gcc_10_pumi [job]
# │ │ └── .gitlab/jobs/dane-reports.yml [used conditionally]
# │ │ ├── report_job_success
# │ │ └── report_job_failure
# │ └── <artifact>/tioga-jobs.yml [conditional, from 'generate-job-lists']
# │ ├── .gitlab/jobs/tioga.yml
# │ │ ├── .tioga_reproducer_vars [job]
# │ │ ├── setup [job]
# │ │ │ └── ./tests/gitlab/build_and_test_setup [script]
# │ │ └── cce_16_0_1 [job]
# │ └── .gitlab/jobs/tioga-reports.yml [used conditionally]
# │ ├── report_job_success
# │ └── report_job_failure
# └── .gitlab/subscribed-pipelines.yml
# ├── .machine-check [job]
# ├── generate-job-lists [job]
# ├── dane-up-check [job]
# ├── dane-build-and-test [job]
# ├── dane-baseline [job]
# │ └── .gitlab/dane-baseline.yml
# │ ├── .on_dane [job]
# │ ├── baselinecheck_mfem_intel_dane [job]
# │ │ └── .gitlab/scripts/baseline [script]
# │ ├── cleanup [job]
# │ ├── report_baseline [job]
# │ │ ├── .gitlab/scripts/safe_create_rundir [script]
# │ │ └── .gitlab/scripts/git_try_to_push [script]
# │ ├── baselinepublish_mfem_dane [job]
# │ │ └── .gitlab/scripts/rebaseline [script]
# │ ├── .gitlab/custom-jobs-and-variables.yml
# │ │ └── <same as above: see .gitlab-ci.yml/.build-and-test>
# │ └── .gitlab/configs/setup-baseline.yml
# │ └── setup_baseline [job]
# ├── tioga-up-check [job]
# ├── tioga-build-and-test [job]
# ├── matrix-up-check [job]
# └── matrix-build-and-test [job]
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# File tree hierarchy with file contents highlights
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# In addition to the files in the MFEM repo, the Gitlab CI uses files from the
# radiuss/radiuss-shared-ci project, see below, after the <mfem-root> tree.
#
# <mfem root>
# ├── .gitlab-ci.yml [this file]
# │ ├── <jobs>
# │ │ └── .build-and-test
# │ ├── <included files>
# │ │ ├── .gitlab/subscribed-pipelines.yml
# │ │ ├── .gitlab/custom-jobs-and-variables.yml [by ".build-and-test"]
# │ │ ├── <artifact> [by ".build-and-test"]
# │ │ │ ├── artifact: '${CI_MACHINE}-jobs.yml'
# │ │ │ └── job: 'generate-job-lists'
# │ │ └── <external> [by ".build-and-test"]
# │ │ ├── project: 'radiuss/radiuss-shared-ci'
# │ │ ├── ref: 'v2025.09.1'
# │ │ └── file: 'pipelines/${CI_MACHINE}.yml'
# │ └── <defined variables>
# │ ├── CUSTOM_CI_BUILDS_DIR
# │ ├── USER_CI_TOP_DIR
# │ ├── SHARED_REPOS_DIR
# │ ├── AUTOTEST_ROOT
# │ ├── MFEM_DATA_DIR
# │ ├── AUTOTEST
# │ ├── AUTOTEST_COMMIT
# │ ├── REBASELINE
# │ ├── GITHUB_PROJECT_NAME
# │ └── GITHUB_PROJECT_ORG
# ├── .gitlab
# │ ├── configs
# │ │ └── setup-baseline.yml
# │ │ ├── <jobs>
# │ │ │ └── setup_baseline
# │ │ └── <used variables>
# │ │ ├── MACHINE_NAME
# │ │ ├── REBASELINE
# │ │ ├── AUTOTEST
# │ │ ├── AUTOTEST_COMMIT
# │ │ ├── BUILD_ROOT
# │ │ ├── TPLS_REPO
# │ │ ├── TESTS_REPO
# │ │ ├── AUTOTEST_ROOT
# │ │ └── AUTOTEST_REPO
# │ ├── jobs
# │ │ ├── matrix-reports.yml
# │ │ │ ├── <jobs>
# │ │ │ │ ├── report_job_success
# │ │ │ │ └── report_job_failure
# │ │ │ └── <used jobs>
# │ │ │ ├── .on_matrix
# │ │ │ ├── .report_job_success
# │ │ │ └── .report_job_failure
# │ │ ├── matrix.yml
# │ │ │ ├── <jobs>
# │ │ │ │ ├── .matrix_reproducer_vars
# │ │ │ │ ├── setup
# │ │ │ │ ├── opt_mpi_cuda_gcc
# │ │ │ │ └── opt_mpi_cuda_hypre_cuda_gcc
# │ │ │ ├── <used jobs>
# │ │ │ │ ├── .reproducer_vars
# │ │ │ │ ├── .on_matrix
# │ │ │ │ └── .job_on_matrix
# │ │ │ ├── <included and used files>
# │ │ │ │ └── tests/gitlab/build_and_test_setup [by "setup"]
# │ │ │ └── <defined variables>
# │ │ │ └── SPEC
# │ │ ├── dane-reports.yml
# │ │ │ ├── <jobs>
# │ │ │ │ ├── report_job_success
# │ │ │ │ └── report_job_failure
# │ │ │ └── <used jobs>
# │ │ │ ├── .on_dane
# │ │ │ ├── .report_job_success
# │ │ │ └── .report_job_failure
# │ │ ├── dane.yml
# │ │ │ ├── <jobs>
# │ │ │ │ ├── .dane_reproducer_vars
# │ │ │ │ ├── setup
# │ │ │ │ ├── debug_ser_gcc_10
# │ │ │ │ ├── debug_par_gcc_10
# │ │ │ │ ├── opt_ser_gcc_10
# │ │ │ │ ├── opt_par_gcc_10
# │ │ │ │ ├── opt_par_gcc_10_sundials
# │ │ │ │ ├── opt_par_gcc_10_petsc
# │ │ │ │ └── opt_par_gcc_10_pumi
# │ │ │ ├── <used jobs>
# │ │ │ │ ├── .reproducer_vars
# │ │ │ │ ├── .on_dane
# │ │ │ │ └── .job_on_dane
# │ │ │ ├── <included and used files>
# │ │ │ │ └── tests/gitlab/build_and_test_setup [by "setup"]
# │ │ │ └── <defined variables>
# │ │ │ ├── SPEC
# │ │ │ └── THREADS
# │ │ ├── tioga-reports.yml
# │ │ │ ├── <jobs>
# │ │ │ │ ├── report_job_success
# │ │ │ │ └── report_job_failure
# │ │ │ └── <used jobs>
# │ │ │ ├── .on_tioga
# │ │ │ ├── .report_job_success
# │ │ │ └── .report_job_failure
# │ │ └── tioga.yml
# │ │ ├── <jobs>
# │ │ │ ├── .tioga_reproducer_vars
# │ │ │ ├── setup
# │ │ │ └── opt_mpi_rocm_hypre_rocm
# │ │ ├── <used jobs>
# │ │ │ ├── .reproducer_vars
# │ │ │ ├── .on_tioga
# │ │ │ └── .job_on_tioga
# │ │ ├── <included and used files>
# │ │ │ └── tests/gitlab/build_and_test_setup [by "setup"]
# │ │ └── <defined variables>
# │ │ ├── SPEC
# │ │ └── THREADS
# │ ├── scripts
# │ │ ├── baseline
# │ │ │ └── <used variables>
# │ │ │ ├── BASELINE_TEST
# │ │ │ ├── SYS_TYPE
# │ │ │ ├── MACHINE_NAME
# │ │ │ ├── CI_PROJECT_DIR
# │ │ │ ├── ARTIFACTS_DIR
# │ │ │ ├── BUILD_ROOT
# │ │ │ └── TPLS_DIR
# │ │ ├── git_try_to_push
# │ │ ├── rebaseline
# │ │ │ └── <used variables>
# │ │ │ ├── CI_PROJECT_DIR
# │ │ │ ├── ARTIFACTS_DIR
# │ │ │ ├── SYS_TYPE
# │ │ │ ├── BUILD_ROOT
# │ │ │ ├── MACHINE_NAME
# │ │ │ └── CI_PIPELINE_ID
# │ │ ├── report_build_and_test
# │ │ │ ├── <used files>
# │ │ │ │ ├── .gitlab/scripts/safe_create_rundir
# │ │ │ │ └── .gitlab/scripts/git_try_to_push
# │ │ │ └── <used variables>
# │ │ │ ├── AUTOTEST_ROOT
# │ │ │ ├── CI_COMMIT_REF_SLUG
# │ │ │ ├── CI_PROJECT_DIR
# │ │ │ ├── CI_PIPELINE_URL
# │ │ │ ├── AUTOTEST_COMMIT
# │ │ │ └── CI_MACHINE
# │ │ └── safe_create_rundir
# │ ├── custom-jobs-and-variables.yml
# │ │ ├── <jobs>
# │ │ │ ├── .custom_job
# │ │ │ ├── .reproducer_vars
# │ │ │ ├── .report_job_success
# │ │ │ └── .report_job_failure
# │ │ ├── <used files>
# │ │ │ ├── tests/gitlab/build_and_test [in JOB_CMD]
# │ │ │ └── .gitlab/scripts/report_build_and_test [by .report_job_*]
# │ │ ├── <defined variables>
# │ │ │ ├── JOB_CMD
# │ │ │ ├── BUILD_ROOT
# │ │ │ ├── ALLOC_NAME
# │ │ │ ├── TPLS_REPO
# │ │ │ ├── TESTS_REPO
# │ │ │ ├── AUTOTEST_REPO
# │ │ │ ├── MFEM_DATA_REPO
# │ │ │ ├── ARTIFACTS_DIR: artifacts
# │ │ │ ├── SLURM_OVERLAP: 1
# │ │ │ ├── DANE_SHARED_ALLOC
# │ │ │ ├── DANE_JOB_ALLOC
# │ │ │ ├── TIOGA_SHARED_ALLOC
# │ │ │ ├── TIOGA_JOB_ALLOC
# │ │ │ └── MATRIX_JOB_ALLOC
# │ │ └── <used variables>
# │ │ ├── SPEC
# │ │ ├── BUILD_ROOT
# │ │ └── ...
# │ ├── dane-baseline.yml
# │ │ ├── <jobs>
# │ │ │ ├── .on_dane
# │ │ │ ├── baselinecheck_mfem_intel_dane
# │ │ │ ├── cleanup
# │ │ │ ├── report_baseline
# │ │ │ └── baselinepublish_mfem_dane
# │ │ ├── <included and used files>
# │ │ │ ├── .gitlab/custom-jobs-and-variables.yml
# │ │ │ ├── .gitlab/configs/setup-baseline.yml
# │ │ │ ├── .gitlab/scripts/rebaseline
# │ │ │ ├── .gitlab/scripts/baseline
# │ │ │ └── .gitlab/scripts/git_try_to_push
# │ │ ├── <defined variables>
# │ │ │ ├── BASELINE_TEST: baseline
# │ │ │ ├── MACHINE_NAME: dane
# │ │ │ ├── TPLS_DIR
# │ │ │ └── export MFEM_TEST_NP
# │ │ └── <used variables>
# │ │ ├── ON_DANE
# │ │ ├── AUTOTEST [defined by .gitlab-ci.yml]
# │ │ ├── BUILD_ROOT [defined by custom-jobs-and-variables.yml]
# │ │ ├── TPLS_DIR [defined by this file]
# │ │ ├── ARTIFACTS_DIR [defined by custom-jobs-and-variables.yml]
# │ │ ├── MACHINE_NAME [defined by this file]
# │ │ ├── AUTOTEST_COMMIT [defined by .gitlab-ci.yml]
# │ │ ├── AUTOTEST_ROOT [defined by .gitlab-ci.yml]
# │ │ ├── BASELINE_TEST [defined by this file]
# │ │ └── REBASELINE [defined by .gitlab-ci.yml]
# │ └── subscribed-pipelines.yml
# │ ├── <jobs>
# │ │ ├── .machine-check
# │ │ ├── generate-job-lists
# │ │ ├── dane-up-check
# │ │ ├── dane-build-and-test
# │ │ ├── dane-baseline
# │ │ ├── tioga-up-check
# │ │ ├── tioga-build-and-test
# │ │ ├── matrix-up-check
# │ │ └── matrix-build-and-test
# │ ├── <used jobs>
# │ │ └── .build-and-test [from ".gitlab-ci.yml"]
# │ ├── <included files>
# │ │ └── .gitlab/dane-baseline.yml [by "dane-baseline"]
# │ └── <used variables>
# │ ├── GITHUB_PROJECT_ORG
# │ ├── GITHUB_PROJECT_NAME
# │ ├── AUTOTEST
# │ ├── AUTOTEST_COMMIT
# │ └── REBASELINE
# └── tests
# ├── gitlab
# │ ├── build_and_test
# │ │ ├── <builds and tests a given MFEM spec with uberenv>
# │ │ ├── <used files>
# │ │ │ ├── tests/uberenv/uberenv.py [deps mode, cloned]
# │ │ │ └── tests/gitlab/get_mfem_uberenv [deps mode]
# │ │ └── <used variables>
# │ │ ├── SYS_TYPE
# │ │ ├── THREADS [num. parallel jobs to build MFEM]
# │ │ ├── MODULE_LIST [modules to load]
# │ │ ├── CI_JOB_ID
# │ │ ├── USE_DEV_SHM
# │ │ ├── SPACK_DEBUG
# │ │ ├── DEBUG_MODE
# │ │ ├── REGISTRY_TOKEN
# │ │ ├── CI_REGISTRY_USER (defined by Gitlab)
# │ │ ├── USER
# │ │ ├── CI_REGISTRY_IMAGE (defined by Gitlab)
# │ │ └── CI_JOB_TOKEN (defined by Gitlab)
# │ ├── build_and_test_setup
# │ │ ├── <updates MFEM_DATA_REPO and AUTOTEST_REPO using locks>
# │ │ └── <used variables>
# │ │ ├── MFEM_DATA_REPO
# │ │ ├── SHARED_REPOS_DIR
# │ │ ├── AUTOTEST_REPO
# │ │ └── AUTOTEST_ROOT
# │ └── get_mfem_uberenv
# │ ├── <github.com/mfem/mfem-uberenv.git -> tests/uberenv>
# │ └── <defines the uberenv hash to use>
# └── uberenv [cloned by tests/gitlab/get_mfem_uberenv]
# └── uberenv.py
#
# <root of radiuss/radiuss-shared-ci, ref: 'v2025.09.1'>
# └── pipelines
# ├── matrix.yml
# │ ├── <jobs>
# │ │ ├── .on_matrix
# │ │ ├── .matrix_reproducer_init
# │ │ ├── .matrix_reproducer_vars
# │ │ ├── .matrix_reproducer_job
# │ │ ├── .matrix_job_command
# │ │ └── .job_on_matrix
# │ ├── <used jobs>
# │ │ └── .custom_job [from .gitlab/custom-jobs-and-variables.yml]
# │ └── <used variables>
# │ ├── ON_MATRIX
# │ ├── ADVANCED_JOB
# │ ├── ALL_TARGETS
# │ ├── SYS_TYPE
# │ ├── LLNL_SERVICE_USER
# │ ├── USER
# │ ├── GITHUB_PROJECT_NAME
# │ ├── GITHUB_PROJECT_ORG
# │ ├── MATRIX_JOB_ALLOC
# │ └── JOB_CMD
# ├── dane.yml
# │ ├── <jobs>
# │ │ ├── .on_dane
# │ │ ├── .dane_reproducer_init
# │ │ ├── .dane_reproducer_vars
# │ │ ├── .dane_reproducer_job
# │ │ ├── .dane_job_command
# │ │ ├── .job_on_dane
# │ │ ├── allocate_resources
# │ │ └── release_resources
# │ ├── <used jobs>
# │ │ └── .custom_job [from .gitlab/custom-jobs-and-variables.yml]
# │ ├── <defined variables>
# │ │ └── export JOBID
# │ └── <used variables>
# │ ├── ON_DANE
# │ ├── ADVANCED_JOB
# │ ├── ALL_TARGETS
# │ ├── SYS_TYPE
# │ ├── LLNL_SERVICE_USER
# │ ├── USER
# │ ├── GITHUB_PROJECT_NAME
# │ ├── GITHUB_PROJECT_ORG
# │ ├── DANE_JOB_ALLOC
# │ ├── JOB_CMD
# │ ├── JOBID
# │ ├── ALLOC_NAME
# │ └── DANE_SHARED_ALLOC
# └── tioga.yml
# ├── <jobs>
# │ ├── .on_tioga
# │ ├── .tioga_reproducer_init
# │ ├── .tioga_reproducer_vars
# │ ├── .tioga_reproducer_job
# │ ├── .tioga_job_command
# │ ├── .job_on_tioga
# │ ├── allocate_resources
# │ └── release_resources
# ├── <used jobs>
# │ └── .custom_job [from .gitlab/custom-jobs-and-variables.yml]
# ├── <defined variables>
# │ └── PROXY
# └── <used variables>
# ├── ON_TIOGA
# ├── ADVANCED_JOB
# ├── ALL_TARGETS
# ├── SYS_TYPE
# ├── LLNL_SERVICE_USER
# ├── USER
# ├── GITHUB_PROJECT_NAME
# ├── GITHUB_PROJECT_ORG
# ├── TIOGA_JOB_ALLOC
# ├── JOB_CMD
# ├── PROXY
# ├── ALLOC_NAME
# └── TIOGA_SHARED_ALLOC
# at Lawrence Livermore National Laboratory (LLNL). This entire pipeline is
# LLNL-specific!
include:
- project: 'lc-templates/id_tokens'
file: 'id_tokens.yml'
# The pipeline is divided into stages. Usually, jobs in a given stage wait for
# the preceding stages to complete before to start. However, we sometimes use
# the "needs" keyword and express the DAG of jobs for more efficiency.
# - We use setup and setup_baseline phases to download content outside of mfem
# directory.
# - Allocate/Release is where ruby resource are allocated/released once for all.
# - Build and Test is where we build and MFEM for multiple toolchains.
# - Baseline_checks gathers baseline-type test suites execution
# - Baseline_publish, only available on master, allows to update baseline
# results
stages:
- sub-pipelines
###############################################################################
# We define the following GitLab pipeline variables:
variables:
##### LC GITLAB CONFIGURATION
CUSTOM_CI_BUILDS_DIR: "/usr/workspace/mfem/gitlab-runner"
##### PROJECT VARIABLES
USER_CI_TOP_DIR: "${CUSTOM_CI_BUILDS_DIR}/${GITLAB_USER_LOGIN}"
SHARED_REPOS_DIR: "${USER_CI_TOP_DIR}/repos"
AUTOTEST_ROOT: "${SHARED_REPOS_DIR}"
# MFEM_DATA_DIR is setup in '.gitlab/configs/setup-build-and-test.yml' and
# used in '.gitlab/configs/<machine>-config.yml':
MFEM_DATA_DIR: "${SHARED_REPOS_DIR}/mfem-data"
# AUTOTEST: enable (ON/YES) or disable (any other value) test reporting. See
# also AUTOTEST_COMMIT.
AUTOTEST: "OFF"
# AUTOTEST_COMMIT: used only when AUTOTEST is set to ON/YES.
# * If AUTOTEST_COMMIT is set to ON/YES, reporting jobs will commit their
# files to the MFEM/autotest repo.
# * If AUTOTEST_COMMIT is NOT set to ON/YES, reporting jobs will NOT commit
# their files to the MFEM/autotest repo. Instead they will just show the
# contents of the report files and remove them.
AUTOTEST_COMMIT: "ON"
# REBASELINE:
# Defines the default choice for updating the saved baseline results. By default
# the baseline can only be updated from the master branch. This variable offers
# the option to manually ask for rebaselining from another branch if necessary.
REBASELINE: "OFF"
REBASELINE: "NO"
AUTOTEST: "NO"
# AUTOTEST_COMMIT: used only when AUTOTEST is set to YES.
# * If AUTOTEST_COMMIT is NOT set to NO, reporting jobs will commit their
# files to the MFEM/autotest repo.
# * If AUTOTEST_COMMIT is set to NO, reporting jobs will NOT commit their
# files to the MFEM/autotest repo. Instead they will just show the contents
# of the report files and remove them.
AUTOTEST_COMMIT: "YES"
##### SHARED_CI CONFIGURATION
# Required information about GitHub repository
GITHUB_PROJECT_NAME: "mfem"
GITHUB_PROJECT_ORG: "MFEM"
# Override the pattern describing branches that will skip the "draft PR filter
# test". Add protected branches here. See default value in
# preliminary-ignore-draft-pr.yml.
# ALWAYS_RUN_PATTERN: ""
###############################################################################
##### High level stages
# We organize the test-pipelines stage with sub-pipelines. Each sub-pipeline
# corresponds to a test batch on a given machine.
stages:
- prerequisites
- test-pipelines
###############################################################################
# Template for jobs triggering a build-and-test sub-pipeline:
.build-and-test:
stage: test-pipelines
# Trigger subpipelines:
ruby-build-and-test:
stage: sub-pipelines
variables:
# Explicitly pass down values that are not always propagated to child
# pipelines, e.g. when a variable is set in the "Settings -> CI" web
# interface (project variables).
# Note: in some cases, this does not work as expected, e.g. when the
# variable is not re-defined in the web interface; in such cases, the child
# pipeline gets a definition like '${AUTOTEST}', i.e. it behaves as if
# AUTOTEST is undefined, even though there is a default value in
# .gitlab-ci.yml.
# Explicitly pass down values that we want to be able to set when triggering
# pipelines manually or using scheduling
AUTOTEST: "${AUTOTEST}"
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
trigger:
include:
- local: '.gitlab/custom-jobs-and-variables.yml'
- project: 'radiuss/radiuss-shared-ci'
ref: 'v2025.09.1'
file: 'pipelines/${CI_MACHINE}.yml'
- artifact: '${CI_MACHINE}-jobs.yml'
job: 'generate-job-lists'
include: .gitlab/ruby-build-and-test.yml
strategy: depend
forward:
pipeline_variables: true
###############################################################################
include:
# Sets ID tokens for every job using `default:`
- project: 'lc-templates/id_tokens'
file: 'id_tokens.yml'
# [Optional] checks preliminary to running the actual CI test
#- project: 'radiuss/radiuss-shared-ci'
# ref: 'v2025.09.1'
# file: 'preliminary-ignore-draft-pr.yml'
# pipelines subscribed by the project
- local: '.gitlab/subscribed-pipelines.yml'
ruby-baseline:
stage: sub-pipelines
variables:
# Explicitly pass down values that we want to be able to set when triggering
# pipelines manually or using scheduling
REBASELINE: "${REBASELINE}"
AUTOTEST: "${AUTOTEST}"
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
trigger:
include: .gitlab/ruby-baseline.yml
strategy: depend
lassen-build-and-test:
stage: sub-pipelines
variables:
# Explicitly pass down values that we want to be able to set when triggering
# pipelines manually or using scheduling
AUTOTEST: "${AUTOTEST}"
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
trigger:
include: .gitlab/lassen-build-and-test.yml
strategy: depend
corona-build-and-test:
stage: sub-pipelines
variables:
# Explicitly pass down values that we want to be able to set when triggering
# pipelines manually or using scheduling
AUTOTEST: "${AUTOTEST}"
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
trigger:
include: .gitlab/corona-build-and-test.yml
strategy: depend
+14 -36
View File
@@ -15,18 +15,18 @@ and nightly testing on GitLab.
## Top level
The root configuration file is `.gitlab-ci.yml` at the root of MFEM repo. This
file only defines three stages, a prerequisites one, and two main stages in
which we trigger several sub-pipelines.
The root configuration file is `.gitlab-ci.yml` at the root of MFEM repo.
This file only defines one stage, in which we trigger several
sub-pipelines.
We use sub-pipelines to isolate the test for one combination of `machine`
and `test type`.
Machines typically include:
* Dane: Intel Sapphire Rapids
* Matrix: Intel Sapphire Rapids + Nvidia H100 GPU
* Tioga: AMD MI250X GPU
* Ruby: 2nd Gen Intel Xeon (Cascade Lake)
* Lassen: Power9 + Nvidia GPU
* Corona: AMD GPU
Test types include:
@@ -39,31 +39,9 @@ altering the scheduling, execution and displaying of the others.
## Sub-pipelines
### build-and-test
The build-and-test sub-pipelines leverage RADIUSS Shared CI to share most of
the CI implementation. RADIUSS Shared CI provides a shared CI infrastructure
vetted on most LC systems of interest and efficiently leveraging each machine
scheduler to increase CI throughput. The maintenance of RADIUSS Shared CI is
shared among several RADIUSS projects.
Jobs for the build-and-test sub-pipelines are defined in the jobs directory.
Because build-and-test jobs leverage Uberenv and Spack to build the
dependencies automatically, the jobs essentially consists in a `spack spec`
defined in the jobs files, and some scheduling parameters defined in the
`.gitlab/custom-jobs-and-variables.yml` file.
Build-and-test jobs all run the `tests/gitlab/build_and_test` script.
The build-and-test pipelines are controlled by the
`.gitlab/subscribed-pipelines.yml` which defines which machines to run on and
implements additional features like machine availability check, and job list
generation.
### baseline
Baseline sub-pipelines are described by files with names reflecting the
machine it runs on, e.g. `dane-baseline`.
Each file is this directory is the root configuration file for one
sub-pipeline. The naming reflects the corresponding couple (`machine`,
`test_type`).
Those files define the *stages* and the *jobs* for the sub-pipeline. They
also contain any configuration that cannot be shared. For the most part
@@ -85,11 +63,11 @@ usage function. This should be improved.
# More testing
## Adding a new target to a build-and-test pipeline
## Adding a new target to a build_and_test pipeline
`build-and-test` pipelines rely on Spack to install dependencies. Spack is
`build_and_test` pipelines rely on Spack to install dependencies. Spack is
driven by Uberenv which helps freezing Spack configuration: the goal being to
point to a specific commit in Spack and isolate its configuration so that it is
point to specific commit in Spack and isolate its configuration so that it is
not influenced by the user environment. More documentation about this can be
found in `tests/gitlab`.
@@ -98,13 +76,13 @@ with a spack spec of MFEM, within the limits permitted by the MFEM spack
package.
In any build-and-test sub-pipeline a job basically consists in defining the
spack spec to use. Adding a job on Dane for example resumes to:
spack spec to use. Adding a job on ruby for example resumes to:
```yaml
<job_name>:
variables:
SPEC: "<spack_spec>"
extends: .job_on_dane
extends: .build_and_test_on_ruby
```
The remaining and non trivial work is to make sure this spec is working. To
+40
View File
@@ -0,0 +1,40 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
include:
- project: 'lc-templates/id_tokens'
file: 'id_tokens.yml'
# We define the following GitLab pipeline variables:
variables:
# The path to the shared resource between all jobs. For example, external
# repositories like 'tests' and 'tpls' are cloned here. Also, 'tpls' is built
# once for all targets, so that build happen here. The BUILD_ROOT is unique to
# the pipeline, preventing any form of concurrency with other pipelines. This
# also means that the BUILD_ROOT directory will never be cleaned.
# TODO: add a clean-up mechanism
BUILD_ROOT: ${USER_CI_TOP_DIR}/${CI_PROJECT_NAME}-${MACHINE_NAME}-pipeline-${CI_PIPELINE_ID}
# On LLNL's ruby, there is only one allocation shared among jobs in order to
# save time and resource. This allocation has to be uniquely named so that we
# are sure to retrieve it.
ALLOC_NAME: ${CI_PROJECT_NAME}_ci_${CI_PIPELINE_ID}
# Git repositories used in the pipeline
TPLS_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/tpls.git
TESTS_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/tests.git
AUTOTEST_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/autotest.git
MFEM_DATA_REPO: https://github.com/mfem/data.git
# Directory used to place artifacts.
ARTIFACTS_DIR: artifacts
SLURM_OVERLAP: 1
+59
View File
@@ -0,0 +1,59 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# GitLab pipeline configuration for the Corona machine at LLNL
variables:
MACHINE_NAME: corona
.on_corona:
tags:
- shell
- corona
rules:
# Don't run corona jobs if...
# Note: This makes corona an "opt-in" machine. To activate builds on corona
# for a given GitLab clone of MFEM, go to Setting/CI-CD/variables, and set
# "ON_CORONA" to "ON". An LC account on for corona is required to trigger a
# pipeline there.
- if: '$CI_COMMIT_BRANCH =~ /_cnone/ || $ON_CORONA != "ON"'
when: never
# Don't run autotest update if...
- if: '$CI_JOB_NAME =~ /report/ && $AUTOTEST != "YES"'
when: never
# Report success on success status
- if: '$CI_JOB_NAME =~ /report_job_success/ && $AUTOTEST == "YES"'
when: on_success
# Report failure on failure status
- if: '$CI_JOB_NAME =~ /report_job_failure/ && $AUTOTEST == "YES"'
when: on_failure
# Always release resource
- if: '$CI_JOB_NAME =~ /release_resource/'
when: always
# Always cleanup
- if: '$CI_JOB_NAME =~ /cleanup/'
when: always
# Default is to run if previous stage succeeded
- when: on_success
# Spack helped builds
# Generic corona build job, extending build script
.build_and_test_on_corona:
extends: [.on_corona]
stage: build_and_test
script:
# THREADS is used by 'tests/gitlab/build_and_test', run below
- export THREADS=12
- echo ${ALLOC_NAME}
- export JOBID=$(squeue -h --name=${ALLOC_NAME} --format=%A)
- echo ${JOBID}
- echo ${MFEM_DATA_DIR}
- echo ${SPEC}
- srun $( [[ -n "${JOBID}" ]] && echo "--jobid=${JOBID}" ) -t 15 -N 1 tests/gitlab/build_and_test --spec "${SPEC}" --data-dir "${MFEM_DATA_DIR}" --data
+48
View File
@@ -0,0 +1,48 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# GitLab pipelines configurations for the Lassen machine at LLNL
variables:
MACHINE_NAME: lassen
.on_lassen:
tags:
- shell
- lassen
rules:
- if: '$CI_COMMIT_BRANCH =~ /_lnone/ || $ON_LASSEN == "OFF"' #run except if ...
when: never
# Don't run autotest update if...
- if: '$CI_JOB_NAME =~ /report/ && $AUTOTEST != "YES"'
when: never
# Report success on success status
- if: '$CI_JOB_NAME =~ /report_job_success/ && $AUTOTEST == "YES"'
when: on_success
# Report failure on failure status
- if: '$CI_JOB_NAME =~ /report_job_failure/ && $AUTOTEST == "YES"'
when: on_failure
# Always cleanup
- if: '$CI_JOB_NAME =~ /cleanup/'
when: always
- when: on_success
# Lassen uses a different job scheduler (spectrum lsf) that does not allow
# pre-allocation the same way slurm does. We use the pci queue on lassen
# to speed-up the allocation.
.build_and_test_on_lassen:
extends: [.on_lassen]
stage: build_and_test
script:
- echo ${MFEM_DATA_DIR}
- echo ${SPEC}
# Next script uses 'THREADS': leaving it empty --> it uses 'make all -j'
- lalloc 1 -W 45 -q pci --atsdisable tests/gitlab/build_and_test --spec "${SPEC}" --data-dir "${MFEM_DATA_DIR}" --data
needs: [setup]
+77
View File
@@ -0,0 +1,77 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Jobs report
.report_job_success:
script:
- echo ${MACHINE_NAME}
- echo ${AUTOTEST}
- echo ${AUTOTEST_COMMIT}
- echo "AUTOTEST_ROOT ${AUTOTEST_ROOT}"
- cd ${AUTOTEST_ROOT}
- |
(
date
echo "Waiting to acquire lock on '$PWD/autotest.lock' ..."
# try to get an exclusive lock on fd 9 (autotest.lock) repeating the try
# every 5 seconds; we may want to add a counter for the number of
# retries to interrupt a potential infinite loop
while ! flock -n 9; do
sleep 5
done
echo "Acquired lock on '$PWD/autotest.lock'"
date
# Report SUCCESS while holding the file lock on 'autotest.lock'.
# The next script uses the following environment variables:
# - MACHINE_NAME, AUTOTEST_ROOT, AUTOTEST_COMMIT
# - CI_COMMIT_REF_SLUG, CI_PROJECT_DIR, CI_PIPELINE_URL
# It also calls the script '.gitlab/scripts/safe_create_rundir'.
${CI_PROJECT_DIR}/.gitlab/scripts/report_build_and_test_success
err=$?
# sleep for a period to allow NFS to propagate the above changes;
# clearly, there is no guarantee that other NFS clients will see the
# changes even after the timeout
sleep 10
exit $err
) 9> autotest.lock
.report_job_failure:
script:
- echo ${MACHINE_NAME}
- echo ${AUTOTEST}
- echo ${AUTOTEST_COMMIT}
- echo "AUTOTEST_ROOT ${AUTOTEST_ROOT}"
- cd ${AUTOTEST_ROOT}
- |
(
date
echo "Waiting to acquire lock on '$PWD/autotest.lock' ..."
# try to get an exclusive lock on fd 9 (autotest.lock) repeating the try
# every 5 seconds; we may want to add a counter for the number of
# retries to interrupt a potential infinite loop
while ! flock -n 9; do
sleep 5
done
echo "Acquired lock on '$PWD/autotest.lock'"
date
# Report FAILURE while holding the file lock on 'autotest.lock'.
# The next script uses the following environment variables:
# - MACHINE_NAME, AUTOTEST_ROOT, AUTOTEST_COMMIT
# - CI_COMMIT_REF_SLUG, CI_PROJECT_DIR, CI_PIPELINE_URL
# It also calls the script '.gitlab/scripts/safe_create_rundir'.
${CI_PROJECT_DIR}/.gitlab/scripts/report_build_and_test_failure
err=$?
# sleep for a period to allow NFS to propagate the above changes;
# clearly, there is no guarantee that other NFS clients will see the
# changes even after the timeout
sleep 10
exit $err
) 9> autotest.lock
+55
View File
@@ -0,0 +1,55 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# GitLab pipelines configurations for the Ruby machine at LLNL
variables:
MACHINE_NAME: ruby
.on_ruby:
tags:
- shell
- ruby
rules:
# Don't run ruby jobs if...
- if: '$CI_COMMIT_BRANCH =~ /_qnone/ || $ON_RUBY == "OFF"'
when: never
# Don't run autotest update if...
- if: '$CI_JOB_NAME =~ /report/ && $AUTOTEST != "YES"'
when: never
# Report success on success status
- if: '$CI_JOB_NAME =~ /report_job_success/ && $AUTOTEST == "YES"'
when: on_success
# Report failure on failure status
- if: '$CI_JOB_NAME =~ /report_job_failure/ && $AUTOTEST == "YES"'
when: on_failure
# Always release resource
- if: '$CI_JOB_NAME =~ /release_resource/'
when: always
# Always cleanup
- if: '$CI_JOB_NAME =~ /cleanup/'
when: always
# Default is to run if previous stage succeeded
- when: on_success
# Spack helped builds
# Generic ruby build job, extending build script
.build_and_test_on_ruby:
extends: [.on_ruby]
stage: build_and_test
script:
# THREADS is used by 'tests/gitlab/build_and_test', run below
- export THREADS=16
- echo ${ALLOC_NAME}
- export JOBID=$(squeue -h --name=${ALLOC_NAME} --format=%A)
- echo ${JOBID}
- echo ${MFEM_DATA_DIR}
- echo ${SPEC}
- srun $( [[ -n "${JOBID}" ]] && echo "--jobid=${JOBID}" ) --reservation=ci -t 45 -N 1 tests/gitlab/build_and_test --spec "${SPEC}" --data-dir "${MFEM_DATA_DIR}" --data
+1 -1
View File
@@ -18,7 +18,7 @@
setup_baseline:
tags:
- shell
- dane
- ruby
stage: setup
variables:
GIT_STRATEGY: none
+90
View File
@@ -0,0 +1,90 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Setup clones the mfem/data repo in ${SHARED_REPOS_DIR}. The build_and_test
# script then symlinks the repo to the parent directory of the MFEM source
# directory. Unit tests that depend on the mfem/data repo will then detect that
# this directory is present and be enabled.
setup:
tags:
- shell
- ruby
stage: setup
variables:
GIT_STRATEGY: none
script:
#
# Setup MFEM_DATA_DIR=${SHARED_REPOS_DIR}/mfem-data, see '.gitlab-ci.yml'
# and '.gitlab/configs/<machine>-config.yml'
#
- echo "MACHINE_NAME = ${MACHINE_NAME}"
- echo "AUTOTEST = ${AUTOTEST}"
- echo "AUTOTEST_COMMIT = ${AUTOTEST_COMMIT}"
- echo "SHARED_REPOS_DIR ${SHARED_REPOS_DIR}"
- mkdir -p ${SHARED_REPOS_DIR} && cd ${SHARED_REPOS_DIR}
- command -v flock || echo "Required command 'flock' not found"
- |
(
date
echo "Waiting to acquire lock on '$PWD/mfem-data.lock' ..."
# try to get an exclusive lock on fd 9 (mfem-data.lock) repeating the
# try every 5 seconds; we may want to add a counter for the number of
# retries to interrupt a potential infinite loop
while ! flock -n 9; do
sleep 5
done
echo "Acquired lock on '$PWD/mfem-data.lock'"
date
# clone/update the mfem/data repo while holding the file lock on
# 'mfem-data.lock'
err=0
if [[ ! -d "mfem-data" ]]; then
git clone ${MFEM_DATA_REPO} "mfem-data"
else
cd "mfem-data" && git pull && cd ..
fi || err=1
# sleep for a period to allow NFS to propagate the above changes;
# clearly, there is no guarantee that other NFS clients will see the
# changes even after the timeout
sleep 10
exit $err
) 9> mfem-data.lock
#
# Setup ${AUTOTEST_ROOT}/autotest:
#
- echo "AUTOTEST_ROOT ${AUTOTEST_ROOT}"
- mkdir -p ${AUTOTEST_ROOT} && cd ${AUTOTEST_ROOT}
- |
(
date
echo "Waiting to acquire lock on '$PWD/autotest.lock' ..."
# try to get an exclusive lock on fd 9 (autotest.lock) repeating the try
# every 5 seconds; we may want to add a counter for the number of
# retries to interrupt a potential infinite loop
while ! flock -n 9; do
sleep 5
done
echo "Acquired lock on '$PWD/autotest.lock'"
date
# clone/update the autotest repo while holding the file lock on
# 'autotest.lock'
err=0
if [[ ! -d "autotest" ]]; then
git clone ${AUTOTEST_REPO}
else
cd autotest && git pull && cd ..
fi || err=1
# sleep for a period to allow NFS to propagate the above changes;
# clearly, there is no guarantee that other NFS clients will see the
# changes even after the timeout
sleep 10
exit $err
) 9> autotest.lock
+67
View File
@@ -0,0 +1,67 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
stages:
- setup
- allocate_resource
- build_and_test
- release_resource_and_report
# Slurm shared allocation
allocate_resource:
variables:
GIT_STRATEGY: none
extends: .on_corona
stage: allocate_resource
script:
- echo ${ALLOC_NAME}
- salloc --exclusive --nodes=1 --partition=mi60 --time=45 --no-shell --job-name=${ALLOC_NAME}
timeout: 6h
needs: [setup]
# Build and test jobs, simply provide a spec
rocm_gcc_8.3.1:
variables:
SPEC: "@develop%gcc@8.3.1+rocm amdgpu_target=gfx906"
extends: .build_and_test_on_corona
needs: [allocate_resource]
# Release slurm allocation
release_resource:
variables:
GIT_STRATEGY: none
extends: .on_corona
stage: release_resource_and_report
script:
- echo ${ALLOC_NAME}
- export JOBID=$(squeue -h --name=${ALLOC_NAME} --format=%A)
- echo ${JOBID}
- ([[ -n "${JOBID}" ]] && scancel ${JOBID})
needs: [rocm_gcc_8.3.1]
# Jobs report
report_job_success:
stage: release_resource_and_report
extends:
- .on_corona
- .report_job_success
report_job_failure:
stage: release_resource_and_report
extends:
- .on_corona
- .report_job_failure
include:
- local: .gitlab/configs/common.yml
- local: .gitlab/configs/corona-config.yml
- local: .gitlab/configs/setup-build-and-test.yml
- local: .gitlab/configs/report-build-and-test.yml
-132
View File
@@ -1,132 +0,0 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
include:
- project: 'lc-templates/id_tokens'
file: 'id_tokens.yml'
# We define the following GitLab pipeline variables:
variables:
# Set the build-and-test command.
# Nested variables are allowed and useful to customize the job command. We
# protect variables with quotes so that their value may remain a string even if
# they contain whitespaces.
JOB_CMD:
value: tests/gitlab/build_and_test --spec \"${SPEC}\" --data-dir ${MFEM_DATA_DIR} --data
# The path to the shared resource between all jobs in the 'dane-baseline'
# pipeline. For example, external repositories like 'tests' and 'tpls' are
# cloned here. Also, 'tpls' is built once for all targets, so that build happens
# here. The BUILD_ROOT is unique to the pipeline, preventing any form of
# concurrency with other pipelines. This directory is removed by the 'cleanup'
# stage in the 'dane-baseline' pipeline.
BUILD_ROOT: ${USER_CI_TOP_DIR}/${CI_PROJECT_NAME}-${CI_MACHINE}-pipeline-${CI_PIPELINE_ID}
# On LLNL's dane and tioga, the 'build-and-test' pipelines creates only one
# allocation shared among jobs in the pipeline in order to save time and
# resources. This allocation has to be uniquely named so that we are sure to
# retrieve it and avoid collisions.
ALLOC_NAME: ${CI_PROJECT_NAME}_ci_${CI_PIPELINE_ID}
# Git repositories used in the pipelines:
# - TPLS_REPO and TESTS_REPO are used only by the 'dane-baseline' pipeline
# - AUTOTEST_REPO is used by all pipelines
# - MFEM_DATA_REPO is used only by the 'build-and-test' pipelines
TPLS_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/tpls.git
TESTS_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/tests.git
AUTOTEST_REPO: ssh://git@mybitbucket.llnl.gov:7999/mfem/autotest.git
MFEM_DATA_REPO: https://github.com/mfem/data.git
# Directory used to place artifacts:
# - ARTIFACTS_DIR is only used by the 'dane-baseline' pipeline
ARTIFACTS_DIR: artifacts
SLURM_OVERLAP: 1
# Dane
# Arguments for top level allocation
DANE_SHARED_ALLOC: "--exclusive --reservation=ci --time=60 --nodes=1"
# Arguments for job level allocation
# Note: We repeat the reservation, necessary when jobs are manually re-triggered.
DANE_JOB_ALLOC: "--reservation=ci --overlap --nodes=1"
# Tioga
# Arguments for top level allocation
TIOGA_SHARED_ALLOC: "--queue=pci --exclusive --time-limit=45m --nodes=1"
# Arguments for job level allocation
TIOGA_JOB_ALLOC: "--nodes=1 --begin-time=+5s"
# Matrix
# Arguments for top level allocation
MATRIX_SHARED_ALLOC: "-p pdebug --exclusive --time=45 --nodes=1 -G 4"
# Arguments for job level allocation
# Note: We repeat the reservation, necessary when jobs are manually re-triggered.
MATRIX_JOB_ALLOC: "--overlap --nodes=1"
# Configuration shared by build and test jobs specific to this project.
# Not all configuration can be shared. Here projects can fine tune the
# CI behavior.
# See Umpire for an example (export junit test reports).
.custom_job:
artifacts:
reports:
# Note: this part is not used by the 'dane-baseline' pipeline.
# FIXME: BUILD_ROOT, TPLS_REPO, TESTS_REPO are not needed here.
# Also, the definition of SHARED_REPOS_DIR is wrong.
.reproducer_vars:
script:
- |
echo -e "
# Variables \n
export SPEC=\"${SPEC//\"/\\\"}\" \n
# Directories \n
export BUILD_ROOT=\"\${working_dir}\" \n
export SHARED_REPOS_DIR=\"\${BUILD_ROOT}/..\" \n
export MFEM_DATA_DIR=\"\${SHARED_REPOS_DIR}/mfem-data\" \n
# Repositories \n
export TPLS_REPO=\"${TPLS_REPO//\"/\\\"}\" \n
export TESTS_REPO=\"${TESTS_REPO//\"/\\\"}\" \n
export AUTOTEST_REPO=\"${AUTOTEST_REPO//\"/\\\"}\" \n
export MFEM_DATA_REPO=\"${MFEM_DATA_REPO//\"/\\\"}\" \n
# Setup directories \n
./tests/gitlab/build_and_test_setup \n
# Using the CI build cache is optional and requires a token. Set it like so: \n
# export REGISTRY_TOKEN=\"<your token here>\" \n"
#
# Jobs report
.report_job_success:
script:
- ${CI_PROJECT_DIR}/.gitlab/scripts/report_build_and_test SUCCESS
rules:
- when: on_success
.report_job_failure:
script:
- ${CI_PROJECT_DIR}/.gitlab/scripts/report_build_and_test FAILURE
rules:
- when: on_failure
# Keep the following for debugging purposes: renaming this job from
# '.show_variables' to 'show_variables' will insert this debug job at the
# beginning of all child pipelines.
.show_variables:
tags: [shell, oslic]
variables:
GIT_STRATEGY: none
stage: .pre
script:
- |
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo "AUTOTEST=${AUTOTEST}"
echo "AUTOTEST_COMMIT=${AUTOTEST_COMMIT}"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
# Fail the job on purpose to prevent the rest of the pipeline from running
false
-19
View File
@@ -1,19 +0,0 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Jobs report
report_job_success:
extends: [.on_dane, .report_job_success]
stage: jobs-stage-3
report_job_failure:
extends: [.on_dane, .report_job_failure]
stage: jobs-stage-3
-92
View File
@@ -1,92 +0,0 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Override reproducer section to define MFEM specific variables.
.dane_reproducer_vars:
script:
- !reference [.reproducer_vars, script]
# TODO: Setup script should be defined as a bash script (but then GIT_STRATEGY
# cannot be "none" anymore).
# Setup clones the mfem/data repo in ${SHARED_REPOS_DIR}. The build_and_test
# script then symlinks the repo to the parent directory of the MFEM source
# directory. Unit tests that depend on the mfem/data repo will then detect that
# this directory is present and be enabled.
setup:
extends: .on_dane
stage: jobs-stage-1
script:
- ./tests/gitlab/build_and_test_setup
########################
# Overridden shared jobs
########################
# When using shared jobs, we can duplicate them here to override description and
# add necessary changes.
# We keep ${PROJECT_<MACHINE>_VARIANTS} and ${PROJECT_<MACHINE>_DEPS} So that
# the comparison with the original job is easier.
############
# Extra jobs
############
# We do not recommend using ${PROJECT_<MACHINE>_VARIANTS} and
# ${PROJECT_<MACHINE>_DEPS} in the extra jobs. There is not reason not to fully
# describe the spec here.
.mfem_job_on_dane:
extends: .job_on_dane
stage: jobs-stage-2
variables:
# Dane has 224 threads/node and we run 7 separate jobs: 224=7*32
THREADS: 28
debug_ser_gcc_10:
extends: .mfem_job_on_dane
variables:
SPEC: "%gcc@10.3.1 +debug~mpi"
debug_par_gcc_10:
extends: .mfem_job_on_dane
variables:
SPEC: "%gcc@10.3.1 +debug+mpi"
opt_ser_gcc_10:
extends: .mfem_job_on_dane
variables:
SPEC: "%gcc@10.3.1 ~mpi"
opt_par_gcc_10:
extends: .mfem_job_on_dane
variables:
SPEC: "%gcc@10.3.1"
opt_par_gcc_10_sundials:
extends: .mfem_job_on_dane
variables:
SPEC: "%gcc@10.3.1 +sundials"
opt_par_gcc_10_petsc:
extends: .mfem_job_on_dane
variables:
SPEC: "%gcc@10.3.1 +petsc ^petsc+mumps~superlu-dist"
opt_par_gcc_10_pumi:
extends: .mfem_job_on_dane
variables:
SPEC: "%gcc@10.3.1 +pumi"
opt_par_gcc_10_gslib:
extends: .mfem_job_on_dane
variables:
SPEC: "%gcc@10.3.1 +gslib"
-19
View File
@@ -1,19 +0,0 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Jobs report
report_job_success:
extends: [.on_matrix, .report_job_success]
stage: jobs-stage-3
report_job_failure:
extends: [.on_matrix, .report_job_failure]
stage: jobs-stage-3
-70
View File
@@ -1,70 +0,0 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Override reproducer section to define UMPIRE specific variables.
.matrix_reproducer_vars:
script:
- !reference [.reproducer_vars, script]
#TODO: Setup script should be defined as a bash script (but then GIT_STRATEGY cannot be "none" anymore).
# Setup clones the mfem/data repo in ${SHARED_REPOS_DIR}. The build_and_test
# script then symlinks the repo to the parent directory of the MFEM source
# directory. Unit tests that depend on the mfem/data repo will then detect that
# this directory is present and be enabled.
setup:
extends: .on_matrix
stage: jobs-stage-1
script:
- ./tests/gitlab/build_and_test_setup
########################
# Overridden shared jobs
########################
# When using shared jobs , we can duplicate them here to override description and add necessary changes.
# We keep ${PROJECT_<MACHINE>_VARIANTS} and ${PROJECT_<MACHINE>_DEPS} So that
# the comparison with the original job is easier.
############
# Extra jobs
############
# We do not recommend using ${PROJECT_<MACHINE>_VARIANTS} and
# ${PROJECT_<MACHINE>_DEPS} in the extra jobs. There is not reason not to fully
# describe the spec here.
.mfem_job_on_matrix:
extends: .job_on_matrix
stage: jobs-stage-2
variables:
# We run 2 jobs on 1 node that has 112 threads
THREADS: 48
# These modules need to be consistent with the uberenv configurations:
MODULE_LIST: "gcc/10.3.1-magic cuda/12.9.1"
allocate_resources:
timeout: 4h
opt_mpi_cuda_gcc:
extends: .mfem_job_on_matrix
variables:
SPEC: "%gcc@10.3.1 +mpi +cuda cuda_arch=90"
opt_mpi_cuda_hypre_cuda_gcc:
extends: .mfem_job_on_matrix
variables:
SPEC: "%gcc@10.3.1 +mpi +cuda cuda_arch=90 ^hypre+cuda"
opt_mpi_cuda_gcc_gslib:
extends: .mfem_job_on_matrix
variables:
SPEC: "%gcc@10.3.1 +mpi +cuda +gslib cuda_arch=90 ^hypre+cuda"
-20
View File
@@ -1,20 +0,0 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Jobs report
report_job_success:
extends: [.on_tioga, .report_job_success]
stage: jobs-stage-3
report_job_failure:
extends: [.on_tioga, .report_job_failure]
stage: jobs-stage-3
-70
View File
@@ -1,70 +0,0 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Override reproducer section to define UMPIRE specific variables.
.tioga_reproducer_vars:
script:
- !reference [.reproducer_vars, script]
#TODO: Setup script should be defined as a bash script (but then GIT_STRATEGY cannot be "none" anymore).
# Setup clones the mfem/data repo in ${SHARED_REPOS_DIR}. The build_and_test
# script then symlinks the repo to the parent directory of the MFEM source
# directory. Unit tests that depend on the mfem/data repo will then detect that
# this directory is present and be enabled.
setup:
extends: .on_tioga
stage: jobs-stage-1
script:
- ./tests/gitlab/build_and_test_setup
########################
# Overridden shared jobs
########################
# When using shared jobs , we can duplicate them here to override description and add necessary changes.
# We keep ${PROJECT_<MACHINE>_VARIANTS} and ${PROJECT_<MACHINE>_DEPS} So that
# the comparison with the original job is easier.
############
# Extra jobs
############
# We do not recommend using ${PROJECT_<MACHINE>_VARIANTS} and
# ${PROJECT_<MACHINE>_DEPS} in the extra jobs. There is not reason not to fully
# describe the spec here.
# Build and test jobs, simply provide a spec
#.tioga_job_command:
# script:
# - echo PROXY="${PROXY}"
# - echo TIOGA_JOB_ALLOC="${TIOGA_JOB_ALLOC}"
# - "printf '#!/bin/bash\n%s\n' \"${JOB_CMD}\" > flux_script.sh"
# - cat flux_script.sh
# - ${PROXY} flux watch $( ${PROXY} flux batch -o output.stdout.type=kvs ${TIOGA_JOB_ALLOC} flux_script.sh )
# - rm -f flux_script.sh
.mfem_job_on_tioga:
extends: .job_on_tioga
stage: jobs-stage-2
variables:
# We run 1 job on 1 node that has 64 threads
THREADS: 64
opt_mpi_rocm_hypre_rocm:
extends: .mfem_job_on_tioga
variables:
SPEC: "%rocmcc@=6.3.1 +rocm amdgpu_target=gfx90a ^hypre+rocm"
# cce_16_0_1:
# extends: .mfem_job_on_tioga
# variables:
# SPEC: "%cce@=16.0.1"
+44
View File
@@ -0,0 +1,44 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
stages:
- setup
- build_and_test
- report
opt_mpi_cuda_gcc:
variables:
SPEC: "%gcc@8.3.1 +mpi +cuda cuda_arch=70"
extends: .build_and_test_on_lassen
opt_mpi_cuda_hypre_cuda_gcc:
variables:
SPEC: "%gcc@8.3.1 +mpi +cuda cuda_arch=70 ^hypre+cuda~shared cuda_arch=70"
extends: .build_and_test_on_lassen
# Jobs report
report_job_success:
stage: report
extends:
- .on_lassen
- .report_job_success
report_job_failure:
stage: report
extends:
- .on_lassen
- .report_job_failure
include:
- local: .gitlab/configs/common.yml
- local: .gitlab/configs/lassen-config.yml
- local: .gitlab/configs/setup-build-and-test.yml
- local: .gitlab/configs/report-build-and-test.yml
@@ -11,7 +11,6 @@
variables:
BASELINE_TEST: baseline
MACHINE_NAME: dane
stages:
- setup
@@ -20,27 +19,8 @@ stages:
- cleanup
- baseline_publish
.on_dane:
tags:
- shell
- dane
rules:
# Don't run dane jobs if...
- if: '$ON_DANE == "OFF"'
when: never
# Don't run autotest update if...
# Note: in some cases, the content of AUTOTEST can be '${AUTOTEST}', so we
# need to treat that value as the default value of 'OFF'.
- if: '$CI_JOB_NAME =~ /report/ && $AUTOTEST != "ON" && $AUTOTEST != "YES"'
when: never
# Always cleanup
- if: '$CI_JOB_NAME =~ /cleanup/'
when: always
# Default is to run if previous stage succeeded
- when: on_success
baselinecheck_mfem_intel_dane:
extends: [.on_dane]
baselinecheck_mfem_intel_ruby:
extends: [.on_ruby]
stage: baseline_check
variables:
# TPLS_DIR is used in .gitlab/scripts/baseline to provide the tpls location
@@ -49,13 +29,10 @@ baselinecheck_mfem_intel_dane:
# .gitlab/configs/setup-baseline.yml.
TPLS_DIR: ${BUILD_ROOT}/tpls
script:
- echo "AUTOTEST=$AUTOTEST"
- echo "AUTOTEST_COMMIT=$AUTOTEST_COMMIT"
- echo "AUTOTEST_ROOT=$AUTOTEST_ROOT"
- echo ${BUILD_ROOT}
- echo ${TPLS_DIR}
# Used by the tests in MFEM/tests, dane has 224 threads/node:
- export MFEM_TEST_NP=192
# Used by the tests in MFEM/tests:
- export MFEM_TEST_NP=48
# The next script uses the following environment variables:
# * BASELINE_TEST, SYS_TYPE, CI_PROJECT_DIR, ARTIFACTS_DIR,
# * BUILD_ROOT, TPLS_DIR, MACHINE_NAME
@@ -67,7 +44,7 @@ baselinecheck_mfem_intel_dane:
allow_failure: true
cleanup:
extends: .on_dane
extends: .on_ruby
stage: cleanup
variables:
GIT_STRATEGY: none
@@ -76,7 +53,7 @@ cleanup:
- rm -rf "${BUILD_ROOT}" || true
report_baseline:
extends: [.on_dane]
extends: [.on_ruby]
stage: baseline_report
script:
- echo ${MACHINE_NAME}
@@ -112,13 +89,7 @@ report_baseline:
cp ${rundir}/pipeline.txt ${rundir}/autotest-email.html
fi
msg="GitLab CI log for ${BASELINE_TEST} on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
# Note: in some cases, the content of AUTOTEST_COMMIT can be
# '${AUTOTEST_COMMIT}', so we need to treat that value as the default
# value of 'ON'.
if [[ "$AUTOTEST_COMMIT" == '${AUTOTEST_COMMIT}' ]]; then
AUTOTEST_COMMIT="ON"
fi
if [[ "$AUTOTEST_COMMIT" == "ON" || "$AUTOTEST_COMMIT" == "YES" ]]; then
if [[ "$AUTOTEST_COMMIT" != "NO" ]]; then
git pull && \
git add ${rundir} && \
git commit -m "${msg}" && \
@@ -142,12 +113,12 @@ report_baseline:
exit $err
) 9> autotest.lock
baselinepublish_mfem_dane:
extends: [.on_dane]
baselinepublish_mfem_ruby:
extends: [.on_ruby]
stage: baseline_publish
rules:
# - if: '$CI_COMMIT_BRANCH == "master" || $REBASELINE == "ON"'
- if: '$REBASELINE == "ON"'
# - if: '$CI_COMMIT_BRANCH == "master" || $REBASELINE == "YES"'
- if: '$REBASELINE == "YES"'
when: manual
script:
- echo ${BUILD_ROOT}
@@ -157,5 +128,6 @@ baselinepublish_mfem_dane:
- .gitlab/scripts/rebaseline
include:
- local: .gitlab/custom-jobs-and-variables.yml
- local: .gitlab/configs/common.yml
- local: .gitlab/configs/ruby-config.yml
- local: .gitlab/configs/setup-baseline.yml
+94
View File
@@ -0,0 +1,94 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
stages:
- setup
- allocate_resource
- build_and_test
- release_resource_and_report
# Allocate
allocate_resource:
variables:
GIT_STRATEGY: none
extends: .on_ruby
stage: allocate_resource
script:
- echo ${ALLOC_NAME}
- salloc --exclusive --nodes=1 --reservation=ci --time=60 --no-shell --job-name=${ALLOC_NAME}
timeout: 6h
# GitLab jobs for the Ruby machine at LLNL
debug_ser_gcc_10:
variables:
SPEC: "%gcc@10.3.1 +debug~mpi"
extends: .build_and_test_on_ruby
debug_par_gcc_10:
variables:
SPEC: "%gcc@10.3.1 +debug+mpi"
extends: .build_and_test_on_ruby
opt_ser_gcc_10:
variables:
SPEC: "%gcc@10.3.1 ~mpi"
extends: .build_and_test_on_ruby
opt_par_gcc_10:
variables:
SPEC: "%gcc@10.3.1"
extends: .build_and_test_on_ruby
opt_par_gcc_10_sundials:
variables:
SPEC: "%gcc@10.3.1 +sundials"
extends: .build_and_test_on_ruby
opt_par_gcc_10_petsc:
variables:
SPEC: "%gcc@10.3.1 +petsc ^petsc+mumps~superlu-dist"
extends: .build_and_test_on_ruby
opt_par_gcc_10_pumi:
variables:
SPEC: "%gcc@10.3.1 +pumi"
extends: .build_and_test_on_ruby
# Release
release_resource:
variables:
GIT_STRATEGY: none
extends: .on_ruby
stage: release_resource_and_report
script:
- echo ${ALLOC_NAME}
- export JOBID=$(squeue -h --name=${ALLOC_NAME} --format=%A)
- echo ${JOBID}
- ([[ -n "${JOBID}" ]] && scancel ${JOBID})
# Jobs report
report_job_success:
stage: release_resource_and_report
extends:
- .on_ruby
- .report_job_success
report_job_failure:
stage: release_resource_and_report
extends:
- .on_ruby
- .report_job_failure
include:
- local: .gitlab/configs/common.yml
- local: .gitlab/configs/ruby-config.yml
- local: .gitlab/configs/setup-build-and-test.yml
- local: .gitlab/configs/report-build-and-test.yml
+6 -4
View File
@@ -14,7 +14,7 @@
# locals
glob_err=${BASELINE_TEST}.err
base=${BASELINE_TEST}-${SYS_TYPE}
if [[ "${MACHINE_NAME}" == "dane" ]]; then
if [[ "${MACHINE_NAME}" == "ruby" ]]; then
base="${BASELINE_TEST}-${MACHINE_NAME}"
fi
base_diff=${base}.diff
@@ -31,10 +31,12 @@ cd tests
mkdir _${BASELINE_TEST} && cd _${BASELINE_TEST}
# run
if [[ "${MACHINE_NAME}" == "dane" ]]; then
srun --nodes=1 -t 60 --exclusive --reservation=ci ../runtest ../../mfem "${BASELINE_TEST} ${TPLS_DIR}"
if [[ "${MACHINE_NAME}" == "ruby" ]]; then
salloc --nodes=1 --exclusive --reservation=ci ../runtest ../../mfem "${BASELINE_TEST} ${TPLS_DIR}"
elif [[ ${MACHINE_NAME} == "corona" ]]; then
srun --nodes=1 -t 60 -p pbatch ../runtest ../../mfem "${BASELINE_TEST} ${TPLS_DIR}"
salloc --nodes=1 -t 60 -p pbatch ../runtest ../../mfem "${BASELINE_TEST} ${TPLS_DIR}"
elif [[ ${MACHINE_NAME} == "lassen" ]]; then
lalloc 1 -q pci ../runtest ../../mfem "${BASELINE_TEST} ${TPLS_DIR}"
else
echo "Unknown machine: MACHINE_NAME=$MACHINE_NAME"
exit 1
+2 -2
View File
@@ -11,7 +11,7 @@
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# There will be collision between corona and dane baselines.
# There will be collision between corona and ruby baselines.
# Once the corresponding files have been generated, we can switch to machine
# specific ref.
ARTIFACT_PATH=${CI_PROJECT_DIR}/${ARTIFACTS_DIR}/baseline-${SYS_TYPE}
@@ -21,7 +21,7 @@ PATCH_FILE=${ARTIFACT_PATH}.patch
FULL_FILE=${ARTIFACT_PATH}.out
DIFF_FILE=${ARTIFACT_PATH}.diff
# There will be collision between corona and dane baselines.
# There will be collision between corona and ruby baselines.
# Once the corresponding files have been generated, we can switch to machine
# specific ref.
SAVED_NAME=baseline-${SYS_TYPE}.saved
-118
View File
@@ -1,118 +0,0 @@
#!/bin/bash
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
function info_msg ()
{
echo "[Information:] ${1}"
}
function error_msg ()
{
echo "[Error:] ${1}"
}
# Perform a report while holding a lock file to prevent concurrency on
# the destination.
# Usage:
# locked_clone <report_function> <lock_name>
function locked_report ()
{
if ! command -v flock
then
error_msg "Required command 'flock' not found"
exit 1
fi
info_msg "Will report ${1} while holding a lock in ${2}"
( date; info_msg "Waiting to acquire lock on '${PWD}/${2}.lock' ..."
# try to get an exclusive lock on fd 9 (mfem-data.lock) repeating the
# try every 5 seconds; we may want to add a counter for the number of
# retries to interrupt a potential infinite loop
while ! flock -n 9; do sleep 5; done
date; info_msg "Acquired lock on '${PWD}/${2}.lock'"
report ${1}
err=$?
# sleep for a period to allow NFS to propagate the above changes;
# clearly, there is no guarantee that other NFS clients will see the
# changes even after the timeout
sleep 10
exit $err
) 9> ${2}.lock
}
function report ()
{
if [[ "${1}" == "SUCCESS" ]]
then
info_msg "All the ${MACHINE_NAME} jobs passed"
status_msg="The 'build-and-test' jobs on ${MACHINE_NAME} were SUCCESSFUL."
elif [[ "${1}" == "FAILURE" ]]
then
info_msg "At least one failure on ${MACHINE_NAME}"
status_msg="Some 'build-and-test' jobs on ${MACHINE_NAME} FAILED."
else
error_msg "Unknown status: ${1} ... aborting"
exit 1
fi
cd ${AUTOTEST_ROOT}/autotest || \
{ error_msg "Invalid 'autotest' dir: ${AUTOTEST_ROOT}/autotest"; exit 1; }
mkdir -p ${MACHINE_NAME}
rundir="${MACHINE_NAME}/$(date +%Y-%m-%d)-gitlab-ci-${CI_COMMIT_REF_SLUG}"
rundir=$(${CI_PROJECT_DIR}/.gitlab/scripts/safe_create_rundir $rundir)
printf "%s\n" "${status_msg}" \
"Pipeline URL:" "$CI_PIPELINE_URL" > ${rundir}/gitlab.err
msg="GitLab CI log for build-and-test on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
if [[ "${1}" == "FAILURE" ]]
then
# Create 'autotest-email.html' to indicate failure:
cp ${rundir}/gitlab.err ${rundir}/autotest-email.html
fi
# Note: in some cases, the content of AUTOTEST_COMMIT can be
# '${AUTOTEST_COMMIT}', so we need to treat that value as the default
# value of 'ON'.
if [[ "$AUTOTEST_COMMIT" == '${AUTOTEST_COMMIT}' ]]; then
AUTOTEST_COMMIT="ON"
fi
if [[ "$AUTOTEST_COMMIT" == "ON" || "$AUTOTEST_COMMIT" == "YES" ]]; then
git pull && \
git add ${rundir} && \
git commit -m "${msg}" && \
${CI_PROJECT_DIR}/.gitlab/scripts/git_try_to_push
else
for file in ${rundir}/*; do
echo "------------------------------"
echo "Content of '$file'"
echo "******************************"
cat $file
echo "******************************"
done
rm -rf ${rundir} || true
fi
}
export MACHINE_NAME=${CI_MACHINE}
info_msg "MACHINE_NAME is ${MACHINE_NAME}"
info_msg "AUTOTEST_ROOT is ${AUTOTEST_ROOT}"
info_msg "AUTOTEST=$AUTOTEST"
info_msg "AUTOTEST_COMMIT=$AUTOTEST_COMMIT"
cd ${AUTOTEST_ROOT} && locked_report ${1} autotest
+45
View File
@@ -0,0 +1,45 @@
#!/bin/bash
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
echo "Runs if there was at least one failure on ${MACHINE_NAME}"
cd ${AUTOTEST_ROOT}/autotest || \
{ echo "Invalid 'autotest' dir: ${AUTOTEST_ROOT}/autotest"; exit 1; }
mkdir -p ${MACHINE_NAME}
rundir="${MACHINE_NAME}/$(date +%Y-%m-%d)-gitlab-ci-${CI_COMMIT_REF_SLUG}"
rundir=$(${CI_PROJECT_DIR}/.gitlab/scripts/safe_create_rundir $rundir)
printf "%s\n" "Some 'build-and-test' jobs on ${MACHINE_NAME} FAILED." \
"Pipeline URL:" "$CI_PIPELINE_URL" > ${rundir}/gitlab.err
msg="GitLab CI log for build-and-test on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
# Create 'autotest-email.html' to indicate failure:
cp ${rundir}/gitlab.err ${rundir}/autotest-email.html
if [[ "$AUTOTEST_COMMIT" != "NO" ]]; then
git pull && \
git add ${rundir} && \
git commit -m "${msg}" && \
${CI_PROJECT_DIR}/.gitlab/scripts/git_try_to_push
else
for file in ${rundir}/*; do
echo "------------------------------"
echo "Content of '$file'"
echo "******************************"
cat $file
echo "******************************"
done
rm -rf ${rundir} || true
fi
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
echo "Can only run if all the ${MACHINE_NAME} jobs passed"
cd ${AUTOTEST_ROOT}/autotest || \
{ echo "Invalid 'autotest' dir: ${AUTOTEST_ROOT}/autotest"; exit 1; }
mkdir -p ${MACHINE_NAME}
rundir="${MACHINE_NAME}/$(date +%Y-%m-%d)-gitlab-ci-${CI_COMMIT_REF_SLUG}"
rundir=$(${CI_PROJECT_DIR}/.gitlab/scripts/safe_create_rundir $rundir)
printf "%s\n" "The 'build-and-test' jobs on ${MACHINE_NAME} were SUCCESSFUL." \
"Pipeline URL:" "$CI_PIPELINE_URL" > ${rundir}/gitlab.out
msg="GitLab CI log for build-and-test on ${MACHINE_NAME} ($(date +%Y-%m-%d))"
if [[ "$AUTOTEST_COMMIT" != "NO" ]]; then
git pull && \
git add ${rundir} && \
git commit -m "${msg}" && \
${CI_PROJECT_DIR}/.gitlab/scripts/git_try_to_push
else
for file in ${rundir}/*; do
echo "------------------------------"
echo "Content of '$file'"
echo "******************************"
cat $file
echo "******************************"
done
rm -rf ${rundir} || true
fi
-130
View File
@@ -1,130 +0,0 @@
# Copyright (c) 2010-2025, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# The template job to test whether a machine is up.
# Expects CI_MACHINE defined to machine name.
.machine-check:
stage: prerequisites
tags: [shell, oslic]
variables:
GIT_STRATEGY: none
script:
- |
if [[ $(jq '.[env.CI_MACHINE].total_nodes_up' /usr/global/tools/lorenz/data/loginnodeStatus) == 0 ]]
then
echo -e "\e[31mNo node available on ${CI_MACHINE}\e[0m"
false && \
curl --url "https://api.github.com/repos/${GITHUB_PROJECT_ORG}/${GITHUB_PROJECT_NAME}/statuses/${CI_COMMIT_SHA}" \
--header 'Content-Type: application/json' \
--header "authorization: Bearer ${GITHUB_TOKEN}" \
--data "{ \"state\": \"failure\", \"target_url\": \"${CI_PIPELINE_URL}\", \"description\": \"GitLab ${CI_MACHINE} down\", \"context\": \"ci/gitlab/${CI_MACHINE}\" }"
exit 1
fi
###
# Trigger a build-and-test pipeline for a machine.
# Comment the jobs for machines you dont need.
###
# One job to generate the job list for all the subpipelines
generate-job-lists:
stage: prerequisites
tags: [shell, oslic]
variables:
LOCAL_JOBS_PATH: ".gitlab/jobs"
script:
- |
echo "AUTOTEST=$AUTOTEST"
echo "AUTOTEST_COMMIT=$AUTOTEST_COMMIT"
echo "AUTOTEST_ROOT=$AUTOTEST_ROOT"
- |
cat ${LOCAL_JOBS_PATH}/dane.yml > dane-jobs.yml
if [[ ${AUTOTEST} == "ON" || ${AUTOTEST} == "YES" ]]
then
cat ${LOCAL_JOBS_PATH}/dane-reports.yml >> dane-jobs.yml
fi
- |
cat ${LOCAL_JOBS_PATH}/matrix.yml > matrix-jobs.yml
if [[ ${AUTOTEST} == "ON" || ${AUTOTEST} == "YES" ]]
then
cat ${LOCAL_JOBS_PATH}/matrix-reports.yml >> matrix-jobs.yml
fi
- |
cat ${LOCAL_JOBS_PATH}/tioga.yml > tioga-jobs.yml
if [[ ${AUTOTEST} == "ON" || ${AUTOTEST} == "YES" ]]
then
cat ${LOCAL_JOBS_PATH}/tioga-reports.yml >> tioga-jobs.yml
fi
artifacts:
paths:
- dane-jobs.yml
- matrix-jobs.yml
- tioga-jobs.yml
# DANE
dane-up-check:
variables:
CI_MACHINE: "dane"
extends: [.machine-check]
dane-build-and-test:
variables:
CI_MACHINE: "dane"
needs: [dane-up-check, generate-job-lists]
extends: [.build-and-test]
# DANE, MFEM Specific
dane-baseline:
stage: test-pipelines
variables:
# Explicitly pass down values that are not always propagated to child
# pipelines, e.g. when a variable is set in the "Settings -> CI" web
# interface (project variables).
# Note: in some cases, this does not work as expected, e.g. when the
# variable is not re-defined in the web interface; in such cases, the child
# pipeline gets a definition like '${AUTOTEST}', i.e. it behaves as if
# AUTOTEST is undefined, even though there is a default value in
# .gitlab-ci.yml.
AUTOTEST: "${AUTOTEST}"
AUTOTEST_COMMIT: "${AUTOTEST_COMMIT}"
trigger:
include: .gitlab/dane-baseline.yml
strategy: depend
forward:
pipeline_variables: true
needs: [dane-up-check]
# TIOGA
tioga-up-check:
variables:
CI_MACHINE: "tioga"
extends: [.machine-check]
tioga-build-and-test:
variables:
CI_MACHINE: "tioga"
needs: [tioga-up-check, generate-job-lists]
extends: [.build-and-test]
# Matrix
matrix-up-check:
variables:
CI_MACHINE: "matrix"
extends: [.machine-check]
matrix-build-and-test:
variables:
CI_MACHINE: "matrix"
needs: [matrix-up-check, generate-job-lists]
extends: [.build-and-test]
+29 -206
View File
@@ -8,44 +8,9 @@
https://mfem.org
Version 4.9.1 (development)
Version 4.8.1 (development)
===========================
- Policy for AI-assisted contribution added to CONTRIBUTING.md
Discretization improvements
---------------------------
- Replaced legacy simplex quadrature rules with symmetric positive-weight
rules for triangles (orders 0-25) and tetrahedra (orders 0-20). These
rules guarantee all-positive weights and interior quadrature points,
improving numerical stability. Higher orders fall back to Grundmann-Moller.
Triangle rules: Witherden & Vincent, Comput. Math. Appl. 69(10):1232-1241,
2015.
Tet rules (d=1-13): Witherden & Vincent (ibid).
Tet rules (d=14-20): Chuluunbaatar et al., Comput. Math. Appl. 124:89-97,
2022.
- Improved the gridfunction projection routines. Projections work for Scalar,
Vector and VectorFE, also NURBS versions. Optionally different types of
projections can be selected, default behaviour has not changed.
- Added methods to estimate function extremum using piecewise linear bounds +
recursive subdivision.
Meshing improvements
--------------------
- Improved support for 1D NURBS meshes with variable order, including using
the patches construct for 1D NURBS meshes.
New and updated examples and miniapps
-------------------------------------
- Electromagnetics/lorentz miniapp has been updated to leverage the ParticleSet
capability.
Version 4.9, released on Dec 11, 2025
=====================================
Starting with this version, MFEM requires a C++17 compiler.
Discretization improvements
@@ -54,199 +19,57 @@ Discretization improvements
nonlinear finite element operators, based on Enzyme or dual numbers AD at
quadrature points. These features are part of the new mfem::future namespace
and some of the API can change in the future. See the new dFEM minimal surface
miniapp in the miniapps/dfem/ directory for illustration of dFEM's use. Using
Enzyme for AD in MFEM is tested with clang v19 and requires clang/LLVM built
with plugin support. See INSTALL for more details.
miniapp in the miniapps/dfem/ directory for illustration of dFEM's use.
- Introduced initial support for particle methods in MFEM with new classes
Particle, ParticleSet and ParticleVector.
* Particle is a convenient interface for individual particle data.
* ParticleSet manages and stores particle data in a struct-of-arrays form,
carrying particle coordinates and IDs along with an arbitrary number of
Vector and integer data for each particle.
* ParticleVector is a Vector-derived container that stores vector data for an
arbitrary number of particles contiguously based on specified vdim/ordering.
See the new particle miniapps in miniapps/gslib/ and miniapps/fluids/navier/.
- Added a new miniapp and specialized AMG solver (AMGF) for optimization-based
contact mechanics. The miniapp solves large-scale frictionless contact using a
self-contained Interior Point (IP) solver, mortar-based contact constraints
provided by Tribol. The resulting linear systems are solved with the new AMGF
solver (see below). Benchmark examples include the two-block, ironing, and
beam-sphere problems. See the miniapps/contact/ directory.
- Added support for boundary integration to the hyperbolic framework. Two new
classes BdrHyperbolicDirichletIntegrator and BoundaryHyperbolicFlowIntegrator
have been introduced for implementation of weak Dirichlet boundary conditions
with a general flux or for the linear case respectively.
- Added a method to compute piecewise linear bounds on high-order functions on
tensor-product elements.
- Added support for interior face integration enabling DG methods in
ParMixedBilinearForm, ParNonlinearForm and ParBlockNonlinearForm.
- Using Enzyme for AD in MFEM is tested with clang v19 and requires clang/LLVM
built with plugin support. See INSTALL for more details.
- In the ParMoonolith integration, added support for variational resampling of
H1 vector fields.
- Introduced IMEX ODE solvers based on a split-operator framework. Added
examples ex41 and ex41p demonstrating IMEX DG/CG discretizations of the
convectiondiffusion equation, with ex41p using DG LOR preconditioning.
Meshing improvements
--------------------
- The TMOP kernel hierarchy has been restructured to reduce compilation time.
Most large kernels have been split into smaller specific kernels for each
metric. The directory structure has been updated with assemble, metrics, mult
and tools subdirectories. New kernel dispatch and specialization system has
also been integrated. Unit tests have been revised to ensure --all tests pass.
- Introduced NC-patch NURBS meshes, which are conforming element-wise but allow
for nonconforming patch topology. This new mesh format supports element
spacing formulas for refinement, as well as local refinement factors for a
subset of knot vectors.
- Added a new miniapp for interpolating a surface grid of points in 3D using a
smooth NURBS surface, that can then be sampled at arbitrary resolution while
staying close to the original geometry. See miniapps/nurbs/nurbs_surface.
- Parallel anisotropic refinement of hexahedral meshes is now supported,
provided that neighboring hexahedra are not refined in conflicting directions.
A new ParMesh method is added to check for such conflicts, before refinement.
- Added support for higher order meshes in (Par)Mesh::MakeSimplicial.
Linear and nonlinear solvers
----------------------------
- Added FilteredSolver: a base class for solvers with filtering. It handles
cases where a solver performs well except in small subspaces, by adding a
filtering step formulated as a subspace correction.
- Added AMGFSolver: a derived class of FilteredSolver, specialized for AMG with
Filtering (AMGF), providing robust preconditioning for linear systems arising
in constrained optimization problems such as frictionless contact.
Added 'GetResiduals' and 'GetFinalAbsResidualNorm' to 'HyprePCG',
'HypreGMRES', and 'HypreFGMRES' to get 'r' and '|r|_p'. Note that the latter
computes '|r|_p' from 'r' instead of returning a cached value like the
relative 'GetFinalResidualNorm'. These require Hypre >= 2.15.0.
Changed the default solver parameters for 'HyprePCG' to 'tol=1e-6' and
'max_iter=1000'. This matches the default parameters in Hypre 3.0.
Added various helper functions for querying/modifying Hypre solvers:
'HypreSmoother::GetType', 'HypreSmoother::GetSOROptions',
'HypreSmoother::GetPolyOptions', 'HypreSmoother::GetWindowParameters',
'HypreSmoother::IsOperatorSymmetric', 'HyprePCG::GetTol',
'HyprePCG::GetAbsTol', 'HyprePCG::GetMaxIter', 'HyprePCG::SetUseTwoNorm',
'HypreGMRES::GetTol', 'HypreGMRES::GetAbsTol', 'HypreGMRES::GetMaxIter',
'HypreGMRES::GetKDim', 'HypreFGMRES::GetTol', 'HypreFGMRES::GetMaxIter',
'HypreFGMRES::GetKDim', and 'HypreBoomerAMG::GetMaxIter'.
- Added support for higher order meshes in Mesh::MakeSimplicial and
ParMesh::MakeSimplicial.
GPU computing
-------------
- Added the 'gpu', 'raja-gpu', and 'ceed-gpu' backend aliases/shortcuts which
automatically select between CUDA or HIP.
- Added the option to enable GPU-aware MPI in MFEM using the environment
variable 'MFEM_GPU_AWARE_MPI' set to any value. Setting this environment
variable is an alternative to calling 'Device::SetGPUAwareMPI(true)'.
- Implemented a GPU-accelerated matrix-free AMR derefinement GridFunction update
operator. This supports mixed geometry meshes and variable order spaces, and
is the default derefinement operator constructed by FiniteElementSpace::Update
and ParFiniteElementSpace::Update. The operator requires the finite element
space to be nonconforming.
- The function Vector::SetSubVector(const Array<int> &, const real_t) now
executes on device if either the vector or the array have the device flag
set. This is most often used for setting constant essential boundary
conditions. A new function Vector::SetSubVectorHost has been added in cases
where host execution is always needed (e.g. when the DOFs array is small).
- Introduced MFEM_FOREACH_THREAD_DIRECT, which directly maps loop tasks to GPU
threads, assigning one task per thread.
- The function Vector::SetSubVector(const Array<int> &, const real_t) now
executes on device if either the vector or the array have the device flag
set. This is most often used for setting constant essential BCs. A new method,
SetSubVectorHost, has been added for cases where host execution is always
needed (e.g. when the DOFs array is small).
- Added GPU support in GradientGridFunction and InnerProduct Coefficient classes
by implementing their Project methods.
- Added new method: GridFunction::GetGradients, with GPU support, for computing
the gradients of a GridFunction on all elements.
- The CUDA-specific names used by some of the unit tests like 'cunit_tests' and
'pcunit_tests' were replaced by names using 'gpu' instead of 'c' (short for
CUDA) or 'cuda'. These tests automatically run the CUDA/HIP tests based on the
MFEM build configuration.
New and updated examples and miniapps
-------------------------------------
- Added the miniapps/fluids directory and moved the previous Navier and the new
incompressible Schrödinger flow miniapps into it.
- Introduced the new Incompressible Schrödinger Flow (ISF) miniapp, which models
inviscid fluid dynamics by solving the linear Schrödinger equation, leveraging
the hydrodynamical analogy to quantum mechanics.
- New particle-related miniapps:
* New transient Navier-Stokes fluid-particles solver NavierParticles in
miniapps/fluids/navier/navier_particles, for modeling tracer particles in
fluid flow, demonstrating use of the new ParticleSet class.
* New Navier miniapp, miniapps/fluids/navier/navier_bifurcation, showing the
use of NavierParticles in a 2D bifurcating channel flow.
* New FindPointsGSLIB miniapp, miniapps/gslib/particles_redist, showing
parallel-redistribution of particle data between MPI ranks.
* Particle visualization features in common/particles_extras for viewing
particle locations and trajectories (ParticleTrajectories) using GLVis.
- Added a new miniapp (meshing/mesh-bounding-boxes) that computes the bounding
boxes for each element of a given mesh, and the bounds on the determinant of
the Jacobian of the transformation.
- Added a new miniapp (tools/gridfunction-bounds) to compute piecewise linear
bounds on a given high-order grid function.
- Added a new miniapp (electromagnetics/lorentz) which computes the trajectory
of a charged particle, subject to Lorentz forces, in electrostatic and/or
magnetostatic fields as computed by the volta or tesla miniapps.
- Added miniapps to demonstrate an implementation of the absolute-value
l1-Jacobi preconditioners in partially assembled operators. This includes
L(1)-Jacobi preconditioners in partially assembled operators. This includes
Multigrid wrapper to demonstrate the effectiveness of these Jacobi-type
operators as smoothers. See the miniapps/diag-smoothers/ directory.
- Updated the mtop miniapp with a GPU enabled forward and adjoint solver for
isotropic linear elasticity.
Miscellaneous
-------------
- Introduced MFEM_FETCH_TPLS CMake option to enable downloading, configuring,
and building of TPLs alongside MFEM (currently supported TPLs are hypre,
METIS, and GSLIB).
- Added quadrature function support to the VisIt and Conduit data collections.
- Added access to the internal parallel matrix in Par(Mixed)BilinearForm and
related utility methods for elimination of BCs.
- FindPointsGSLIB has a new constructor that accepts the mesh object and
internally calls the Setup() method so users do not have to. The FreeData()
method has also been moved to the destructor so users do not need to manually
free-up the memory if the destructor is called before MPI_Finalize().
- Added parallel Address Sanitizer, serial and parallel Undefined Behavior
Sanitizer and serial Memory Sanitizer GitHub actions tests on Ubuntu.
operators as smoothers.
These miniapps can be found in `miniapps/diag-smoothers`.
API changes
-----------
- mfem::internal::tensor and mfem::internal::dual have been moved to
mfem::future::tensor and mfem::future::dual.
- API addition: in class `Operator`, added virtual functions: `AbsMult`, and
`AbsMultTranspose`; in class `Vector`, added `Abs` and `Pow`.
- API addition: in class Operator, added virtual functions: AbsMult, and
AbsMultTranspose; in class Vector, added Abs and Pow.
- ParBilinearForm::EliminateEssentialVDofsInRhs() has been deprecated in favor
of ParallelEliminateEssentialTDofsInRhs().
Miscellaneous
-------------
- Added the "gpu", "raja-gpu", and "ceed-gpu" backend aliases/shortcuts which
automatically select between CUDA or HIP.
- The CUDA-specific names used by some of the unit tests like 'cunit_tests' and
'pcunit_tests' were replaced by names using 'gpu' instead of 'c' (short for
CUDA) or 'cuda'. These tests automatically run the CUDA/HIP tests based on the
MFEM build configuration.
- Added the option to enable GPU-aware MPI in MFEM using the environment
variable 'MFEM_GPU_AWARE_MPI' set to any value. Setting this environment
variable is an alternative to calling 'Device::SetGPUAwareMPI(true)'.
- Added parallel Address Sanitizer, serial and parallel Undefined Behavior
Sanitizer and serial Memory Sanitizer GitHub actions tests on Ubuntu.
Version 4.8, released on Apr 9, 2025
====================================
+41 -98
View File
@@ -59,7 +59,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.9.1)
set(${PROJECT_NAME}_VERSION 4.8.1)
# Prohibit in-source build
if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
@@ -133,49 +133,33 @@ if (MFEM_USE_CUDA)
if (NOT CMAKE_CUDA_HOST_COMPILER)
set(CMAKE_CUDA_HOST_COMPILER ${CMAKE_CXX_COMPILER})
endif()
if (NOT CMAKE_CUDA_ARCHITECTURES)
# make CUDA_ARCH resemble the same form as CMAKE_CUDA_ARCHITECTURES
string(REPLACE "sm_" "" CUDA_ARCH_TMP "${CUDA_ARCH}")
string(REPLACE "," ";" CUDA_ARCH "${CUDA_ARCH_TMP}")
set(CMAKE_CUDA_ARCHITECTURES "${CUDA_ARCH}")
if (CMAKE_VERSION VERSION_LESS 3.18.0)
set(CUDA_FLAGS "-arch=${CUDA_ARCH} ${CUDA_FLAGS}")
elseif (NOT CMAKE_CUDA_ARCHITECTURES)
string(REGEX REPLACE "^sm_" "" ARCH_NUMBER "${CUDA_ARCH}")
if ("${CUDA_ARCH}" STREQUAL "sm_${ARCH_NUMBER}")
set(CMAKE_CUDA_ARCHITECTURES "${ARCH_NUMBER}")
else()
message(FATAL_ERROR "Unknown CUDA_ARCH: ${CUDA_ARCH}")
endif()
else()
set(CUDA_ARCH "CMAKE_CUDA_ARCHITECTURES: ${CMAKE_CUDA_ARCHITECTURES}")
endif()
message(STATUS "Using CUDA architecture: ${CUDA_ARCH}")
enable_language(CUDA)
if (CMAKE_VERSION VERSION_LESS 3.18.0)
# backup try to detect if this is clang or nvcc
if(CMAKE_CUDA_COMPILER MATCHES "nvcc$")
# nvcc
set(MFEM_CUDA_COMPILER_IS_NVCC ON)
set(CUDA_FLAGS "${CUDA_FLAGS} --expt-extended-lambda --expt-relaxed-constexpr")
if ("all" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}"
OR "native" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}"
OR "all-major" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}")
set(CUDA_FLAGS "-arch=${CMAKE_CUDA_ARCHITECTURES} ${CUDA_FLAGS}")
else()
# build -gencode sequence for multiple architectures
foreach(ENTRY IN LISTS CMAKE_CUDA_ARCHITECTURES)
set(CUDA_FLAGS
"-gencode arch=compute_${ENTRY},code=sm_${ENTRY} ${CUDA_FLAGS}")
endforeach()
endif()
else()
# build cuda-gpu-arch sequence for multiple architectures
# does not support all/all-major/native
foreach(ENTRY IN LISTS CMAKE_CUDA_ARCHITECTURES)
set(CUDA_FLAGS "-cuda-gpu-arch=sm_${ENTRY} ${CUDA_FLAGS}")
endforeach()
endif()
# backup try to detect if this is clang or nvcc
if(CMAKE_CUDA_COMPILER MATCHES "nvcc$")
# nvcc
set(MFEM_CUDA_COMPILER_IS_NVCC ON)
set(CUDA_FLAGS "${CUDA_FLAGS} --expt-extended-lambda --expt-relaxed-constexpr")
endif()
else()
# TODO: all, native, all-major require CMake 3.24+
# backport support for CMake 3.18 to 3.24
if (CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
# nvcc
set(MFEM_CUDA_COMPILER_IS_NVCC ON)
set(CUDA_FLAGS
"${CUDA_FLAGS} --expt-extended-lambda --expt-relaxed-constexpr")
endif()
if (CMAKE_CUDA_COMPILER_ID STREQUAL "NVIDIA")
# nvcc
set(MFEM_CUDA_COMPILER_IS_NVCC ON)
set(CUDA_FLAGS "${CUDA_FLAGS} --expt-extended-lambda --expt-relaxed-constexpr")
endif()
endif()
set(CMAKE_CUDA_STANDARD ${CMAKE_CXX_STANDARD} CACHE STRING
"CUDA standard to use.")
@@ -258,16 +242,10 @@ endif()
# AMD HIP
if (MFEM_USE_HIP)
if (NOT CMAKE_HIP_ARCHITECTURES)
if (HIP_ARCH)
set(CMAKE_HIP_ARCHITECTURES CACHE STRING "HIP targets to compile for" "${HIP_ARCH}")
set(GPU_TARGETS "${HIP_ARCH}" CACHE STRING "HIP targets to compile for" FORCE)
endif()
else()
set(HIP_ARCH CACHE STRING "HIP targets to compile for" "${CMAKE_HIP_ARCHITECTURES}")
set(GPU_TARGETS "${CMAKE_HIP_ARCHITECTURES}" CACHE STRING "HIP targets to compile for" FORCE)
if (HIP_ARCH)
message(STATUS "Using HIP architecture: ${HIP_ARCH}")
set(GPU_TARGETS "${HIP_ARCH}" CACHE STRING "HIP targets to compile for")
endif()
message(STATUS "Using HIP architecture: ${CMAKE_HIP_ARCHITECTURES}")
if (ROCM_PATH)
list(INSERT CMAKE_PREFIX_PATH 0 ${ROCM_PATH})
endif()
@@ -300,22 +278,6 @@ if (MFEM_USE_OPENMP OR MFEM_USE_LEGACY_OPENMP)
endif()
endif()
# Warn user if deprecated FETCH_TPLS is provided
if (DEFINED FETCH_TPLS)
message(STATUS "Setting MFEM_FETCH_TPLS to user-provided value of FETCH_TPLS (i.e., MFEM_FETCH_TPLS=${FETCH_TPLS})")
set (MFEM_FETCH_TPLS FETCH_TPLS)
message(DEPRECATION "The use of FETCH_TPLS is deprecated and will be removed in future verison. Please use MFEM_FETCH_TPLS instead.")
endif()
# Umpire (must be included before hypre, so hypre can use it if needed)
if (MFEM_USE_UMPIRE)
# umpire uses FindCUDA, which needs CMP0146=OLD in CMake >= 3.27
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.27.0)
cmake_policy(SET CMP0146 OLD)
endif()
find_package(UMPIRE REQUIRED)
endif()
# MPI -> hypre; PETSc (optional)
if (MFEM_USE_MPI)
find_package(MPI REQUIRED)
@@ -533,13 +495,14 @@ endif()
# RAJA
if (MFEM_USE_RAJA)
# RAJA uses FindCUDA, which needs CMP0146=OLD in CMake >= 3.27
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.27.0)
cmake_policy(SET CMP0146 OLD)
endif()
find_package(RAJA REQUIRED)
endif()
# UMPIRE
if (MFEM_USE_UMPIRE)
find_package(UMPIRE REQUIRED)
endif()
# GOOGLE-BENCHMARK
if (MFEM_USE_BENCHMARK)
find_package(Benchmark REQUIRED)
@@ -633,27 +596,18 @@ set(MFEM_TPLS OPENMP HYPRE LAPACK BLAS SuperLUDist STRUMPACK METIS SuiteSparse
NETCDF MPFR PUMI HIOP POSIXCLOCKS MFEMBacktrace ZLIB OCCA CEED RAJA UMPIRE
ADIOS2 MKL_CPARDISO MKL_PARDISO AMGX MAGMA CUSPARSE CUBLAS CALIPER CODIPACK
BENCHMARK PARELAG TRIBOL MPI_CXX HIP HIPBLAS HIPSPARSE MOONOLITH BLITZ
ALGOIM ENZYME CUDA::cudart)
ALGOIM ENZYME)
# Add all created targets and *_FOUND libraries in the variables TPL_TARGETS and
# TPL_LIBRARIES, respectively.
set(TPL_TARGETS)
# Add all *_FOUND libraries in the variable TPL_LIBRARIES.
set(TPL_LIBRARIES "")
set(TPL_INCLUDE_DIRS "")
foreach(TPL IN LISTS MFEM_TPLS)
if (${TPL}_FOUND OR TARGET ${TPL})
if (${TPL}_FOUND)
message(STATUS "MFEM: using package ${TPL}")
if (TARGET ${TPL})
list(APPEND TPL_TARGETS ${TPL})
else()
list(APPEND TPL_LIBRARIES ${${TPL}_LIBRARIES})
list(APPEND TPL_INCLUDE_DIRS ${${TPL}_INCLUDE_DIRS})
endif()
list(APPEND TPL_LIBRARIES ${${TPL}_LIBRARIES})
list(APPEND TPL_INCLUDE_DIRS ${${TPL}_INCLUDE_DIRS})
endif()
endforeach(TPL)
# reverse to remove the first instance of entries in TPL_LIBRARIES
# so later duplicates are kept (for dependency ordering)
list(REVERSE TPL_LIBRARIES)
list(REMOVE_DUPLICATES TPL_LIBRARIES)
list(REVERSE TPL_LIBRARIES)
@@ -725,12 +679,8 @@ set(MFEM_INSTALL_DIR ${CMAKE_INSTALL_PREFIX})
# Declaring the library
mfem_add_library(mfem ${SOURCES} ${HEADERS} ${MASTER_HEADERS})
target_compile_features(mfem PUBLIC cxx_std_${CMAKE_CXX_STANDARD})
# message(STATUS "TPL_LIBRARIES = ${TPL_LIBRARIES}")
target_link_libraries(mfem PUBLIC ${TPL_LIBRARIES} ${TPL_TARGETS})
if (TPL_TARGETS)
add_dependencies(mfem ${TPL_TARGETS})
endif()
target_link_libraries(mfem PUBLIC ${TPL_LIBRARIES})
if (MINGW)
target_link_libraries(mfem PRIVATE ws2_32)
endif()
@@ -872,12 +822,11 @@ add_dependencies(exec
# - https://cmake.org/Bug/view.php?id=8438
# Add a target to copy the mfem data directory to the build directory
# Implementable as a single copy_directory_if_different command w/ CMake >= 3.26
file(GLOB DATA_FILES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/data/*)
add_custom_target(copy_data
COMMAND ${CMAKE_COMMAND} -E make_directory data
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${DATA_FILES} data
COMMENT "Syncing the data directory ...")
add_custom_command(OUTPUT data_is_copied
COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_SOURCE_DIR}/data data
COMMAND ${CMAKE_COMMAND} -E touch data_is_copied
COMMENT "Copying the data directory ...")
add_custom_target(copy_data DEPENDS data_is_copied)
# Add 'copy_data' as a prerequisite for all executables, if the source and the
# build directories are not the same.
if (NOT ("${PROJECT_SOURCE_DIR}" STREQUAL "${PROJECT_BINARY_DIR}"))
@@ -1009,15 +958,9 @@ install(FILES
install(EXPORT ${PROJECT_NAME_UC}Targets
DESTINATION ${INSTALL_CMAKE_DIR})
# Install the data directory if present, i.e. if the copy_data target is built
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/data
DESTINATION ${MFEM_INSTALL_DIR} OPTIONAL)
#-------------------------------------------------------------------------------
# Create 'config.mk' from 'config.mk.in' for the build and install locations and
# define install rules for 'config.mk' and 'test.mk'
#-------------------------------------------------------------------------------
if (MFEM_USE_CUDA OR MFEM_USE_HIP)
option(MFEM_EXPORT_GPU_CONFIG "Export config.mk for GPU-enabled downstream packages" ON)
endif()
mfem_export_mk_files()
+1 -16
View File
@@ -24,14 +24,6 @@ must be made under this license.
Note also that MFEM has a [Code of Conduct](CODE_OF_CONDUCT.md). By participating
in the MFEM community, you agree to abide by its rules.
## AI Policy
- Use of AI code generation in MFEM is allowed but must be disclosed, e.g. by
selecting the `AI-assisted` label on the PR.
- By submitting a PR, the author acknowledges that they have reviewed and
understand the changes they are proposing.
- PR authors are still responsible for correctness, licensing, and attribution
of all changes.
If you plan on contributing to MFEM, consider reviewing the
[issue tracker](https://github.com/mfem/mfem/issues) first to check if a thread
already exists for your desired feature or the bug you ran into. Use a pull
@@ -137,10 +129,6 @@ The MFEM source code has the following structure:
│ ├── moonolith
│ ├── qinterp
│ └── tmop
│ | ├── assemble
│ | ├── metrics
│ | ├── mult
│ | └── tools
├── general
├── linalg
│ ├── batched
@@ -151,19 +139,16 @@ The MFEM source code has the following structure:
│ ├── adjoint
│ ├── autodiff
│ ├── common
│ ├── contact
│ ├── dfem
│ ├── dpg
│ ├── electromagnetics
│ ├── fluids
│ │ ├── navier
│ │ └── schrodinger-flow
│ ├── gslib
│ ├── hdiv-linear-solver
│ ├── hooke
│ ├── meshing
│ ├── mtop
│ ├── multidomain
│ ├── navier
│ ├── nurbs
│ ├── parelag
│ ├── performance
+2 -22
View File
@@ -121,11 +121,6 @@ Parallel build:
make -j 4
(For METIS 5, see https://mfem.org/building/#parallel-build-using-metis-5)
Parallel build with fetching of hypre and METIS:
mkdir <mfem-buil-dir> ; cd <mfem-build-dir>
cmake <mfem-source-dir> -DMFEM_USE_MPI=YES -DMFEM_FETCH_TPLS=YES
make -j 4
CUDA build:
(this build requires CMake 3.17 or newer)
mkdir <mfem-build-dir> ; cd <mfem-build-dir>
@@ -668,7 +663,6 @@ The specific libraries and their options are:
- OpenMP (optional), usually part of compiler, used when either MFEM_USE_OPENMP
or MFEM_USE_LEGACY_OPENMP is set to YES.
Options: OPENMP_OPT, OPENMP_LIB.
Versions: OpenMP >= 3.1 when MFEM_USE_OPENMP=YES.
- High-resolution POSIX clocks: when using MFEM_TIMER_TYPE = 2, it may be
necessary to link with a system library (e.g. librt.so).
@@ -725,9 +719,7 @@ The specific libraries and their options are:
URL: https://ginkgo-project.github.io
Options: GINKGO_OPT, GINKGO_LIB, GINKGO_DIR, GINKGO_BUILD_TYPE (Release or
Debug).
Versions: Ginkgo >= 1.9.0. When building Ginkgo with distributed support, a
recent version of the "develop" branch is required (1.11 as defined
in include/ginkgo/config.hpp).
Versions: Ginkgo >= 1.9.0.
- AmgX (optional), used when MFEM_USE_AMGX = YES.
URL: https://github.com/NVIDIA/AMGX
@@ -850,7 +842,6 @@ The specific libraries and their options are:
- HIP (optional), used when MFEM_USE_HIP = YES.
URL: https://rocmdocs.amd.com
Options: HIP_CXX, HIP_ARCH, HIP_OPT, HIP_LIB.
Versions: ROCm >= 5.6.1.
- OCCA (optional), used when MFEM_USE_OCCA = YES.
URL: https://libocca.org
@@ -861,7 +852,7 @@ The specific libraries and their options are:
URL: https://github.com/CEED/libCEED
https://ceed.exascaleproject.org/libceed
Options: CEED_DIR, CEED_OPT, CEED_LIB.
Versions: libCEED >= 0.12.0.
Versions: libCEED >= 0.12.
- RAJA (optional), used when MFEM_USE_RAJA = YES.
Beginning with MFEM v4.5.1, only RAJA v2022.10.3+ is supported.
@@ -1083,10 +1074,6 @@ The following options are CMake specific:
MFEM_ENABLE_TESTING - Enable the ctest framework for testing.
MFEM_ENABLE_EXAMPLES - Build all of the examples by default.
MFEM_ENABLE_MINIAPPS - Build all of the miniapps by default.
MFEM_FETCH_TPLS - Enable fetching of all supported third-party libraries.
MFEM_FETCH_GSLIB - Enable fetching of gslib.
MFEM_FETCH_HYPRE - Enable fetching of hypre.
MFEM_FETCH_METIS - Enable fetching of metis.
External libraries (CMake):
---------------------------
@@ -1148,13 +1135,6 @@ The following built-in CMake packages are also used:
set the <LIBNAME>_LIBRARIES option directly; the configuration option
<LIBNAME>_DIR is not supported.
The MFEM CMake build system also provides fetching (automated building) for the
packages/libraries listed below. Note that when fetching is enabled, any related
auto-detection functionality is disabled.
- GSLIB
- HYPRE
- METIS
Building without GNU make or CMake
==================================
-29
View File
@@ -84,35 +84,6 @@ set_and_check(MFEM_LIBRARY_DIR "@PACKAGE_LIB_INSTALL_DIR@")
check_required_components(MFEM)
include(CMakeFindDependencyMacro)
if (MFEM_USE_CUDA)
# required for projects linking to MFEM+CUDA, even if they don't use CUDA directly
find_dependency(CUDAToolkit)
endif (MFEM_USE_CUDA)
if (MFEM_USE_HIP)
# hip/rocm uses the modern MFEM way of linking to targets, need to find dependencies
find_dependency(HIP)
find_dependency(HIPBLAS)
find_dependency(HIPSPARSE)
if (MFEM_USE_MPI)
# assume HYPRE uses HIP
# alternatively could check HYPRE_USING_HIP
find_dependency(rocsparse)
find_dependency(rocrand)
find_dependency(rocsolver)
endif (MFEM_USE_MPI)
endif (MFEM_USE_HIP)
if (MFEM_USE_RAJA)
find_dependency(RAJA)
endif()
if (MFEM_USE_UMPIRE)
find_dependency(umpire)
endif()
if (NOT TARGET mfem)
include(${CMAKE_CURRENT_LIST_DIR}/MFEMTargets.cmake)
endif (NOT TARGET mfem)
+1 -38
View File
@@ -9,47 +9,10 @@
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Defines the following variables if fetching of TPLs is disabled (default):
# Defines the following variables:
# - GSLIB_FOUND
# - GSLIB_LIBRARIES
# - GSLIB_INCLUDE_DIRS
# otherwise, the following are defined:
# - GSLIB (imported library target)
if (MFEM_FETCH_GSLIB OR MFEM_FETCH_TPLS)
enable_language(C)
string(TOUPPER "${CMAKE_BUILD_TYPE}" BUILD_TYPE)
set(GSLIB_FETCH_VERSION 1.0.9)
set(GSLIB_C_FLAGS ${CMAKE_C_FLAGS_${BUILD_TYPE}})
if (CMAKE_C_FLAGS)
set(GSLIB_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_C_FLAGS_${BUILD_TYPE}}")
endif()
if (BUILD_SHARED_LIBS)
set(GSLIB_C_FLAGS "${GSLIB_C_FLAGS} -fPIC")
endif()
add_library(GSLIB STATIC IMPORTED)
# define external project and create future include directory so it is present
# to pass CMake checks at end of MFEM configuration step
message(STATUS "Will fetch GSLIB ${GSLIB_FETCH_VERSION} to be built with ${GSLIB_C_FLAGS}")
set(PREFIX ${CMAKE_BINARY_DIR}/fetch/gslib)
include(ExternalProject)
ExternalProject_Add(gslib
GIT_REPOSITORY https://github.com/Nek5000/gslib
GIT_TAG v${GSLIB_FETCH_VERSION}
GIT_SHALLOW TRUE
UPDATE_DISCONNECTED TRUE
PREFIX ${PREFIX}
CONFIGURE_COMMAND ""
BUILD_COMMAND cd ${PREFIX}/src/gslib && $(MAKE) clean && $(MAKE) DESTDIR=${PREFIX} MPI=$<BOOL:${MFEM_USE_MPI}> "CFLAGS= ${GSLIB_C_FLAGS}"
INSTALL_COMMAND "")
file(MAKE_DIRECTORY ${PREFIX}/include)
# set imported library target properties
add_dependencies(GSLIB gslib)
set_target_properties(GSLIB PROPERTIES
IMPORTED_LOCATION ${PREFIX}/lib/libgs.a
INTERFACE_INCLUDE_DIRECTORIES ${PREFIX}/include)
return()
endif()
include(MfemCmakeUtilities)
mfem_find_package(GSLIB GSLIB GSLIB_DIR "include" gslib.h "lib" gs
+3 -97
View File
@@ -9,25 +9,21 @@
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Defines the following variables if fetching of TPLs is disabled (default):
# Defines the following variables:
# - HYPRE_FOUND
# - HYPRE_LIBRARIES
# - HYPRE_INCLUDE_DIRS
# - HYPRE_VERSION
# - HYPRE_USING_CUDA (internal)
# - HYPRE_USING_HIP (internal)
# otherwise, the following are defined:
# - HYPRE (imported library target)
# - HYPRE_VERSION (cache variable)
if (HYPRE_FOUND OR TARGET HYPRE)
if (HYPRE_FOUND)
if (HYPRE_USING_CUDA)
find_package(CUDAToolkit REQUIRED)
endif()
if (HYPRE_USING_HIP)
find_package(rocsparse REQUIRED)
find_package(rocrand REQUIRED)
find_package(rocsolver REQUIRED)
endif()
if (HYPRE_LIBRARIES AND HYPRE_INCLUDE_DIRS AND HYPRE_VERSION)
find_package_handle_standard_args(HYPRE
@@ -37,95 +33,6 @@ if (HYPRE_FOUND OR TARGET HYPRE)
endif()
endif()
if (MFEM_FETCH_HYPRE OR MFEM_FETCH_TPLS)
set(HYPRE_FETCH_VERSION 2.33.0)
set(HYPRE_FETCH_TAG "v${HYPRE_FETCH_VERSION}" CACHE STRING "Tag, branch, or commit for HYPRE")
add_library(HYPRE STATIC IMPORTED)
# set options and associated dependencies
set(HYPRE_CMAKE_OPTIONS "")
list(APPEND HYPRE_CMAKE_OPTIONS -DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE})
# collect all HYPRE_ENABLE variables and pass them to hypre, assuming they are BOOL.
get_cmake_property(all_vars VARIABLES)
foreach(var ${all_vars})
if(var MATCHES "^HYPRE_ENABLE")
list(APPEND HYPRE_CMAKE_OPTIONS "-D${var}:BOOL=${${var}}")
endif()
endforeach()
# process all MFEM_USE variables that impact hypre
if (MFEM_USE_CUDA)
list(APPEND HYPRE_CMAKE_OPTIONS -DHYPRE_ENABLE_CUDA:BOOL=ON -DCMAKE_CUDA_ARCHITECTURES:STRING=${CMAKE_CUDA_ARCHITECTURES})
find_package(CUDAToolkit REQUIRED)
target_link_libraries(HYPRE INTERFACE CUDA::cusparse CUDA::curand CUDA::cublas)
elseif (MFEM_USE_HIP)
list(APPEND HYPRE_CMAKE_OPTIONS -DHYPRE_ENABLE_HIP:BOOL=ON)
find_package(rocsparse REQUIRED)
find_package(rocrand REQUIRED)
target_link_libraries(HYPRE INTERFACE rocsparse rocrand)
endif()
if (MFEM_USE_CUDA OR MFEM_USE_HIP)
if (MFEM_USE_UMPIRE)
if (EXISTS ${umpire_DIR})
list(APPEND HYPRE_CMAKE_OPTIONS -DHYPRE_ENABLE_UMPIRE:BOOL=ON -Dumpire_DIR:PATH=${umpire_DIR})
else()
message(FATAL_ERROR "MFEM_USE_UMPIRE=ON, however umpire_DIR isn't visible to HYPRE")
endif()
else()
list(APPEND HYPRE_CMAKE_OPTIONS -DHYPRE_ENABLE_UMPIRE:BOOL=OFF)
message(WARNING
"================================================================================
Umpire is disabled while building HYPRE with GPU support.
This is not recommended for performance reasons!
Consider enabling Umpire with -DMFEM_USE_UMPIRE=ON and providing -DUMPIRE_DIR.
================================================================================")
endif()
endif()
if (MFEM_USE_SINGLE)
list(APPEND HYPRE_CMAKE_OPTIONS -DHYPRE_ENABLE_SINGLE:BOOL=ON)
endif()
# define external project and create future include directory so it is present
# to pass CMake checks at end of MFEM configuration step
message(STATUS "Will fetch HYPRE ${HYPRE_FETCH_TAG} to be built with ${HYPRE_CMAKE_OPTIONS}")
set(HYPRE_INSTALL ${CMAKE_BINARY_DIR}/fetch/hypre)
include(ExternalProject)
ExternalProject_Add(hypre
GIT_REPOSITORY https://github.com/hypre-space/hypre.git
GIT_TAG ${HYPRE_FETCH_TAG}
GIT_SHALLOW TRUE
GIT_PROGRESS TRUE
UPDATE_DISCONNECTED TRUE
SOURCE_SUBDIR src
PREFIX ${HYPRE_INSTALL}
BUILD_COMMAND ${CMAKE_COMMAND} --build . -- -j${CMAKE_BUILD_PARALLEL_LEVEL}
CMAKE_CACHE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=${HYPRE_INSTALL} -DCMAKE_INSTALL_LIBDIR:PATH=lib ${HYPRE_CMAKE_OPTIONS})
file(MAKE_DIRECTORY ${HYPRE_INSTALL}/include)
# set imported library target properties
add_dependencies(HYPRE hypre)
set_target_properties(HYPRE PROPERTIES
IMPORTED_LOCATION ${HYPRE_INSTALL}/lib/libHYPRE.a
INTERFACE_INCLUDE_DIRECTORIES ${HYPRE_INSTALL}/include)
# convert HYPRE version to integer
if (HYPRE_FETCH_TAG MATCHES "^v?([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
# Exact release tag X.Y.Z
string(REGEX MATCHALL "[0-9]+" HYPRE_SPLIT_VERSION "${HYPRE_FETCH_TAG}")
elseif (HYPRE_FETCH_VERSION MATCHES "([0-9]+)\\.([0-9]+)(\\.([0-9]+))?")
string(REGEX MATCHALL "[0-9]+" HYPRE_SPLIT_VERSION "${HYPRE_FETCH_VERSION}")
else (NOT DEFINED HYPRE_VERSION)
message(FATAL_ERROR "Unable to find HYPRE release version. Please provide it via -DHYPRE_VERSION")
endif()
if (HYPRE_SPLIT_VERSION AND NOT DEFINED HYPRE_VERSION)
list(GET HYPRE_SPLIT_VERSION 0 HYPRE_MAJOR_VERSION)
list(GET HYPRE_SPLIT_VERSION 1 HYPRE_MINOR_VERSION)
if (HYPRE_SPLIT_VERSION GREATER 2)
list(GET HYPRE_SPLIT_VERSION 2 HYPRE_PATCH_VERSION)
else()
set(HYPRE_PATCH_VERSION 0)
endif()
math(EXPR HYPRE_VERSION "10000*${HYPRE_MAJOR_VERSION} + 100*${HYPRE_MINOR_VERSION} + ${HYPRE_PATCH_VERSION}")
set(HYPRE_VERSION ${HYPRE_VERSION} CACHE STRING "HYPRE version." FORCE)
endif()
return()
endif()
include(MfemCmakeUtilities)
mfem_find_package(HYPRE HYPRE HYPRE_DIR "include" "HYPRE.h" "lib" "HYPRE"
"Paths to headers required by HYPRE." "Libraries required by HYPRE."
@@ -190,8 +97,7 @@ endif()
if (HYPRE_FOUND AND HYPRE_USING_HIP)
find_package(rocsparse REQUIRED)
find_package(rocrand REQUIRED)
find_package(rocsolver REQUIRED)
list(APPEND HYPRE_LIBRARIES ${rocsparse_LIBRARIES} ${rocrand_LIBRARIES} roc::rocsolver roc::rocblas)
list(APPEND HYPRE_LIBRARIES ${rocsparse_LIBRARIES} ${rocrand_LIBRARIES})
set(HYPRE_LIBRARIES ${HYPRE_LIBRARIES} CACHE STRING
"HYPRE libraries + dependencies." FORCE)
message(STATUS "Updated HYPRE_LIBRARIES: ${HYPRE_LIBRARIES}")
+1 -30
View File
@@ -9,39 +9,10 @@
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Defines the following variables if fetching of TPLs is disabled (default):
# Defines the following variables:
# - METIS_FOUND
# - METIS_LIBRARIES
# - METIS_INCLUDE_DIRS
# - METIS_VERSION_5
# otherwise, the following are defined:
# - METIS (imported library target)
# - METIS_VERSION_5 (cache variable)
if (MFEM_FETCH_METIS OR MFEM_FETCH_TPLS)
set(METIS_FETCH_VERSION 4.0.3)
add_library(METIS STATIC IMPORTED)
# define external project
message(STATUS "Will fetch METIS ${METIS_FETCH_VERSION} to be built with default options")
set(PREFIX ${CMAKE_BINARY_DIR}/fetch/metis)
include(ExternalProject)
ExternalProject_Add(metis
GIT_REPOSITORY https://github.com/mfem/tpls
GIT_TAG b60352fbe9675d374b00828055e55be4584c7995 # tag from 1/16/25
GIT_SHALLOW TRUE
UPDATE_DISCONNECTED TRUE
PREFIX ${PREFIX}
CONFIGURE_COMMAND tar -xzf ../metis/metis-${METIS_FETCH_VERSION}-mac.tgz --strip=1
BUILD_COMMAND $(MAKE) COPTIONS=-Wno-incompatible-pointer-types
INSTALL_COMMAND mkdir -p ${PREFIX}/lib && cp libmetis.a ${PREFIX}/lib/)
# set imported library target properties
add_dependencies(METIS metis)
set_target_properties(METIS PROPERTIES
IMPORTED_LOCATION ${PREFIX}/lib/libmetis.a)
# set cache variables that would otherwise be set after mfem_find_package call
set(METIS_VERSION_5 FALSE CACHE BOOL "Is METIS version 5?")
return()
endif()
include(MfemCmakeUtilities)
mfem_find_package(METIS METIS METIS_DIR "include;Lib" "metis.h"
+3 -3
View File
@@ -14,12 +14,12 @@
# - UMPIRE_LIBRARIES
# - UMPIRE_INCLUDE_DIRS
if (NOT umpire_ROOT AND UMPIRE_DIR)
set(umpire_ROOT ${UMPIRE_DIR})
if (NOT umpire_DIR AND UMPIRE_DIR)
set(umpire_DIR ${UMPIRE_DIR}/lib/cmake/umpire)
endif()
message(STATUS "Looking for UMPIRE ...")
message(STATUS " in UMPIRE_DIR = ${UMPIRE_DIR}")
message(STATUS " umpire_ROOT = ${umpire_ROOT}")
message(STATUS " umpire_DIR = ${umpire_DIR}")
find_package(umpire CONFIG)
set(UMPIRE_FOUND ${umpire_FOUND})
set(UMPIRE_LIBRARIES "umpire")
+18 -92
View File
@@ -701,6 +701,7 @@ endfunction(mfem_find_library)
# Extract compile and link options needed by the given target.
#
function(mfem_get_target_options Target CompileOptsVar LinkOptsVar)
if (NOT TARGET ${Target})
return()
endif()
@@ -717,7 +718,7 @@ function(mfem_get_target_options Target CompileOptsVar LinkOptsVar)
get_target_property(IsImported ${tgt} IMPORTED)
# message(STATUS "${tgt}[IMPORTED]: ${IsImported}")
# Generally, the possible target types are: STATIC_LIBRARY, MODULE_LIBRARY,
# SHARED_LIBRARY, INTERFACE_LIBRARY, UNKNOWN_LIBRARY, EXECUTABLE.
# SHARED_LIBRARY, INTERFACE_LIBRARY, EXECUTABLE.
get_target_property(type ${tgt} TYPE)
# message(STATUS "${tgt}[TYPE]: ${type}")
unset(ImportConfig)
@@ -765,7 +766,7 @@ function(mfem_get_target_options Target CompileOptsVar LinkOptsVar)
else()
message(STATUS " *** Warning: [${tgt}] LOCATION not defined!")
endif()
elseif ("${type}" STREQUAL "SHARED_LIBRARY" OR "${type}" STREQUAL "UNKNOWN_LIBRARY")
elseif ("${type}" STREQUAL "SHARED_LIBRARY")
get_target_property(Location ${tgt} LOCATION)
if (Location)
get_filename_component(Dir ${Location} DIRECTORY)
@@ -798,12 +799,7 @@ function(mfem_get_target_options Target CompileOptsVar LinkOptsVar)
# message(STATUS "Lib = ${Lib}")
# Filter-out generator expressions
if (NOT ("${Lib}" MATCHES "^\\$"))
if(NOT ("${Lib}" STREQUAL "dl"))
list(APPEND LinkOpts "${Lib}")
else()
# for some reason libdl doesn't include the "-l"
list(APPEND LinkOpts "-ldl")
endif()
list(APPEND LinkOpts "${Lib}")
endif()
else()
mfem_get_target_options(${Lib} COpts LOpts)
@@ -892,18 +888,9 @@ function(mfem_export_mk_files)
set(${var} NO)
endif()
endforeach()
if (MFEM_USE_CUDA AND MFEM_EXPORT_GPU_CONFIG)
set(MFEM_CXX ${CMAKE_CUDA_COMPILER})
if(MFEM_CUDA_COMPILER_IS_NVCC)
set(MFEM_HOST_CXX ${CMAKE_CUDA_HOST_COMPILER})
else()
set(MFEM_HOST_CXX ${CMAKE_CXX_COMPILER})
endif()
else()
# mfem doesn't use enable_language(HIP)
set(MFEM_CXX ${CMAKE_CXX_COMPILER})
set(MFEM_HOST_CXX ${CMAKE_CXX_COMPILER})
endif()
# TODO: Add support for MFEM_USE_CUDA=YES
set(MFEM_CXX ${CMAKE_CXX_COMPILER})
set(MFEM_HOST_CXX ${MFEM_CXX})
set(MFEM_CPPFLAGS "")
get_target_property(cxx_std mfem CXX_STANDARD)
# For now, we ignore the setting of the CXX_EXTENSIONS property. If this
@@ -913,50 +900,6 @@ function(mfem_export_mk_files)
string(STRIP
"${cxx_std_flag} ${CMAKE_CXX_FLAGS_${BUILD_TYPE}} ${CMAKE_CXX_FLAGS}"
MFEM_CXXFLAGS)
if(MFEM_EXPORT_GPU_CONFIG)
if (MFEM_USE_CUDA)
set(MFEM_CXXFLAGS "${MFEM_CXXFLAGS} ${CMAKE_CUDA_FLAGS}")
if (MFEM_CUDA_COMPILER_IS_NVCC)
set(MFEM_CXXFLAGS "-x=cu ${MFEM_CXXFLAGS} -ccbin ${CMAKE_CXX_COMPILER} --forward-unknown-to-host-compiler")
# The following intentionally hides CUDA deprecation warnings
foreach(ENTRY IN LISTS CUDAToolkit_INCLUDE_DIRS)
set(MFEM_CXXFLAGS "${MFEM_CXXFLAGS} -isystem ${ENTRY}")
endforeach()
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18.0)
# architecture flags not part of CMAKE_CUDA_FLAGS
if ("all" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}"
OR "native" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}"
OR "all-major" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}")
set(MFEM_CXXFLAGS "${MFEM_CXXFLAGS} -arch=${CMAKE_CUDA_ARCHITECTURES}")
else()
foreach (ENTRY IN LISTS CMAKE_CUDA_ARCHITECTURES)
set(MFEM_CXXFLAGS
"${MFEM_CXXFLAGS} -gencode arch=compute_${ENTRY},code=sm_${ENTRY}")
endforeach()
endif()
endif()
else()
set(MFEM_CXXFLAGS "${MFEM_CXXFLAGS} -xcuda --cuda-path=${CUDAToolkit_LIBRARY_ROOT}")
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.18.0)
# architecture flags not part of CMAKE_CUDA_FLAGS
if ("all" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}"
OR "native" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}"
OR "all-major" STREQUAL "${CMAKE_CUDA_ARCHITECTURES}")
# TODO: not supported
else()
foreach(ENTRY IN LISTS CMAKE_CUDA_ARCHITECTURES)
set(MFEM_CXXFLAGS "-cuda-gpu-arch=sm_${ENTRY} ${MFEM_CXXFLAGS}")
endforeach()
endif()
endif()
endif()
elseif (MFEM_USE_HIP)
set(MFEM_CXXFLAGS "${MFEM_CXXFLAGS} -xhip")
foreach(ENTRY IN LISTS CMAKE_HIP_ARCHITECTURES)
set(MFEM_CXXFLAGS "--offload-arch=${ENTRY} ${MFEM_CXXFLAGS}")
endforeach()
endif()
endif()
set(MFEM_TPLFLAGS "")
foreach(dir ${TPL_INCLUDE_DIRS})
set(MFEM_TPLFLAGS "${MFEM_TPLFLAGS} -I${dir}")
@@ -987,26 +930,14 @@ function(mfem_export_mk_files)
set(MFEM_SHARED NO)
set(MFEM_STATIC YES)
endif()
if (MFEM_USE_CUDA)
set(MFEM_EXT_LIBS "${MFEM_EXT_LIBS} -lcudart")
endif()
set(MFEM_BUILD_TAG "${CMAKE_SYSTEM}")
set(MFEM_PREFIX "${CMAKE_INSTALL_PREFIX}")
# For the next 4 variables, these are the values for the build-tree version of
# For the next 4 variable, these are the values for the build-tree version of
# 'config.mk'
set(MFEM_INC_DIR "${PROJECT_BINARY_DIR}")
set(MFEM_LIB_DIR "${PROJECT_BINARY_DIR}")
set(MFEM_TEST_MK "${PROJECT_SOURCE_DIR}/config/test.mk")
set(MFEM_CONFIG_EXTRA "MFEM_BUILD_DIR ?= ${PROJECT_BINARY_DIR}")
if (MFEM_USE_CUDA AND MFEM_EXPORT_GPU_CONFIG)
if (MFEM_CUDA_COMPILER_IS_NVCC)
set(MFEM_XLINKER "-Xlinker=")
else()
set(MFEM_XLINKER "${CMAKE_CUDA_LINKER_WRAPPER_FLAG}")
endif()
else()
set(MFEM_XLINKER "${CMAKE_CXX_LINKER_WRAPPER_FLAG}")
endif()
set(MFEM_MPIEXEC ${MPIEXEC})
if (NOT MFEM_MPIEXEC)
set(MFEM_MPIEXEC "mpirun")
@@ -1054,21 +985,16 @@ function(mfem_export_mk_files)
# handle interfaces (e.g., SCOREC::apf)
if ("${lib}" MATCHES "SCOREC::.*" OR "${lib}" MATCHES "Ginkgo::.*" OR "${lib}" MATCHES "ParMoonolith::.*")
elseif (TARGET "${lib}")
mfem_get_target_options(${lib} CompileOpts2 LinkOpts2)
# remove generator expressions
string(GENEX_STRIP "${CompileOpts2}" CompileOpts)
string(GENEX_STRIP "${LinkOpts2}" LinkOpts)
mfem_get_target_options(${lib} CompileOpts LinkOpts)
# Removing duplicates may lead to issues:
# list(REMOVE_DUPLICATES CompileOpts)
# list(REMOVE_DUPLICATES LinkOpts)
# message(WARNING "${lib}[LinkOpts]: ${LinkOpts}")
# message(WARNING "${lib}[CompileOpts]: ${CompileOpts}")
foreach(LOpt IN LISTS LinkOpts)
set(MFEM_EXT_LIBS "${MFEM_EXT_LIBS} ${LOpt}")
endforeach()
foreach(COpt IN LISTS CompileOpts)
set(MFEM_TPLFLAGS "${MFEM_TPLFLAGS} ${COpt}")
endforeach()
string(REPLACE ";" " " COpts "${CompileOpts}")
string(REPLACE ";" " " LOpts "${LinkOpts}")
# message(STATUS "${lib}[COpts]: '${COpts}'")
# message(STATUS "${lib}[LOpts]: '${LOpts}'")
set(MFEM_TPLFLAGS "${MFEM_TPLFLAGS} ${COpts}")
set(MFEM_EXT_LIBS "${MFEM_EXT_LIBS} ${LOpts}")
# message(FATAL_ERROR "***** interface lib found ... exiting *****")
# handle static and shared libs
elseif ("${suffix}" STREQUAL "${CMAKE_SHARED_LIBRARY_SUFFIX}")
@@ -1076,7 +1002,7 @@ function(mfem_export_mk_files)
get_filename_component(fullLibName ${lib} NAME_WE)
string(REGEX REPLACE "^lib" "" libname ${fullLibName})
set(MFEM_EXT_LIBS
"${MFEM_EXT_LIBS} ${shared_link_flag}${dir} -L${dir} -l${libname}")
"${MFEM_EXT_LIBS} ${shared_link_flag}${dir} -L${dir} -l${libname}")
else()
set(MFEM_EXT_LIBS "${MFEM_EXT_LIBS} ${lib}")
endif()
@@ -1085,7 +1011,7 @@ function(mfem_export_mk_files)
# Create the build-tree version of 'config.mk'
configure_file(
"${PROJECT_SOURCE_DIR}/config/config.mk.in"
"${PROJECT_BINARY_DIR}/config/config.mk" @ONLY)
"${PROJECT_BINARY_DIR}/config/config.mk")
# Copy 'test.mk' from the source-tree to the build-tree
configure_file(
"${PROJECT_SOURCE_DIR}/config/test.mk"
@@ -1103,7 +1029,7 @@ function(mfem_export_mk_files)
# Create the install-tree version of 'config.mk'
configure_file(
"${PROJECT_SOURCE_DIR}/config/config.mk.in"
"${PROJECT_BINARY_DIR}/config/config-install.mk" @ONLY)
"${PROJECT_BINARY_DIR}/config/config-install.mk")
# Install rules for 'config.mk' and 'test.mk'
install(FILES ${PROJECT_SOURCE_DIR}/config/test.mk
+10 -4
View File
@@ -23,14 +23,11 @@
#include "_config.hpp"
#endif
#include <cstdint>
#include <climits>
namespace mfem
{
#if (defined(MFEM_USE_CUDA) && defined(__CUDACC__)) || \
(defined(MFEM_USE_HIP) && defined(__HIP__))
(defined(MFEM_USE_HIP) && defined(__HIPCC__))
#define MFEM_HOST_DEVICE __host__ __device__
#else
#define MFEM_HOST_DEVICE
@@ -64,6 +61,15 @@ constexpr real_t operator""_r(unsigned long long v)
} // namespace mfem
// Defines 'MFEM_THROW' depending if we are compiled with -fno-exceptions
#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)
#define MFEM_HAS_EXCEPTIONS
#define MFEM_THROW(exception_type, msg) throw exception_type(msg)
#else
#undef MFEM_HAS_EXCEPTIONS
#define MFEM_THROW(...)
#endif
// Return value for main function in examples that should be skipped by testing
// in some case. This return value prevents failures in testing.
#define MFEM_SKIP_RETURN_VALUE 242
-1
View File
@@ -88,7 +88,6 @@ MFEM_BUILD_TAG = @MFEM_BUILD_TAG@
MFEM_PREFIX = @MFEM_PREFIX@
MFEM_INC_DIR = @MFEM_INC_DIR@
MFEM_LIB_DIR = @MFEM_LIB_DIR@
MFEM_XLINKER = @MFEM_XLINKER@
# Location of test.mk
MFEM_TEST_MK = @MFEM_TEST_MK@
-7
View File
@@ -89,13 +89,6 @@ option(MFEM_ENABLE_EXAMPLES "Build all of the examples" OFF)
option(MFEM_ENABLE_MINIAPPS "Build all of the miniapps" OFF)
option(MFEM_ENABLE_BENCHMARKS "Build all of the benchmarks" OFF)
# Allow a user to specify fetching of certain third-party libraries instead of
# searching for existing installations.
option(MFEM_FETCH_TPLS "Enable fetching of all supported third-party libraries" OFF)
option(MFEM_FETCH_GSLIB "Enable fetching of GSLIB" OFF)
option(MFEM_FETCH_HYPRE "Enable fetching of hypre" OFF)
option(MFEM_FETCH_METIS "Enable fetching of METIS" OFF)
# Setting CXX/MPICXX on the command line or in user.cmake will overwrite the
# autodetected C++ compiler.
# set(CXX g++)
+2 -3
View File
@@ -18,7 +18,6 @@
# Some choices below are based on the OS type:
NOTMAC := $(subst Darwin,,$(shell uname -s))
ASTYLE_BIN = astyle
ETAGS_BIN = $(shell command -v etags 2> /dev/null)
EGREP_BIN = $(shell command -v egrep 2> /dev/null)
@@ -58,7 +57,7 @@ CUDA_DIR = $(or $(CUDA_HOME),$(patsubst %/,%,$(dir \
CLANG_CUDA_FLAGS = -xcuda --cuda-path=$(CUDA_DIR) --cuda-gpu-arch=$(CUDA_ARCH)
# flags for nvcc
NVCC_FLAGS = -x=cu --expt-extended-lambda --expt-relaxed-constexpr \
-arch=$(CUDA_ARCH) -isystem "$(CUDA_DIR)/include"
-arch=$(CUDA_ARCH)
# Prefixes for passing flags to the host compiler and linker when using
# CUDA_CXX=nvcc
CUDA_XCOMPILER = -Xcompiler=
@@ -408,7 +407,7 @@ AMGX_LIB = -L$(AMGX_DIR)/lib -lamgx -lcusparse -lcusolver -lcublas -lnvToolsExt
# MAGMA library configuration
MAGMA_DIR = @MFEM_DIR@/../magma
MAGMA_OPT = -I$(MAGMA_DIR)/include
MAGMA_LIB = -L$(MAGMA_DIR)/lib -l:libmagma.a $(LAPACK_LIB)
MAGMA_LIB = -L$(MAGMA_DIR)/lib -l:libmagma.a -lcublas -lcusparse $(LAPACK_LIB)
# GnuTLS library configuration
GNUTLS_OPT =
+1 -1
View File
@@ -101,7 +101,7 @@ $ cd ../miniapps
$ ls
CMakeLists.txt common meshing nurbs shifted toys
adjoint electromagnetics mtop parelag solvers
autodiff gslib fluids performance tools
autodiff gslib navier performance tools
```
And an example in "toys"
+2 -14
View File
@@ -85,10 +85,6 @@ groups_serial=(
"DPG miniapps:"
"miniapps/dpg"
"{acoustics,convection-diffusion,diffusion,maxwell}.cpp"'
'"isf"
"Schrodinger flow miniapps:"
"miniapps/fluids/schrodinger-flow"
"schrodinger_flow.cpp"'
'"gslib"
"GSLIB miniapps:"
"miniapps/gslib"
@@ -170,10 +166,6 @@ groups_parallel=(
"miniapps/electromagnetics"
"joule.cpp"'
# "{joule,maxwell,tesla,volta}.cpp"' # todo: multiline sample runs
'"isf"
"Schrodinger flow miniapps:"
"miniapps/fluids/schrodinger-flow"
"pschrodinger_flow.cpp"'
'"adjoint"
"Adjoint miniapps:"
"miniapps/adjoint"
@@ -199,7 +191,7 @@ groups_parallel=(
# todo: miniapps/multidomain
'"navier"
"Navier miniapps:"
"miniapps/fluids/navier"
"miniapps/navier"
"navier_cht.cpp"'
# todo: add other navier miniapps
'"nurbs"
@@ -289,10 +281,6 @@ groups_all=(
"miniapps/electromagnetics"
"joule.cpp"'
# "{joule,maxwell,tesla,volta}.cpp"' # todo: multiline sample runs
'"isf"
"Schrodinger flow miniapps:"
"miniapps/fluids/schrodinger-flow"
"{,p}schrodinger_flow.cpp"'
'"adjoint"
"Adjoint miniapps:"
"miniapps/adjoint"
@@ -320,7 +308,7 @@ groups_all=(
# todo: miniapps/multidomain
'"navier"
"Navier miniapps:"
"miniapps/fluids/navier"
"miniapps/navier"
"navier_cht.cpp"'
# todo: add other navier miniapps
'"nurbs"
-156
View File
@@ -1,156 +0,0 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see fem/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
# PYRAMID = 7
#
dimension
2
elements
25
3 3 0 1 2 3
3 3 1 4 5 2
3 3 4 6 7 5
3 3 6 8 9 7
3 3 8 10 11 9
3 3 10 12 13 11
3 3 12 14 15 13
3 3 14 16 17 15
3 3 16 18 19 17
3 3 18 20 21 19
3 3 20 22 23 21
3 3 22 24 25 23
3 3 24 26 27 25
3 3 26 28 29 27
3 3 28 30 31 29
3 3 30 32 33 31
3 3 32 34 35 33
3 3 17 19 36 37
3 3 37 36 38 39
3 3 39 38 40 41
3 3 41 40 42 43
3 3 43 42 44 45
3 3 45 44 46 47
3 3 47 46 48 49
3 3 49 48 50 51
boundary
52
2 1 0 1
2 1 2 3
1 1 3 0
2 1 1 4
2 1 5 2
2 1 4 6
2 1 7 5
2 1 6 8
2 1 9 7
2 1 8 10
2 1 11 9
2 1 10 12
2 1 13 11
2 1 12 14
2 1 15 13
2 1 14 16
2 1 17 15
2 1 16 18
2 1 18 20
2 1 21 19
2 1 20 22
2 1 23 21
2 1 22 24
2 1 25 23
2 1 24 26
2 1 27 25
2 1 26 28
2 1 29 27
2 1 28 30
2 1 31 29
2 1 30 32
2 1 33 31
2 1 32 34
3 1 34 35
2 1 35 33
2 1 19 36
2 1 37 17
2 1 36 38
2 1 39 37
2 1 38 40
2 1 41 39
2 1 40 42
2 1 43 41
2 1 42 44
2 1 45 43
2 1 44 46
2 1 47 45
2 1 46 48
2 1 49 47
2 1 48 50
4 1 50 51
2 1 51 49
vertices
52
2
0 0
1 0
1 1
0 1
2 0
2 1
3 0
3 1
4 0
4 1
5 0
5 1
6 0
6 1
7 0
7 1
8 0
8 1
9 0
9 1
10 0
10 1
11 0
11 1
12 0
12 1
13 0
13 1
14 0
14 1
15 0
15 1
16 0
16 1
17 0
17 1
9 2
8 2
9 3
8 3
9 4
8 4
9 5
8 5
9 6
8 6
9 7
8 7
9 8
8 8
9 9
8 9
-593
View File
@@ -1,593 +0,0 @@
MFEM mesh v1.0
# Created by: Pointwise
# MFEM Geometry Types:
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
dimension
2
elements
160
1 3 1 164 163 0
1 3 164 165 162 163
1 3 2 166 164 1
1 3 166 132 165 164
1 3 3 167 166 2
1 3 167 131 132 166
1 3 4 168 167 3
1 3 168 130 131 167
1 3 5 169 168 4
1 3 169 129 130 168
1 3 6 170 169 5
1 3 170 128 129 169
1 3 171 172 170 6
1 3 172 127 128 170
1 3 124 125 172 171
1 3 125 126 127 172
1 3 162 165 173 161
1 3 165 132 133 173
1 3 161 173 174 160
1 3 173 133 134 174
1 3 160 174 175 159
1 3 174 134 135 175
1 3 6 7 176 171
1 3 7 8 177 176
1 3 171 176 123 124
1 3 176 177 122 123
1 3 159 175 178 158
1 3 175 135 136 178
1 3 158 178 179 157
1 3 178 136 137 179
1 3 157 179 180 156
1 3 179 137 138 180
1 3 122 177 181 121
1 3 177 8 182 181
1 3 8 9 183 182
1 3 9 10 184 183
1 3 10 11 185 184
1 3 11 12 186 185
1 3 12 13 187 186
1 3 13 14 15 187
1 3 121 181 119 120
1 3 181 182 118 119
1 3 182 183 117 118
1 3 183 184 188 117
1 3 184 185 109 188
1 3 185 186 108 109
1 3 186 187 189 108
1 3 187 15 16 189
1 3 109 110 190 188
1 3 110 111 191 190
1 3 111 112 113 191
1 3 188 190 116 117
1 3 190 191 115 116
1 3 191 113 114 115
1 3 189 192 107 108
1 3 192 193 106 107
1 3 193 194 105 106
1 3 194 195 104 105
1 3 195 196 103 104
1 3 16 17 192 189
1 3 17 18 193 192
1 3 18 19 194 193
1 3 19 20 195 194
1 3 20 21 196 195
1 3 97 98 197 96
1 3 98 99 198 197
1 3 99 100 199 198
1 3 100 101 200 199
1 3 101 102 201 200
1 3 102 103 202 201
1 3 103 196 203 202
1 3 196 21 22 203
1 3 96 197 204 95
1 3 197 198 39 204
1 3 198 199 38 39
1 3 199 200 205 38
1 3 200 201 32 205
1 3 201 202 31 32
1 3 202 203 206 31
1 3 203 22 23 206
1 3 32 33 207 205
1 3 33 34 35 207
1 3 205 207 37 38
1 3 207 35 36 37
1 3 39 40 208 204
1 3 40 41 209 208
1 3 41 42 210 209
1 3 42 43 211 210
1 3 43 44 212 211
1 3 204 208 94 95
1 3 208 209 93 94
1 3 209 210 92 93
1 3 210 211 91 92
1 3 211 212 90 91
1 3 90 212 213 89
1 3 212 44 214 213
1 3 44 45 215 214
1 3 45 46 216 215
1 3 46 47 217 216
1 3 47 48 218 217
1 3 48 49 219 218
1 3 49 50 51 219
1 3 89 213 87 88
1 3 213 214 86 87
1 3 214 215 85 86
1 3 215 216 84 85
1 3 216 217 83 84
1 3 217 218 82 83
1 3 218 219 220 82
1 3 219 51 52 220
1 3 53 221 220 52
1 3 221 81 82 220
1 3 54 222 221 53
1 3 222 80 81 221
1 3 55 223 222 54
1 3 223 79 80 222
1 3 26 27 224 25
1 3 27 28 29 224
1 3 25 224 225 24
1 3 224 29 30 225
1 3 24 225 206 23
1 3 225 30 31 206
1 3 154 155 226 153
1 3 155 156 180 226
1 3 153 226 227 152
1 3 226 180 138 227
1 3 152 227 228 151
1 3 227 138 139 228
1 3 151 228 229 150
1 3 228 139 140 229
1 3 150 229 230 149
1 3 229 140 141 230
1 3 149 230 231 148
1 3 230 141 142 231
1 3 148 231 232 147
1 3 231 142 143 232
1 3 147 232 145 146
1 3 232 143 144 145
1 3 56 233 223 55
1 3 233 78 79 223
1 3 57 234 233 56
1 3 234 77 78 233
1 3 58 235 234 57
1 3 235 76 77 234
1 3 61 236 59 60
1 3 236 235 58 59
1 3 62 237 236 61
1 3 237 76 235 236
1 3 63 238 237 62
1 3 238 75 76 237
1 3 64 239 238 63
1 3 239 74 75 238
1 3 65 240 239 64
1 3 240 73 74 239
1 3 66 241 240 65
1 3 241 72 73 240
1 3 67 242 241 66
1 3 242 71 72 241
1 3 68 69 242 67
1 3 69 70 71 242
boundary
164
3 1 0 1
3 1 1 2
3 1 2 3
3 1 3 4
3 1 4 5
3 1 5 6
3 1 6 7
3 1 7 8
3 1 8 9
3 1 9 10
3 1 10 11
3 1 11 12
3 1 12 13
3 1 13 14
3 1 16 17
3 1 17 18
3 1 18 19
3 1 19 20
3 1 20 21
3 1 21 22
3 1 22 23
3 1 23 24
3 1 24 25
3 1 25 26
3 1 26 27
3 1 27 28
3 1 28 29
3 1 29 30
3 1 30 31
3 1 31 32
3 1 32 33
3 1 33 34
3 1 34 35
3 1 35 36
3 1 36 37
3 1 37 38
3 1 38 39
3 1 39 40
3 1 40 41
3 1 41 42
3 1 42 43
3 1 43 44
3 1 49 50
3 1 48 49
3 1 47 48
3 1 46 47
3 1 45 46
3 1 44 45
3 1 52 53
3 1 53 54
3 1 54 55
3 1 57 58
3 1 56 57
3 1 55 56
3 1 60 61
3 1 61 62
3 1 62 63
3 1 63 64
3 1 64 65
3 1 65 66
3 1 66 67
3 1 67 68
3 1 75 76
3 1 74 75
3 1 73 74
3 1 72 73
3 1 71 72
3 1 70 71
3 1 76 77
3 1 77 78
3 1 78 79
3 1 81 82
3 1 80 81
3 1 79 80
3 1 82 83
3 1 83 84
3 1 84 85
3 1 85 86
3 1 86 87
3 1 87 88
3 1 94 95
3 1 93 94
3 1 92 93
3 1 91 92
3 1 90 91
3 1 96 97
3 1 95 96
3 1 97 98
3 1 98 99
3 1 99 100
3 1 100 101
3 1 101 102
3 1 102 103
3 1 107 108
3 1 106 107
3 1 105 106
3 1 104 105
3 1 103 104
3 1 108 109
3 1 109 110
3 1 110 111
3 1 111 112
3 1 112 113
3 1 113 114
3 1 114 115
3 1 115 116
3 1 116 117
3 1 119 120
3 1 118 119
3 1 117 118
3 1 131 132
3 1 130 131
3 1 129 130
3 1 128 129
3 1 127 128
3 1 126 127
3 1 132 133
3 1 133 134
3 1 134 135
3 1 137 138
3 1 136 137
3 1 135 136
3 1 138 139
3 1 139 140
3 1 140 141
3 1 141 142
3 1 142 143
3 1 143 144
3 1 147 148
3 1 146 147
3 1 153 154
3 1 152 153
3 1 151 152
3 1 150 151
3 1 149 150
3 1 148 149
3 1 156 157
3 1 157 158
3 1 158 159
3 1 161 162
3 1 160 161
3 1 159 160
2 1 69 70
2 1 68 69
3 1 88 89
3 1 89 90
3 1 121 122
3 1 120 121
3 1 123 124
3 1 122 123
3 1 125 126
3 1 124 125
1 1 144 145
1 1 145 146
3 1 15 16
3 1 14 15
3 1 50 51
3 1 51 52
3 1 59 60
3 1 58 59
3 1 154 155
3 1 155 156
3 1 163 0
3 1 162 163
vertices
243
2
4 4
4 3.5
4 3
4 2.5
4 2
4 1.5
4 1
4.5 1
5 1
5 1.5
5 2
5 2.5
5 3
5 3.5
5 4
5.500 4
6 4
6.500 4
7 4
7.5 4
8 4
8.5 4
9 4
9.5 4
10 4
10.5 4
11 4
11 3.5
11 3
10.5 3
10 3
9.5 3
9.5 2.5
10 2.5
10.5 2.5
10.5 2
10.5 1.5
10 1.5
9.5 1.5
9.5 1
10 1
10.5 1
11 1
11.5 1
12 1
12 1.5
12 2
12 2.5
12 3
12 3.5
12 4
12.5 4
13 4
13.333 3.75
13.666 3.5
14.000 3.25
14.333 3.5
14.666 3.75
15.000 4
15.500 4
16.000 4
16.000 3.5
16.000 3
16.000 2.5
16.000 2
16.000 1.5
16.000 1
16.000 0.5
16.000 0
15.500 0
15.000 0
15.000 0.5000000000000002
15.000 1
15.000 1.5
15.000 2
15.000 2.5
15.000 3
14.666 2.75
14.333 2.5
14.000 2.25
13.666 2.5
13.333 2.75
13 3
13 2.5
13 2
13 1.5
13 1
13 0.500
13 0
12.5 0
12 0
11.5 0
11 0
10.5 0
10 0
9.5 0
9 0
8.5 0
8.5 0.5
8.5 1
8.5 1.5
8.5 2
8.5 2.5
8.5 3
8 3
7.5 3
7 3
6.500 3
6 3
6 2.5
6.5 2.5
7 2.5
7.5 2.5
7.5 2
7.5 1.5
7.000 1.5
6.5 1.5
6 1.5
6 1
6 0.5
6 0
5.5 0
5 0
4.5 0
4 0
3.5 0
3 0
3 0.500
3 1
3 1.5
3 2
3 2.5
3 3
2.666 2.75
2.333 2.5
2.000 2.25
1.666 2.5
1.333 2.75
1.000 3
1.000 2.5
1.000 2
1.000 1.5
1.000 1
1.000 0.5000
1.000 0
0.5000 0
0.0000 0
0.0000 0.5
0.0000 1
0.0000 1.5
0.0000 2
0.0000 2.5
0.0000 3
0.0000 3.5
0.0000 4
0.5000 4
1.000 4
1.333 3.75
1.666 3.5
2.000 3.25
2.333 3.5
2.666 3.75
3 4
3.5 4
3.5 3.5
3 3.5
3.5 3
3.5 2.5
3.5 2
3.5 1.5
3.5 1
4 0.5
3.5 0.5
2.666 3.25
2.333 3
2.000 2.75
4.5 0.5
5 0.5
1.666 3
1.333 3.25
1.000 3.5
5.5 0.5
5.500 1
5.500 1.5
5.500 2
5.500 2.5
5.500 3
5.500 3.5
6 2
6 3.5
6.5 2
7 2
6.5 3.5
7 3.5
7.5 3.5
8 3.5
8.5 3.5
9 0.5
9 1
9 1.5
9 2
9 2.5
9 3
9 3.5
9.5 0.5
9.5 2
9.5 3.5
10 2
10 0.5
10.5 0.5
11 0.5
11.5 0.5
12 0.5
12.5 0.500
12.5 1
12.5 1.5
12.5 2
12.5 2.5
12.5 3
12.5 3.5
13 3.5
13.333 3.250
13.666 3
14.000 2.75
10.5 3.5
10 3.5
0.500 3.5
0.500 3
0.500 2.5
0.500 2
0.500 1.5
0.500 1
0.500 0.5
14.333 3
14.666 3.25
15.000 3.5
15.500 3.5
15.500 3
15.500 2.5
15.500 2
15.500 1.5
15.500 1
15.500 0.5
-342
View File
@@ -1,342 +0,0 @@
MFEM NURBS NC-patch mesh v1.0
dimension
3
elements
13
0 1 5 0 8 10 11 9 4 6 7 5
0 1 5 0 18 8 24 32 30 23 36 38
0 1 5 0 0 18 32 14 12 30 38 29
0 1 5 0 32 24 10 20 38 36 26 35
0 1 5 0 14 32 20 2 29 38 35 16
0 1 5 0 30 23 36 38 31 22 37 39
0 1 5 0 12 30 38 29 13 31 39 28
0 1 5 0 38 36 26 35 39 37 27 34
0 1 5 0 29 38 35 16 28 39 34 17
0 1 5 0 31 22 37 39 19 9 25 33
0 1 5 0 13 31 39 28 1 19 33 15
0 1 5 0 39 37 27 34 33 25 11 21
0 1 5 0 28 39 34 17 15 33 21 3
boundary
31
9999 3 8 10 6 4
9999 3 10 11 7 6
9999 3 11 9 5 7
9999 3 9 8 4 5
9999 3 4 6 7 5
9999 3 32 24 8 18
9999 3 18 8 23 30
9999 3 14 32 18 0
9999 3 0 18 30 12
9999 3 14 0 12 29
9999 3 20 10 24 32
9999 3 10 20 35 26
9999 3 2 20 32 14
9999 3 20 2 16 35
9999 3 2 14 29 16
9999 3 30 23 22 31
9999 3 12 30 31 13
9999 3 29 12 13 28
9999 3 26 35 34 27
9999 3 35 16 17 34
9999 3 16 29 28 17
9999 3 31 22 9 19
9999 3 19 9 25 33
9999 3 13 31 19 1
9999 3 28 13 1 15
9999 3 1 19 33 15
9999 3 27 34 21 11
9999 3 33 25 11 21
9999 3 34 17 3 21
9999 3 17 28 15 3
9999 3 15 33 21 3
vertex_to_knotspan
8
23 0 1 8 10 11 9
22 0 2 8 10 11 9
24 1 0 8 10 11 9
36 1 1 8 10 11 9
37 1 2 8 10 11 9
25 1 3 8 10 11 9
26 2 1 8 10 11 9
27 2 2 8 10 11 9
coordinates
40
3
0 0 0
0 1 0
4 0 0
4 1 0
0 0 4
0 1 4
4 0 4
4 1 4
0 0 2
0 1 2
4 0 2
4 1 2
0 0.333333333333333 0
0 0.666666666666667 0
2 0 0
2 1 0
4 0.333333333333334 0
4 0.666666666666667 0
0 0 1
0 1 1
4 0 1
4 1 1
0 0.666666666666667 2
0 0.333333333333333 2
2 0 2
2 1 2
4 0.333333333333333 2
4 0.666666666666667 2
2 0.666666666666667 0
2 0.333333333333333 0
0 0.333333333333333 1
0 0.666666666666667 1
1.81325211007895 0 1
1.81325211007895 1 1
4 0.666666666666667 1
4 0.333333333333333 1
2 0.333333333333333 2
2 0.666666666666667 2
1.81325211007895 0.333333333333333 1
1.81325211007895 0.666666666666667 1
edges
87
0 8 10
1 10 11
0 9 11
1 8 9
0 4 6
1 6 7
0 5 7
1 4 5
2 4 8
2 6 10
2 7 11
2 5 9
9 18 8
7 8 24
9 32 24
7 18 32
9 30 23
7 23 36
9 38 36
7 30 38
3 18 30
3 8 23
3 24 36
3 32 38
8 0 18
8 14 32
7 0 14
8 12 30
8 29 38
7 12 29
3 0 12
3 14 29
6 24 10
9 20 10
6 32 20
6 36 26
9 35 26
6 38 35
3 10 26
3 20 35
8 2 20
6 14 2
8 16 35
6 29 16
3 2 16
9 31 22
7 22 37
9 39 37
7 31 39
4 30 31
4 23 22
4 36 37
4 38 39
8 13 31
8 28 39
7 13 28
4 12 13
4 29 28
6 37 27
9 34 27
6 39 34
4 26 27
4 35 34
8 17 34
6 28 17
4 16 17
9 19 9
7 9 25
9 33 25
7 19 33
5 31 19
5 22 9
5 37 25
5 39 33
8 1 19
8 15 33
7 1 15
5 13 1
5 28 15
6 25 11
9 21 11
6 33 21
5 27 11
5 34 21
8 3 21
6 15 3
5 17 3
knotvectors
10
1 3 0 0 0.5 1 1
1 4 0 0 0.333333333333333 0.666666666666667 1 1
1 3 0 0 0.5 1 1
1 2 0 0 1 1
1 2 0 0 1 1
1 2 0 0 1 1
1 2 0 0 1 1
1 2 0 0 1 1
1 2 0 0 1 1
1 2 0 0 1 1
spacing
0
weights
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
FiniteElementSpace
FiniteElementCollection: NURBS1
VDim: 3
Ordering: 1
0 0 0
0 1 0
4 0 0
4 1 0
0 0 4
0 1 4
4 0 4
4 1 4
0 0 2
0 1 2
4 0 2
4 1 2
0 0.333333333333333 0
0 0.666666666666667 0
2 0 0
2 1 0
4 0.333333333333334 0
4 0.666666666666667 0
0 0 1
0 1 1
4 0 1
4 1 1
0 0.666666666666667 2
0 0.333333333333333 2
2 0 2
2 1 2
4 0.333333333333333 2
4 0.666666666666667 2
2 0.666666666666667 0
2 0.333333333333333 0
0 0.333333333333333 1
0 0.666666666666667 1
1.81325211007895 0 1
1.81325211007895 1 1
4 0.666666666666667 1
4 0.333333333333333 1
2 0.333333333333333 2
2 0.666666666666667 2
1.81325211007895 0.333333333333333 1
1.81325211007895 0.666666666666667 1
2 0 4
4 0.333333333333333 4
4 0.666666666666667 4
2 1 4
0 0.333333333333333 4
0 0.666666666666667 4
0 0 3
4 0 3
4 1 3
0 1 3
2 0 3
4 0.333333333333333 3
4 0.666666666666667 3
2 1 3
0 0.666666666666667 3
0 0.333333333333333 3
2 0.333333333333333 4
2 0.666666666666667 4
2 0.333333333333333 3
2 0.666666666666667 3
-96
View File
@@ -1,96 +0,0 @@
MFEM NURBS NC-patch mesh v1.0
dimension
2
# rank attr geom ref_type nodes/children
elements
3
0 1 3 0 0 4 5 1
0 1 3 0 6 7 4 2
0 1 3 0 6 3 5 7
# attr geom nodes
boundary
7
1 1 0 4
1 1 5 1
1 1 1 0
1 1 2 6
1 1 6 3
1 1 4 2
1 1 5 3
vertex_to_knotspan
1
7 1 4 5
# top-level node coordinates
coordinates
8
2
0 0
0 1
2 0
2 1
1 0
1 1
2 0.5
1 0.5
edges
11
0 0 4
1 4 5
0 1 5
1 0 1
2 6 7
4 7 4
2 2 4
4 6 2
3 6 3
2 3 5
3 7 5
knotvectors
5
1 3 0 0 0.5 1 1
1 3 0 0 0.5 1 1
1 2 0 0 1 1
1 2 0 0 1 1
1 2 0 0 1 1
spacing
0
weights
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
1.0
FiniteElementSpace
FiniteElementCollection: NURBS1
VDim: 2
Ordering: 1
0 0
0 1
2 0
2 1
1 0
1 1
2 0.5
1 0.5
0.5 0
0.5 1
0 0.5
0.5 0.5
mfem_mesh_end
@@ -1,86 +0,0 @@
MFEM NURBS mesh v1.0
dimension
1
# Four segments with different NURBS orders, described via patches.
elements
4
1 1 0 1
2 1 2 3
3 1 4 5
4 1 6 7
boundary
0
edges
4
0 0 1
1 2 3
2 4 5
3 6 7
vertices
8
patches
# Patch 0: linear (order 1, 3 spans)
knotvectors
1
1 4 0 0 .4 .6 1 1
dimension
2
controlpoints
0.0 0.0 1.0
0.6 0.4 1.0
0.4 0.6 1.0
1.0 1.0 1.0
# Patch 1: quadratic (order 2, 2 spans)
knotvectors
1
2 4 0 0 0 .5 1 1 1
dimension
2
controlpoints
1.0 0.0 1.0
1.9 0.0 1.21
2.0 0.9 1.22
2.0 1.0 1.0
# Patch 2: cubic (order 3, 3 spans)
knotvectors
1
3 6 0 0 0 0 .33 .66 1 1 1 1
dimension
2
controlpoints
2.0 0.0 1.0
2.1 0.2 1.31
3.5 0.4 1.32
2.5 0.6 1.33
2.9 1.0 1.34
3.0 1.0 1.0
# Patch 3: quartic (order 4, 1 span)
knotvectors
1
4 5 0 0 0 0 0 1 1 1 1 1
dimension
2
controlpoints
3.0 0.0 1.0
3.45 0.5 1.41
3.50 1.0 1.42
3.75 0.8 1.43
4.0 0.0 1.0
-79
View File
@@ -1,79 +0,0 @@
MFEM NURBS mesh v1.0
#
# MFEM Geometry Types (see fem/geom.hpp):
#
# SEGMENT = 1
# SQUARE = 3
# CUBE = 5
#
dimension
1
# Three segments with different NURBS orders, described via patches.
elements
3
1 1 0 1
2 1 2 3
3 1 4 5
boundary
6
1 0 0
1 0 1
1 0 2
1 0 3
1 0 4
1 0 5
edges
3
0 0 1
1 2 3
2 4 5
vertices
6
patches
# Patch 0: linear (order 1, 2 control points)
knotvectors
1
1 2 0 0 1 1
dimension
2
controlpoints
0.0 0.0 1.0
1.0 1.0 1.0
# Patch 1: quadratic (order 2, 3 control points)
knotvectors
1
2 3 0 0 0 1 1 1
dimension
2
controlpoints
1.0 0.0 1.0
1.02 1.02 1.2
2.0 1.0 1.0
# Patch 2: cubic (order 3, 4 control points)
knotvectors
1
3 4 0 0 0 0 1 1 1 1
dimension
2
controlpoints
2.0 0.0 1.0
2.03 0.83 1.31
2.33 1.03 1.32
3.0 1.0 1.0
-72
View File
@@ -1,72 +0,0 @@
MFEM NURBS mesh v1.0
#
# MFEM Geometry Types (see fem/geom.hpp):
#
# SEGMENT = 1
# SQUARE = 3
# CUBE = 5
#
dimension
1
elements
3
1 1 0 1
2 1 2 3
3 1 4 5
boundary
6
1 0 0
1 0 1
1 0 2
1 0 3
1 0 4
1 0 5
edges
3
0 0 1
1 2 3
2 4 5
vertices
6
# Edge 0: linear (order 1, 2 control points)
# Edge 1: quadratic (order 2, 3 control points)
# Edge 2: cubic (order 3, 4 control points)
knotvectors
3
1 2 0 0 1 1
2 3 0 0 0 1 1 1
3 4 0 0 0 0 1 1 1 1
# One weight per control point, in the same order as the control points; (2 + 3 + 4) = 9 weights total
weights
1
1
1
1
1
1
1.2
1.31
1.32
FiniteElementSpace
FiniteElementCollection: NURBS
VDim: 2
Ordering: 1
0.0 0.0
1.0 1.0
1.0 0.0
2.0 1.0
2.0 0.0
3.0 1.0
1.02 1.02
2.03 0.83
2.33 1.03
-79
View File
@@ -1,79 +0,0 @@
MFEM NURBS mesh v1.0
#
# MFEM Geometry Types (see fem/geom.hpp):
#
# SEGMENT = 1
# SQUARE = 3
# CUBE = 5
#
dimension
1
# Three segments with different NURBS orders, described via patches.
elements
3
1 1 0 1
2 1 2 3
3 1 4 5
boundary
6
1 0 0
1 0 1
1 0 2
1 0 3
1 0 4
1 0 5
edges
3
0 0 1
1 2 3
2 4 5
vertices
6
patches
# Patch 0: linear (order 1, 2 control points)
knotvectors
1
1 2 0 0 1 1
dimension
3
controlpoints
0.0 0.0 0.01 1.0
1.0 1.0 1.01 1.0
# Patch 1: quadratic (order 2, 3 control points)
knotvectors
1
2 3 0 0 0 1 1 1
dimension
3
controlpoints
1.0 0.0 0.02 1.0
1.02 1.02 0.52 1.2
2.0 1.0 1.02 1.0
# Patch 2: cubic (order 3, 4 control points)
knotvectors
1
3 4 0 0 0 0 1 1 1 1
dimension
3
controlpoints
2.0 0.0 0.03 1.0
2.03 0.83 0.33 1.31
2.33 1.03 0.63 1.32
3.0 1.0 1.03 1.0
-72
View File
@@ -1,72 +0,0 @@
MFEM NURBS mesh v1.0
#
# MFEM Geometry Types (see fem/geom.hpp):
#
# SEGMENT = 1
# SQUARE = 3
# CUBE = 5
#
dimension
1
elements
3
1 1 0 1
2 1 2 3
3 1 4 5
boundary
6
1 0 0
1 0 1
1 0 2
1 0 3
1 0 4
1 0 5
edges
3
0 0 1
1 2 3
2 4 5
vertices
6
# Edge 0: linear (order 1, 2 control points)
# Edge 1: quadratic (order 2, 3 control points)
# Edge 2: cubic (order 3, 4 control points)
knotvectors
3
1 2 0 0 1 1
2 3 0 0 0 1 1 1
3 4 0 0 0 0 1 1 1 1
# One weight per control point, in the same order as the control points; (2 + 3 + 4) = 9 weights total
weights
1
1
1
1
1
1
1.2
1.31
1.32
FiniteElementSpace
FiniteElementCollection: NURBS
VDim: 3
Ordering: 1
0.0 0.0 0.01
1.0 1.0 1.01
1.0 0.0 0.02
2.0 1.0 1.02
2.0 0.0 0.03
3.0 1.0 1.03
1.02 1.02 0.52
2.03 0.83 0.33
2.33 1.03 0.63
+2 -4
View File
@@ -48,7 +48,7 @@ PROJECT_NAME = MFEM
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = v4.9.1
PROJECT_NUMBER = v4.8.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
@@ -973,13 +973,10 @@ INPUT = @MFEM_SOURCE_DIR@/doc/CodeDocumentation.dox \
@MFEM_SOURCE_DIR@/miniapps/adjoint \
@MFEM_SOURCE_DIR@/miniapps/autodiff \
@MFEM_SOURCE_DIR@/miniapps/common \
@MFEM_SOURCE_DIR@/miniapps/contact \
@MFEM_SOURCE_DIR@/miniapps/dfem \
@MFEM_SOURCE_DIR@/miniapps/dpg \
@MFEM_SOURCE_DIR@/miniapps/dpg/util \
@MFEM_SOURCE_DIR@/miniapps/electromagnetics \
@MFEM_SOURCE_DIR@/miniapps/fluids/navier \
@MFEM_SOURCE_DIR@/miniapps/fluids/schrodinger-flow \
@MFEM_SOURCE_DIR@/miniapps/gslib \
@MFEM_SOURCE_DIR@/miniapps/hdiv-linear-solver \
@MFEM_SOURCE_DIR@/miniapps/hooke \
@@ -990,6 +987,7 @@ INPUT = @MFEM_SOURCE_DIR@/doc/CodeDocumentation.dox \
@MFEM_SOURCE_DIR@/miniapps/meshing \
@MFEM_SOURCE_DIR@/miniapps/mtop \
@MFEM_SOURCE_DIR@/miniapps/multidomain \
@MFEM_SOURCE_DIR@/miniapps/navier \
@MFEM_SOURCE_DIR@/miniapps/nurbs \
@MFEM_SOURCE_DIR@/miniapps/parelag \
@MFEM_SOURCE_DIR@/miniapps/performance \
+1 -8
View File
@@ -117,8 +117,6 @@ namespace mfem {
* - <a class="el" href="ex39p_8cpp_source.html">Example 39p</a>: parallel named mesh attributes
* - <a class="el" href="ex40_8cpp_source.html">Example 40</a>: eikonal equation
* - <a class="el" href="ex40p_8cpp_source.html">Example 40p</a>: parallel eikonal equation
* - <a class="el" href="ex41_8cpp_source.html">Example 41</a>: DG/CG IMEX time-dependent advection-diffusion
* - <a class="el" href="ex41p_8cpp_source.html">Example 41p</a>: parallel DG/CG IMEX time-dependent advection-diffusion
*
* <H4>AmgX Examples</H4>
* - Variants of Examples
@@ -190,8 +188,6 @@ namespace mfem {
* <a class="el" href="nurbs__ex1p_8cpp_source.html">1p</a>,
* <a class="el" href="nurbs__ex3_8cpp_source.html">3</a>,
* <a class="el" href="nurbs__ex5_8cpp_source.html">5</a>,
* <a class="el" href="nurbs__ex10_8cpp_source.html">10</a>,
* <a class="el" href="nurbs__ex10p_8cpp_source.html">10p</a>,
* <a class="el" href="nurbs__ex11p_8cpp_source.html">11p</a>, and
* <a class="el" href="nurbs__ex24_8cpp_source.html">24</a>,
* demonstrating howto perform NURBS-based Isogeometric Analysis.
@@ -200,14 +196,12 @@ namespace mfem {
* - <a class="el" href="nurbs__curveint_8cpp_source.html">NURBS Interpolation</a>: NURBS interpolation of given geometry
* - <a class="el" href="nurbs__naca__cmesh_8cpp_source.html">NURBS NACA Mesher</a>: generate NURBS based mesh around a NACA foil
* - <a class="el" href="nurbs__printfunc_8cpp_source.html">NURBS Printer</a>: print the NURBS-basis
* - <a class="el" href="nurbs__mesh_info_8cpp_source.html">NURBS Mesh info</a>: print the info of a NURBS mesh
*
* <H3>Miniapps</H3>
* - <a class="el" href="volta_8cpp_source.html">Volta</a>: simple electrostatics simulation code
* - <a class="el" href="tesla_8cpp_source.html">Tesla</a>: simple magnetostatics simulation code
* - <a class="el" href="maxwell_8cpp_source.html">Maxwell</a>: simple transient full-wave electromagnetics simulation code
* - <a class="el" href="joule_8cpp_source.html">Joule</a>: transient magnetics and Joule heating miniapp
* - <a class="el" href="lorentz_8cpp_source.html">Lorentz</a>: simple particle tracking code based on the Lorentz force
* - <a class="el" href="classmfem_1_1navier_1_1NavierSolver.html">Navier</a>: solve the transient incompressible Navier-Stokes equations
* - <a class="el" href="mobius-strip_8cpp_source.html">Mobius Strip</a>: generate various Mobius strip-like meshes
* - <a class="el" href="klein-bottle_8cpp_source.html">Klein Bottle</a>: generate three types of Klein bottle surfaces
@@ -239,8 +233,7 @@ namespace mfem {
* - <a class="el" href="miniapps_2performance_2ex1_8cpp_source.html">HPC Example 1</a>: high-performance nodal H1 FEM for the Poisson problem
* - <a class="el" href="miniapps_2performance_2ex1p_8cpp_source.html">HPC Example 1p</a>: high-performance parallel nodal H1 FEM for the Poisson problem
* - <a class="el" href="generate__random__field_8cpp_source.html">SPDE Solvers</a>: SPDE solver random field generation
* - <a class="el" href="contact-patch-test_8cpp_source.html">Tribol</a>: mortar contact patch test for elasticity
* - <a class="el" href="contact_8cpp_source.html">Contact</a>: Frictionless contact examples using <a class="el" href="classmfem_1_1IPSolver.html#details">IP optimization</a> and the <a class="el" href="classmfem_1_1AMGFSolver.html#details">AMGF solver</a>
* - <a class="el" href="contact-patch-test_8cpp_source.html">Contact</a>: mortar contact patch test for elasticity
* - <a class="el" href="multidomain_8cpp_source.html">Multidomain miniapp</a>: Multidomain and Submesh demonstration miniapp
* - <a class="el" href="pdiffusion_8cpp_source.html">DPG Diffusion example</a>: DPG formulation for the diffusion problem
* - <a class="el" href="pmaxwell_8cpp_source.html">DPG Maxwell example</a>: DPG formulation for the indefinite Maxwell problem
-13
View File
@@ -46,7 +46,6 @@ list(APPEND ALL_EXE_SRCS
ex38.cpp
ex39.cpp
ex40.cpp
ex41.cpp
)
if (MFEM_USE_MPI)
@@ -90,7 +89,6 @@ if (MFEM_USE_MPI)
ex37p.cpp
ex39p.cpp
ex40p.cpp
ex41p.cpp
)
endif()
@@ -133,8 +131,6 @@ if (MFEM_ENABLE_TESTING)
list(APPEND THIS_TEST_OPTIONS "-dg")
elseif(${TEST_NAME} MATCHES "ex37p*")
list(APPEND THIS_TEST_OPTIONS "-mi" "3")
elseif(${TEST_NAME} MATCHES "ex41p*")
list(APPEND THIS_TEST_OPTIONS "-tf" "1.0")
endif()
if (NOT (${TEST_NAME} MATCHES ".*p$"))
@@ -209,15 +205,6 @@ if (MFEM_ENABLE_TESTING)
$<TARGET_FILE:ex25p> "-no-vis" "--mumps-solver"
${MPIEXEC_POSTFLAGS})
endif()
# Parallel libCEED example
if (MFEM_USE_CEED AND MFEM_USE_MPI)
add_test(NAME ex1p_ceed_np=${MFEM_MPI_NP}
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
${MPIEXEC_PREFLAGS}
$<TARGET_FILE:ex1p> "-no-vis" "-d" "ceed-cpu" "-pa" "-a"
${MPIEXEC_POSTFLAGS})
endif()
endif()
# Include the examples/amgx directory if AmgX is enabled
+1 -1
View File
@@ -64,7 +64,7 @@ PARALLEL_NAME := Parallel AMGX example
$(MFEM_LIB_FILE):
$(error The MFEM library is not build)
clean: clean-build clean-exec
clean: clean-build
clean-build:
rm -f *.o *~ $(SEQ_EXAMPLES) $(PAR_EXAMPLES)
+3 -3
View File
@@ -64,12 +64,12 @@ ex1p-test-par: ex1p
$(MFEM_LIB_FILE):
$(error The MFEM library is not built)
clean: clean-build clean-exec
clean: clean-build clean-exec $(SUBDIRS_CLEAN)
clean-build:
rm -f *.o *~ $(SEQ_EXAMPLES) $(PAR_EXAMPLES)
rm -rf *.dSYM *.TVD.*breakpoints
clean-exec:
@rm -f refined.mesh mesh.*
@rm -f sol.*
@rm -f refined.mesh displaced.mesh mesh.* ex5.mesh
@rm -f sphere_refined.* sol.* sol_u.* sol_p.* sol_r.* sol_i.*
-1
View File
@@ -27,7 +27,6 @@
// ex1 -m ../data/fichera-amr.mesh
// ex1 -m ../data/mobius-strip.mesh
// ex1 -m ../data/mobius-strip.mesh -o -1 -sc
// ex1 -m ../data/nc3-nurbs.mesh -o -1
//
// Device sample runs:
// ex1 -pa -d cuda
+2 -2
View File
@@ -5,9 +5,9 @@
// Sample runs:
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -s 464 -n 10 -o 2 -elast
// mpirun -np 4 ex12p -m ../data/beam-tet.mesh -s 462 -n 10 -o 2 -elast
// mpirun -np 4 ex12p -m ../data/beam-hex.mesh -s 3878
// mpirun -np 4 ex12p -m ../data/beam-wedge.mesh -s 82
// mpirun -np 4 ex12p -m ../data/beam-wedge.mesh -s 81
// mpirun -np 4 ex12p -m ../data/beam-tri.mesh -s 3877 -o 2 -sys
// mpirun -np 4 ex12p -m ../data/beam-quad.mesh -s 4544 -n 6 -o 3 -elast
// mpirun -np 4 ex12p -m ../data/beam-quad-nurbs.mesh
+6 -29
View File
@@ -105,7 +105,6 @@ int main(int argc, char *argv[])
bool visualization = true;
bool visit = false;
int vis_steps = 5;
bool solve_implicit_state = false;
int precision = 8;
cout.precision(precision);
@@ -127,9 +126,6 @@ int main(int argc, char *argv[])
"Alpha coefficient.");
args.AddOption(&kappa, "-k", "--kappa",
"Kappa coefficient offset.");
args.AddOption(&solve_implicit_state, "-imp-state", "--implicit-state",
"-imp-slope", "--implicit-slope",
"Implicitly solve for stage state or slope.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
@@ -183,11 +179,6 @@ int main(int argc, char *argv[])
// 7. Initialize the conduction operator and the visualization.
ConductionOperator oper(fespace, alpha, kappa, u);
using ImplicitVariableType = ConductionOperator::ImplicitVariableType;
ImplicitVariableType imp_var = solve_implicit_state ?
ImplicitVariableType::STATE
: ImplicitVariableType::SLOPE;
oper.SetImplicitVariableType(imp_var);
u_gf.SetFromTrueDofs(u);
{
@@ -325,14 +316,11 @@ void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
}
void ConductionOperator::ImplicitSolve(const real_t dt,
const Vector &u, Vector &k)
const Vector &u, Vector &du_dt)
{
// Solve the equation:
// M*k = -K(u + dt*k) for k = du/dt, if solving for stage-slope
// or
// M*k = -dt*K(k) + M*u for k = u_s, if solving for stage-state
// where K is linearized by using u from the previous timestep, and
// the stage-state and slope relation: du/dt = (u_s - u)/dt.
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
// for du_dt, where K is linearized by using u from the previous timestep
if (!T)
{
T = Add(1.0, Mmat, dt, Kmat);
@@ -340,20 +328,9 @@ void ConductionOperator::ImplicitSolve(const real_t dt,
T_solver.SetOperator(*T);
}
MFEM_VERIFY(dt == current_dt, ""); // SDIRK methods use the same dt
// Construct current right-hand side for stage state vs. slope solve
if (ImplicitVarTypeIsState())
{
// k, on return, is the stage value u_s
Mmat.Mult(u, z);
}
else
{
// k, on return, is the stage slope du/dt
Kmat.Mult(u, z);
z.Neg();
}
T_solver.Mult(z, k);
Kmat.Mult(u, z);
z.Neg();
T_solver.Mult(z, du_dt);
}
void ConductionOperator::SetParameters(const Vector &u)
+6 -29
View File
@@ -115,7 +115,6 @@ int main(int argc, char *argv[])
bool visit = false;
int vis_steps = 5;
bool adios2 = false;
bool solve_implicit_state = false;
int precision = 8;
cout.precision(precision);
@@ -139,9 +138,6 @@ int main(int argc, char *argv[])
"Alpha coefficient.");
args.AddOption(&kappa, "-k", "--kappa",
"Kappa coefficient offset.");
args.AddOption(&solve_implicit_state, "-imp-state", "--implicit-state",
"-imp-slope", "--implicit-slope",
"Implicitly solve for stage state or slope.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
@@ -216,11 +212,6 @@ int main(int argc, char *argv[])
// 9. Initialize the conduction operator and the VisIt visualization.
ConductionOperator oper(fespace, alpha, kappa, u);
using ImplicitVariableType = ConductionOperator::ImplicitVariableType;
ImplicitVariableType imp_var = solve_implicit_state ?
ImplicitVariableType::STATE
: ImplicitVariableType::SLOPE;
oper.SetImplicitVariableType(imp_var);
u_gf.SetFromTrueDofs(u);
{
@@ -416,14 +407,11 @@ void ConductionOperator::Mult(const Vector &u, Vector &du_dt) const
}
void ConductionOperator::ImplicitSolve(const real_t dt,
const Vector &u, Vector &k)
const Vector &u, Vector &du_dt)
{
// Solve the equation:
// M*k = -K(u + dt*k) for k = du/dt, if solving for stage-slope
// or
// M*k = -dt*K(k) + M*u for k = u_s, if solving for stage-state
// where K is linearized by using u from the previous timestep, and
// the stage-state and slope relation: du/dt = (u_s - u)/dt.
// du_dt = M^{-1}*[-K(u + dt*du_dt)]
// for du_dt, where K is linearized by using u from the previous timestep
if (!T)
{
T = Add(1.0, Mmat, dt, Kmat);
@@ -431,20 +419,9 @@ void ConductionOperator::ImplicitSolve(const real_t dt,
T_solver.SetOperator(*T);
}
MFEM_VERIFY(dt == current_dt, ""); // SDIRK methods use the same dt
// Construct current right-hand side for stage state vs. slope solve
if (ImplicitVarTypeIsState())
{
// k, on return, is the stage value u
Mmat.Mult(u, z);
}
else
{
// k, on return, is the stage slope du/dt
Kmat.Mult(u, z);
z.Neg();
}
T_solver.Mult(z, k);
Kmat.Mult(u, z);
z.Neg();
T_solver.Mult(z, du_dt);
}
void ConductionOperator::SetParameters(const Vector &u)
+1 -1
View File
@@ -119,7 +119,7 @@ int main(int argc, char *argv[])
}
LinearForm b(&fespace);
b.AddBoundaryIntegrator(new VectorBoundaryLFIntegrator(f));
b.AddDomainIntegrator(new VectorBoundaryLFIntegrator(f));
// 6. Set up the bilinear form a(.,.) on the finite element space
// corresponding to the linear elasticity integrator with piece-wise
+1 -1
View File
@@ -140,7 +140,7 @@ int main(int argc, char *argv[])
}
ParLinearForm b(&fespace);
b.AddBoundaryIntegrator(new VectorBoundaryLFIntegrator(f));
b.AddDomainIntegrator(new VectorBoundaryLFIntegrator(f));
// 6. Set up the bilinear form a(.,.) on the finite element space
// corresponding to the linear elasticity integrator with piece-wise
-3
View File
@@ -471,13 +471,10 @@ int main(int argc, char *argv[])
ofstream sol_r_ofs("sol_r.gf");
ofstream sol_i_ofs("sol_i.gf");
ofstream sol_z_ofs("sol_z.gf");
sol_r_ofs.precision(8);
sol_i_ofs.precision(8);
sol_z_ofs.precision(8);
u.real().Save(sol_r_ofs);
u.imag().Save(sol_i_ofs);
u.Save(sol_z_ofs);
}
// 14. Send the solution by socket to a GLVis server.
+10 -32
View File
@@ -302,21 +302,15 @@ int main(int argc, char *argv[])
char vishost[] = "localhost";
int visport = 19916;
socketstream sol_sock_r(vishost, visport);
socketstream sol_sock_i(vishost, visport);
sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
sol_sock_r.precision(8);
sol_sock_i.precision(8);
sol_sock_r << "solution\n" << *pmesh << u_exact->real()
<< "window_title 'Exact: Real Part'" << flush;
// Make sure all ranks have sent their real solution before initiating
// another set of GLVis connections (one from each rank):
MPI_Barrier(pmesh->GetComm());
socketstream sol_sock_i(vishost, visport);
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
sol_sock_i.precision(8);
sol_sock_i << "solution\n" << *pmesh << u_exact->imag()
<< "window_title 'Exact: Imaginary Part'" << flush;
// Make sure all ranks have sent their imaginary solution before initiating
// another set of GLVis connections (one from each rank):
MPI_Barrier(pmesh->GetComm());
}
// 11. Set up the parallel sesquilinear form a(.,.) on the finite element
@@ -513,11 +507,10 @@ int main(int argc, char *argv[])
// 15. Save the refined mesh and the solution in parallel. This output can be
// viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
{
ostringstream mesh_name, sol_r_name, sol_i_name, sol_z_name;
ostringstream mesh_name, sol_r_name, sol_i_name;
mesh_name << "mesh." << setfill('0') << setw(6) << myid;
sol_r_name << "sol_r." << setfill('0') << setw(6) << myid;
sol_i_name << "sol_i." << setfill('0') << setw(6) << myid;
sol_z_name << "sol_z." << setfill('0') << setw(6) << myid;
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(8);
@@ -525,13 +518,10 @@ int main(int argc, char *argv[])
ofstream sol_r_ofs(sol_r_name.str().c_str());
ofstream sol_i_ofs(sol_i_name.str().c_str());
ofstream sol_z_ofs(sol_z_name.str().c_str());
sol_r_ofs.precision(8);
sol_i_ofs.precision(8);
sol_z_ofs.precision(8);
u.real().Save(sol_r_ofs);
u.imag().Save(sol_i_ofs);
u.Save(sol_z_ofs);
}
// 16. Send the solution by socket to a GLVis server.
@@ -540,21 +530,15 @@ int main(int argc, char *argv[])
char vishost[] = "localhost";
int visport = 19916;
socketstream sol_sock_r(vishost, visport);
socketstream sol_sock_i(vishost, visport);
sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
sol_sock_r.precision(8);
sol_sock_i.precision(8);
sol_sock_r << "solution\n" << *pmesh << u.real()
<< "window_title 'Solution: Real Part'" << flush;
// Make sure all ranks have sent their real solution before initiating
// another set of GLVis connections (one from each rank):
MPI_Barrier(pmesh->GetComm());
socketstream sol_sock_i(vishost, visport);
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
sol_sock_i.precision(8);
sol_sock_i << "solution\n" << *pmesh << u.imag()
<< "window_title 'Solution: Imaginary Part'" << flush;
// Make sure all ranks have sent their imaginary solution before initiating
// another set of GLVis connections (one from each rank):
MPI_Barrier(pmesh->GetComm());
}
if (visualization && exact_sol)
{
@@ -563,21 +547,15 @@ int main(int argc, char *argv[])
char vishost[] = "localhost";
int visport = 19916;
socketstream sol_sock_r(vishost, visport);
socketstream sol_sock_i(vishost, visport);
sol_sock_r << "parallel " << num_procs << " " << myid << "\n";
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
sol_sock_r.precision(8);
sol_sock_i.precision(8);
sol_sock_r << "solution\n" << *pmesh << u_exact->real()
<< "window_title 'Error: Real Part'" << flush;
// Make sure all ranks have sent their real solution before initiating
// another set of GLVis connections (one from each rank):
MPI_Barrier(pmesh->GetComm());
socketstream sol_sock_i(vishost, visport);
sol_sock_i << "parallel " << num_procs << " " << myid << "\n";
sol_sock_i.precision(8);
sol_sock_i << "solution\n" << *pmesh << u_exact->imag()
<< "window_title 'Error: Imaginary Part'" << flush;
// Make sure all ranks have sent their imaginary solution before initiating
// another set of GLVis connections (one from each rank):
MPI_Barrier(pmesh->GetComm());
}
if (visualization)
{
+52 -11
View File
@@ -5,8 +5,8 @@
// Sample runs:
// ex37 -alpha 10
// ex37 -alpha 10 -pv
// ex37 -lambda 0.1 -mu 0.1 -growth 1
// ex37 -o 2 -alpha 10.0 -mi 50 -vf 0.4 -ntol 1e-5 -growth 1.5
// 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 solve a
@@ -55,6 +55,53 @@
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 real_t Final volume, ∫_Ω sigmoid(ψ)
*/
real_t proj(GridFunction &psi, real_t target_volume, real_t tol=1e-12,
int max_its=10)
{
MappedGridFunctionCoefficient sigmoid_psi(&psi, sigmoid);
MappedGridFunctionCoefficient der_sigmoid_psi(&psi, der_sigmoid);
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_sigmoid_psi.Assemble(); // Recompute f(c) with updated ψ
const real_t f = int_sigmoid_psi.Sum() - target_volume;
int_der_sigmoid_psi.Assemble(); // Recompute df(c) with updated ψ
const real_t df = int_der_sigmoid_psi.Sum();
const real_t 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();
return int_sigmoid_psi.Sum();
}
/*
* ---------------------------------------------------------------
* ALGORITHM PREAMBLE
@@ -133,11 +180,10 @@ int main(int argc, char *argv[])
int ref_levels = 5;
int order = 2;
real_t alpha = 1.0;
real_t growth = 2;
real_t epsilon = 0.01;
real_t vol_fraction = 0.5;
int max_it = 1e3;
real_t itol = 1e-2;
real_t itol = 1e-1;
real_t ntol = 1e-4;
real_t rho_min = 1e-6;
real_t lambda = 1.0;
@@ -152,8 +198,6 @@ int main(int argc, char *argv[])
"Order (degree) of the finite elements.");
args.AddOption(&alpha, "-alpha", "--alpha-step-length",
"Step length for gradient descent.");
args.AddOption(&growth, "-growth", "--alpha-growth-rate",
"Growth rate of step length for gradient descent.");
args.AddOption(&epsilon, "-epsilon", "--epsilon-thickness",
"Length scale for ρ.");
args.AddOption(&max_it, "-mi", "--max-it",
@@ -288,7 +332,6 @@ int main(int argc, char *argv[])
}
FilterSolver->SetEssentialBoundary(ess_bdr_filter);
FilterSolver->SetupFEM();
FilterSolver->AssembleDiffusionBilinear();
BilinearForm mass(&control_fes);
mass.AddDomainIntegrator(new InverseIntegrator(new MassIntegrator(one)));
@@ -342,7 +385,7 @@ int main(int argc, char *argv[])
// 11. Iterate:
for (int k = 1; k <= max_it; k++)
{
if (k > 1) { alpha = std::pow((real_t) k,growth); }
if (k > 1) { alpha *= ((real_t) k) / ((real_t) k-1); }
mfem::out << "\nStep = " << k << std::endl;
@@ -379,9 +422,7 @@ int main(int argc, char *argv[])
// Step 5 - Update design variable ψ ← proj(ψ - αG)
psi.Add(-alpha, grad);
GridFunction alpha_grad(grad);
alpha_grad *= alpha;
const real_t material_volume = proj(psi, alpha_grad, target_volume);
const real_t material_volume = proj(psi, target_volume);
// Compute ||ρ - ρ_old|| in control fes.
real_t norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
+23 -183
View File
@@ -137,7 +137,7 @@ public:
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(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");
}
@@ -231,12 +231,9 @@ private:
FiniteElementCollection * fec = nullptr;
FiniteElementSpace * fes = nullptr;
Array<int> ess_bdr;
Array<int> ess_tdof_list;
Array<int> neumann_bdr;
GridFunction * u = nullptr;
LinearForm * b = nullptr;
BilinearForm * a = nullptr;
OperatorPtr A;
bool parallel;
#ifdef MFEM_USE_MPI
ParMesh * pmesh = nullptr;
@@ -270,8 +267,6 @@ public:
void ResetFEM();
void SetupFEM();
void UpdateEssentialTDofs();
void AssembleDiffusionBilinear(bool update_ess_tdofs=true);
void Solve();
GridFunction * GetFEMSolution();
LinearForm * GetLinearForm() {return b;}
@@ -376,130 +371,6 @@ public:
};
/**
* @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(Ω)
* using the Illinois method
* 2. Set ψ ← ψ + c.
*
* @param psi a GridFunction to be updated
* @param alpha_grad alpha multiplied by gradient
* @param target_volume θ vol(Ω)
* @param tol Illinois iteration tolerance
* @param max_its Illinois maximum iteration number
* @return real_t Final volume (∫_Ω sigmoid(ψ) dx)
*/
real_t proj(GridFunction &psi, GridFunction &alpha_grad, real_t target_volume,
real_t tol = 1e-12, int max_its = 100)
{
#ifdef MFEM_USE_MPI
FiniteElementSpace *fes = psi.FESpace();
ParFiniteElementSpace *pfes = dynamic_cast<ParFiniteElementSpace*>(fes);
#endif
ConstantCoefficient zero_cf(0.0);
real_t a = -alpha_grad.ComputeMaxError(zero_cf);
real_t b = -a;
real_t y = 0.0;
MappedGridFunctionCoefficient sigmoid_psi(
&psi, [&y](const real_t x) { return sigmoid(x + y); });
std::unique_ptr<LinearForm> int_sigmoid_psi;
#ifdef MFEM_USE_MPI
ParGridFunction *par_psi = dynamic_cast<ParGridFunction *>(&psi);
if (par_psi)
{
int_sigmoid_psi.reset(new ParLinearForm(par_psi->ParFESpace()));
}
else
{
int_sigmoid_psi.reset(new LinearForm(psi.FESpace()));
}
#else
int_sigmoid_psi.reset(new LinearForm(psi.FESpace()));
#endif
int_sigmoid_psi->AddDomainIntegrator(new DomainLFIntegrator(sigmoid_psi));
y = a;
int_sigmoid_psi->Assemble();
real_t f_a = int_sigmoid_psi->Sum(); // f_a := f(a) + θ vol(Ω)
y = b;
int_sigmoid_psi->Assemble();
real_t f_b = int_sigmoid_psi->Sum(); // f_b := f(b) + θ vol(Ω)
#ifdef MFEM_USE_MPI
if (pfes)
{
MPI_Allreduce(MPI_IN_PLACE, &f_a, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, MPI_COMM_WORLD);
MPI_Allreduce(MPI_IN_PLACE, &f_b, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, MPI_COMM_WORLD);
}
#endif
f_a -= target_volume; // f_a := f(a)
f_b -= target_volume; // f_b := f(b)
real_t c = 0.0;
real_t f_c = 0.0;
int side = 0;
bool done = false;
for (int k=0; k < max_its; k++)
{
c = (f_a * b - f_b * a) / (f_a - f_b);
if (abs(b - a) < tol * abs(b + a)) { done = true; break; }
y = c;
int_sigmoid_psi->Assemble();
f_c = int_sigmoid_psi->Sum(); // f_c := f(c) + θ vol(Ω)
#ifdef MFEM_USE_MPI
if (pfes)
{
MPI_Allreduce(MPI_IN_PLACE, &f_c, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, MPI_COMM_WORLD);
}
#endif
f_c -= target_volume; // f_c := f(c)
if (f_c * f_b > 0)
{
b = c;
f_b = f_c;
if (side == -1) { f_a /= 2.0; }
side = -1;
}
else if (f_c * f_a > 0)
{
a = c;
f_a = f_c;
if (side == 1) { f_b /= 2.0; }
side = 1;
}
else
{
done = true; break;
}
}
if (!done)
{
mfem_warning("Projection reached maximum iteration without converging. "
"Result may not be accurate.");
}
y = 0.0;
psi += c;
int_sigmoid_psi->Assemble();
real_t material_volume = int_sigmoid_psi->Sum();
#ifdef MFEM_USE_MPI
if (pfes)
{
MPI_Allreduce(MPI_IN_PLACE, &material_volume, 1,
MPITypeMap<real_t>::mpi_type, MPI_SUM, MPI_COMM_WORLD);
}
#endif
return material_volume;
}
// Poisson solver
@@ -551,8 +422,12 @@ void DiffusionSolver::SetupFEM()
}
}
void DiffusionSolver::UpdateEssentialTDofs()
void DiffusionSolver::Solve()
{
OperatorPtr A;
Vector B, X;
Array<int> ess_tdof_list;
#ifdef MFEM_USE_MPI
if (parallel)
{
@@ -565,39 +440,7 @@ void DiffusionSolver::UpdateEssentialTDofs()
#else
fes->GetEssentialTrueDofs(ess_bdr,ess_tdof_list);
#endif
}
void DiffusionSolver::AssembleDiffusionBilinear(bool update_ess_tdofs)
{
if (update_ess_tdofs)
{
UpdateEssentialTDofs();
}
#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();
a->FormSystemMatrix(ess_tdof_list, A);
}
void DiffusionSolver::Solve()
{
Vector B, X;
*u=0.0;
if (b)
{
delete b;
@@ -632,33 +475,31 @@ void DiffusionSolver::Solve()
b->Assemble();
*u=0.0;
if (essbdr_cf)
{
u->ProjectBdrCoefficient(*essbdr_cf,ess_bdr);
}
BilinearForm * a = nullptr;
#ifdef MFEM_USE_MPI
if (parallel)
{
X.SetSize(pfes->TrueVSize());
B.SetSize(pfes->TrueVSize());
dynamic_cast<ParGridFunction*>(u)->ParallelAssemble(X);
dynamic_cast<ParLinearForm*>(b)->ParallelAssemble(B);
dynamic_cast<ParBilinearForm*>(a)->ParallelEliminateTDofsInRHS(
ess_tdof_list, X, B);
a = new ParBilinearForm(pfes);
}
else
{
X.NewDataAndSize(u->GetData(), u->Size());
B.NewDataAndSize(b->GetData(), b->Size());
a->EliminateVDofsInRHS(ess_tdof_list, X, B);
a = new BilinearForm(fes);
}
#else
X.NewDataAndSize(u->GetData(), u->Size());
B.NewDataAndSize(b->GetData(), b->Size());
a->EliminateVDofsInRHS(ess_tdof_list, X, B);
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;
@@ -687,6 +528,7 @@ void DiffusionSolver::Solve()
delete M;
delete cg;
a->RecoverFEMSolution(X, *b, *u);
delete a;
}
GridFunction * DiffusionSolver::GetFEMSolution()
@@ -718,8 +560,6 @@ DiffusionSolver::~DiffusionSolver()
#endif
delete fec; fec = nullptr;
delete b;
A.Clear();
delete a;
}
+60 -11
View File
@@ -4,8 +4,8 @@
//
// Sample runs:
// mpirun -np 4 ex37p -alpha 10 -pv
// mpirun -np 4 ex37p -lambda 0.1 -mu 0.1 -growth 1
// mpirun -np 4 ex37p -o 2 -alpha 10.0 -mi 50 -vf 0.4 -ntol 1e-5 -growth 1.5
// 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
@@ -54,6 +54,61 @@
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 real_t Final volume, ∫_Ω sigmoid(ψ)
*/
real_t proj(ParGridFunction &psi, real_t target_volume, real_t 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 ψ
real_t f = int_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &f, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, MPI_COMM_WORLD);
f -= target_volume;
int_der_sigmoid_psi.Assemble(); // Recompute df(c) with updated ψ
real_t df = int_der_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &df, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, MPI_COMM_WORLD);
const real_t 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();
real_t material_volume = int_sigmoid_psi.Sum();
MPI_Allreduce(MPI_IN_PLACE, &material_volume, 1,
MPITypeMap<real_t>::mpi_type, MPI_SUM, MPI_COMM_WORLD);
return material_volume;
}
/*
* ---------------------------------------------------------------
* ALGORITHM PREAMBLE
@@ -138,11 +193,10 @@ int main(int argc, char *argv[])
int ref_levels = 5;
int order = 2;
real_t alpha = 1.0;
real_t growth = 2;
real_t epsilon = 0.01;
real_t vol_fraction = 0.5;
int max_it = 1e3;
real_t itol = 1e-2;
real_t itol = 1e-1;
real_t ntol = 1e-4;
real_t rho_min = 1e-6;
real_t lambda = 1.0;
@@ -157,8 +211,6 @@ int main(int argc, char *argv[])
"Order (degree) of the finite elements.");
args.AddOption(&alpha, "-alpha", "--alpha-step-length",
"Step length for gradient descent.");
args.AddOption(&growth, "-growth", "--alpha-growth-rate",
"Growth rate of step length for gradient descent.");
args.AddOption(&epsilon, "-epsilon", "--epsilon-thickness",
"Length scale for ρ.");
args.AddOption(&max_it, "-mi", "--max-it",
@@ -307,7 +359,6 @@ int main(int argc, char *argv[])
}
FilterSolver->SetEssentialBoundary(ess_bdr_filter);
FilterSolver->SetupFEM();
FilterSolver->AssembleDiffusionBilinear();
ParBilinearForm mass(&control_fes);
mass.AddDomainIntegrator(new InverseIntegrator(new MassIntegrator(one)));
@@ -361,7 +412,7 @@ int main(int argc, char *argv[])
// 11. Iterate:
for (int k = 1; k <= max_it; k++)
{
if (k > 1) { alpha = std::pow((real_t) k,growth); }
if (k > 1) { alpha *= ((real_t) k) / ((real_t) k-1); }
if (myid == 0)
{
@@ -401,9 +452,7 @@ int main(int argc, char *argv[])
// Step 5 - Update design variable ψ ← proj(ψ - αG)
psi.Add(-alpha, grad);
ParGridFunction alpha_grad(grad);
alpha_grad *= alpha;
const real_t material_volume = proj(psi, alpha_grad, target_volume);
const real_t material_volume = proj(psi, target_volume);
// Compute ||ρ - ρ_old|| in control fes.
real_t norm_increment = zerogf.ComputeL1Error(succ_diff_rho);
+1 -5
View File
@@ -9,7 +9,6 @@
// ex4 -m ../data/beam-hex.mesh -o 2 -pa
// ex4 -m ../data/escher.mesh
// ex4 -m ../data/fichera.mesh -o 2 -hb
// ex4 -m ../data/fichera.mesh -o 2 -hb -ea
// ex4 -m ../data/fichera-q2.vtk
// ex4 -m ../data/fichera-q3.mesh -o 2 -sc
// ex4 -m ../data/square-disc-nurbs.mesh
@@ -19,7 +18,6 @@
// ex4 -m ../data/amr-quad.mesh
// ex4 -m ../data/amr-hex.mesh
// ex4 -m ../data/amr-hex.mesh -o 2 -hb
// ex4 -m ../data/amr-hex.mesh -o 2 -hb -ea
// ex4 -m ../data/fichera-amr.mesh -o 2 -sc
// ex4 -m ../data/ref-prism.mesh -o 1
// ex4 -m ../data/octahedron.mesh -o 1
@@ -27,8 +25,6 @@
//
// Device sample runs:
// ex4 -m ../data/star.mesh -pa -d cuda
// ex4 -m ../data/star.mesh -hb -ea -d cuda
// ex4 -m ../data/amr-quad.mesh -hb -ea -d cuda
// ex4 -m ../data/star.mesh -pa -d raja-cuda
// ex4 -m ../data/star.mesh -pa -d raja-omp
// ex4 -m ../data/beam-hex.mesh -pa -d cuda
@@ -197,7 +193,7 @@ int main(int argc, char *argv[])
cout << "Size of linear system: " << A->Height() << endl;
// 11. Solve the linear system A X = B.
if (!pa && (!ea || hybridization))
if (!pa)
{
#ifndef MFEM_USE_SUITESPARSE
// Use a simple symmetric Gauss-Seidel preconditioner with PCG.
-589
View File
@@ -1,589 +0,0 @@
// MFEM Example 41
//
// Compile with: make ex41
//
// Sample runs:
// ex41
// ex41 -cg
// ex41 -m ../data/periodic-hexagon.mesh -p 0 -r 2 -dt 0.005 -tf 10
// ex41 -m ../data/periodic-square.mesh -p 1 -r 2 -dt 0.005 -tf 9
// ex41 -m ../data/periodic-hexagon.mesh -p 1 -r 2 -dt 0.005 -tf 9
// ex41 -m ../data/amr-quad.mesh -p 1 -r 2 -dt 0.002 -tf 9
// ex41 -m ../data/star-q3.mesh -p 1 -r 2 -dt 0.001 -tf 9
// ex41 -m ../data/star-mixed.mesh -p 1 -r 2 -dt 0.005 -tf 9
// ex41 -m ../data/disc-nurbs.mesh -p 1 -r 3 -dt 0.005 -tf 9
// ex41 -m ../data/disc-nurbs.mesh -p 2 -r 3 -dt 0.005 -tf 9
// ex41 -m ../data/periodic-square.mesh -p 3 -r 4 -dt 0.0025 -tf 9 -vs 20
// ex41 -m ../data/periodic-cube.mesh -p 0 -r 2 -o 2 -dt 0.01 -tf 8
//
// Device sample runs:
//
// Description: This example code solves the time-dependent advection-diffusion
// equation du/dt + v.grad(u) - a div(grad(u)) = 0, where v is a
// given fluid velocity, a is the diffusion coefficient, and
// u0(x)=u(0,x) is a given initial condition.
//
// The example demonstrates the use of Discontinuous Galerkin (DG)
// bilinear forms in MFEM (face integrators), and the use of IMEX
// ODE time integrators.
//
// The option to use continuous finite elements is available too.
#include "mfem.hpp"
using namespace std;
using namespace mfem;
// Mesh bounding box
Vector bb_min, bb_max;
// Velocity coefficient
template<int problem=0>
void velocity_function(const Vector &x, Vector &v)
{
int dim = x.Size();
// map to the reference [-1,1] domain
Vector X(dim);
for (int i = 0; i < dim; i++)
{
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
switch (problem)
{
case 0:
{
// Translations in 1D, 2D, and 3D
switch (dim)
{
case 1: v(0) = 1.0; break;
case 2: v(0) = sqrt(2./3.); v(1) = sqrt(1./3.); break;
case 3: v(0) = sqrt(3./6.); v(1) = sqrt(2./6.); v(2) = sqrt(1./6.);
break;
}
break;
}
case 1:
case 2:
{
// Clockwise rotation in 2D around the origin
const real_t w = M_PI/2;
switch (dim)
{
case 1: v(0) = 1.0; break;
case 2: v(0) = w*X(1); v(1) = -w*X(0); break;
case 3: v(0) = w*X(1); v(1) = -w*X(0); v(2) = 0.0; break;
}
break;
}
case 3:
{
// Clockwise twisting rotation in 2D around the origin
const real_t w = M_PI/2;
real_t d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
d = d*d;
switch (dim)
{
case 1: v(0) = 1.0; break;
case 2: v(0) = d*w*X(1); v(1) = -d*w*X(0); break;
case 3: v(0) = d*w*X(1); v(1) = -d*w*X(0); v(2) = 0.0; break;
}
break;
}
}
}
// Initial condition
template<int problem=0>
real_t u0_function(const Vector &x)
{
int dim = x.Size();
// map to the reference [-1,1] domain
Vector X(dim);
for (int i = 0; i < dim; i++)
{
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
switch (problem)
{
case 0:
case 1:
{
switch (dim)
{
case 1:
return exp(-40.*pow(X(0)-0.5,2));
case 2:
case 3:
{
real_t rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
if (dim == 3)
{
const real_t s = (1. + 0.25*cos(2*M_PI*X(2)));
rx *= s;
ry *= s;
}
return ( std::erfc(w*(X(0)-cx-rx))*std::erfc(-w*(X(0)-cx+rx)) *
std::erfc(w*(X(1)-cy-ry))*std::erfc(-w*(X(1)-cy+ry)) )/16;
}
}
}
case 2:
{
real_t x_ = X(0), y_ = X(1), rho, phi;
rho = std::hypot(x_, y_);
phi = atan2(y_, x_);
return pow(sin(M_PI*rho),2)*sin(3*phi);
}
case 3:
{
const real_t f = M_PI;
return sin(f*X(0))*sin(f*X(1));
}
}
return 0.0;
}
/// Solver for the implicit part of the ODE (the diffusion term).
/// Solves systems of the form: (M + dt*S) k = rhs.
class Implicit_Solver : public Solver
{
private:
SparseMatrix &M, &S, A;
CGSolver linear_solver;
BlockILU prec;
real_t dt;
public:
Implicit_Solver(SparseMatrix &M_, SparseMatrix &S_,
const FiniteElementSpace &fes)
: M(M_),
S(S_),
prec(fes.GetTypicalFE()->GetDof(),
BlockILU::Reordering::MINIMUM_DISCARDED_FILL),
dt(1.0)
{
linear_solver.iterative_mode = false;
linear_solver.SetRelTol(1e-9);
linear_solver.SetAbsTol(0.0);
linear_solver.SetMaxIter(100);
linear_solver.SetPrintLevel(0);
linear_solver.SetPreconditioner(prec);
}
void SetTimeStep(real_t dt_)
{
real_t ddt = dt-dt_;
real_t epsilon;
epsilon = std::numeric_limits<real_t>::epsilon();
epsilon*=10;
if (std::abs(ddt) > epsilon)
{
dt = dt_;
// Form operator A = M + dt*S
A = S;
A *= dt;
A += M;
// this will also call SetOperator on the preconditioner
linear_solver.SetOperator(A);
}
}
void SetOperator(const Operator &op) override
{
linear_solver.SetOperator(op);
}
void Mult(const Vector &x, Vector &y) const override
{
linear_solver.Mult(x, y);
}
};
/** A time-dependent operator for the right-hand side of the ODE. The weak
form of the advection-diffusion equation is M du/dt = K u - S u + b,
where M is the mass matrix, K and S are the advection and diffusion
matrices, and b describes the flow on the boundary. In the case of IMEX
evolution, the diffusion term is treated implicitly, and the advection
term is treated explicitly. */
class IMEX_Evolution : public TimeDependentOperator
{
private:
BilinearForm &M, &K, &S;
const Vector &b;
unique_ptr<Solver> M_prec;
CGSolver M_solver;
unique_ptr<Implicit_Solver> implicit_solver;
mutable Vector z;
public:
IMEX_Evolution(BilinearForm &M_, BilinearForm &K_, BilinearForm &S_,
const Vector &b_);
/// Evaluate k1=M^{-1}*G1(u,t); -> k1 = M^{-1}*(K*u + b)
void Mult1(const Vector &x, Vector &y) const;
/// Evaluate k2: M*k2 = G2(u+k2*dt,t); -> (M+S*dt)*k2=-S*u
void ImplicitSolve2(const real_t dt, const Vector &x, Vector &k);
void Mult(const Vector &x, Vector &y) const override
{
if (TimeDependentOperator::EvalMode::ADDITIVE_TERM_1 == GetEvalMode())
{
Mult1(x,y);
}
else
{
mfem_error("TimeDependentOperator::Mult() is not overridden!");
}
}
void ImplicitSolve(const real_t dt, const Vector &x, Vector &k) override
{
if (TimeDependentOperator::EvalMode::ADDITIVE_TERM_2 == GetEvalMode())
{
ImplicitSolve2(dt,x,k);
}
else
{
mfem_error("TimeDependentOperator::ImplicitSolve() is not overridden!");
}
}
};
int main(int argc, char *argv[])
{
// 1. Parse command-line options.
int problem = 0;
const char *mesh_file = "../data/periodic-square.mesh";
int ref_levels = 2;
int order = 3;
int ode_solver_type = 64; //IMEXRK3(3,4,3)
real_t t_final = 10.0;
real_t dt = 0.01;
bool paraview = false;
bool cg = false;
int vis_steps = 50;
real_t diffusion_term = 0.01;
real_t kappa = -1.0;
real_t sigma = -1.0;
bool visualization = true;
bool visit = false;
bool binary = false;
int precision = 8;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh", "Mesh file to use.");
args.AddOption(&problem, "-p", "--problem",
"Problem setup to use. See options in velocity_function().");
args.AddOption(&ref_levels, "-r", "--refine",
"Number of times to refine the mesh uniformly.");
args.AddOption(&order, "-o", "--order", "Order of the finite elements.");
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
ODESolver::IMEXTypes.c_str());
args.AddOption(&t_final, "-tf", "--t-final", "Final time; start time is 0.");
args.AddOption(&dt, "-dt", "--time-step", "Time step.");
args.AddOption(&diffusion_term, "-dc", "--diffusion-coeff",
"Diffusion coefficient in the PDE.");
args.AddOption(&paraview, "-paraview", "--paraview-datafiles", "-no-paraview",
"--no-paraview-datafiles",
"Save data files for ParaView (paraview.org) visualization.");
args.AddOption(&vis_steps, "-vs", "--visualization-steps",
"Visualize every n-th timestep.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&binary, "-binary", "--binary-datafiles", "-ascii",
"--ascii-datafiles",
"Use binary (Sidre) or ascii format for VisIt data files.");
args.AddOption(&visit, "-visit", "--visit-datafiles", "-no-visit",
"--no-visit-datafiles",
"Save data files for VisIt (visit.llnl.gov) visualization.");
args.AddOption(&cg, "-cg", "--continuous-galerkin", "-dg",
"--discontinuous-galerkin",
"Use Continuous-Galerkin Finite elements (Default is DG)");
args.Parse();
if (!args.Good())
{
args.PrintUsage(cout);
return 1;
}
if (kappa < 0)
{
kappa = (order+1)*(order+1);
}
args.PrintOptions(cout);
// 2. Read the mesh from the given mesh file. We can handle geometrically
// periodic meshes in this code.
Mesh mesh(mesh_file);
const int dim = mesh.Dimension();
// 3. Define the IMEX (Split) ODE solver used for time integration. The IMEX
// solvers currently available are: 61 - Forward Backward Euler,
// 62 - IMEXRK2(2,2,2), 63 - IMEXRK2(2,3,2), and 64 - IMEX_DIRK_RK3.
unique_ptr<ODESolver> ode_solver = ODESolver::SelectIMEX(ode_solver_type);
// 4. Refine the mesh to increase the resolution. In this example we do
// 'ref_levels' of uniform refinement, where 'ref_levels' is a
// command-line parameter.
for (int lev = 0; lev < ref_levels; lev++) {mesh.UniformRefinement();}
if (mesh.NURBSext) {mesh.SetCurvature(max(order, 1));}
mesh.GetBoundingBox(bb_min, bb_max, max(order, 1));
// 5. Define the discontinuous DG finite element space of the given
// polynomial order on the refined mesh.
FiniteElementCollection *fec = NULL;
if (cg)
{
fec = new H1_FECollection(order, dim);
}
else
{
fec = new DG_FECollection(order, dim, BasisType::GaussLobatto);
}
FiniteElementSpace fes(&mesh, fec);
cout << "Number of unknowns: " << fes.GetVSize() << endl;
// 6. Set up and assemble the bilinear and linear forms corresponding to the
// DG discretization. The DGTraceIntegrator involves integrals over mesh
// interior faces.
std::unique_ptr<VectorFunctionCoefficient> velocity;
if (0==problem)
{
velocity.reset(new VectorFunctionCoefficient(dim, velocity_function<0>));
}
else if (1==problem)
{
velocity.reset(new VectorFunctionCoefficient(dim, velocity_function<1>));
}
else if (2==problem)
{
velocity.reset(new VectorFunctionCoefficient(dim, velocity_function<2>));
}
else if (3==problem)
{
velocity.reset(new VectorFunctionCoefficient(dim, velocity_function<3>));
}
ConstantCoefficient diff_coeff(diffusion_term);
BilinearForm m(&fes);
BilinearForm k(&fes);
BilinearForm s(&fes);
Vector b(fes.GetTrueVSize());
b = 0.0; //The inflow on the boundaries is set to zero.
m.AddDomainIntegrator(new MassIntegrator);
constexpr real_t alpha = -1.0;
k.AddDomainIntegrator(new ConvectionIntegrator(*velocity, alpha));
s.AddDomainIntegrator(new DiffusionIntegrator(diff_coeff));
if (!cg)
{
k.AddInteriorFaceIntegrator(new NonconservativeDGTraceIntegrator(*velocity,
alpha));
k.AddBdrFaceIntegrator(new NonconservativeDGTraceIntegrator(*velocity, alpha));
s.AddInteriorFaceIntegrator(new DGDiffusionIntegrator(diff_coeff, sigma,
kappa));
s.AddBdrFaceIntegrator(new DGDiffusionIntegrator(diff_coeff, sigma, kappa));
}
int skip_zeros = 0;
m.Assemble(skip_zeros);
k.Assemble(skip_zeros);
s.Assemble(skip_zeros);
m.Finalize(skip_zeros);
k.Finalize(skip_zeros);
s.Finalize(skip_zeros);
// 7. Define the initial conditions.
std::unique_ptr<FunctionCoefficient> u0;
if (0==problem)
{
u0.reset(new FunctionCoefficient(u0_function<0>));
}
else if (1==problem)
{
u0.reset(new FunctionCoefficient(u0_function<1>));
}
else if (2==problem)
{
u0.reset(new FunctionCoefficient(u0_function<2>));
}
else if (3==problem)
{
u0.reset(new FunctionCoefficient(u0_function<3>));
}
GridFunction u(&fes);
u.ProjectCoefficient(*u0);
// Create data collection for solution output: either VisItDataCollection for
// ascii data files, or SidreDataCollection for binary data files.
DataCollection *dc = NULL;
if (visit)
{
if (binary)
{
#ifdef MFEM_USE_SIDRE
dc = new SidreDataCollection("Example41", &mesh);
#else
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
#endif
}
else
{
dc = new VisItDataCollection("Example41", &mesh);
dc->SetPrecision(precision);
}
dc->RegisterField("solution", &u);
dc->SetCycle(0);
dc->SetTime(0.0);
dc->Save();
}
// 8. Set up paraview visualization, if desired.
unique_ptr<ParaViewDataCollection> pv;
if (paraview)
{
pv = make_unique<ParaViewDataCollection>("Example41", &mesh);
pv->SetPrefixPath("ParaView");
pv->RegisterField("solution", &u);
pv->SetLevelsOfDetail(order);
pv->SetDataFormat(VTKFormat::BINARY);
pv->SetHighOrderOutput(true);
pv->SetCycle(0);
pv->SetTime(0.0);
pv->Save();
}
socketstream sout;
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
sout.open(vishost, visport);
if (!sout)
{
cout << "Unable to connect to GLVis server at "
<< vishost << ':' << visport << endl;
visualization = false;
cout << "GLVis visualization disabled.\n";
}
else
{
sout.precision(precision);
sout << "solution\n" << mesh << u;
sout << "pause\n";
sout << flush;
cout << "GLVis visualization paused."
<< " Press space (in the GLVis window) to resume it.\n";
}
}
// 9. Define the time-dependent evolution operator describing the ODE
// right-hand side, and perform time-integration (looping over the time
// iterations, ti, with a time-step dt).
IMEX_Evolution adv(m, k, s, b);
real_t t = 0.0;
adv.SetTime(t);
ode_solver->Init(adv);
bool done = false;
for (int ti = 0; !done; )
{
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(u, t, dt_real);
ti++;
done = (t >= t_final - 1e-8*dt);
if (done || ti % vis_steps == 0)
{
cout << "time step: " << ti << ", time: " << t << endl;
if (paraview)
{
pv->SetCycle(ti);
pv->SetTime(t);
pv->Save();
}
if (visualization)
{
sout << "solution\n" << mesh << u << flush;
}
if (visit)
{
dc->SetCycle(ti);
dc->SetTime(t);
dc->Save();
}
}
}
delete fec;
return 0;
}
// Implementation of class IMEX_Evolution
IMEX_Evolution::IMEX_Evolution(BilinearForm &M_, BilinearForm &K_,
BilinearForm &S_, const Vector &b_)
: TimeDependentOperator(M_.FESpace()->GetTrueVSize()),
M(M_), K(K_), S(S_), b(b_), z(height)
{
Array<int> ess_tdof_list;
if (M.GetAssemblyLevel() == AssemblyLevel::LEGACY)
{
M_prec = make_unique<DSmoother>(M.SpMat());
M_solver.SetOperator(M.SpMat());
implicit_solver = make_unique<Implicit_Solver>(M.SpMat(), S.SpMat(),
*M.FESpace());
}
else
{
MFEM_ABORT("Implicit time integration is not supported with partial assembly");
}
M_solver.SetPreconditioner(*M_prec);
M_solver.iterative_mode = false;
M_solver.SetRelTol(1e-9);
M_solver.SetAbsTol(0.0);
M_solver.SetMaxIter(100);
M_solver.SetPrintLevel(0);
}
void IMEX_Evolution::Mult1(const Vector &x, Vector &y) const
{
// Perform the explicit step
// y = M^{-1} (K x + b)
K.Mult(x, z);
z += b;
M_solver.Mult(z, y);
}
void IMEX_Evolution::ImplicitSolve2(const real_t dt, const Vector &x, Vector &k)
{
// Perform the implicit step
// solve for k, k = -(M+dt S)^{-1} S x
MFEM_VERIFY(implicit_solver != NULL,
"Implicit time integration is not supported with partial assembly");
S.Mult(x, z);
z.Neg();
implicit_solver->SetTimeStep(dt);
implicit_solver->Mult(z, k);
}
-737
View File
@@ -1,737 +0,0 @@
// MFEM Example 41 - Parallel Version
//
// Compile with: make ex41p
//
// Sample runs:
// mpirun -np 4 ex41p
// mpirun -np 4 ex41p -cg
// mpirun -np 4 ex41p -m ../data/periodic-hexagon.mesh -p 0 -dt 0.005 -tf 10
// mpirun -np 4 ex41p -m ../data/periodic-square.mesh -p 1 -dt 0.005 -tf 9
// mpirun -np 4 ex41p -m ../data/periodic-hexagon.mesh -p 1 -dt 0.005 -tf 9
// mpirun -np 4 ex41p -m ../data/star-q3.mesh -p 1 -rp 1 -dt 0.001 -tf 9
// mpirun -np 4 ex41p -m ../data/disc-nurbs.mesh -p 1 -rp 1 -dt 0.005 -tf 9
// mpirun -np 4 ex41p -m ../data/disc-nurbs.mesh -p 2 -rp 1 -dt 0.005 -tf 9
// mpirun -np 4 ex41p -m ../data/periodic-square.mesh -rp 2 -dt 0.0025 -tf 9 -vs 20
// mpirun -np 4 ex41p -m ../data/periodic-cube.mesh -p 0 -rs 2 -o 2 -dt 0.01 -tf 8
//
// Device sample runs:
//
// Description: This example code solves the time-dependent advection-diffusion
// equation du/dt + v.grad(u) - a div(grad(u)) = 0, where v is a
// given fluid velocity, a is the diffusion coefficient, and
// u0(x)=u(0,x) is a given initial condition.
//
// The example demonstrates the use of Discontinuous Galerkin (DG)
// bilinear forms in MFEM (face integrators), DG-LOR Preconditioning
// and the use of IMEX ODE time integrators.
//
// The Option to use Continuous Finite Elements is available too.
#include "mfem.hpp"
using namespace std;
using namespace mfem;
// Mesh bounding box
Vector bb_min, bb_max;
// Velocity coefficient
template<int problem=0>
void velocity_function(const Vector &x, Vector &v)
{
int dim = x.Size();
// map to the reference [-1,1] domain
Vector X(dim);
for (int i = 0; i < dim; i++)
{
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
switch (problem)
{
case 0:
{
// Translations in 1D, 2D, and 3D
switch (dim)
{
case 1: v(0) = 1.0; break;
case 2: v(0) = sqrt(2./3.); v(1) = sqrt(1./3.); break;
case 3: v(0) = sqrt(3./6.); v(1) = sqrt(2./6.); v(2) = sqrt(1./6.);
break;
}
break;
}
case 1:
case 2:
{
// Clockwise rotation in 2D around the origin
const real_t w = M_PI/2;
switch (dim)
{
case 1: v(0) = 1.0; break;
case 2: v(0) = w*X(1); v(1) = -w*X(0); break;
case 3: v(0) = w*X(1); v(1) = -w*X(0); v(2) = 0.0; break;
}
break;
}
case 3:
{
// Clockwise twisting rotation in 2D around the origin
const real_t w = M_PI/2;
real_t d = max((X(0)+1.)*(1.-X(0)),0.) * max((X(1)+1.)*(1.-X(1)),0.);
d = d*d;
switch (dim)
{
case 1: v(0) = 1.0; break;
case 2: v(0) = d*w*X(1); v(1) = -d*w*X(0); break;
case 3: v(0) = d*w*X(1); v(1) = -d*w*X(0); v(2) = 0.0; break;
}
break;
}
}
}
// Initial condition
template<int problem=0>
real_t u0_function(const Vector &x)
{
int dim = x.Size();
// map to the reference [-1,1] domain
Vector X(dim);
for (int i = 0; i < dim; i++)
{
real_t center = (bb_min[i] + bb_max[i]) * 0.5;
X(i) = 2 * (x(i) - center) / (bb_max[i] - bb_min[i]);
}
switch (problem)
{
case 0:
case 1:
{
switch (dim)
{
case 1:
return exp(-40.*pow(X(0)-0.5,2));
case 2:
case 3:
{
real_t rx = 0.45, ry = 0.25, cx = 0., cy = -0.2, w = 10.;
if (dim == 3)
{
const real_t s = (1. + 0.25*cos(2*M_PI*X(2)));
rx *= s;
ry *= s;
}
return ( std::erfc(w*(X(0)-cx-rx))*std::erfc(-w*(X(0)-cx+rx)) *
std::erfc(w*(X(1)-cy-ry))*std::erfc(-w*(X(1)-cy+ry)) )/16;
}
}
}
case 2:
{
real_t x_ = X(0), y_ = X(1), rho, phi;
rho = std::hypot(x_, y_);
phi = atan2(y_, x_);
return pow(sin(M_PI*rho),2)*sin(3*phi);
}
case 3:
{
const real_t f = M_PI;
return sin(f*X(0))*sin(f*X(1));
}
}
return 0.0;
}
class Implicit_Solver : public Solver
{
private:
HypreParMatrix &M, &S;
HypreParMatrix *A;
CGSolver linear_solver;
real_t dt;
SparseMatrix M_diag;
public:
Implicit_Solver(HypreParMatrix &M_, HypreParMatrix &S_,
const FiniteElementSpace &fes)
: M(M_),
S(S_),
A(nullptr),
linear_solver(M.GetComm()),
dt(1.0)
{
linear_solver.iterative_mode = false;
linear_solver.SetRelTol(1e-9);
linear_solver.SetAbsTol(0.0);
linear_solver.SetMaxIter(100);
linear_solver.SetPrintLevel(0);
M.GetDiag(M_diag);
}
void SetTimeStep(real_t dt_)
{
real_t ddt = dt-dt_;
// syncronize ddt across all processes
MPI_Comm comm = M.GetComm();
int myrank;
MPI_Comm_rank(comm, &myrank);
MPI_Bcast(&ddt, 1, MPI_DOUBLE, 0, comm);
real_t epsilon;
epsilon = std::numeric_limits<real_t>::epsilon();
// allow for some tolerance in the time stepping process
epsilon*=10;
if (fabs(ddt) > epsilon)
{
if (0==myrank)
{
cout << "Updating Implicit_Solver time step from " << dt
<< " to " << dt_ << endl;
}
delete A;
dt = dt_;
// Form operator A = M + dt*S
A = Add(dt, S, 1.0, M);
linear_solver.SetOperator(*A);
}
}
void SetOperator(const Operator &op) override
{
linear_solver.SetOperator(op);
}
void Mult(const Vector &x, Vector &y) const override
{
linear_solver.Mult(x, y);
}
void SetPreconditioner(Solver &precond)
{
linear_solver.SetPreconditioner(precond);
}
~Implicit_Solver() override
{
delete A;
}
};
/** A time-dependent operator for the right-hand side of the ODE. The DG weak
form of the advection-diffusion equation is (M + dt S) du/dt = Su - K u + b
, where M and K are the mass and advection matrices, and b describes the
flow on the boundary. In the case of IMEX evolution, the diffusion term is
treated implicitly, and the advection term is treated explicitly. */
class IMEX_Evolution : public TimeDependentOperator
{
private:
OperatorHandle M, K, S, A;
const Vector &b;
Solver *M_prec;
CGSolver M_solver;
Implicit_Solver *implicit_solver;
LORSolver<HypreBoomerAMG>* lor_solver;
mutable Vector z;
mutable Vector w;
public:
IMEX_Evolution(ParBilinearForm &M_, ParBilinearForm &K_, ParBilinearForm &S_,
const Vector &b_, ParBilinearForm &A_);
virtual
~IMEX_Evolution()
{
delete implicit_solver;
delete lor_solver;
delete M_prec;
}
void Mult1(const Vector &x, Vector &y) const;
void ImplicitSolve2(const real_t dt, const Vector &x, Vector &k);
void Mult(const Vector &x, Vector &y) const override
{
if (TimeDependentOperator::EvalMode::ADDITIVE_TERM_1 == GetEvalMode())
{
Mult1(x,y);
}
else
{
mfem_error("TimeDependentOperator::Mult() is not overridden!");
}
}
void ImplicitSolve(const real_t dt, const Vector &x, Vector &k) override
{
if (TimeDependentOperator::EvalMode::ADDITIVE_TERM_2 == GetEvalMode())
{
ImplicitSolve2(dt,x,k);
}
else
{
mfem_error("TimeDependentOperator::ImplicitSolve() is not overridden!");
}
}
};
int main(int argc, char *argv[])
{
// 1. Initialize MPI and HYPRE.
Mpi::Init();
int num_procs = Mpi::WorldSize();
int myid = Mpi::WorldRank();
Hypre::Init();
// 2. Parse command-line options.
int problem = 0;
const char *mesh_file = "../data/periodic-square.mesh";
int ser_ref_levels = 2;
int par_ref_levels = 0;
int order = 3;
int ode_solver_type = 64; // 61 - Forward Backward Euler
// 62 - IMEXRK2(2,2,2)
// 63 - IMEXRK2(2,3,2)
// 64 - IMEXRK3(3,4,3)
real_t t_final = 10.0;
real_t dt = 0.01;
bool paraview = false;
bool cg = false;
int vis_steps = 50;
bool adios2 = false;
bool binary = false;
real_t diffusion_term = 0.01;
real_t kappa = -1.0;
real_t sigma = -1.0;
bool visualization = true;
bool visit = false;
int precision = 16;
cout.precision(precision);
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&problem, "-p", "--problem",
"Problem setup to use. See options in velocity_function().");
args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
"Number of times to refine the mesh uniformly in serial.");
args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
"Number of times to refine the mesh uniformly in parallel.");
args.AddOption(&order, "-o", "--order",
"Order (degree) of the finite elements.");
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
ODESolver::IMEXTypes.c_str());
args.AddOption(&t_final, "-tf", "--t-final",
"Final time; start time is 0.");
args.AddOption(&dt, "-dt", "--time-step",
"Time step.");
args.AddOption(&diffusion_term, "-dc", "--diffusion-coeff",
"Diffusion coefficient in the PDE.");
args.AddOption(&paraview, "-paraview", "--paraview-datafiles", "-no-paraview",
"--no-paraview-datafiles",
"Save data files for ParaView (paraview.org) visualization.");
args.AddOption(&visit, "-visit", "--visit-datafiles", "-no-visit",
"--no-visit-datafiles",
"Save data files for VisIt (visit.llnl.gov) visualization.");
args.AddOption(&adios2, "-adios2", "--adios2-streams", "-no-adios2",
"--no-adios2-streams",
"Save data using adios2 streams.");
args.AddOption(&binary, "-binary", "--binary-datafiles", "-ascii",
"--ascii-datafiles",
"Use binary (Sidre) or ascii format for VisIt data files.");
args.AddOption(&vis_steps, "-vs", "--visualization-steps",
"Visualize every n-th timestep.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&cg, "-cg", "--continuous-galerkin", "-dg",
"--discontinuous-galerkin",
"Use Continuous-Galerkin Finite elements (Default is DG)");
args.Parse();
if (!args.Good())
{
if (Mpi::Root())
{
args.PrintUsage(cout);
}
return 1;
}
if (Mpi::Root())
{
args.PrintOptions(cout);
}
if (kappa < 0)
{
kappa = (order+1)*(order+1);
}
// 3. Read the mesh from the given mesh file. We can handle geometrically
// periodic meshes in this code.
Mesh *mesh = new Mesh(mesh_file);
const int dim = mesh->Dimension();
// 4. Define the IMEX (Split) ODE solver used for time integration. The IMEX
// solvers currently available are: 55 - Forward Backward Euler,
// 56 - IMEXRK2(2,2,2), 57 - IMEXRK2(2,3,2), and
unique_ptr<ODESolver> ode_solver = ODESolver::SelectIMEX(ode_solver_type);
// 5. Refine the mesh to increase the resolution. In this example we do
// 'ref_levels' of uniform refinement, where 'ref_levels' is a
// command-line parameter.
for (int lev = 0; lev < ser_ref_levels; lev++) { mesh->UniformRefinement(); }
if (mesh->NURBSext)
{
mesh->SetCurvature(max(order, 1));
}
mesh->GetBoundingBox(bb_min, bb_max, max(order, 1));
// 6. Define the parallel mesh by a partitioning of the serial mesh. Refine
// this mesh further in parallel to increase the resolution. Once the
// parallel mesh is defined, the serial mesh can be deleted.
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
for (int lev = 0; lev < par_ref_levels; lev++)
{
pmesh->UniformRefinement();
}
// 7. Define the discontinuous DG finite element space of the given
// polynomial order on the refined mesh.
FiniteElementCollection *fec = NULL;
if (cg)
{
fec = new H1_FECollection(order, dim);
}
else
{
fec = new DG_FECollection(order, dim, BasisType::GaussLobatto);
}
ParFiniteElementSpace *fes = new ParFiniteElementSpace(pmesh, fec);
HYPRE_BigInt global_vSize = fes->GlobalTrueVSize();
if (Mpi::Root())
{
cout << "Number of unknowns: " << global_vSize << endl;
}
// 8. Set up and assemble the bilinear and linear forms corresponding to the
// DG discretization. The DGTraceIntegrator involves integrals over mesh
// interior faces.
std::unique_ptr<VectorFunctionCoefficient> velocity;
if (0==problem)
{
velocity.reset(new VectorFunctionCoefficient(dim, velocity_function<0>));
}
else if (1==problem)
{
velocity.reset(new VectorFunctionCoefficient(dim, velocity_function<1>));
}
else if (2==problem)
{
velocity.reset(new VectorFunctionCoefficient(dim, velocity_function<2>));
}
else if (3==problem)
{
velocity.reset(new VectorFunctionCoefficient(dim, velocity_function<3>));
}
ConstantCoefficient diff_coeff(diffusion_term);
ConstantCoefficient dt_diff_coeff(dt*diffusion_term);
ParBilinearForm *m = new ParBilinearForm(fes);
ParBilinearForm *k = new ParBilinearForm(fes);
ParBilinearForm *s = new ParBilinearForm(fes);
m->AddDomainIntegrator(new MassIntegrator());
constexpr real_t alpha = -1.0;
k->AddDomainIntegrator(new ConvectionIntegrator(*velocity, alpha));
s->AddDomainIntegrator(new DiffusionIntegrator(diff_coeff));
// For the preconditioner - create billinear form corresponding to
// operator (M + dt S)
ParBilinearForm *a = new ParBilinearForm(fes);
a->AddDomainIntegrator(new MassIntegrator);
a->AddDomainIntegrator(new DiffusionIntegrator(dt_diff_coeff));
if (!cg)
{
k->AddInteriorFaceIntegrator(new NonconservativeDGTraceIntegrator(*velocity,
alpha));
k->AddBdrFaceIntegrator(new NonconservativeDGTraceIntegrator(*velocity, alpha));
s->AddInteriorFaceIntegrator(new DGDiffusionIntegrator(diff_coeff, sigma,
kappa));
s->AddBdrFaceIntegrator(new DGDiffusionIntegrator(diff_coeff, sigma, kappa));
a->AddInteriorFaceIntegrator(new DGDiffusionIntegrator(dt_diff_coeff, sigma,
kappa));
a->AddBdrFaceIntegrator(new DGDiffusionIntegrator(dt_diff_coeff, sigma, kappa));
}
int skip_zeros = 0;
m->Assemble(skip_zeros);
k->Assemble(skip_zeros);
s->Assemble(skip_zeros);
a->Assemble();
m->Finalize(skip_zeros);
k->Finalize(skip_zeros);
s->Finalize(skip_zeros);
a->Finalize(skip_zeros);
HypreParVector b(fes);
b = 0.0;
// 9. Define the initial conditions. Set up visualization (if desired).
std::unique_ptr<FunctionCoefficient> u0;
if (0==problem)
{
u0.reset(new FunctionCoefficient(u0_function<0>));
}
else if (1==problem)
{
u0.reset(new FunctionCoefficient(u0_function<1>));
}
else if (2==problem)
{
u0.reset(new FunctionCoefficient(u0_function<2>));
}
else if (3==problem)
{
u0.reset(new FunctionCoefficient(u0_function<3>));
}
ParGridFunction *u = new ParGridFunction(fes);
u->ProjectCoefficient(*u0);
HypreParVector *U = u->GetTrueDofs();
DataCollection *dc = NULL;
if (visit)
{
if (binary)
{
#ifdef MFEM_USE_SIDRE
dc = new SidreDataCollection("Example41-Parallel", pmesh);
#else
MFEM_ABORT("Must build with MFEM_USE_SIDRE=YES for binary output.");
#endif
}
else
{
dc = new VisItDataCollection("Example41-Parallel", pmesh);
dc->SetPrecision(precision);
// To save the mesh using MFEM's parallel mesh format:
// dc->SetFormat(DataCollection::PARALLEL_FORMAT);
}
dc->RegisterField("solution", u);
dc->SetCycle(0);
dc->SetTime(0.0);
dc->Save();
}
ParaViewDataCollection *pd = NULL;
if (paraview)
{
pd = new ParaViewDataCollection("Example41P", pmesh);
pd->SetPrefixPath("ParaView");
pd->RegisterField("solution", u);
pd->SetLevelsOfDetail(order);
pd->SetDataFormat(VTKFormat::BINARY);
pd->SetHighOrderOutput(true);
pd->SetCycle(0);
pd->SetTime(0.0);
pd->Save();
}
socketstream sout;
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
sout.open(vishost, visport);
if (!sout)
{
if (Mpi::Root())
{
cout << "Unable to connect to GLVis server at "
<< vishost << ':' << visport << endl;
}
visualization = false;
if (Mpi::Root())
{
cout << "GLVis visualization disabled.\n";
}
}
else
{
sout << "parallel " << num_procs << " " << myid << "\n";
sout.precision(precision);
sout << "solution\n" << *pmesh << *u;
sout << "pause\n";
sout << flush;
if (Mpi::Root())
{
cout << "GLVis visualization paused."
<< " Press space (in the GLVis window) to resume it.\n";
}
}
}
#ifdef MFEM_USE_ADIOS2
ADIOS2DataCollection *adios2_dc = NULL;
if (adios2)
{
std::string postfix(mesh_file);
postfix.erase(0, std::string("../data/").size() );
postfix += "_o" + std::to_string(order);
const std::string collection_name = "ex41-p-" + postfix + ".bp";
adios2_dc = new ADIOS2DataCollection(MPI_COMM_WORLD, collection_name, pmesh);
// output data substreams are half the number of mpi processes
adios2_dc->SetParameter("SubStreams", std::to_string(num_procs/2) );
// adios2_dc->SetLevelsOfDetail(2);
adios2_dc->RegisterField("solution", u);
adios2_dc->SetCycle(0);
adios2_dc->SetTime(0.0);
adios2_dc->Save();
}
#endif
// 10. Define the time-dependent evolution operator describing the
// ODE right-hand side, and perform time-integration (looping
// over the time iterations, ti, with a time-step dt).
IMEX_Evolution adv(*m, *k, *s, b, *a);
real_t t = 0.0;
adv.SetTime(t);
ode_solver->Init(adv);
bool done = false;
for (int ti = 0; !done; )
{
real_t dt_real = min(dt, t_final - t);
ode_solver->Step(*U, t, dt_real);
ti++;
done = (t >= t_final - 1e-8*dt);
if (done || ti % vis_steps == 0)
{
if (Mpi::Root())
{
cout << "time step: " << ti << ", time: " << t << endl;
}
*u = *U;
if (visualization)
{
sout << "parallel " << num_procs << " " << myid << "\n";
sout << "solution\n" << *pmesh << *u << flush;
}
if (paraview)
{
pd->SetCycle(ti);
pd->SetTime(t);
pd->Save();
}
#ifdef MFEM_USE_ADIOS2
// transient solutions can be visualized with ParaView
if (adios2)
{
adios2_dc->SetCycle(ti);
adios2_dc->SetTime(t);
adios2_dc->Save();
}
#endif
}
}
// 11. Free the used memory.
delete pd;
delete U;
delete u;
delete a;
delete s;
delete k;
delete m;
delete fes;
delete pmesh;
delete dc;
delete fec;
return 0;
}
// Implementation of class IMEX_Evolution
IMEX_Evolution::IMEX_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
ParBilinearForm &S_, const Vector &b_, ParBilinearForm &A_)
: TimeDependentOperator(M_.ParFESpace()->GetTrueVSize()), b(b_),
M_solver(M_.ParFESpace()->GetComm()), z(height), w(height)
{
if (M_.GetAssemblyLevel()==AssemblyLevel::LEGACY)
{
M.Reset(M_.ParallelAssemble(), true);
K.Reset(K_.ParallelAssemble(), true);
S.Reset(S_.ParallelAssemble(), true);
}
else
{
M.Reset(&M_, false);
K.Reset(&K_, false);
S.Reset(&S_, false);
}
M_solver.SetOperator(*M);
Array<int> ess_tdof_list;
if (M_.GetAssemblyLevel() == AssemblyLevel::LEGACY)
{
A.Reset(A_.ParallelAssemble(), true);
HypreParMatrix &M_mat = *M.As<HypreParMatrix>();
HypreParMatrix &S_mat = *S.As<HypreParMatrix>();
HypreSmoother *hypre_prec = new HypreSmoother(M_mat, HypreSmoother::Jacobi);
M_prec = hypre_prec;
implicit_solver = new Implicit_Solver(M_mat, S_mat, *M_.FESpace());
lor_solver = new LORSolver<HypreBoomerAMG>(A_, ess_tdof_list);
lor_solver->GetSolver().SetSystemsOptions(A_.ParFESpace()->GetVDim(), true);
implicit_solver -> SetPreconditioner(*lor_solver);
}
else
{
MFEM_ABORT("Implicit time integration is not supported with partial assembly");
}
M_solver.SetPreconditioner(*M_prec);
M_solver.iterative_mode = false;
M_solver.SetRelTol(1e-9);
M_solver.SetAbsTol(0.0);
M_solver.SetMaxIter(100);
M_solver.SetPrintLevel(0);
}
void IMEX_Evolution::Mult1(const Vector &x, Vector &y) const
{
// Perform the explicit step
// y = M^{-1} (K x + b)
K->Mult(x, z);
z += b;
M_solver.Mult(z, y);
}
void IMEX_Evolution::ImplicitSolve2(const real_t dt, const Vector &x, Vector &k)
{
// Perform the implicit step
// solve for k, k = -(M+dt S)^{-1} S x
MFEM_VERIFY(implicit_solver != NULL,
"Implicit time integration is not supported with partial assembly");
S->Mult(x, z);
z*= -1.0;
implicit_solver->SetTimeStep(dt);
implicit_solver->Mult(z, k);
}
+1 -6
View File
@@ -9,7 +9,6 @@
// mpirun -np 4 ex4p -m ../data/beam-hex.mesh -o 2 -pa
// mpirun -np 4 ex4p -m ../data/escher.mesh -o 2 -sc
// mpirun -np 4 ex4p -m ../data/fichera.mesh -o 2 -hb
// mpirun -np 4 ex4p -m ../data/fichera.mesh -o 2 -hb -ea
// mpirun -np 4 ex4p -m ../data/fichera-q2.vtk
// mpirun -np 4 ex4p -m ../data/fichera-q3.mesh -o 2 -sc
// mpirun -np 4 ex4p -m ../data/square-disc-nurbs.mesh -o 3
@@ -18,18 +17,14 @@
// mpirun -np 4 ex4p -m ../data/periodic-cube.mesh -no-bc
// mpirun -np 4 ex4p -m ../data/amr-quad.mesh
// mpirun -np 3 ex4p -m ../data/amr-quad.mesh -o 2 -hb
// mpirun -np 3 ex4p -m ../data/amr-quad.mesh -o 2 -hb -ea
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -sc
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -hb
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -hb -ea
// mpirun -np 4 ex4p -m ../data/ref-prism.mesh -o 1
// mpirun -np 4 ex4p -m ../data/octahedron.mesh -o 1
// mpirun -np 4 ex4p -m ../data/star-surf.mesh -o 3 -hb
//
// Device sample runs:
// mpirun -np 4 ex4p -m ../data/star.mesh -pa -d cuda
// mpirun -np 4 ex4p -m ../data/star.mesh -ea -hb -d cuda
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -ea -hb -d cuda
// mpirun -np 4 ex4p -m ../data/star.mesh -pa -d raja-cuda
// mpirun -np 4 ex4p -m ../data/star.mesh -pa -d raja-omp
// mpirun -np 4 ex4p -m ../data/beam-hex.mesh -pa -d cuda
@@ -235,7 +230,7 @@ int main(int argc, char *argv[])
pcg->SetMaxIter(2000);
pcg->SetPrintLevel(1);
if (hybridization) { prec = new HypreBoomerAMG(*A.As<HypreParMatrix>()); }
else if (pa || ea) { prec = new OperatorJacobiSmoother(*a, ess_tdof_list); }
else if (pa) { prec = new OperatorJacobiSmoother(*a, ess_tdof_list); }
else
{
ParFiniteElementSpace *prec_fespace =
+1 -20
View File
@@ -160,7 +160,6 @@ int main(int argc, char *argv[])
bool paraview = false;
bool binary = false;
int vis_steps = 5;
bool solve_implicit_state = false;
int precision = 8;
cout.precision(precision);
@@ -188,9 +187,6 @@ int main(int argc, char *argv[])
"Final time; start time is 0.");
args.AddOption(&dt, "-dt", "--time-step",
"Time step.");
args.AddOption(&solve_implicit_state, "-imp-state", "--implicit-state",
"-imp-slope", "--implicit-slope",
"Implicitly solve for stage state or slope.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
@@ -370,11 +366,6 @@ int main(int argc, char *argv[])
// right-hand side, and perform time-integration (looping over the time
// iterations, ti, with a time-step dt).
FE_Evolution adv(m, k, b);
using ImplicitVariableType = FE_Evolution::ImplicitVariableType;
ImplicitVariableType imp_var = solve_implicit_state ?
ImplicitVariableType::STATE
: ImplicitVariableType::SLOPE;
adv.SetImplicitVariableType(imp_var);
real_t t = 0.0;
adv.SetTime(t);
@@ -468,17 +459,7 @@ void FE_Evolution::ImplicitSolve(const real_t dt, const Vector &x, Vector &k)
{
MFEM_VERIFY(dg_solver != NULL,
"Implicit time integration is not supported with partial assembly");
// Construct current right-hand side for stage state vs. slope solve
if (ImplicitVarTypeIsState())
{
// k, on return, is the stage value u
M.Mult(x, z);
}
else
{
// k, on return, is the stage slope du/dt
K.Mult(x, z);
}
K.Mult(x, z);
z += b;
dg_solver->SetTimeStep(dt);
dg_solver->Mult(z, k);
+1 -20
View File
@@ -257,7 +257,6 @@ int main(int argc, char *argv[])
bool adios2 = false;
bool binary = false;
int vis_steps = 5;
bool solve_implicit_state = false;
#if MFEM_HYPRE_VERSION >= 21800
PrecType prec_type = PrecType::AIR;
#else
@@ -291,9 +290,6 @@ int main(int argc, char *argv[])
"Final time; start time is 0.");
args.AddOption(&dt, "-dt", "--time-step",
"Time step.");
args.AddOption(&solve_implicit_state, "-imp-state", "--implicit-state",
"-imp-slope", "--implicit-slope",
"Implicitly solve for stage state or slope.");
args.AddOption((int *)&prec_type, "-pt", "--prec-type", "Preconditioner for "
"implicit solves. 0 for ILU, 1 for pAIR-AMG.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
@@ -540,11 +536,6 @@ int main(int argc, char *argv[])
// right-hand side, and perform time-integration (looping over the time
// iterations, ti, with a time-step dt).
FE_Evolution adv(*m, *k, *B, prec_type);
using ImplicitVariableType = FE_Evolution::ImplicitVariableType;
ImplicitVariableType imp_var = solve_implicit_state ?
ImplicitVariableType::STATE
: ImplicitVariableType::SLOPE;
adv.SetImplicitVariableType(imp_var);
real_t t = 0.0;
adv.SetTime(t);
@@ -685,17 +676,7 @@ FE_Evolution::FE_Evolution(ParBilinearForm &M_, ParBilinearForm &K_,
// (M - dt*K) d = K*u + b
void FE_Evolution::ImplicitSolve(const real_t dt, const Vector &x, Vector &k)
{
// Construct current right-hand side for stage state vs. slope solve
if (ImplicitVarTypeIsState())
{
// k, on return, is the stage value u
M->Mult(x, z);
}
else
{
// k, on return, is the stage slope du/dt
K->Mult(x, z);
}
K->Mult(x, z);
z += b;
dg_solver->SetTimeStep(dt);
dg_solver->Mult(z, k);
-6
View File
@@ -14,12 +14,6 @@ list(APPEND GINKGO_EXAMPLES_SRCS
ex1.cpp
)
if (MFEM_USE_MPI AND GINKGO_BUILD_MPI)
list(APPEND GINKGO_EXAMPLES_SRCS
ex1p.cpp
)
endif()
# Include the source directory where mfem.hpp and mfem-performance.hpp are.
include_directories(BEFORE ${PROJECT_BINARY_DIR})
+3 -3
View File
@@ -207,7 +207,7 @@ int main(int argc, char *argv[])
Ginkgo::IcPreconditioner ginkgo_precond(exec, "paric", 30);
Ginkgo::CGSolver ginkgo_solver(exec, ginkgo_precond);
ginkgo_solver.SetPrintLevel(print_lvl);
ginkgo_solver.SetRelTol(sqrt(1e-12));
ginkgo_solver.SetRelTol(1e-12);
ginkgo_solver.SetAbsTol(0.0);
ginkgo_solver.SetMaxIter(400);
ginkgo_solver.SetOperator(*(A.Ptr()));
@@ -225,7 +225,7 @@ int main(int argc, char *argv[])
Ginkgo::MFEMPreconditioner gko_M(exec, M);
Ginkgo::CGSolver ginkgo_solver(exec, gko_M);
ginkgo_solver.SetPrintLevel(print_lvl);
ginkgo_solver.SetRelTol(sqrt(1e-12));
ginkgo_solver.SetRelTol(1e-12);
ginkgo_solver.SetAbsTol(0.0);
ginkgo_solver.SetMaxIter(400);
ginkgo_solver.SetOperator(*(A.Ptr()));
@@ -283,7 +283,7 @@ int main(int argc, char *argv[])
Ginkgo::MFEMPreconditioner gko_M(exec, M);
Ginkgo::CGSolver ginkgo_solver(exec, gko_M);
ginkgo_solver.SetPrintLevel(print_lvl);
ginkgo_solver.SetRelTol(sqrt(1e-12));
ginkgo_solver.SetRelTol(1e-12);
ginkgo_solver.SetAbsTol(0.0);
ginkgo_solver.SetMaxIter(400);
ginkgo_solver.SetOperator(*(A.Ptr()));
-436
View File
@@ -1,436 +0,0 @@
// MFEM Example 1 - Parallel Version
// GINKGO Modification
//
// Compile with: make ex1p
//
// Sample runs: mpirun -np 4 ex1p -m ../data/square-disc.mesh
// mpirun -np 4 ex1p -m ../data/star.mesh
// mpirun -np 4 ex1p -m ../data/star-mixed.mesh
// mpirun -np 4 ex1p -m ../data/escher.mesh
// mpirun -np 4 ex1p -m ../data/fichera.mesh
// mpirun -np 4 ex1p -m ../data/fichera-mixed.mesh
// mpirun -np 4 ex1p -m ../data/toroid-wedge.mesh
// mpirun -np 4 ex1p -m ../data/octahedron.mesh -o 1
// mpirun -np 4 ex1p -m ../data/periodic-annulus-sector.msh
// mpirun -np 4 ex1p -m ../data/periodic-torus-sector.msh
// mpirun -np 4 ex1p -m ../data/square-disc-p2.vtk -o 2
// mpirun -np 4 ex1p -m ../data/square-disc-p3.mesh -o 3
// mpirun -np 4 ex1p -m ../data/square-disc-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/star-mixed-p2.mesh -o 2
// mpirun -np 4 ex1p -m ../data/disc-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/pipe-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/ball-nurbs.mesh -o 2
// mpirun -np 4 ex1p -m ../data/fichera-mixed-p2.mesh -o 2
// mpirun -np 4 ex1p -m ../data/star-surf.mesh
// mpirun -np 4 ex1p -m ../data/square-disc-surf.mesh
// mpirun -np 4 ex1p -m ../data/inline-segment.mesh
// mpirun -np 4 ex1p -m ../data/amr-quad.mesh
// mpirun -np 4 ex1p -m ../data/amr-hex.mesh
// mpirun -np 4 ex1p -m ../data/mobius-strip.mesh
// mpirun -np 4 ex1p -m ../data/mobius-strip.mesh -o -1 -sc
//
// Device sample runs:
// mpirun -np 4 ex1p -pa -d cuda
// mpirun -np 4 ex1p -fa -d cuda
// mpirun -np 4 ex1p -pa -d occa-cuda
// mpirun -np 4 ex1p -pa -d raja-omp
// mpirun -np 4 ex1p -pa -d ceed-cpu
// mpirun -np 4 ex1p -pa -d ceed-cpu -o 4 -a
// mpirun -np 4 ex1p -pa -d ceed-cpu -m ../data/square-mixed.mesh
// mpirun -np 4 ex1p -pa -d ceed-cpu -m ../data/fichera-mixed.mesh
// * mpirun -np 4 ex1p -pa -d ceed-cuda
// * mpirun -np 4 ex1p -pa -d ceed-hip
// mpirun -np 4 ex1p -pa -d ceed-cuda:/gpu/cuda/shared
// mpirun -np 4 ex1p -pa -d ceed-cuda:/gpu/cuda/shared -m ../data/square-mixed.mesh
// mpirun -np 4 ex1p -pa -d ceed-cuda:/gpu/cuda/shared -m ../data/fichera-mixed.mesh
// mpirun -np 4 ex1p -m ../data/beam-tet.mesh -pa -d ceed-cpu
//
// Description: This example code demonstrates the use of MFEM to define a
// simple finite element discretization of the Laplace problem
// -Delta u = 1 with homogeneous Dirichlet boundary conditions.
// Specifically, we discretize using a FE space of the specified
// order, or if order < 1 using an isoparametric/isogeometric
// space (i.e. quadratic for quadratic curvilinear mesh, NURBS for
// NURBS mesh, etc.)
//
// The example highlights the use of mesh refinement, finite
// element grid functions, as well as linear and bilinear forms
// corresponding to the left-hand side and right-hand side of the
// discrete linear system. We also cover the explicit elimination
// of essential boundary conditions, static condensation, and the
// optional connection to the GLVis tool for visualization.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
#ifndef MFEM_USE_GINKGO
#error This example requires that MFEM is built with MFEM_USE_GINKGO=YES
#endif
using namespace std;
using namespace mfem;
int main(int argc, char *argv[])
{
// 1. Initialize MPI and HYPRE.
Mpi::Init();
int num_procs = Mpi::WorldSize();
int myid = Mpi::WorldRank();
Hypre::Init();
// 2. Parse command-line options.
const char *mesh_file = "../../data/star.mesh";
int order = 1;
bool static_cond = false;
bool pa = false;
bool fa = false;
const char *device_config = "cpu";
bool visualization = true;
int solver_config = 0;
int print_lvl = 1;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree) or -1 for"
" isoparametric space.");
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
"--no-static-condensation", "Enable static condensation.");
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
"--no-partial-assembly", "Enable Partial Assembly.");
args.AddOption(&fa, "-fa", "--full-assembly", "-no-fa",
"--no-full-assembly", "Enable Full Assembly.");
args.AddOption(&device_config, "-d", "--device",
"Device configuration string, see Device::Configure().");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&solver_config, "-s", "--solver-config",
"Solver and preconditioner combination: \n\t"
" 0 - Ginkgo solver and Ginkgo preconditioner, \n\t"
" 1 - Ginkgo solver and MFEM preconditioner, \n\t"
" 2 - MFEM solver and Ginkgo preconditioner, \n\t"
" 3 - MFEM solver and MFEM preconditioner.");
args.AddOption(&print_lvl, "-pl", "--print-level",
"Print level for iterative solver (1 prints every iteration).");
args.Parse();
if (!args.Good())
{
if (myid == 0)
{
args.PrintUsage(cout);
}
return 1;
}
if (myid == 0)
{
args.PrintOptions(cout);
}
// 3. Enable hardware devices such as GPUs, and programming models such as
// CUDA, OCCA, RAJA and OpenMP based on command line options.
Device device(device_config);
device.SetGPUAwareMPI(true);
if (myid == 0) { device.Print(); }
// 4. Read the (serial) mesh from the given mesh file on all processors. We
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
// and volume meshes with the same code.
Mesh mesh(mesh_file, 1, 1);
int dim = mesh.Dimension();
// 5. Refine the serial mesh on all processors to increase the resolution. In
// this example we do 'ref_levels' of uniform refinement. We choose
// 'ref_levels' to be the largest number that gives a final mesh with no
// more than 10,000 elements.
{
int ref_levels =
(int)floor(log(10000./mesh.GetNE())/log(2.)/dim);
for (int l = 0; l < ref_levels; l++)
{
mesh.UniformRefinement();
}
}
// 6. Define a parallel mesh by a partitioning of the serial mesh. Refine
// this mesh further in parallel to increase the resolution. Once the
// parallel mesh is defined, the serial mesh can be deleted.
ParMesh pmesh(MPI_COMM_WORLD, mesh);
mesh.Clear();
{
int par_ref_levels = 2;
for (int l = 0; l < par_ref_levels; l++)
{
pmesh.UniformRefinement();
}
}
// 7. Define a parallel finite element space on the parallel mesh. Here we
// use continuous Lagrange finite elements of the specified order. If
// order < 1, we instead use an isoparametric/isogeometric space.
FiniteElementCollection *fec;
bool delete_fec;
if (order > 0)
{
fec = new H1_FECollection(order, dim);
delete_fec = true;
}
else if (pmesh.GetNodes())
{
fec = pmesh.GetNodes()->OwnFEC();
delete_fec = false;
if (myid == 0)
{
cout << "Using isoparametric FEs: " << fec->Name() << endl;
}
}
else
{
fec = new H1_FECollection(order = 1, dim);
delete_fec = true;
}
ParFiniteElementSpace fespace(&pmesh, fec);
HYPRE_BigInt size = fespace.GlobalTrueVSize();
if (myid == 0)
{
cout << "Number of finite element unknowns: " << size << endl;
}
// 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 from the mesh as essential
// (Dirichlet) and converting them to a list of true dofs.
Array<int> ess_tdof_list;
if (pmesh.bdr_attributes.Size())
{
Array<int> ess_bdr(pmesh.bdr_attributes.Max());
ess_bdr = 1;
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
// 9. Set up the parallel linear form b(.) which corresponds to the
// right-hand side of the FEM linear system, which in this case is
// (1,phi_i) where phi_i are the basis functions in fespace.
ParLinearForm b(&fespace);
ConstantCoefficient one(1.0);
b.AddDomainIntegrator(new DomainLFIntegrator(one));
b.Assemble();
// 10. Define the solution vector x as a parallel finite element grid
// function corresponding to fespace. Initialize x with initial guess of
// zero, which satisfies the boundary conditions.
ParGridFunction x(&fespace);
x = 0.0;
// 11. Set up the parallel bilinear form a(.,.) on the finite element space
// corresponding to the Laplacian operator -Delta, by adding the
// Diffusion domain integrator.
ParBilinearForm a(&fespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
if (fa)
{
a.SetAssemblyLevel(AssemblyLevel::FULL);
// Sort the matrix column indices when running on GPU or with OpenMP (i.e.
// when Device::IsEnabled() returns true). This makes the results
// bit-for-bit deterministic at the cost of somewhat longer run time.
a.EnableSparseMatrixSorting(Device::IsEnabled());
}
a.AddDomainIntegrator(new DiffusionIntegrator(one));
// 12. Assemble the parallel bilinear form and the corresponding linear
// system, applying any necessary transformations such as: parallel
// assembly, eliminating boundary conditions, applying conforming
// constraints for non-conforming AMR, static condensation, etc.
if (static_cond) { a.EnableStaticCondensation(); }
a.Assemble();
OperatorPtr A;
Vector B, X;
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
// 13. Solve the linear system A X = B.
if (!pa)
{
switch (solver_config)
{
// Solve the linear system with CG + Schwarz (with IC) from Ginkgo
case 0:
{
if (myid == 0) { cout << "Using Ginkgo solver + preconditioner...\n"; }
Ginkgo::GinkgoExecutor exec(device);
Ginkgo::IcPreconditioner local_solver(exec, "exact");
Ginkgo::SchwarzPreconditioner gko_M(exec, MPI_COMM_WORLD, local_solver);
Ginkgo::CGSolver ginkgo_solver(exec, MPI_COMM_WORLD, gko_M);
ginkgo_solver.SetPrintLevel(print_lvl);
ginkgo_solver.SetRelTol(sqrt(1e-12));
ginkgo_solver.SetAbsTol(0.0);
ginkgo_solver.SetMaxIter(400);
ginkgo_solver.SetOperator(*(A.Ptr()));
ginkgo_solver.Mult(B, X);
break;
}
// Solve the linear system with CG from Ginkgo + MFEM preconditioner
case 1:
{
if (myid == 0) { cout << "Using Ginkgo solver + MFEM preconditioner...\n"; }
Ginkgo::GinkgoExecutor exec(device);
//Create MFEM preconditioner and wrap it for Ginkgo's use.
HypreBoomerAMG M((HypreParMatrix&)(*A));
Ginkgo::MFEMPreconditioner gko_M(exec, M, MPI_COMM_WORLD);
Ginkgo::CGSolver ginkgo_solver(exec, MPI_COMM_WORLD, gko_M);
ginkgo_solver.SetPrintLevel(print_lvl);
ginkgo_solver.SetRelTol(sqrt(1e-12));
ginkgo_solver.SetAbsTol(0.0);
ginkgo_solver.SetMaxIter(400);
ginkgo_solver.SetOperator(*(A.Ptr()));
ginkgo_solver.Mult(B, X);
break;
}
// Ginkgo Schwarz preconditioner (local ParIC) + MFEM CG solver
case 2:
{
if (myid == 0) { cout << "Using MFEM solver + Ginkgo preconditioner...\n"; }
Ginkgo::GinkgoExecutor exec(device);
Ginkgo::IcPreconditioner local_M(exec, "exact");
Ginkgo::SchwarzPreconditioner M(exec, MPI_COMM_WORLD, local_M);
M.SetOperator(*(A.Ptr())); // Generate the preconditioner for the matrix A.
CGSolver cg(MPI_COMM_WORLD);
cg.SetRelTol(sqrt(1e-12));
cg.SetMaxIter(400);
cg.SetPrintLevel(1);
cg.SetPreconditioner(M);
cg.SetOperator(*A);
cg.Mult(B, X);
break;
}
// MFEM solver + MFEM preconditioner
case 3:
{
if (myid == 0) { cout << "Using MFEM solver + MFEM preconditioner...\n"; }
HypreBoomerAMG M((HypreParMatrix&)(*A));
CGSolver cg(MPI_COMM_WORLD);
cg.SetRelTol(sqrt(1e-12));
cg.SetMaxIter(400);
cg.SetPrintLevel(1);
cg.SetPreconditioner(M);
cg.SetOperator(*A);
cg.Mult(B, X);
break;
}
} // End switch on solver_config
}
// Partial assembly mode. Cannot use Ginkgo preconditioners, but can use Ginkgo
// solvers.
else
{
if (UsesTensorBasis(fespace))
{
// Use Jacobi preconditioning in partial assembly mode.
OperatorJacobiSmoother M(a, ess_tdof_list);
switch (solver_config)
{
case 0:
{
if (myid == 0) { cout << "Using Ginkgo solver + preconditioner...\n"; }
MFEM_ABORT("Cannot use Ginkgo preconditioner in partial assembly mode.\n"
" Try -s 1 to test Ginkgo solver with an MFEM preconditioner.");
break;
}
// Use Ginkgo solver with MFEM preconditioner
case 1:
{
if (myid == 0) { cout << "Using Ginkgo solver + MFEM preconditioner...\n"; }
Ginkgo::GinkgoExecutor exec(device);
// Wrap MFEM preconditioner for Ginkgo's use.
Ginkgo::MFEMPreconditioner gko_M(exec, M, MPI_COMM_WORLD);
Ginkgo::CGSolver ginkgo_solver(exec, MPI_COMM_WORLD, gko_M);
ginkgo_solver.SetPrintLevel(print_lvl);
ginkgo_solver.SetRelTol(sqrt(1e-12));
ginkgo_solver.SetAbsTol(0.0);
ginkgo_solver.SetMaxIter(400);
ginkgo_solver.SetOperator(*(A.Ptr()));
ginkgo_solver.Mult(B, X);
break;
}
// No Ginkgo preconditioners work with matrix-free; error
case 2:
{
if (myid == 0) { cout << "Using Ginkgo solver + preconditioner...\n"; }
MFEM_ABORT("Cannot use Ginkgo preconditioner in partial assembly mode.\n"
" Try -s 1 to test Ginkgo solver with an MFEM preconditioner.");
break;
}
// Use MFEM solver and preconditioner
case 3:
{
if (myid == 0) { cout << "Using MFEM solver + MFEM preconditioner...\n"; }
CGSolver cg(MPI_COMM_WORLD);
cg.SetRelTol(sqrt(1e-12));
cg.SetMaxIter(400);
cg.SetPrintLevel(1);
cg.SetPreconditioner(M);
cg.SetOperator(*A);
cg.Mult(B, X);
break;
}
} // End switch on solver_config
}
else // CG with no preconditioning
{
if (myid == 0) { cout << "Using MFEM solver + no preconditioner...\n"; }
CGSolver cg(MPI_COMM_WORLD);
cg.SetRelTol(sqrt(1e-12));
cg.SetMaxIter(400);
cg.SetPrintLevel(1);
cg.SetOperator(*A);
cg.Mult(B, X);
}
}
// 14. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
a.RecoverFEMSolution(X, b, x);
// 15. Save the refined mesh and the solution in parallel. This output can
// be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
{
ostringstream mesh_name, sol_name;
mesh_name << "mesh." << setfill('0') << setw(6) << myid;
sol_name << "sol." << setfill('0') << setw(6) << myid;
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(8);
pmesh.Print(mesh_ofs);
ofstream sol_ofs(sol_name.str().c_str());
sol_ofs.precision(8);
x.Save(sol_ofs);
}
// 16. Send the solution by socket to a GLVis server.
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
socketstream sol_sock(vishost, visport);
sol_sock << "parallel " << num_procs << " " << myid << "\n";
sol_sock.precision(8);
sol_sock << "solution\n" << pmesh << x << flush;
}
// 17. Free the used memory.
if (delete_fec)
{
delete fec;
}
return 0;
}
+3 -2
View File
@@ -20,8 +20,9 @@ CONFIG_MK = $(or $(wildcard $(MFEM_BUILD_DIR)/config/config.mk),\
MFEM_LIB_FILE = mfem_is_not_built
-include $(CONFIG_MK)
# Currently there are only serial Ginkgo examples
SEQ_EXAMPLES = ex1
PAR_EXAMPLES = ex1p
PAR_EXAMPLES =
ifeq ($(MFEM_USE_MPI),NO)
EXAMPLES = $(SEQ_EXAMPLES)
else
@@ -76,4 +77,4 @@ clean-build:
rm -rf *.dSYM *.TVD.*breakpoints
clean-exec:
@rm -f refined.mesh sol.gf mesh.* sol.*
@rm -f refined.mesh sol.gf
+6 -21
View File
@@ -22,11 +22,11 @@ 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 ex37 ex38 ex39 ex40 ex41
ex31 ex33 ex34 ex36 ex37 ex38 ex39 ex40
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 \
ex37p ex39p ex40p ex41p
ex37p ex39p ex40p
SEQ_DEVICE_EXAMPLES = ex1 ex3 ex4 ex5 ex6 ex9 ex14 ex22 ex24 ex25 ex26 ex34
PAR_DEVICE_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex9p ex13p ex14p \
ex22p ex24p ex25p ex26p ex34p ex35p
@@ -71,7 +71,6 @@ endif
SUBDIRS_ALL = $(addsuffix /all,$(SUBDIRS))
SUBDIRS_TEST = $(addsuffix /test,$(SUBDIRS))
SUBDIRS_TEST_NOCLEAN = $(addsuffix /test-noclean,$(SUBDIRS))
SUBDIRS_CLEAN = $(addsuffix /clean,$(SUBDIRS))
SUBDIRS_TPRINT = $(addsuffix /test-print,$(SUBDIRS))
@@ -88,9 +87,8 @@ SUBDIRS_TPRINT = $(addsuffix /test-print,$(SUBDIRS))
all: $(EXAMPLES) $(SUBDIRS_ALL)
.PHONY: $(SUBDIRS_ALL) $(SUBDIRS_TEST) $(SUBDIRS_TEST_NOCLEAN) \
$(SUBDIRS_CLEAN) $(SUBDIRS_TPRINT)
$(SUBDIRS_ALL) $(SUBDIRS_TEST) $(SUBDIRS_TEST_NOCLEAN) $(SUBDIRS_CLEAN):
.PHONY: $(SUBDIRS_ALL) $(SUBDIRS_TEST) $(SUBDIRS_CLEAN) $(SUBDIRS_TPRINT)
$(SUBDIRS_ALL) $(SUBDIRS_TEST) $(SUBDIRS_CLEAN):
$(MAKE) -C $(@D) $(@F)
$(SUBDIRS_TPRINT):
@$(MAKE) -C $(@D) $(@F)
@@ -109,7 +107,6 @@ endif
MFEM_TESTS = EXAMPLES
include $(MFEM_TEST_MK)
test: $(SUBDIRS_TEST)
test-noclean: $(SUBDIRS_TEST_NOCLEAN)
test-print: $(SUBDIRS_TPRINT)
# Testing: Parallel vs. serial runs
@@ -160,12 +157,6 @@ ex37-test-seq: ex37
@$(call mfem-test,$<,, Serial example,-mi 3)
ex37p-test-par: ex37p
@$(call mfem-test,$<, $(RUN_MPI), Parallel example,-mi 3)
ex39-test-seq: ex39
@$(call mfem-test,$<,, Serial example,-m ../data/compass.mesh)
ex41-test-seq: ex41
@$(call mfem-test,$<,, Serial example,-tf 1.0)
ex41p-test-par: ex41p
@$(call mfem-test,$<, $(RUN_MPI), Parallel example,-tf 1.0)
# Testing: optional tests
ifeq ($(MFEM_USE_STRUMPACK),YES)
ex11p-test-strumpack: ex11p
@@ -182,12 +173,6 @@ ex11p-test-cpardiso: ex11p
@$(call mfem-test,$<, $(RUN_MPI), MKL_CPARDISO example,--cpardiso)
test-par-YES: ex11p-test-cpardiso
endif
ifeq ($(MFEM_USE_CEED),YES)
ex1p-test-ceed: ex1p
@$(call mfem-test,$<, $(RUN_MPI),\
Parallel libCEED example,-d ceed-cpu -pa -a)
test-par-YES: ex1p-test-ceed
endif
# Testing: "test" target and mfem-test* variables are defined in config/test.mk
@@ -204,8 +189,8 @@ clean-build:
clean-exec:
@rm -f refined.mesh displaced.mesh mesh.* ex5.mesh ex6p-checkpoint.*
@rm -rf Example5* Example9* Example15* Example16* Example23* ParaView
@rm -f sphere_refined.* sol.* sol_u.* sol_p.* sol_r.* sol_i.* sol_z.*
@rm -f order.* ex9.mesh ex9-mesh.* ex9-init.* ex9-final.*
@rm -f sphere_refined.* sol.* sol_u.* sol_p.* sol_r.* sol_i.* order.*
@rm -f ex9.mesh ex9-mesh.* ex9-init.* ex9-final.*
@rm -f deformed.* velocity.* elastic_energy.* mode_* mode_deriv_* flux.*
@rm -f ex5-p-*.bp ex9-p-*.bp ex12-p-*.bp ex16-p-*.bp
@rm -f ex16.mesh ex16-mesh.* ex16-init.* ex16-final.*
+27 -62
View File
@@ -82,8 +82,6 @@ set(SRCS
fe/fe_ser.cpp
fe_coll.cpp
fespace.cpp
derefmat_op.cpp
pderefmat_op.cpp
geom.cpp
gridfunc.cpp
hybridization.cpp
@@ -128,46 +126,32 @@ set(SRCS
normal_deriv_restriction.cpp
staticcond.cpp
tmop.cpp
tmop/pa.cpp
tmop/assemble/diag2_limit.cpp
tmop/assemble/diag2.cpp
tmop/assemble/grad2_limit.cpp
tmop/assemble/grad2.cpp
tmop/assemble/diag3_limit.cpp
tmop/assemble/diag3.cpp
tmop/assemble/grad3_limit.cpp
tmop/assemble/grad3.cpp
tmop/metrics/001.cpp
tmop/metrics/002.cpp
tmop/metrics/007.cpp
tmop/metrics/056.cpp
tmop/metrics/077.cpp
tmop/metrics/080.cpp
tmop/metrics/094.cpp
tmop/metrics/302.cpp
tmop/metrics/303.cpp
tmop/metrics/315.cpp
tmop/metrics/318.cpp
tmop/metrics/321.cpp
tmop/metrics/332.cpp
tmop/metrics/338.cpp
tmop/mult/grad2_limit.cpp
tmop/mult/grad2.cpp
tmop/mult/mult2_limit.cpp
tmop/mult/mult2.cpp
tmop/mult/grad3_limit.cpp
tmop/mult/grad3.cpp
tmop/mult/mult3_limit.cpp
tmop/mult/mult3.cpp
tmop/tools/det2_jpr.cpp
tmop/tools/det3_jpr.cpp
tmop/tools/discrete.cpp
tmop/tools/energy2_limit.cpp
tmop/tools/energy2.cpp
tmop/tools/energy3_limit.cpp
tmop/tools/energy3.cpp
tmop/tools/target2.cpp
tmop/tools/target3.cpp
tmop/tmop_pa.cpp
tmop/tmop_pa_da3.cpp
tmop/tmop_pa_h2d.cpp
tmop/tmop_pa_h2d_c0.cpp
tmop/tmop_pa_h2m.cpp
tmop/tmop_pa_h2m_c0.cpp
tmop/tmop_pa_h2s.cpp
tmop/tmop_pa_h2s_c0.cpp
tmop/tmop_pa_h3d.cpp
tmop/tmop_pa_h3d_c0.cpp
tmop/tmop_pa_h3m.cpp
tmop/tmop_pa_h3m_c0.cpp
tmop/tmop_pa_h3s.cpp
tmop/tmop_pa_h3s_c0.cpp
tmop/tmop_pa_jp2.cpp
tmop/tmop_pa_jp3.cpp
tmop/tmop_pa_p2.cpp
tmop/tmop_pa_p2_c0.cpp
tmop/tmop_pa_p3.cpp
tmop/tmop_pa_p3_c0.cpp
tmop/tmop_pa_tc2.cpp
tmop/tmop_pa_tc3.cpp
tmop/tmop_pa_w2.cpp
tmop/tmop_pa_w2_c0.cpp
tmop/tmop_pa_w3.cpp
tmop/tmop_pa_w3_c0.cpp
tmop_tools.cpp
tmop_amr.cpp
gslib.cpp
@@ -179,26 +163,18 @@ set(SRCS
hyperbolic.cpp
integrator.cpp
bounds.cpp
particleset.cpp
)
set(HDRS
bilinearform.hpp
bilinearform_ext.hpp
bilininteg.hpp
integ/lininteg_domain_kernels.hpp
integ/bilininteg_dgdiffusion_kernels.hpp
integ/bilininteg_dgtrace_kernels.hpp
integ/bilininteg_vecdiffusion_kernels.hpp
integ/bilininteg_convection_kernels.hpp
integ/bilininteg_diffusion_kernels.hpp
integ/bilininteg_elasticity_kernels.hpp
integ/bilininteg_hcurl_kernels.hpp
integ/bilininteg_hdiv_kernels.hpp
integ/bilininteg_hcurlhdiv_kernels.hpp
integ/bilininteg_mass_kernels.hpp
integ/bilininteg_vecdiffusion_pa.hpp
integ/bilininteg_vecmass_pa.hpp
coefficient.hpp
complex_fem.hpp
convergence.hpp
@@ -263,13 +239,8 @@ set(HDRS
lor/lor_ams.hpp
lor/lor_batched.hpp
lor/lor_h1.hpp
lor/lor_dg.hpp
lor/lor_nd.hpp
lor/lor_rt.hpp
lor/lor_h1_impl.hpp
lor/lor_dg_impl.hpp
lor/lor_nd_impl.hpp
lor/lor_rt_impl.hpp
lor/lor_util.hpp
multigrid.hpp
nonlinearform.hpp
@@ -296,12 +267,7 @@ set(HDRS
tfespace.hpp
tintrules.hpp
tmop.hpp
tmop/pa.hpp
tmop/assemble/grad2.hpp
tmop/assemble/grad2.hpp
tmop/mult/mult2.hpp
tmop/mult/mult3.hpp
tmop/tools/energy2.hpp
tmop/tmop_pa.hpp
tmop_tools.hpp
tmop_amr.hpp
gslib.hpp
@@ -309,7 +275,6 @@ set(HDRS
hyperbolic.hpp
integrator.hpp
bounds.hpp
particleset.hpp
)
if (MFEM_USE_SIDRE)
+9 -42
View File
@@ -729,8 +729,7 @@ void BilinearForm::Assemble(int skip_zeros)
tr = mesh -> GetBdrFaceTransformations (i);
if (tr != NULL)
{
mfem::DofTransformation doftrans;
fes -> GetElementVDofs (tr -> Elem1No, vdofs, doftrans);
fes -> GetElementVDofs (tr -> Elem1No, vdofs);
fe1 = fes -> GetFE (tr -> Elem1No);
// The fe2 object is really a dummy and not used on the boundaries,
// but we can't dereference a NULL pointer, and we don't want to
@@ -744,7 +743,6 @@ void BilinearForm::Assemble(int skip_zeros)
boundary_face_integs[k] -> AssembleFaceMatrix (*fe1, *fe2, *tr,
elemmat);
doftrans.TransformDual(elemmat);
mat -> AddSubMatrix (vdofs, vdofs, elemmat, skip_zeros);
}
}
@@ -827,46 +825,14 @@ void BilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x,
Vector &b, OperatorHandle &A, Vector &X,
Vector &B, int copy_interior)
{
const SparseMatrix *P = fes->GetConformingProlongation();
const SparseMatrix *R = fes->GetConformingRestriction();
if (ext)
{
if (hybridization)
{
FormSystemMatrix(ess_tdof_list, A);
std::unique_ptr<ConstrainedOperator> A_constrained([&]()
{
Operator *op;
Operator::FormSystemOperator(ess_tdof_list, op);
return dynamic_cast<ConstrainedOperator*>(op);
}());
MFEM_ASSERT(A_constrained != nullptr, "");
Vector conf_b, conf_x;
if (P)
{
// Nonconforming
conf_b.SetSize(P->Width());
conf_x.SetSize(P->Width());
P->MultTranspose(b, conf_b);
R->Mult(x, conf_x);
}
else
{
// Conforming
conf_b.MakeRef(b, 0, b.Size());
conf_x.MakeRef(x, 0, x.Size());
}
A_constrained->EliminateRHS(conf_x, conf_b);
if (P)
{
R->MultTranspose(conf_b, b); // store eliminated rhs in b
}
hybridization->ReduceRHS(conf_b, B);
ConstrainedOperator A_constrained(this, ess_tdof_list);
A_constrained.EliminateRHS(x, b);
hybridization->ReduceRHS(b, B);
X.SetSize(B.Size());
X = 0.0;
}
@@ -876,6 +842,7 @@ void BilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x,
}
return;
}
const SparseMatrix *P = fes->GetConformingProlongation();
FormSystemMatrix(ess_tdof_list, A);
// Transform the system and perform the elimination in B, based on the
@@ -911,6 +878,7 @@ void BilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x,
if (hybridization)
{
// Reduction to the Lagrange multipliers system
const SparseMatrix *R = fes->GetConformingRestriction();
Vector conf_b(P->Width()), conf_x(P->Width());
P->MultTranspose(b, conf_b);
R->Mult(x, conf_x);
@@ -923,6 +891,7 @@ void BilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list, Vector &x,
else
{
// Variational restriction with P
const SparseMatrix *R = fes->GetConformingRestriction();
B.SetSize(P->Width());
P->MultTranspose(b, B);
X.SetSize(R->Height());
@@ -1725,7 +1694,6 @@ void MixedBilinearForm::Assemble(int skip_zeros)
}
}
DofTransformation dom_dof_trans, ran_dof_trans;
for (int i = 0; i < trial_fes -> GetNBE(); i++)
{
const int bdr_attr = mesh->GetBdrAttribute(i);
@@ -1734,8 +1702,8 @@ void MixedBilinearForm::Assemble(int skip_zeros)
ftr = mesh -> GetBdrFaceTransformations (i);
if (ftr != NULL)
{
trial_fes->GetElementVDofs(ftr->Elem1No, trial_vdofs, dom_dof_trans);
test_fes->GetElementVDofs(ftr->Elem1No, test_vdofs, ran_dof_trans);
trial_fes->GetElementVDofs(ftr->Elem1No, trial_vdofs);
test_fes->GetElementVDofs(ftr->Elem1No, test_vdofs);
trial_fe1 = trial_fes->GetFE(ftr->Elem1No);
test_fe1 = test_fes->GetFE(ftr->Elem1No);
// The test_fe2 object is really a dummy and not used on the
@@ -1751,7 +1719,6 @@ void MixedBilinearForm::Assemble(int skip_zeros)
boundary_face_integs[k]->AssembleFaceMatrix(*trial_fe1, *test_fe1, *trial_fe2,
*test_fe2,
*ftr, elemmat);
TransformDual(ran_dof_trans, dom_dof_trans, elemmat);
mat->AddSubMatrix(test_vdofs, trial_vdofs, elemmat, skip_zeros);
}
}
+64 -26
View File
@@ -266,7 +266,11 @@ void PABilinearFormExtension::SetupRestrictionOperators(const L2FaceValues m)
// Gather the attributes on the host from all the elements
const Mesh &mesh = *trial_fes->GetMesh();
elem_attributes = &mesh.GetElementAttributes();
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
@@ -325,7 +329,45 @@ void PABilinearFormExtension::SetupRestrictionOperators(const L2FaceValues m)
bdr_face_dYdn.SetSize(bdr_face_restrict_lex->Height());
}
bdr_face_attributes = &trial_fes->GetMesh()->GetBdrFaceAttributes();
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.GetBdrElementFaceIndex(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.");
}
}
}
@@ -387,7 +429,7 @@ void PABilinearFormExtension::AssembleDiagonal(Vector &y) const
mfem::forall(ne, [=] MFEM_HOST_DEVICE (int e)
{
const int attr = d_attr[e];
if (attr <= 0 || d_m[attr - 1] == 0)
if (d_m[attr - 1] == 0)
{
for (int i = 0; i < nd; ++i)
{
@@ -408,7 +450,7 @@ void PABilinearFormExtension::AssembleDiagonal(Vector &y) const
for (int i = 0; i < iSz; ++i)
{
assemble_diagonal_with_markers(*integrators[i], elem_markers[i],
*elem_attributes, localY);
elem_attributes, localY);
}
const ElementRestriction* H1elem_restrict =
dynamic_cast<const ElementRestriction*>(elem_restrict);
@@ -434,7 +476,7 @@ void PABilinearFormExtension::AssembleDiagonal(Vector &y) const
for (int i = 0; i < iSz; ++i)
{
assemble_diagonal_with_markers(*integrators[i], elem_markers[i],
*elem_attributes, y);
elem_attributes, y);
}
}
@@ -447,7 +489,7 @@ void PABilinearFormExtension::AssembleDiagonal(Vector &y) const
for (int i = 0; i < n_bdr_integs; ++i)
{
assemble_diagonal_with_markers(*bdr_integs[i], bdr_markers[i],
*bdr_face_attributes, bdr_face_Y);
bdr_attributes, bdr_face_Y);
}
bdr_face_restrict_lex->AddAbsMultTranspose(bdr_face_Y, y);
}
@@ -546,7 +588,7 @@ void PABilinearFormExtension::MultInternal(const Vector &x, Vector &y,
for (int i = 0; i < iSz; ++i)
{
AddMultWithMarkers(*integrators[i], localX, elem_markers[i],
*elem_attributes, false, localY, useAbs);
elem_attributes, false, localY, useAbs);
}
if (H1elem_restrict && useAbs)
{
@@ -648,8 +690,8 @@ void PABilinearFormExtension::MultInternal(const Vector &x, Vector &y,
}
for (int i = 0; i < n_bdr_integs; ++i)
{
AddMultWithMarkers(*bdr_integs[i], bdr_face_X, bdr_markers[i],
*bdr_face_attributes, false, 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)
{
@@ -657,14 +699,12 @@ void PABilinearFormExtension::MultInternal(const Vector &x, Vector &y,
{
AddMultNormalDerivativesWithMarkers(
*bdr_face_integs[i], bdr_face_X, bdr_face_dXdn,
bdr_face_markers[i], *bdr_face_attributes, bdr_face_Y,
bdr_face_dYdn);
bdr_face_markers[i], bdr_attributes, bdr_face_Y, bdr_face_dYdn);
}
else
{
AddMultWithMarkers(*bdr_face_integs[i], bdr_face_X,
bdr_face_markers[i], *bdr_face_attributes, false,
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);
@@ -687,7 +727,7 @@ void PABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
localY = 0.0;
for (int i = 0; i < iSz; ++i)
{
AddMultWithMarkers(*integrators[i], localX, elem_markers[i], *elem_attributes,
AddMultWithMarkers(*integrators[i], localX, elem_markers[i], elem_attributes,
true, localY);
}
elem_restrict->MultTranspose(localY, y);
@@ -734,14 +774,13 @@ void PABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
bdr_face_Y = 0.0;
for (int i = 0; i < n_bdr_integs; ++i)
{
AddMultWithMarkers(*bdr_integs[i], bdr_face_X, bdr_markers[i],
*bdr_face_attributes, true, 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_face_attributes, true,
bdr_face_Y);
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);
}
@@ -765,7 +804,7 @@ static void AddWithMarkers_(
mfem::forall(ne, [=] MFEM_HOST_DEVICE (int e)
{
const int attr = d_attr[e];
if (attr <= 0 || d_m[attr - 1] == 0) { return; }
if (d_m[attr - 1] == 0) { return; }
for (int i = 0; i < nd; ++i)
{
d_y(i, e) += d_x(i, e);
@@ -881,8 +920,7 @@ void EABilinearFormExtension::Assemble()
{
const int i = idx % sz;
const int e = idx / sz;
const real_t val =
d_a[e] > 0 ? (d_m[d_a[e] - 1] ? d_ea_1(i, e) : 0) : 0;
const real_t val = d_m[d_a[e] - 1] ? d_ea_1(i, e) : 0.0;
if (add)
{
d_ea_2(i, e) += val;
@@ -915,7 +953,7 @@ void EABilinearFormExtension::Assemble()
ea_data_tmp.SetSize(ea_data.Size());
integrators[i]->AssembleEA(*a->FESpace(), ea_data_tmp, false);
add_with_markers(ea_data_tmp, ea_data, ne, *markers,
*elem_attributes, add);
elem_attributes, add);
}
}
}
@@ -944,7 +982,7 @@ void EABilinearFormExtension::Assemble()
ea_data_tmp.SetSize(ea_data_bdr.Size());
bdr_integs[i]->AssembleEABoundary(*a->FESpace(), ea_data_tmp, add);
add_with_markers(ea_data_tmp, ea_data_bdr, nf_bdr, *markers,
*bdr_face_attributes, add);
bdr_attributes, add);
}
}
}
@@ -993,7 +1031,7 @@ void EABilinearFormExtension::Assemble()
ea_data_tmp,
add);
add_with_markers(ea_data_tmp, ea_data_bdr, nf_bdr, *markers,
*bdr_face_attributes, add);
bdr_attributes, add);
}
}
}
+1 -2
View File
@@ -69,8 +69,7 @@ class PABilinearFormExtension : public BilinearFormExtension
protected:
const FiniteElementSpace *trial_fes, *test_fes; // Not owned
/// Attributes of all mesh elements.
const Array<int> *elem_attributes; // Not owned
const Array<int> *bdr_face_attributes; // Not owned
Array<int> elem_attributes, bdr_attributes;
mutable Vector tmp_evec; // Work array
mutable Vector localX, localY;
mutable Vector int_face_X, int_face_Y;
+1
View File
@@ -3066,6 +3066,7 @@ void VectorDiffusionIntegrator::AssembleElementMatrix(
for (int i = 0; i < ir -> GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
el.CalcDShape(ip, dshape);
+98 -198
View File
@@ -23,8 +23,6 @@
namespace mfem
{
class QuadratureSpace;
class FaceQuadratureSpace;
/// Abstract base class BilinearFormIntegrator
class BilinearFormIntegrator : public NonlinearFormIntegrator
@@ -814,7 +812,7 @@ protected:
const FiniteElement & test_fe) const
{
return (trial_fe.GetDim() == 1 && test_fe.GetDim() == 1 &&
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
test_fe.GetRangeType() == mfem::FiniteElement::SCALAR );
}
@@ -886,7 +884,7 @@ protected:
const FiniteElement & trial_fe,
const FiniteElement & test_fe) const
{
return (trial_fe.GetDerivType() == mfem::FiniteElement::DIV &&
return (trial_fe.GetDerivType() == mfem::FiniteElement::DIV &&
test_fe.GetRangeType() == mfem::FiniteElement::SCALAR );
}
@@ -921,7 +919,7 @@ protected:
const FiniteElement & trial_fe,
const FiniteElement & test_fe) const
{
return (trial_fe.GetDerivType() == mfem::FiniteElement::DIV &&
return (trial_fe.GetDerivType() == mfem::FiniteElement::DIV &&
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
}
@@ -1602,7 +1600,7 @@ public:
{
return (trial_fe.GetCurlDim() == 3 && test_fe.GetRangeDim() == 3 &&
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
}
@@ -1637,7 +1635,7 @@ public:
{
return (trial_fe.GetDim() == 2 && test_fe.GetDim() == 2 &&
trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
}
@@ -1671,7 +1669,7 @@ public:
{
return (trial_fe.GetDim() == 2 && test_fe.GetDim() == 2 &&
trial_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
test_fe.GetRangeType() == mfem::FiniteElement::SCALAR );
}
@@ -1762,7 +1760,7 @@ public:
const FiniteElement & test_fe) const
{
return (trial_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
test_fe.GetRangeType() == mfem::FiniteElement::SCALAR );
}
@@ -1795,7 +1793,7 @@ public:
const FiniteElement & test_fe) const
{
return (trial_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
trial_fe.GetDerivType() == mfem::FiniteElement::GRAD &&
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
test_fe.GetDerivType() == mfem::FiniteElement::DIV );
}
@@ -1834,7 +1832,7 @@ public:
const FiniteElement & test_fe) const
{
return (trial_fe.GetRangeType() == mfem::FiniteElement::VECTOR &&
trial_fe.GetDerivType() == mfem::FiniteElement::DIV &&
trial_fe.GetDerivType() == mfem::FiniteElement::DIV &&
test_fe.GetRangeType() == mfem::FiniteElement::SCALAR &&
test_fe.GetDerivType() == mfem::FiniteElement::GRAD
);
@@ -1975,7 +1973,7 @@ protected:
const FiniteElement & test_fe) const override
{
return (trial_fe.GetCurlDim() == 3 && test_fe.GetRangeDim() == 3 &&
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
trial_fe.GetDerivType() == mfem::FiniteElement::CURL &&
test_fe.GetRangeType() == mfem::FiniteElement::VECTOR );
}
@@ -2178,18 +2176,22 @@ class DiffusionIntegrator: public BilinearFormIntegrator
{
public:
using ApplyKernelType = void(*)(const int, const bool, const Array<real_t>&,
const Array<real_t>&, const Array<real_t>&,
const Array<real_t>&,
const Vector&, const Vector&,
Vector&, const int, const int);
using DiffusionApplyKernelType = void(*)(const int, const bool,
const Array<real_t>&,
const Array<real_t>&, const Array<real_t>&,
const Array<real_t>&,
const Vector&, const Vector&,
Vector&, const int, const int);
using DiagonalKernelType = void(*)(const int, const bool, const Array<real_t>&,
const Array<real_t>&, const Vector&, Vector&,
const int, const int);
using DiffusionDiagonalKernelType = void(*)(const int, const bool,
const Array<real_t>&,
const Array<real_t>&, const Vector&, Vector&,
const int, const int);
MFEM_REGISTER_KERNELS(ApplyPAKernels, ApplyKernelType, (int, int, int));
MFEM_REGISTER_KERNELS(DiagonalPAKernels, DiagonalKernelType, (int, int, int));
MFEM_REGISTER_KERNELS(DiffusionApplyPAKernel, DiffusionApplyKernelType,
(int, int, int));
MFEM_REGISTER_KERNELS(DiffusionDiagonalPAKernel, DiffusionDiagonalKernelType,
(int, int, int));
struct Kernels { Kernels(); };
protected:
@@ -2209,6 +2211,7 @@ private:
const FiniteElementSpace *fespace;
const DofToQuad *maps; ///< Not owned
const GeometricFactors *geom; ///< Not owned
public:
int dim, ne, dofs1D, quad1D;
Vector pa_data;
bool symmetric = true; ///< False if using a nonsymmetric matrix coefficient
@@ -2350,8 +2353,8 @@ public:
template <int DIM, int D1D, int Q1D>
static void AddSpecialization()
{
ApplyPAKernels::Specialization<DIM,D1D,Q1D>::Add();
DiagonalPAKernels::Specialization<DIM,D1D,Q1D>::Add();
DiffusionApplyPAKernel::Specialization<DIM,D1D,Q1D>::Add();
DiffusionDiagonalPAKernel::Specialization<DIM,D1D,Q1D>::Add();
}
protected:
const IntegrationRule* GetDefaultIntegrationRule(
@@ -2496,7 +2499,8 @@ private:
#endif
public:
ConvectionIntegrator(VectorCoefficient &q, real_t a = 1.0);
ConvectionIntegrator(VectorCoefficient &q, real_t a = 1.0)
: Q(&q) { alpha = a; }
void AssembleElementMatrix(const FiniteElement &,
ElementTransformation &,
@@ -2529,28 +2533,6 @@ public:
bool SupportsCeed() const override { return DeviceCanUseCeed(); }
/// arguments: NE, B, G, Bt, Gt, pa_data, x, y, D1D, Q1D
using ApplyKernelType = void (*)(const int, const Array<real_t> &,
const Array<real_t> &,
const Array<real_t> &,
const Array<real_t> &, const Vector &,
const Vector &, Vector &, const int,
const int);
/// arguments: DIMS, D1D, Q1D
MFEM_REGISTER_KERNELS(ApplyPAKernels, ApplyKernelType, (int, int, int));
/// arguments: DIMS, D1D, Q1D
MFEM_REGISTER_KERNELS(ApplyPATKernels, ApplyKernelType, (int, int, int));
template <int DIM, int D1D, int Q1D>
static void AddSpecialization()
{
ApplyPAKernels::Specialization<DIM, D1D, Q1D>::Add();
ApplyPATKernels::Specialization<DIM, D1D, Q1D>::Add();
}
struct Kernels { Kernels(); };
protected:
const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe,
@@ -2596,40 +2578,41 @@ public:
by scalar FE through standard transformation. */
class VectorMassIntegrator: public BilinearFormIntegrator
{
int vdim = -1, Q_order = 0;
private:
int vdim;
Vector shape, te_shape, vec;
DenseMatrix partelmat;
DenseMatrix mcoeff;
int Q_order;
protected:
Coefficient *Q = nullptr;
VectorCoefficient *VQ = nullptr;
MatrixCoefficient *MQ = nullptr;
Coefficient *Q;
VectorCoefficient *VQ;
MatrixCoefficient *MQ;
// PA extension
Vector pa_data;
const DofToQuad *maps; ///< Not owned
const GeometricFactors *geom; ///< Not owned
int ne, dim, dofs1D, quad1D, coeff_vdim;
Vector pa_data;
int dim, ne, nq, dofs1D, quad1D;
public:
/// Construct an integrator with coefficient 1.0
VectorMassIntegrator() = default;
VectorMassIntegrator()
: vdim(-1), Q_order(0), Q(NULL), VQ(NULL), MQ(NULL) { }
/** Construct an integrator with scalar coefficient q. If possible, save
memory by using a scalar integrator since the resulting matrix is block
diagonal with the same diagonal block repeated. */
VectorMassIntegrator(Coefficient &q, int qo = 0): Q_order(qo), Q(&q) { }
VectorMassIntegrator(Coefficient &q, const IntegrationRule *ir):
BilinearFormIntegrator(ir), Q(&q) { }
VectorMassIntegrator(Coefficient &q, int qo = 0)
: vdim(-1), Q_order(qo), Q(&q), VQ(NULL), MQ(NULL) { }
VectorMassIntegrator(Coefficient &q, const IntegrationRule *ir)
: BilinearFormIntegrator(ir), vdim(-1), Q_order(0), Q(&q), VQ(NULL),
MQ(NULL) { }
/// Construct an integrator with diagonal coefficient q
VectorMassIntegrator(VectorCoefficient &q, int qo = 0):
vdim(q.GetVDim()), Q_order(qo), VQ(&q) { }
VectorMassIntegrator(VectorCoefficient &q, int qo = 0)
: vdim(q.GetVDim()), Q_order(qo), Q(NULL), VQ(&q), MQ(NULL) { }
/// Construct an integrator with matrix coefficient q
VectorMassIntegrator(MatrixCoefficient &q, int qo = 0):
vdim(q.GetVDim()), Q_order(qo), MQ(&q) { }
VectorMassIntegrator(MatrixCoefficient &q, int qo = 0)
: vdim(q.GetVDim()), Q_order(qo), Q(NULL), VQ(NULL), MQ(&q) { }
int GetVDim() const { return vdim; }
void SetVDim(int vdim_) { vdim = vdim_; }
@@ -2641,7 +2624,6 @@ public:
const FiniteElement &test_fe,
ElementTransformation &Trans,
DenseMatrix &elmat) override;
using BilinearFormIntegrator::AssemblePA;
void AssemblePA(const FiniteElementSpace &fes) override;
void AssembleMF(const FiniteElementSpace &fes) override;
@@ -2650,15 +2632,6 @@ public:
void AddMultPA(const Vector &x, Vector &y) const override;
void AddMultMF(const Vector &x, Vector &y) const override;
bool SupportsCeed() const override { return DeviceCanUseCeed(); }
using VectorMassAddMultPAType =
void(*)(const int, const int,
const Array<real_t>&, const Vector&,
const Vector&, Vector&, const int, const int);
MFEM_REGISTER_KERNELS(VectorMassAddMultPA,
VectorMassAddMultPAType,
(int, int, int));
};
@@ -2710,7 +2683,7 @@ public:
/** Integrator for $(-Q u, \nabla v)$ for Nedelec ($u$) and $H^1$ ($v$) elements.
This is equivalent to a weak divergence of the $H(curl)$ basis functions. */
This is equivalent to a weak divergence of the $H(curl$ basis functions. */
class VectorFEWeakDivergenceIntegrator: public BilinearFormIntegrator
{
protected:
@@ -2830,13 +2803,15 @@ protected:
bool symmetric = true; ///< False if using a nonsymmetric matrix coefficient
public:
CurlCurlIntegrator();
CurlCurlIntegrator() { Q = NULL; DQ = NULL; MQ = NULL; }
/// Construct a bilinear form integrator for Nedelec elements
CurlCurlIntegrator(Coefficient &q, const IntegrationRule *ir = nullptr);
CurlCurlIntegrator(Coefficient &q, const IntegrationRule *ir = NULL) :
BilinearFormIntegrator(ir), Q(&q), DQ(NULL), MQ(NULL) { }
CurlCurlIntegrator(DiagonalMatrixCoefficient &dq,
const IntegrationRule *ir = nullptr);
CurlCurlIntegrator(MatrixCoefficient &mq,
const IntegrationRule *ir = nullptr);
const IntegrationRule *ir = NULL) :
BilinearFormIntegrator(ir), Q(NULL), DQ(&dq), MQ(NULL) { }
CurlCurlIntegrator(MatrixCoefficient &mq, const IntegrationRule *ir = NULL) :
BilinearFormIntegrator(ir), Q(NULL), DQ(NULL), MQ(&mq) { }
/* Given a particular Finite Element, compute the
element curl-curl matrix elmat */
@@ -2866,34 +2841,6 @@ public:
void AssembleDiagonalPA(Vector& diag) override;
const Coefficient *GetCoefficient() const { return Q; }
/// arguments: d1d, q1d, symmetric, NE, bo, bc, bot, bct, gc, gct, pa_data,
/// x, y, useAbs
using ApplyKernelType = void (*)(
const int, const int, const bool, const int, const Array<real_t> &,
const Array<real_t> &, const Array<real_t> &, const Array<real_t> &,
const Array<real_t> &, const Array<real_t> &, const Vector &,
const Vector &, Vector &, const bool);
/// arguments: d1d, q1d, symmetric, ne, Bo, Bc, Go, Gc, pa_data, diag
using DiagonalKernelType = void (*)(const int, const int, const bool,
const int, const Array<real_t> &,
const Array<real_t> &,
const Array<real_t> &,
const Array<real_t> &, const Vector &,
Vector &);
/// parameters: dim, d1d, q1d
MFEM_REGISTER_KERNELS(ApplyPAKernels, ApplyKernelType, (int, int, int));
/// parameters: dim, d1d, q1d
MFEM_REGISTER_KERNELS(DiagonalPAKernels, DiagonalKernelType, (int, int, int));
struct Kernels { Kernels(); };
template <int DIM, int D1D, int Q1D> static void AddSpecialization()
{
ApplyPAKernels::Specialization<DIM, D1D, Q1D>::Add();
DiagonalPAKernels::Specialization<DIM, D1D, Q1D>::Add();
}
};
/** Integrator for $(\mathrm{curl}(u), \mathrm{curl}(v))$ for FE spaces defined by 'dim' copies of a
@@ -3129,34 +3076,39 @@ public:
to be the spatial dimension (i.e. 2-dimension or 3-dimension). */
class VectorDiffusionIntegrator : public BilinearFormIntegrator
{
int vdim = -1;
DenseMatrix dshape, dshapedxt, pelmat;
DenseMatrix mcoeff;
Vector vcoeff;
protected:
Coefficient *Q = nullptr;
VectorCoefficient *VQ = nullptr;
MatrixCoefficient *MQ = nullptr;
Coefficient *Q = NULL;
VectorCoefficient *VQ = NULL;
MatrixCoefficient *MQ = NULL;
// PA extension
const DofToQuad *maps; ///< Not owned
const GeometricFactors *geom; ///< Not owned
int ne, dim, sdim, dofs1D, quad1D, coeff_vdim;
int dim, sdim, ne, dofs1D, quad1D;
Vector pa_data;
private:
DenseMatrix dshape, dshapedxt, pelmat;
int vdim = -1;
DenseMatrix mcoeff;
Vector vcoeff;
public:
VectorDiffusionIntegrator(const IntegrationRule *ir = nullptr);
VectorDiffusionIntegrator() { }
/** \brief Integrator with unit coefficient for caller-specified vector
dimension.
If the vector dimension does not match the true dimension of the space,
the resulting element matrix will be mathematically invalid. */
VectorDiffusionIntegrator(int vector_dimension);
VectorDiffusionIntegrator(int vector_dimension)
: vdim(vector_dimension) { }
VectorDiffusionIntegrator(Coefficient &q);
VectorDiffusionIntegrator(Coefficient &q)
: Q(&q) { }
VectorDiffusionIntegrator(Coefficient &q, const IntegrationRule *ir);
VectorDiffusionIntegrator(Coefficient &q, const IntegrationRule *ir)
: BilinearFormIntegrator(ir), Q(&q) { }
/** \brief Integrator with scalar coefficient for caller-specified vector
dimension.
@@ -3166,7 +3118,8 @@ public:
If the vector dimension does not match the true dimension of the space,
the resulting element matrix will be mathematically invalid. */
VectorDiffusionIntegrator(Coefficient &q, int vector_dimension);
VectorDiffusionIntegrator(Coefficient &q, int vector_dimension)
: Q(&q), vdim(vector_dimension) { }
/** \brief Integrator with \c VectorCoefficient. The vector dimension of the
\c FiniteElementSpace is assumed to be the same as the dimension of the
@@ -3177,7 +3130,8 @@ public:
If the vector dimension does not match the true dimension of the space,
the resulting element matrix will be mathematically invalid. */
VectorDiffusionIntegrator(VectorCoefficient &vq);
VectorDiffusionIntegrator(VectorCoefficient &vq)
: VQ(&vq), vdim(vq.GetVDim()) { }
/** \brief Integrator with \c MatrixCoefficient. The vector dimension of the
\c FiniteElementSpace is assumed to be the same as the dimension of the
@@ -3188,7 +3142,8 @@ public:
If the vector dimension does not match the true dimension of the space,
the resulting element matrix will be mathematically invalid. */
VectorDiffusionIntegrator(MatrixCoefficient& mq);
VectorDiffusionIntegrator(MatrixCoefficient& mq)
: MQ(&mq), vdim(mq.GetVDim()) { }
void AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
@@ -3196,7 +3151,6 @@ public:
void AssembleElementVector(const FiniteElement &el,
ElementTransformation &Tr,
const Vector &elfun, Vector &elvect) override;
using BilinearFormIntegrator::AssemblePA;
void AssemblePA(const FiniteElementSpace &fes) override;
void AssembleMF(const FiniteElementSpace &fes) override;
@@ -3205,23 +3159,6 @@ public:
void AddMultPA(const Vector &x, Vector &y) const override;
void AddMultMF(const Vector &x, Vector &y) const override;
bool SupportsCeed() const override { return DeviceCanUseCeed(); }
/// arguments: ne, coeff_vdim, B, G, pa_data, x, y, d1d, q1d, vdim
using ApplyKernelType = void (*)(const int, const int,
const Array<real_t> &, const Array<real_t> &,
const Vector &, const Vector &, Vector &,
const int, const int, const int);
/// arguments: dim, vdim, d1d, q1d
MFEM_REGISTER_KERNELS(ApplyPAKernels, ApplyKernelType, (int, int, int, int));
template <int DIM, int VDIM, int D1D, int Q1D>
static void AddSpecialization()
{
ApplyPAKernels::Specialization<DIM, VDIM, D1D, Q1D>::Add();
}
// struct Kernels { Kernels(); };
};
/** Integrator for the linear elasticity form:
@@ -3375,8 +3312,8 @@ public:
class DGTraceIntegrator : public BilinearFormIntegrator
{
protected:
Coefficient *rho = nullptr;
VectorCoefficient *u = nullptr;
Coefficient *rho;
VectorCoefficient *u;
real_t alpha, beta;
// PA extension
Vector pa_data;
@@ -3389,16 +3326,17 @@ private:
Vector tr_shape1, te_shape1, tr_shape2, te_shape2;
public:
DGTraceIntegrator(real_t a, real_t b);
/// Construct integrator with $\rho = 1$, $\beta = \alpha/2$.
DGTraceIntegrator(VectorCoefficient &u_, real_t a);
DGTraceIntegrator(VectorCoefficient &u_, real_t a)
{ rho = NULL; u = &u_; alpha = a; beta = 0.5*a; }
/// Construct integrator with $\rho = 1$.
DGTraceIntegrator(VectorCoefficient &u_, real_t a, real_t b);
DGTraceIntegrator(VectorCoefficient &u_, real_t a, real_t b)
{ rho = NULL; u = &u_; alpha = a; beta = b; }
DGTraceIntegrator(Coefficient &rho_, VectorCoefficient &u_,
real_t a, real_t b);
real_t a, real_t b)
{ rho = &rho_; u = &u_; alpha = a; beta = b; }
using BilinearFormIntegrator::AssembleFaceMatrix;
void AssembleFaceMatrix(const FiniteElement &el1,
@@ -3437,26 +3375,6 @@ public:
static const IntegrationRule &GetRule(Geometry::Type geom, int order,
const ElementTransformation &T);
/// arguments: nf, B, Bt, pa_data, x, y, dofs1D, quad1D
using ApplyKernelType = void (*)(const int, const Array<real_t> &,
const Array<real_t> &, const Vector &,
const Vector &, Vector &, const int,
const int);
/// arguments: DIM, d1d, q1d
MFEM_REGISTER_KERNELS(ApplyPAKernels, ApplyKernelType, (int, int, int));
/// arguments: DIM, d1d, q1d
MFEM_REGISTER_KERNELS(ApplyPATKernels, ApplyKernelType, (int, int, int));
template <int DIM, int D1D, int Q1D> static void AddSpecialization()
{
ApplyPAKernels::Specialization<DIM, D1D, Q1D>::Add();
ApplyPATKernels::Specialization<DIM, D1D, Q1D>::Add();
}
struct Kernels { Kernels(); };
private:
void SetupPA(const FiniteElementSpace &fes, FaceType type);
};
@@ -3503,8 +3421,8 @@ public:
class DGDiffusionIntegrator : public BilinearFormIntegrator
{
protected:
Coefficient *Q = nullptr;
MatrixCoefficient *MQ = nullptr;
Coefficient *Q;
MatrixCoefficient *MQ;
real_t sigma, kappa;
// these are not thread-safe!
@@ -3519,11 +3437,15 @@ protected:
IntegrationRules irs{0, Quadrature1D::GaussLobatto};
public:
DGDiffusionIntegrator(const real_t s, const real_t k);
DGDiffusionIntegrator(Coefficient &q, const real_t s, const real_t k);
DGDiffusionIntegrator(MatrixCoefficient &q, const real_t s, const real_t k);
DGDiffusionIntegrator(const real_t s, const real_t k)
: Q(NULL), MQ(NULL), sigma(s), kappa(k) { }
DGDiffusionIntegrator(Coefficient &q, const real_t s, const real_t k)
: Q(&q), MQ(NULL), sigma(s), kappa(k) { }
DGDiffusionIntegrator(MatrixCoefficient &q, const real_t s, const real_t k)
: Q(NULL), MQ(&q), sigma(s), kappa(k) { }
using BilinearFormIntegrator::AssembleFaceMatrix;
void AssembleFaceMatrix(const FiniteElement &el1, const FiniteElement &el2,
void AssembleFaceMatrix(const FiniteElement &el1,
const FiniteElement &el2,
FaceElementTransformations &Trans,
DenseMatrix &elmat) override;
@@ -3542,28 +3464,6 @@ public:
const IntegrationRule &GetRule(int order, Geometry::Type geom);
real_t GetPenaltyParameter() const { return kappa; }
/// arguments: nf, B, Bt, G, Gt, sigma, pa_data, x, dxdn, y, dydn, dofs1D,
/// quad1D
using ApplyKernelType = void (*)(const int, const Array<real_t> &,
const Array<real_t> &,
const Array<real_t> &,
const Array<real_t> &, const real_t,
const Vector &, const Vector &_,
const Vector &, Vector &, Vector &,
const int, const int);
/// arguments: DIM, d1d, q1d
MFEM_REGISTER_KERNELS(ApplyPAKernels, ApplyKernelType, (int, int, int));
template <int DIM, int D1D, int Q1D> static void AddSpecialization()
{
ApplyPAKernels::Specialization<DIM, D1D, Q1D>::Add();
}
struct Kernels { Kernels(); };
private:
void SetupPA(const FiniteElementSpace &fes, FaceType type);
};
+32 -91
View File
@@ -39,16 +39,11 @@ void PLBound::Setup(const int nb_i, const int ncp_i,
b_type = b_type_i;
cp_type = cp_type_i;
tol = tol_i;
lbound.SetSize(ncp, nb);
ubound.SetSize(ncp, nb);
lbound_t.SetSize(nb, ncp);
ubound_t.SetSize(nb, ncp);
lbound.SetSize(nb, ncp);
ubound.SetSize(nb, ncp);
nodes.SetSize(nb);
weights.SetSize(nb);
control_points.SetSize(ncp);
xhat.SetSize(nb);
what.SetSize(nb);
cphat.SetSize(ncp);
auto scalenodes = [](const Vector &in, const real_t a, const real_t b) -> Vector
{
@@ -95,10 +90,6 @@ void PLBound::Setup(const int nb_i, const int ncp_i,
MFEM_ABORT("Unsupported interval points. Use [0,1].\n");
}
control_points = scalenodes(control_points, 0.0, 1.0); // rescale to [0,1]
for (int i = 0; i < ncp; i++)
{
cphat(i) = 2.0*control_points(i) - 1.0;
}
Poly_1D::Basis &basis1d(poly1d.GetBasis(nb-1, b_type));
@@ -134,28 +125,22 @@ void PLBound::Setup(const int nb_i, const int ncp_i,
{
if (j == 0)
{
lbound(j,i) = bv(i);
ubound(j,i) = bv(i);
lbound(i, j) = bv(i);
ubound(i, j) = bv(i);
}
else if (j == ncp-1)
{
lbound(j,i) = bv(i);
ubound(j,i) = bv(i);
lbound(i, j) = bv(i);
ubound(i, j) = bv(i);
}
else
{
vals(0) = bv(i);
vals(1) = bmv(i) + dm*bdmv(i);
vals(2) = bpv(i) + dp*bdpv(i);
lbound(j,i) = vals.Min()-tol; // tolerance for good measure
ubound(j,i) = vals.Max()+tol; // tolerance for good measure
if (b_type == 2)
{
lbound(j,i) = std::max(lbound(j,i),0_r);
}
lbound(i, j) = vals.Min()-tol; // tolerance for good measure
ubound(i, j) = vals.Max()+tol; // tolerance for good measure
}
lbound_t(i,j) = lbound(j,i);
ubound_t(i,j) = ubound(j,i);
}
}
@@ -187,11 +172,6 @@ void PLBound::Setup(const int nb_i, const int ncp_i,
nodes(i) = irule.IntPoint(i).x;
}
}
for (int i = 0; i < nb; i++)
{
xhat(i) = 2.0*nodes(i) - 1.0;
what(i) = 2.0*weights(i);
}
if (b_type == 2)
{
@@ -227,8 +207,7 @@ void PLBound::Setup(const int nb_i, const int ncp_i,
}
}
PLBound::PLBound(const FiniteElementSpace *fes, const int ncp_i,
const int cp_type_i)
PLBound::PLBound(FiniteElementSpace *fes, int ncp_i, int cp_type_i)
{
MFEM_VERIFY(!fes->IsVariableOrder(),
"Variable order meshes not yet supported.");
@@ -285,15 +264,15 @@ PLBound::PLBound(const FiniteElementSpace *fes, const int ncp_i,
Setup(nb, ncp, b_type, cp_type, tol);
}
void PLBound::Get1DBounds(const Vector &coeff, Vector &intmin,
Vector &intmax) const
void PLBound::Get1DBounds(Vector &coeff, Vector &intmin, Vector &intmax) const
{
real_t x,w;
intmin.SetSize(ncp);
intmax.SetSize(ncp);
intmin = 0.0;
intmax = 0.0;
Vector coeffm;
Vector coeffm(nb);
coeffm = 0.0;
real_t a0 = 0.0;
real_t a1 = 0.0;
@@ -321,8 +300,6 @@ void PLBound::Get1DBounds(const Vector &coeff, Vector &intmin,
// compute L2 projection for linear bases: a0 + a1*x
if (proj)
{
coeffm.SetSize(nb);
coeffm = 0.0;
for (int i = 0; i < nb; i++)
{
x = 2.0*nodes_int(i)-1;
@@ -363,14 +340,13 @@ void PLBound::Get1DBounds(const Vector &coeff, Vector &intmin,
real_t c = coeffm(i);
for (int j = 0; j < ncp; j++)
{
intmin(j) += min(lbound(j,i)*c, ubound(j,i)*c);
intmax(j) += max(lbound(j,i)*c, ubound(j,i)*c);
intmin(j) += min(lbound(i,j)*c, ubound(i,j)*c);
intmax(j) += max(lbound(i,j)*c, ubound(i,j)*c);
}
}
}
void PLBound::Get2DBounds(const Vector &coeff, Vector &intmin,
Vector &intmax) const
void PLBound::Get2DBounds(Vector &coeff, Vector &intmin, Vector &intmax) const
{
intmin.SetSize(ncp*ncp);
intmax.SetSize(ncp*ncp);
@@ -495,10 +471,10 @@ void PLBound::Get2DBounds(const Vector &coeff, Vector &intmin,
real_t w1 = intmaxT(id2++);
for (int k = 0; k < ncp; k++) // kth row
{
vals(0) = w0*lbound(k,j);
vals(1) = w0*ubound(k,j);
vals(2) = w1*lbound(k,j);
vals(3) = w1*ubound(k,j);
vals(0) = w0*lbound(j,k);
vals(1) = w0*ubound(j,k);
vals(2) = w1*lbound(j,k);
vals(3) = w1*ubound(j,k);
intmin(k*ncp+i) += vals.Min();
intmax(k*ncp+i) += vals.Max();
}
@@ -506,8 +482,7 @@ void PLBound::Get2DBounds(const Vector &coeff, Vector &intmin,
}
}
void PLBound::Get3DBounds(const Vector &coeff, Vector &intmin,
Vector &intmax) const
void PLBound::Get3DBounds(Vector &coeff, Vector &intmin, Vector &intmax) const
{
int nb2 = nb*nb,
ncp2 = ncp*ncp,
@@ -574,17 +549,17 @@ void PLBound::Get3DBounds(const Vector &coeff, Vector &intmin,
for (int i = 0; i < nb; i++)
{
x = 2.0*nodes(i)-1; // x-coordinate
minNodalVals(i) -= a0V(j) + a1V(j)*x;
maxNodalVals(i) -= a0V(j) + a1V(j)*x;
minBounds(i) -= a0V(j) + a1V(j)*x;
maxBounds(i) -= a0V(j) + a1V(j)*x;
}
// Compute Bernstein coefficients
LUFactors lu(basisMatLU.GetData(), lu_ip.GetData());
lu.Solve(nb, 1, minNodalVals.GetData());
lu.Solve(nb, 1, maxNodalVals.GetData());
lu.Solve(nb, 1, minBounds.GetData());
lu.Solve(nb, 1, maxBounds.GetData());
for (int i = 0; i < nb; i++)
{
intminT(i*ncp2+j) = minNodalVals(i);
intmaxT(i*ncp2+j) = maxNodalVals(i);
intminT(i*ncp2+j) = minBounds(i);
intmaxT(i*ncp2+j) = maxBounds(i);
}
}
}
@@ -638,10 +613,10 @@ void PLBound::Get3DBounds(const Vector &coeff, Vector &intmin,
real_t w1 = intmaxT(id2++);
for (int k = 0; k < ncp; k++) // kth slice
{
vals(0) = w0*lbound(k,j);
vals(1) = w0*ubound(k,j);
vals(2) = w1*lbound(k,j);
vals(3) = w1*ubound(k,j);
vals(0) = w0*lbound(j,k);
vals(1) = w0*ubound(j,k);
vals(2) = w1*lbound(j,k);
vals(3) = w1*ubound(j,k);
intmin(k*ncp2+i) += vals.Min();
intmax(k*ncp2+i) += vals.Max();
}
@@ -649,7 +624,7 @@ void PLBound::Get3DBounds(const Vector &coeff, Vector &intmin,
}
}
void PLBound::GetNDBounds(const int rdim, const Vector &coeff,
void PLBound::GetNDBounds(int rdim, Vector &coeff,
Vector &intmin, Vector &intmax) const
{
if (rdim == 1)
@@ -674,8 +649,7 @@ void PLBound::SetupBernsteinBasisMat(DenseMatrix &basisMat,
Vector &nodesBern) const
{
const int nbern = nodesBern.Size();
L2_SegmentElement el(nbern-1, 2);
// we use L2 to leverage lexicographic order
L2_SegmentElement el(nbern-1, 2); // we use L2 to leverage lexicographic order
Array<int> ordering = el.GetLexicographicOrdering();
basisMat.SetSize(nbern, nbern);
Vector shape(nbern);
@@ -688,39 +662,6 @@ void PLBound::SetupBernsteinBasisMat(DenseMatrix &basisMat,
}
}
DenseMatrix PLBound::GetBoundingMatrix(int dim, bool is_lower) const
{
if (dim > 1)
{
const int ncpd = static_cast<int>(std::pow(ncp, dim));
const int nbd = static_cast<int>(std::pow(nb, dim));
DenseMatrix boundND(ncpd, nbd);
Vector phimin, phimax, col;
Vector coeffs(nbd);
coeffs = 0.0;
for (int j = 0; j < nbd; j++)
{
coeffs(j) = 1.0;
boundND.GetColumnReference(j, col);
GetNDBounds(dim, coeffs, phimin, phimax);
col = is_lower ? phimin : phimax;
coeffs(j) = 0.0;
}
return boundND;
}
return is_lower ? lbound : ubound;
}
DenseMatrix PLBound::GetLowerBoundMatrix(int dim) const
{
return GetBoundingMatrix(dim, true);
}
DenseMatrix PLBound::GetUpperBoundMatrix(int dim) const
{
return GetBoundingMatrix(dim, false);
}
constexpr int PLBound::min_ncp_gl_x[2][11];
constexpr int PLBound::min_ncp_gll_x[2][11];
constexpr int PLBound::min_ncp_pos_x[2][11];

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