Compare commits

..
Author SHA1 Message Date
psocratis b40b0dae3e minor 2020-09-30 19:04:31 -07:00
psocratis a9ccfdd7b2 merge with mkl=pardiso 2020-09-30 17:56:24 -07:00
psocratis 5137ef5604 clean up 2020-09-29 19:42:44 -07:00
psocratis 8f1d08dc93 Adding symmetric and SPD matrix case 2020-09-29 19:04:17 -07:00
Julian Andrej e63f9887f4 add MUMPS version check to makefile build system 2020-09-29 14:13:14 -07:00
psocratis 2819c0e361 more cleaning up 2020-09-29 13:23:43 -07:00
psocratis 30b0ae9581 cleanup 2020-09-28 17:47:08 -07:00
psocratis 59a32942f2 make style 2020-09-28 15:06:23 -07:00
psocratis 90af7527d0 mumps interface works with any combination of distributed RHS and Solution or not... still needs some cleanup and a valgrind run 2020-09-28 15:05:18 -07:00
psocratis ac6ff275ba Adding MUMPSSolver interface. Finished the case where RHS and Solution are gathered on host 2020-09-27 18:09:25 -07:00
Julian Andrej b78402803f bugs everywhere 2020-09-26 18:21:36 -07:00
Julian Andrej 6e5bb7e5e1 more distributed solution vector fiddling 2020-09-26 16:25:48 -07:00
Julian Andrej 99a3803b4f distributed rhs and solution 2020-09-26 15:48:07 -07:00
Julian Andrej c0495229fc add MUMPS to the makefile buildsystem 2020-09-26 14:08:56 -07:00
psocratis adce9a5755 Adding interface for distributed MUMPS still needs implementation for distributed RHS 2020-09-25 20:22:36 -07:00
Julian Andrej 197854c4c0 guard source and header 2020-09-25 18:50:51 -07:00
Julian Andrej baeed18fc6 remove user.mk 2020-09-25 18:44:40 -07:00
Julian Andrej c18b00f9a3 add to makefile build system 2020-09-25 18:38:20 -07:00
Julian Andrej 765918926f spellcheck 2020-09-25 15:24:52 -07:00
Julian Andrej 5aec9ffe25 change matrix data ownership 2020-09-25 13:32:50 -07:00
Julian Andrej 145877e2e3 correct interface comment 2020-09-25 11:03:28 -07:00
Julian Andrej cf336ec28f correct delete calls 2020-09-25 11:03:15 -07:00
Julian Andrej 14771eeb79 cmake build system tweak for LC 2020-09-25 10:31:43 -07:00
Julian Andrej 32d0df49d6 added changelog entry 2020-09-25 09:11:58 -07:00
Julian Andrej e5c5d1e419 make style 2020-09-25 08:56:53 -07:00
Julian Andrej 18dc8f7a56 documentation and refactor on teh pardiso interface 2020-09-25 08:07:29 -07:00
Julian Andrej 5720512ef2 add pardiso option to ex11p 2020-09-25 08:07:12 -07:00
Julian Andrej 8f602ab9d3 add support for MKL Cluster Pardiso 2020-09-24 15:15:13 -07:00
Tzanio Kolev 27acd4f56d Merge pull request #1764 from mfem/mesh-boundary-fix
Mesh bug fix and unit test
2020-09-20 10:32:37 -07:00
Tzanio Kolev 1cd7ef1599 Merge pull request #1584 from mfem/pacurlsmem
Shared memory for H(curl) PA
2020-09-17 17:41:31 -07:00
Tzanio Kolev 7087ae37a7 Merge pull request #1704 from mfem/adios2-element-attribute
Add element attribute to adios2 bp dataset
2020-09-17 17:40:22 -07:00
Jakub Červený efebb2ceb3 The CheckEnlarge line needs to stay, this is the new behavior from nc-init-dev. 2020-09-17 11:05:15 +02:00
Dylan Copeland dac6f6afe7 Fixing a bug and adding a small unit test that catches it. 2020-09-16 14:55:12 -07:00
Tzanio 2b2410e0bd minor 2020-09-11 12:25:12 -07:00
Robert Carson efd71f438f changelog wording 2020-09-11 10:00:07 -07:00
Dylan Copeland 2a5fcacbb1 Merge branch 'master' of github.com:mfem/mfem into pacurlsmem 2020-09-08 18:28:53 -07:00
Tzanio Kolev a40523a7cf Merge pull request #1655 from mfem/curl-curl-coef
Support additional coefficient options in CurlCurlIntegrator
2020-09-08 12:52:55 -07:00
Tzanio Kolev 44696d423d Merge pull request #1688 from mfem/feature/lassen_ci_dev
Add tests on Lassen in Gitlab CI
2020-09-08 12:46:54 -07:00
Tzanio Kolev 1cf578ea0b Merge pull request #1649 from mfem/nc-init-dev
On the fly NC mesh initialization [nc-init-dev]
2020-09-06 18:55:35 -07:00
Dylan Copeland e75f242ff6 Removing unnecessary ifdef. 2020-09-02 12:06:32 -07:00
Tzanio Kolev 065f5692b0 Merge pull request #1561 from mfem/convergence-dev
Convergence rate tests [convergence-dev]
2020-09-02 08:26:13 -07:00
Tzanio Kolev 00a54534d7 Update .gitignore 2020-09-01 17:14:28 -07:00
Tzanio 73433a7515 Final changes 2020-09-01 17:12:15 -07:00
Tzanio aa3b111af1 Styling 2020-09-01 16:25:25 -07:00
Tzanio e02ee0ed95 Updated CHANGELOG 2020-09-01 16:25:14 -07:00
psocratis 271aab3537 modified CHANGELOG 2020-09-01 15:28:14 -07:00
Tzanio 2d2151e4e5 minor 2020-09-01 14:51:22 -07:00
Tzanio 6f1a090c06 Merge branch 'master' into convergence-dev 2020-09-01 14:50:43 -07:00
Tzanio Kolev e8a8691680 Merge pull request #1632 from mfem/ex6-pa-preconditioner
Ex6[p] diagonal preconditioner for PA
2020-09-01 14:49:31 -07:00
Tzanio a7de792214 Fix copyright header 2020-09-01 14:46:14 -07:00
Tzanio b91aebd35a Merge branch 'master' into ex6-pa-preconditioner
Conflicts:
	CHANGELOG
2020-09-01 14:41:57 -07:00
Tzanio 7e283304a3 Merge branch 'master' into convergence-dev 2020-09-01 14:38:56 -07:00
Tzanio 72cf086b27 edits 2020-09-01 14:21:03 -07:00
Tzanio Kolev a194e35053 Merge pull request #1560 from mfem/findpts-crystalrouter
FindPointsGSLIB support for non-H1 gridfunctions
2020-09-01 10:20:19 -07:00
Tzanio c218bba6d4 Final changes 2020-09-01 10:18:31 -07:00
Jakub Červený 8c1e9337c0 Moved finalization after setting curvature in 2D. Added more validations. 2020-08-31 19:26:45 +02:00
Tzanio Kolev b2983cb965 Merge pull request #1705 from mfem/jeremy/libceed-refactor-dev
libCEED - prevent duplicate Ceed objects from MFEM FES
2020-08-30 17:42:12 -07:00
Tzanio Kolev 65c3984b54 Merge pull request #1697 from mfem/nc-face-neighbors-fix
Fix crash in ParNCMesh::GetFaceNeighbors [nc-face-neighbors-fix]
2020-08-30 17:39:58 -07:00
Tzanio Kolev 2b7ac1d5c1 Merge pull request #1685 from benzwick/error-messages
Improve DenseMatrix error messages
2020-08-30 17:39:12 -07:00
William F Godoy 18ddb79f10 Updated Changelog 2020-08-28 15:58:58 -04:00
Ketan Mittal 6f36aad054 removing hdiv file and minor changes 2020-08-26 15:41:15 -07:00
Dylan Copeland b708606309 Adding support for general coefficients in curl-curl diagonal assembly, with unit testing. 2020-08-25 20:27:16 -07:00
Dylan Copeland ffeadb4f8c Merge branch 'master' of github.com:mfem/mfem into curl-curl-coef 2020-08-25 15:12:01 -07:00
Tzanio Kolev 4f521a1be6 Merge pull request #1718 from mfem/debug_device
Backend::DEBUG to Backend::DEBUG_DEVICE [debug_device]
2020-08-25 14:20:25 -07:00
Tzanio Kolev ca15d29cf4 Merge pull request #1691 from mfem/yohann/EA-add-set
Add an option to set or add when using AssembleEA.
2020-08-25 14:19:23 -07:00
Tzanio Kolev 829c2e3a6c Merge pull request #1575 from mfem/complex-operator-gpu
GPU support for complex operators
2020-08-25 14:13:39 -07:00
Tzanio cf953c2275 Minor styling 2020-08-25 14:10:49 -07:00
jeremylt 841d6e7bee Drop extra destroys for basis/restr 2020-08-25 14:14:52 -06:00
jeremylt 1527dcbf44 Expand keys to include ncomp 2020-08-25 13:53:07 -06:00
jeremylt 956a37a2d9 Drop unused variables 2020-08-25 13:44:30 -06:00
Veselin Dobrev d02aa95619 Merge pull request #1645 from mfem/bugfix/dof-marker-gpu
MarkerToList: delete and reset the underlying data object
2020-08-25 12:36:42 -07:00
camierjs fe425fafbf Merge master in debug_device 2020-08-25 10:17:20 -07:00
Tzanio Kolev 85749266f4 Merge pull request #1682 from mfem/catch2
Upgrade unit tests to Catch v2.13.0 from v1.6.1
2020-08-25 08:14:51 -07:00
camierjs fa7ea733ab Merge master in debug_device 2020-08-24 11:44:45 -07:00
camierjs 2678423e6e Add a line to clarify the 'debug' device exception. 2020-08-24 08:13:58 -07:00
Tzanio ca82238e40 Minor edits 2020-08-23 14:44:13 -07:00
Tzanio Kolev bb3c788a05 Merge pull request #1623 from mfem/barker29/reorder-boomeramg
HypreBoomerAMG: allow Ordering::byNODES in systems version
2020-08-23 14:03:32 -07:00
Tzanio Kolev b79d3de89a Merge pull request #1706 from mfem/okina-mmu-mflags
Okina mmu mflags [okina-mmu-flags]
2020-08-23 13:34:17 -07:00
camierjs ea24d37651 Typo 2020-08-21 17:03:24 -07:00
camierjs eaf2257263 Rename Backend::DEBUG to Backend::DEBUG_DEVICE 2020-08-21 14:34:15 -07:00
Ketan Mittal c3eb129cc8 adding support for user-defined functions 2020-08-21 11:14:58 -07:00
Tzanio Kolev b3beafe905 Merge pull request #1638 from mfem/tmop-el-type
Mixed meshes in TMOP
2020-08-20 06:24:33 -07:00
Tzanio Kolev 9c936e24bb Merge pull request #1474 from mfem/h1-hessian-dev
Add CalcHessian for H1-conforming tensor finite elements [h1-hessian-dev]
2020-08-20 06:23:43 -07:00
stefanhenneking 6b24cac9bb minor 2020-08-19 17:30:03 -05:00
jeremylt e13d898c1f Ceed - drop unused functions 2020-08-19 15:47:47 -06:00
Tzanio Kolev 3005dee1af Merge pull request #1622 from mfem/feature/stitt4/more-work-units
Expose more parallelism in some kernels [feature/stitt4/more-work-units]
2020-08-19 14:40:13 -07:00
Tzanio Kolev 7ef5575ab4 Merge pull request #1694 from mfem/boundary-integ-fix
Assert that added bilinear form integrators are supported by PA/EA
2020-08-19 14:38:48 -07:00
jeremylt ce3e27fc99 minor style 2020-08-19 13:50:28 -06:00
stefanhenneking 0db216e51d Merged master into feature branch. 2020-08-19 12:50:31 -05:00
stefanhenneking 2417a4328c minor 2020-08-19 12:47:58 -05:00
camierjs 3f2c2acf23 Merge master in feature/stitt4/more-work-units 2020-08-19 08:12:42 -07:00
camierjs a2f144d0db Merge master in okina-mmu-mflags 2020-08-19 08:04:49 -07:00
camierjs c10364d3f2 Move assignments inside if statements 2020-08-19 08:03:11 -07:00
jeremylt c968ed6920 Ceed - revert typo 2020-08-18 19:20:11 -06:00
jeremylt 32f6bf55fa Ceed -fix const in the key tuples 2020-08-18 19:19:22 -06:00
jeremylt 5b8bb9cc17 Ceed - fix embarassing pointer mistake 2020-08-18 19:07:30 -06:00
Tzanio Kolev 04b5626fd4 Merge pull request #1571 from mfem/ho-gmsh-dev
Adding high order Gmsh support [ho-gmsh-dev]
2020-08-18 17:33:40 -07:00
Veselin Dobrev 8162d3047e Merge pull request #1641 from mfem/eval-state-dev
Reset ElementTransformation::EvalState in new situations [eval-state-dev]
2020-08-18 17:23:03 -07:00
Will Pazner 5cd33e391a Fix bug 2020-08-18 16:57:24 -07:00
Will Pazner f285421dfe Workaround for nvcc/Catch compatibility
Certain REQUIRE statements were causing nvcc (specifically cicc) to
crash when compiling.

This can be temporarily worked around by introducing temporary
variables.

See https://github.com/catchorg/Catch2/issues/2005
2020-08-18 16:22:58 -07:00
jeremylt af09a4ec59 style updates from Travis 2020-08-18 17:17:12 -06:00
jeremylt 49fdfd73de Ceed - refactor FES->Basis,ElemRestriction hash table to use tuples 2020-08-18 16:50:19 -06:00
psocratis d184bc43ff Editing some comments 2020-08-18 11:18:21 -07:00
jeremylt 3140782959 style fixes from Travis 2020-08-18 11:59:04 -06:00
jeremylt de1100519d Ceed - refactor to use standard library hash table and avoid null arguments 2020-08-18 11:34:59 -06:00
stefanhenneking 5e94c43b7c minor 2020-08-17 17:41:30 -05:00
Yohann Dudouit 172e8ffe08 Fix the logic to transpose faces in ElementAssembly. 2020-08-17 14:53:14 -07:00
Yohann Dudouit 1522a69a83 Merge branch 'master' into yohann/EA-add-set 2020-08-17 13:48:33 -07:00
Yohann Dudouit 8f02cdb352 Remove more unnecessary zero initializations. 2020-08-17 13:47:13 -07:00
Yohann Dudouit dcfd8c72ca Remove unnecessary zero initialization. 2020-08-17 13:16:23 -07:00
YohannandTzanio Kolev 2b93007196 Update fem/bilininteg.hpp
Co-authored-by: Tzanio Kolev <tzanio@llnl.gov>
2020-08-17 12:14:39 -07:00
Tzanio 52530f419e Various small changes 2020-08-16 19:44:08 -07:00
Tzanio 8d5c51ebd1 Merge branch 'master' into findpts-crystalrouter 2020-08-16 15:48:18 -07:00
Tzanio 62ee56e544 minor 2020-08-16 15:39:27 -07:00
Tzanio Kolev 00550ef4f7 Merge pull request #1489 from mfem/feature/artv3/cusparse-Spmv
SpMV with CuSPARSE
2020-08-16 15:16:10 -07:00
Tzanio a16b216c91 Final editorial changes 2020-08-16 15:14:03 -07:00
Tzanio 4b0d543114 Merge branch 'master' into ho-gmsh-dev
Conflicts:
	CHANGELOG
2020-08-16 14:50:28 -07:00
Tzanio 940ec885ef Clarify that 'l' in Mesh Explorer can be used for any function 2020-08-16 14:48:33 -07:00
Will Pazner da94f8631e Adjust tolerance in NCMesh unit test 2020-08-16 14:39:45 -07:00
Will Pazner 6d9d0aa07d Change tolerances in new unit tests 2020-08-16 14:03:33 -07:00
Tzanio ccf5b8df5f Merge branch 'master' into catch2 2020-08-16 11:47:14 -07:00
Will Pazner 2ae8010ee2 Update CHANGELOG 2020-08-14 17:14:46 -07:00
Ketan Mittal e74ebc977b minor 2020-08-14 15:06:16 -07:00
Ketan Mittal 3b9328a937 account for L2 functions of order 0 and enable a no averaging option 2020-08-14 15:05:04 -07:00
Dylan Copeland c7006c63f1 Merge branch 'master' of github.com:mfem/mfem into pacurlsmem 2020-08-14 14:19:32 -07:00
stefanhenneking 186d605b71 minor 2020-08-14 16:09:16 -05:00
jeremylt bd83eab2e9 CEED - allow null arguments to InitCeedBasisAndRestriction as well 2020-08-14 13:03:37 -06:00
jeremylt 813a68ed15 Ceed - update libCEED git hash 2020-08-14 12:59:34 -06:00
camierjs a72fa476c5 Merge master in feature/stitt4/more-work-units 2020-08-14 11:23:42 -07:00
camierjs 98450102f5 Merge master in okina-mmu-mflags 2020-08-14 11:21:55 -07:00
camierjs 97b31f641e Remove dead code 2020-08-14 11:07:37 -07:00
camierjs 0b79c6a742 Fix aliases test_mem and cleanup 2020-08-14 11:04:23 -07:00
stefanhenneking a6139cc245 Merge branch 'master' of github.com:mfem/mfem into ex6-pa-preconditioner 2020-08-14 12:52:57 -05:00
stefanhenneking 8d0d4e4bc1 Merging master into feature branch. 2020-08-14 12:51:55 -05:00
Tzanio Kolev 3a06bc39df Merge pull request #1618 from mfem/abs-mult-dev
AbsMult and AbsMultTranspose
2020-08-14 10:48:53 -07:00
jeremylt ad66b16d0d Ceed - add ceed-hash tables for mfem fes -> ceed basis, restriction 2020-08-14 11:48:35 -06:00
Tzanio a3e9ac8e8d minor 2020-08-14 10:48:17 -07:00
stefanhenneking 2fbfaf80de Merge branch 'master' of github.com:mfem/mfem into curl-curl-coef 2020-08-14 12:04:50 -05:00
stefanhenneking 353fd60e42 Adding comment to explain usage of AbsMult. 2020-08-14 11:40:09 -05:00
jeremylt 0546ed1030 Ceed - allow null arguments to InitCeed*BasisAndRestriction 2020-08-14 10:19:20 -06:00
jeremylt f2343c6f9b Ceed - update libCEED git hash for install 2020-08-14 09:46:55 -06:00
jeremylt a11c00e12e libCEED - add new qfunction context data object, mild perf improvement 2020-08-14 09:46:32 -06:00
camierjs c9b9dd8f07 Merge branch 'master' into okina-mmu-mflags 2020-08-14 08:31:04 -07:00
camierjs da8624fd45 Merge branch 'master' into feature/stitt4/more-work-units 2020-08-14 08:28:52 -07:00
Ketan Mittal 48fb45bf1b minor 2020-08-13 20:26:30 -07:00
Ketan Mittal 569ad39379 doxygen comments 2020-08-13 19:49:32 -07:00
Tzanio Kolev 064eeb6591 Merge pull request #1620 from mfem/matcoefpa
Matrix coefficient support for H(curl) PA.
2020-08-13 18:39:42 -07:00
Tzanio Kolev 690807d631 Merge pull request #1633 from mfem/residual-bc-monitor
Add residual monitor for checking for correct handling of essential boundary conditions
2020-08-13 18:35:31 -07:00
Will Pazner f1271d5ffe Merge remote-tracking branch 'origin/master' into catch2
# Conflicts:
#	tests/unit/fem/test_assembly_levels.cpp
#	tests/unit/fem/test_pa_kernels.cpp
2020-08-13 17:02:24 -07:00
Ketan Mittal b1f54d1215 remove extra lines 2020-08-13 16:14:45 -07:00
Ketan Mittal d15bdaa7df doxygen comment fix 2020-08-13 15:05:21 -07:00
camierjs 69bfdbe248 Merge branch 'master' into feature/stitt4/more-work-units 2020-08-13 14:54:59 -07:00
camierjs 2f2a4ca5fd Merge branch 'master' into okina-mmu-mflags 2020-08-13 14:35:31 -07:00
Ketan Mittal c7f49ba820 make style 2020-08-13 12:48:36 -07:00
Ketan Mittal e5e37bb104 minor 2020-08-13 12:28:15 -07:00
Tzanio Kolev df22d9da86 Merge pull request #1674 from mfem/branch-history-update
Update the script branch-history [branch-history-update]
2020-08-13 12:24:20 -07:00
Tzanio Kolev 40045b01e2 Merge pull request #1660 from mfem/yohann/fix-diff3D-EA
Fix a bug in Diffusion Element Assembly in 3D.
2020-08-13 12:23:28 -07:00
Tzanio Kolev 91fc72b021 Merge pull request #1686 from mfem/jeremy/libceed-version
Update libCEED install git hash
2020-08-13 12:21:19 -07:00
Ketan Mittal 9d05f6a69c introduce default values for point not found 2020-08-13 12:07:04 -07:00
Ketan Mittal 95118654a2 fix for when points are not found 2020-08-13 11:32:13 -07:00
William F Godoy 219083b48c Add element attribute to adios2 bp dataset
Update dataset format version
Save element attribute as "material" local array variable
Add material as CellData in xml schema
Update FindADIOS2.cmake for adios2 v2.6.0.
2020-08-13 13:04:44 -04:00
Ketan Mittal 848872ee26 resolve conflict 2020-08-13 09:26:38 -07:00
Ketan Mittal d6f0eb888a update CHANGELOG 2020-08-13 09:25:20 -07:00
Tomov 4cb7b3bd4d Merge branch 'master' into findpts-crystalrouter 2020-08-12 17:39:45 -07:00
Ketan Mittal 6105236ac8 minor fix if freedata is called more than once 2020-08-12 15:24:57 -07:00
Ketan Mittal 9f78b74272 print out only unique points in pfinfpts 2020-08-11 16:11:59 -07:00
Stowell, Mark L 66be99b4f5 Adding an assert to SetFE 2020-08-10 17:00:29 -07:00
Stowell, Mark L 8b69106bef Adding a constructor to IsoparametricTransformation so that its internal data can be initialized 2020-08-10 16:53:51 -07:00
Jakub Červený cf8a86dde6 Fix crash in ParNCMesh::GetFaceNeighbors due to slave edges/faces beyond the ghost layer. 2020-08-10 10:21:53 +02:00
Veselin Dobrev bfdfec0a2c Minor formatting edits. 2020-08-07 16:58:35 -07:00
Dylan Copeland be65608e07 Moving constexpr ints into MFEM_FORALL. 2020-08-07 16:45:43 -07:00
Dylan Copeland a2309b6044 Moved some constexpr ints inside the MFEM_FORALL. 2020-08-07 14:56:26 -07:00
Adrien M. Bernede b9ca2a3013 Apply review suggestion 2020-08-07 14:43:59 -07:00
Dylan Copeland c09cb09a65 Changing the condition for deciding whether to use smem kernels. 2020-08-07 11:19:29 -07:00
stefanhenneking 6edd9b07ad Using MFEM_VERIFY instead of MFEM_ASSERT. 2020-08-07 11:50:32 -05:00
Veselin DobrevandAndrew T. Barker d767b6f541 Update linalg/solvers.cpp
Applying change suggested on github.

Co-authored-by: Andrew T. Barker <barker29@llnl.gov>
2020-08-07 03:28:56 -07:00
stefanhenneking 6ab34c27c1 Minor 2020-08-07 00:59:20 -05:00
stefanhenneking d565ad7d84 Adding additional assertions for MixedBilinearForm. 2020-08-06 16:47:08 -05:00
stefanhenneking 32df373a82 Adding assertions inform the user about missing support for BoundaryIntegrator. 2020-08-06 16:37:36 -05:00
Ketan Mittal 59e33bcd3d Merge branch 'findpts-crystalrouter' of https://github.com/mfem/mfem into findpts-crystalrouter 2020-08-06 13:16:00 -07:00
Ketan Mittal 5aefc6e2ec minor fix with ip.SetD 2020-08-06 13:15:32 -07:00
Tomov 747cae6785 Minor. 2020-08-06 12:22:29 -07:00
Tomov 57bc15f4b3 AMR sample run. 2020-08-06 12:18:33 -07:00
Tomov 84c81f32e5 Minor. 2020-08-06 12:15:46 -07:00
Tomov 88e63a1692 Extra output and examples in field-interp. 2020-08-06 12:11:09 -07:00
Dylan Copeland a37e4c5adb Using templates for all shared memory kernels. 2020-08-06 11:25:17 -07:00
stefanhenneking 79ad2cfda4 Adding a few sample runs with PA on CPU. 2020-08-06 13:15:43 -05:00
Adrien M. Bernede e099e0d3eb Possible fix 2020-08-06 09:49:06 -07:00
stefanhenneking 1b2bd158e1 Adding assertion to ensure dynamically cast pointer is not NULL. 2020-08-06 10:48:14 -05:00
Ben Zwick 845daf78d0 Clarify error messages 2020-08-06 08:46:00 +08:00
Ketan Mittal ddda149fd4 Merge branch 'findpts-crystalrouter' of https://github.com/mfem/mfem into findpts-crystalrouter 2020-08-05 16:47:27 -07:00
Ketan Mittal 7cf2680f8e minor fix for H1 2020-08-05 16:47:02 -07:00
Tomov dddf17c8f5 Corrected the creation of ND and RD spaces in findpts.cpp. 2020-08-05 16:39:52 -07:00
Yohann Dudouit 97f51343cb Fix a bug in AssembleEA Transpose 3D. 2020-08-05 16:13:02 -07:00
Yohann Dudouit 6329d712b7 Set default to true. 2020-08-05 16:00:55 -07:00
Dylan Copeland 26f4a0c585 Minor changes. 2020-08-05 16:00:17 -07:00
Yohann Dudouit 1d6eefe56e make style 2020-08-05 15:59:31 -07:00
Dylan Copeland 12c9c9fe3e Merge branch 'pacurlsmem-tmp' of github.com:mfem/mfem into pacurlsmem 2020-08-05 15:44:53 -07:00
Yohann Dudouit 073d9526d9 Add an option to set or add when using AssembleEA. 2020-08-05 15:40:50 -07:00
Will PaznerandStefan Henneking 9ea7f160db Change documentation comment type
Co-authored-by: Stefan Henneking <stefan.henneking@gmail.com>
2020-08-05 13:25:34 -07:00
Dylan Copeland eef3f16f7a Moving useConfigData out of the MPI ifdef. 2020-08-05 12:58:50 -07:00
Dylan Copeland 45457af5a6 Changing shared memory array definition. 2020-08-05 10:38:11 -07:00
Adrien M. Bernede 719556056a Minor changes, essentially to trigger CI 2020-08-05 09:15:52 -07:00
Adrien M. Bernede 23a20ed498 Basic lassen tests 2020-08-05 09:15:52 -07:00
Dylan Copeland 9cc330035f Making 3D mass diagonal PA SMEM version templated. 2020-08-05 08:39:14 -07:00
Dylan Copeland 47c980d1e5 Adding CUDA tag to diagonal PA test. Restoring an old unit test. 2020-08-05 08:34:28 -07:00
jeremylt 0d1f3028f4 Update libCEED install git hash 2020-08-05 08:47:08 -06:00
Jakub Červený de56b17a73 polar-nc: fixed unused variable ('origin'). 2020-08-05 13:41:32 +02:00
Jakub Červený 3333f1a0ba Updated CHANGELOG 2020-08-05 13:36:46 +02:00
Jakub Červený 0463a6c2e2 Merge branch 'master' into nc-init-dev 2020-08-05 12:59:44 +02:00
Jakub Červený 11f6fe668a polar-nc: output is now called the same as the miniapp 2020-08-05 12:57:28 +02:00
Ben Zwick eef546bb91 Improve DenseMatrix error messages 2020-08-05 16:59:40 +08:00
Jakub Červený 3cd393dddb polar-nc: added visualization option 2020-08-05 09:49:18 +02:00
Jakub Červený 3f74fc0a1b Fixed tabs in miniapps/meshing/makefile 2020-08-05 09:25:17 +02:00
Will Pazner 4fee14d514 Merge branch 'master' into catch2 2020-08-04 21:05:59 -07:00
Will Pazner 78468b8481 Minor 2020-08-04 21:03:55 -07:00
stefanhenneking 3277d9619e Minor (simplification). 2020-08-04 16:52:07 -05:00
camierjs 7afce5a62c Use inner threads for mass and diffusion setup 2020-08-04 14:19:43 -07:00
Dylan Copeland 7364d761a5 Changing kernel argument variable names to not begin with underscore or a capital letter. 2020-08-04 13:51:45 -07:00
stefanhenneking 2db150149d Minor change. 2020-08-04 15:12:04 -05:00
camierjs 1e6cd92ad7 Merge branch 'master' into feature/stitt4/more-work-units 2020-08-04 11:57:58 -07:00
Will Pazner b8663ce965 Re-enable Assembly Levels test. CI will fail until #1660 is merged. 2020-08-04 11:49:10 -07:00
Will Pazner ebe07eaa36 make style 2020-08-04 09:48:53 -07:00
camierjs 84f59e1afc Merge branch 'master' into okina-mmu-mflags 2020-08-04 09:24:23 -07:00
Will Pazner 9d83eed55c Upgrade to Catch v2.13.0 from v1.6.1 2020-08-04 08:37:48 -07:00
Yohann Dudouit efa35e4a79 Modify test_pa_kernels.cpp to run all tests. 2020-08-03 17:53:14 -07:00
Yohann Dudouit 5feb9c21db Add Diffusion test for DG. 2020-08-03 15:56:52 -07:00
Yohann Dudouit 9b049b134a make style 2020-08-03 15:32:57 -07:00
Yohann Dudouit 28a4a8cc24 Remove unnecessary SetCurvature. 2020-08-03 14:26:19 -07:00
Yohann Dudouit bbcadbcc3b Fix testing of assembly levels.
- WARNING: catch SECTION inside for loops result in only the first iteration of the loop being executed.
2020-08-03 14:21:38 -07:00
stefanhenneking 4be4d220a8 Adding Sync and SyncAlias methods for [Par]ComplexGridFunction and [Par]ComplexLinearForm. 2020-08-03 14:35:22 -05:00
Stowell, Mark L dc64a38a86 Reworked the torus-sector mesh using a butterfly configuration 2020-08-03 11:09:58 -07:00
Veselin Dobrev 088db70ad2 Fix doxygen warning. 2020-08-02 16:59:20 -07:00
Veselin Dobrev 2162829989 Fix reporting of warnings by './runtest documentation'. 2020-08-02 15:33:37 -07:00
Jakub Červený c1d32eb781 polar-nc: miniapp description, makefile cleaning, gitignore 2020-08-02 22:15:06 +02:00
Veselin Dobrev 4c1a849631 Small addition to the 'mesh-explorer' miniapp to support viewing
(the projection of) an analytic 'level_function' defined in the
source file. In particular, this allows us to view how much a mesh
boundary deviates from any level set of the 'level_function'.
2020-08-02 13:10:34 -07:00
Jakub Červený 73d9b2b468 More renaming. 2020-08-02 18:05:37 +02:00
Jakub Červený 7fc19f99e1 Renamed miniapp radial-nc to polar-nc. 2020-08-02 18:02:10 +02:00
Jakub Červený a448f94afd radial-nc: center tets in 3D now respect the aspect setting. 2020-08-02 17:59:06 +02:00
Jakub Červený be806c66cd radial-nc: boundary elements in 3D added. 2020-08-02 17:24:57 +02:00
Jakub Červený 20fdb60ca6 Finished mesh initialization API improvements. 2020-08-02 17:24:34 +02:00
Jakub Červený 2dab711e35 radial-nc: higher order curvature in 3D works 2020-08-02 14:53:50 +02:00
Veselin Dobrev 898a33125c In 'branch-history', handle a couple of less common mode strings
when parsing merge commits. Also, when the checks for a branch fail,
print the name of the failed branch.
2020-08-01 14:38:01 -07:00
Veselin Dobrev a058e2ce63 Update the script 'branch-history':
* Allow setting the branch on the command line. This allows for
  testing branches that do not have the script or its latest version
  merged-in, or simply testing branches without checkout.
* When inspecting the branch commits, also consider merge- and root-
  commits -- these can also introduce new or modify existing files.
2020-07-31 22:34:16 -07:00
Ketan Mittal 44b3749566 minor 2020-07-31 17:00:20 -07:00
Ketan Mittal 7e29e7a66f remove an extra line 2020-07-31 12:38:17 -07:00
Ketan Mittal a73a473055 fix for Tpr->ElementType due to another PR 2020-07-31 12:01:54 -07:00
Ketan Mittal a97e0f081e allow source and target function type to be different 2020-07-31 10:14:10 -07:00
stefanhenneking 9dba6a2429 Fixing a typo (comment). 2020-07-30 13:50:18 -05:00
Veselin Dobrev 50d720c4d7 Tweak the CUDA support in the CMake build system, including
support for cuSPARSE and more CMake versions.
2020-07-29 21:42:11 -07:00
Tzanio 2ecf10cfe5 minor 2020-07-29 19:40:51 -07:00
Stowell, Mark L a1b3fedde3 Switching to finer torus mesh 2020-07-29 19:30:26 -07:00
Tzanio 747e871e80 Smaller periodic-torus-sector.msh with mesh optimization 2020-07-29 17:25:51 -07:00
Ketan Mittal 9deac910fa account for basis type 2020-07-29 16:53:44 -07:00
Ketan Mittal 2becd019a3 minor 2020-07-29 16:05:25 -07:00
Ketan Mittal 9d83a0d23c minor 2020-07-29 15:59:36 -07:00
Stowell, Mark L 04904936f7 Swapping a larger example mesh to avoid badly shaped hexahedra. 2020-07-29 13:38:30 -07:00
stefanhenneking 0db7b843f5 Using std::abs 2020-07-29 15:23:11 -05:00
Veselin Dobrev 06ec0d019f Merge branch 'master' into feature/artv3/cusparse-Spmv
Resolved conflicts:
   CHANGELOG
2020-07-29 12:55:06 -07:00
Jakub Červený 729f568ac5 radial-nc: 3D meshing works for linear elements. 2020-07-29 21:40:37 +02:00
Stowell, Mark L 2e2d42a8a9 Cleanup compiler warnings 2020-07-29 10:45:08 -07:00
Ketan Mittal d905170a28 addressing reviewers' comments 2020-07-29 08:44:32 -07:00
Tomov a09e19e4f5 Minor. 2020-07-28 17:22:10 -07:00
Tomov 0080f2898d Changelog. 2020-07-28 16:09:36 -07:00
Tomov 90bdac177e Minor. 2020-07-28 16:00:22 -07:00
Dylan Copeland 79a1aaaa98 Fixing coefficient dimensions in the 2D case. 2020-07-28 17:14:39 -05:00
Tzanio fd0d5927f6 Final updates 2020-07-28 14:30:42 -07:00
stefanhenneking a98ef3ae5b Merge branch 'master' of github.com:mfem/mfem into curl-curl-coef 2020-07-28 15:48:47 -05:00
Stowell, Mark L a30eb78a6b Calculating spaceDim by inspecting the bounding box of the mesh 2020-07-28 13:37:10 -07:00
Ketan Mittal b85fccf3d6 added file for sample run in field-interp 2020-07-28 11:07:00 -07:00
Ketan Mittal 834cef52b7 minor changes 2020-07-28 10:04:24 -07:00
stefanhenneking 2f37cc37de Add a similar fix for ListToMarker(). 2020-07-28 11:44:19 -05:00
stefanhenneking c1f395c813 Adding fix to ensure the list is valid on host. 2020-07-28 11:40:01 -05:00
stefanhenneking e4df598c0b Reverting changes in example 6. 2020-07-28 11:39:07 -05:00
Ketan Mittal 167cda84c9 minor 2020-07-28 09:00:58 -07:00
Jakub Červený 26d8d91118 radial-nc: trying to fix 3D parametrization 2020-07-28 14:40:20 +02:00
Yohann Dudouit 5a3f58bdf7 Fix a bug in Diffusion EA 3D. 2020-07-27 16:57:27 -07:00
Dylan Copeland 411d3fc96d Implemented vector and matrix coefficients for 3D curl-curl PA integrator, with unit tests. Added the option to specify integration rule, which is necessary for the unit tests. 2020-07-27 16:21:40 -07:00
Dylan Copeland 2d464874e1 Merge branch 'master' of https://github.com/mfem/mfem into matcoefpa 2020-07-27 14:39:40 -07:00
stefanhenneking 4de6b5eeba Merge branch 'master' of github.com:mfem/mfem into complex-operator-gpu 2020-07-27 16:32:53 -05:00
Tzanio e938ec6d95 Small updates to *.geo files 2020-07-27 11:25:06 -07:00
Dylan Copeland 9258085c3d Further improving readability. 2020-07-27 11:18:19 -07:00
stefanhenneking db1d1f3aa5 Minor change in comment. 2020-07-27 12:21:16 -05:00
Tzanio d4b06b41cc Editing 2020-07-27 10:14:55 -07:00
Dylan Copeland 534d74a281 Improving readability with some boolean variables. 2020-07-27 09:50:10 -07:00
Stefan Henneking a8e2e7383f A few minor changes to reproduce the issue. 2020-07-27 09:46:50 -07:00
stefanhenneking 1520991750 Adding NCMesh unit test for PA diagonal assembly. 2020-07-25 18:07:53 -05:00
stefanhenneking a16de090e4 Minor fix. 2020-07-25 17:50:40 -05:00
psocratis 15f871eafa added small comment on the computation of the rate 2020-07-24 17:33:37 -07:00
psocratis a817874f12 make style 2020-07-24 16:15:15 -07:00
Tomov 857ddd0c24 Merge branch 'master' into tmop-el-type 2020-07-24 16:06:58 -07:00
psocratis 48c9b0f92f Merge branch 'master' into curl-curl-coef 2020-07-24 16:06:45 -07:00
psocratis 5977679b6b fixed typo 2020-07-24 16:06:31 -07:00
psocratis 25ded86cd3 Replaced PMLMatrixCoefficient with PMLDiagMatrixCoefficient (VectorCoefficient) in ex25p.cpp 2020-07-24 15:55:24 -07:00
Tomov 30acc283d6 Reverted the change in the limiting; make style. 2020-07-24 15:36:52 -07:00
psocratis 8fa68c42ff Modified ex25 to use VectorCoefficient instead of a MatrixCoefficient 2020-07-24 15:22:40 -07:00
psocratis c5538ff8dc Added Diagonal Matrix Coefficient (VectorCoefficient) in CurlCurlintegrator 2020-07-24 15:09:13 -07:00
Jakub Červený 5b345e43a5 radial-nc: WIP 3D mesh 2020-07-24 19:25:04 +02:00
stefanhenneking 7595b945b8 Minor change. 2020-07-24 12:01:27 -05:00
stefanhenneking 7b392632eb Merge branch 'abs-mult-dev' of github.com:mfem/mfem into ex6-pa-preconditioner 2020-07-24 11:55:17 -05:00
stefanhenneking bb74169b37 Merge branch 'master' of github.com:mfem/mfem into ex6-pa-preconditioner 2020-07-24 11:55:07 -05:00
Jakub Červený 85713406a7 radial-nc: added SFC ordering option. 2020-07-23 20:16:58 +02:00
Dylan Copeland e00be4f28e Adding 2D versions of H(curl)-H(div) mixed mass PA operators with support for all coefficient types. 2020-07-23 11:13:01 -07:00
stefanhenneking c922f6926e Minor change in comments. 2020-07-23 12:20:30 -05:00
stefanhenneking 768a689aa5 Merging support for block operator on device into feature branch. 2020-07-23 12:16:53 -05:00
stefanhenneking a16150a436 Minor change to changelog. 2020-07-23 12:13:48 -05:00
Arturo Vargas ad208cadfa update changelog 2020-07-23 09:28:44 -07:00
Dylan Copeland 23a34bd2e7 Fix cuda unit tests build. 2020-07-22 21:03:12 -07:00
Dylan Copeland 27b1a97cc9 Excluding cunit_tests from build if not using cuda. 2020-07-22 19:47:16 -07:00
psocratis 0219828ca6 Renaming public methods and signatures for better readability. Modified the examples accordingly 2020-07-22 18:14:45 -07:00
Stowell, Mark L 33e4d56213 Updating CHANGELOG and improving comments as suggested by reviewers 2020-07-22 17:24:11 -07:00
Tzanio cb1fd6fccb Merge branch 'master' into feature/artv3/cusparse-Spmv 2020-07-22 16:39:38 -07:00
Julian Andrej e6af88c98c fix cuda unit test in cmake 2020-07-22 16:11:46 -07:00
Dylan Copeland d34b094f27 Merge branch 'master' of https://github.com/mfem/mfem into pacurlsmem 2020-07-22 15:51:02 -07:00
Dylan Copeland eb6a7afb9c Adding PA for 3D mass operator with H(div) trial and H(curl) test functions, supporting all coefficient types, and with unit tests. 2020-07-22 13:54:30 -07:00
psocratis ab0955357c minor changes addressing reviewers comments 2020-07-22 11:11:36 -07:00
psocratis e520ed9647 Merge branch 'master' into convergence-dev 2020-07-22 10:43:21 -07:00
Jakub Červený 13f5a48fa4 radial-nc: added mesh curvature 2020-07-22 19:39:51 +02:00
Dylan Copeland 95985e9c83 Adding PA for H(curl)-H(div) mass operator with scalar, diagonal vector, or matrix (symmetric or asymmetric) coefficients. Unit tests cover the new features. Fixed a bug in PAHcurlHdivApply3D which had no effect so far. 2020-07-21 22:16:28 -07:00
Tzanio a7f182e47c minor 2020-07-21 17:14:19 -07:00
Tzanio 10ebf2c2a2 Merge branch 'master' into ho-gmsh-dev 2020-07-21 16:39:41 -07:00
stefanhenneking 8f7db4d393 Merge branch 'master' of github.com:mfem/mfem into abs-mult-dev 2020-07-21 17:35:01 -05:00
Veselin Dobrev 51397513f1 Merge branch 'master' into residual-bc-monitor 2020-07-21 15:23:14 -07:00
stefanhenneking 733630ee14 Ensure to delete and reset the underlying data object. 2020-07-21 16:31:48 -05:00
Ketan Mittal be240f9242 minor stylistic changes 2020-07-21 14:18:38 -07:00
stefanhenneking d1b5234a09 Merging master into feature branch. 2020-07-21 16:18:38 -05:00
stefanhenneking 91e3853cd4 Merge branch 'master' of github.com:mfem/mfem into ex6-pa-preconditioner 2020-07-21 16:15:55 -05:00
Stowell, Mark L 8591f4eb0a Adding calls to Reset in locations where GetPointMat is used to update the point matrix 2020-07-21 12:07:51 -07:00
Stowell, Mark L 94c241c368 Adding comment to remind users of GetPointMat to call the new Reset member function 2020-07-21 12:07:04 -07:00
Stowell, Mark L c35a943aba Resetting EvalState when new FiniteElement or a new point matrix is set 2020-07-21 12:03:36 -07:00
Stowell, Mark L bc20049cd9 Adding ElementTransformation::Reset method to set EvalState to zero. 2020-07-21 12:02:49 -07:00
Ketan Mittal 0881487256 Merge branch 'master' of https://github.com/mfem/mfem into findpts-crystalrouter 2020-07-21 11:17:20 -07:00
Jakub Červený 13d2c2eaec Mesh::AddVertexParents works, added boundary elements in radial-nc miniapp. 2020-07-21 19:29:58 +02:00
Dylan Copeland 8412926d1f Documentation 2020-07-21 10:27:53 -07:00
Dylan CopelandandStefan Henneking e6a0818041 Minor change.
Co-authored-by: Stefan Henneking <stefan.henneking@gmail.com>
2020-07-21 10:08:16 -07:00
Dylan CopelandandStefan Henneking 1bb517c695 Minor change.
Co-authored-by: Stefan Henneking <stefan.henneking@gmail.com>
2020-07-21 10:02:49 -07:00
Jakub Červený 69a04bb7f0 radial-nc miniapp: doubling rows and creating hanging vertices. 2020-07-21 15:30:24 +02:00
Jakub Červený 338b484217 WIP improvements of on-the-fly mesh initialization, including NC meshing. 2020-07-21 14:27:48 +02:00
Tomov 8327c249de Old TODO comment. 2020-07-20 18:07:30 -07:00
Tomov 8208a13de4 Corresponding changes in the serial miniapp. 2020-07-20 17:35:53 -07:00
Tomov a000402216 Minor. 2020-07-20 17:18:01 -07:00
Tomov 85d171e7cb Sample runs for mixed meshes in pmesh-optimizer. 2020-07-20 17:10:29 -07:00
Tomov 8e631732e1 Merge branch 'master' into tmop-el-type 2020-07-20 16:13:27 -07:00
Dylan Copeland a2910dadb7 Updating CMakeLists.txt for cunit_tests. 2020-07-17 22:38:33 -07:00
Dylan Copeland 93865c8176 Adding smem versions of mixed curl integrators. Adding unit test to run all tests with tag CUDA, using "cuda" device. 2020-07-17 22:08:20 -07:00
Ketan Mittal 320f491661 fix for discrete adaptivity 2020-07-17 15:58:21 -07:00
Veselin Dobrev fd45ae843a Extend the class IterativeSolverMonitor to store a pointer to
the last IterativeSolver that uses it.

Add a simple ResidualBCMonitor that can be used to check if
essential b.c. are properly imposed on the initial guess, rhs,
operator, and preconditioner.
2020-07-17 12:57:34 -07:00
stefanhenneking 48c0d02405 Updating CHANGELOG. 2020-07-17 14:37:27 -05:00
stefanhenneking 8e54a05376 Adding diagonal preconditioner to PA case. 2020-07-17 14:31:08 -05:00
stefanhenneking 9a6c263019 Merge branch 'abs-mult-dev' of github.com:mfem/mfem into ex6-pa-preconditioner 2020-07-17 13:19:25 -05:00
Dylan Copeland 5ede2d36b9 Adding pa_tests_cuda to unit tests. 2020-07-17 10:46:05 -07:00
Ketan Mittal d850f810ce return mfem_elem instead of gslib_elem 2020-07-16 16:55:15 -07:00
Stowell, Mark L bfad6c9903 Removing unneeded Gmsh files 2020-07-16 15:19:41 -07:00
Stowell, Mark L 3d94969a8b Replacing sample Gmsh meshes with high order meshes 2020-07-16 12:43:00 -07:00
Stowell, Mark L 973e0486ff Switching to periodic annulus by default 2020-07-16 12:31:38 -07:00
Stowell, Mark L 655536e919 Adding element type improvements to periodic torus geo file (thanks to @bslazarov) 2020-07-16 12:26:22 -07:00
Stowell, Mark L 5d5e0a5320 Adjusting comments and user options in periodic annulus geo file 2020-07-16 12:24:57 -07:00
Dylan Copeland 140d93ab33 Enabled smem kernels for up to order 4. 2020-07-16 10:34:45 -07:00
Dylan Copeland 77b6729309 Updating description of input parameters omitted from a previous PR. 2020-07-16 10:11:18 -07:00
lazarov ff03595251 Merge branch 'ho-gmsh-dev' of https://github.com/mfem/mfem into ho-gmsh-dev 2020-07-15 22:59:12 -07:00
lazarov f84f1c9416 periodic sector and 3rd order generated mesh 2020-07-15 22:57:50 -07:00
Dylan Copeland f5c9fee3c0 Adding smem version of 3D H(curl) mass diagonal assembly. 2020-07-15 20:26:12 -07:00
Dylan Copeland f6542b6a8f Switching between kernel versions (smem or not) depending on whether using device. This allows unit tests to pass. 2020-07-15 17:32:01 -07:00
Andrew T. Barker fc8475828d HypreBoomerAMG: allow Ordering::byNODES in systems version 2020-07-15 16:18:58 -07:00
stefanhenneking b570911a15 Updating changelog. 2020-07-15 17:31:56 -05:00
Tzanio Kolev 0da14b3875 Merge branch 'master' into ho-gmsh-dev 2020-07-15 14:52:44 -07:00
psocratis 5108a8b28d Updated copyright banner 2020-07-15 14:43:39 -07:00
Veselin Dobrev c1a15aa858 Merge branch 'master' into h1-hessian-dev 2020-07-15 14:33:29 -07:00
stefanhenneking 3da43efb86 Merge branch 'master' of github.com:mfem/mfem into complex-operator-gpu 2020-07-15 16:32:57 -05:00
Tzanio Kolev 4b011866f8 Merge branch 'master' into convergence-dev 2020-07-15 14:29:05 -07:00
stefanhenneking 064a859fd1 Minor fix in member variable initialization. 2020-07-15 15:18:36 -05:00
stefanhenneking 56211dfeb9 Merging complex-operator-pa branch. 2020-07-15 15:15:59 -05:00
stefanhenneking f2c7e4f166 Adding required preprocessor directives. 2020-07-15 14:55:40 -05:00
Tom Stitt 4877a6d350 Updates PADiffusionSetup{2,3}D and QuadratureInterpolator::Eval{2,3}D to
expose more units of work, there wasn't enough work with 1
thread/element.

The PADiffusionSetup kernels are now over NE*NQ instead of just NE
and the Eval{2,3}D kernels are now shared-memory kernels of size max(NQ,
ND) instead being over NE.
2020-07-15 12:47:02 -07:00
psocratis 930fa24327 minor comment addition 2020-07-15 12:23:28 -07:00
Dylan Copeland ea4d8c365c Restoring another unit test. 2020-07-15 11:29:00 -07:00
psocratis 7de90075e1 Merge branch 'abs-mult-dev' of https://github.com/mfem/mfem into abs-mult-dev 2020-07-15 11:19:25 -07:00
psocratis dba8b05843 cleanup 2020-07-15 11:18:29 -07:00
stefanhenneking 8fc24ace79 Adding AssembleDiagonal for NCMesh using AbsMultTranspose. 2020-07-15 11:39:35 -05:00
Stefan Henneking 79aa92e217 Merge branch 'master' into abs-mult-dev 2020-07-15 10:51:00 -05:00
Stefan Henneking ac69933f77 Merge branch 'master' into complex-operator-gpu 2020-07-15 10:50:21 -05:00
Dylan Copeland 96dd27f68f Restoring changes. 2020-07-14 22:30:10 -07:00
Dylan Copeland ab51c0ad38 Merge branch 'master' of https://github.com/mfem/mfem into matcoefpa 2020-07-14 21:33:08 -07:00
Dylan Copeland 26b36ef71b Merge branch 'master' of github.com:mfem/mfem into pacurlsmem 2020-07-14 20:23:26 -07:00
psocratis 5ef9a11e9f unit test for rectangular HyprePar and Sparse Matrices 2020-07-14 18:25:10 -07:00
stefanhenneking 7009af9ecc Simplifying MakeRef functions. 2020-07-14 19:21:54 -05:00
psocratis ae6b431161 Added unit test for SparseMatrix::AbsMultTranspose 2020-07-14 16:44:07 -07:00
psocratis e3a9948ab6 Added unit test for HypreParMatrix::AbsMultTranspose 2020-07-14 16:43:43 -07:00
psocratis b3e18e733b Added implementation for hypre_CSRMatrixAbsMatvecT and hypre_ParCSRMatrixAbsMatvecT 2020-07-14 16:43:10 -07:00
stefanhenneking a2da036bdb Destroying alias vectors to avoid issues with dangling references in memory manager. 2020-07-14 18:18:04 -05:00
Dylan Copeland c71428a623 Rearranging SmemPACurlCurlApply3D to reduce shared memory access. 2020-07-14 15:56:24 -07:00
psocratis 6fc3b74033 Added unit tests for HypreParMatrix::AbsMult and SparseMatrix::AbsMult 2020-07-14 15:34:59 -07:00
psocratis b20b819e0e Added implementation for hypre_ParCSRMatrixAbsMatvec 2020-07-14 14:55:23 -07:00
psocratis 3b016624ca minor 2020-07-14 11:02:47 -07:00
psocratis 0b538f5cd1 Added implementation of hypre_CSRMatrixAbsMatvec 2020-07-13 20:19:27 -07:00
psocratis e9e9741f48 merge master 2020-07-13 18:52:31 -07:00
Socratis 043227cae0 fixed valgrind issue in ratesp 2020-07-13 17:44:46 -07:00
psocratis 39b695dd72 minor 2020-07-13 17:32:27 -07:00
psocratis 0df63b1d08 cleaned up the example rates[p] 2020-07-13 17:14:32 -07:00
psocratis 3e6e5a3685 Added comments in [p]gridfunction and clean up 2020-07-13 17:13:34 -07:00
psocratis 88713bcd12 added cpp and hpp in CmakeList and in fem.hpp path 2020-07-13 17:12:37 -07:00
psocratis 7ff584c893 Added convergence hpp and cpp in /fem 2020-07-13 17:10:59 -07:00
stefanhenneking a97509648a Adding signatures for hypre AbsMult and AbsMultTranpose. 2020-07-13 17:39:36 -05:00
stefanhenneking 6fc40b1ee5 Adding AbsMult and AbsMultTranspose to SparseMatrix. 2020-07-13 14:55:57 -05:00
psocratis dd2f0140f3 combined all examples into 1 : rates.cpp, ratesp.cpp 2020-07-12 19:04:18 -07:00
Dylan Copeland db191b082f Adding smem version of PAHcurlMassApply3D. 2020-07-11 12:15:04 -07:00
psocratis e2a1ac8be6 make style 2020-07-10 19:43:39 -07:00
psocratis e93a91d5f6 clean up 2020-07-10 19:43:06 -07:00
Dylan Copeland 8c942e2a9a Adding smem version of PACurlCurlApply3D. 2020-07-10 17:31:56 -07:00
Will Pazner 31825b99b1 make style 2020-07-10 16:11:12 -07:00
Will Pazner 20380cfe07 Add parallel DG convergence test 2020-07-10 16:10:32 -07:00
Will Pazner e01bcf074b Add parallel computation of DG face error 2020-07-10 16:10:24 -07:00
stefanhenneking 6cb82fa126 Merge branch 'master' of github.com:mfem/mfem into complex-operator-gpu 2020-07-10 11:35:55 -05:00
Ketan Mittal 315c9b80e1 make style 2020-07-09 13:24:06 -07:00
Ketan Mittal 39ba9e9c0e cleanup 2020-07-09 10:29:05 -07:00
Ketan Mittal de832c96e3 minor fix for L2 and added comments 2020-07-08 18:18:13 -07:00
Ketan Mittal f36e548b24 minor 2020-07-08 16:29:15 -07:00
Ketan Mittal 0944109ef3 minor changes to gslib 2020-07-08 15:21:12 -07:00
Ketan Mittal 0a972edbd8 update findpts serial example 2020-07-08 15:20:19 -07:00
psocratis 90ecd5fc1b Added DG example 2020-07-08 13:35:28 -07:00
stefanhenneking 8e90fcde40 Merging complex-operator-pa features into this complex-operator-gpu. 2020-07-08 14:48:54 -05:00
stefanhenneking ef41d0f3c1 Merge branch 'complex-operator-gpu' of github.com:mfem/mfem into complex-operator-gpu 2020-07-08 14:38:12 -05:00
stefanhenneking d32f760854 Merge branch 'master' of github.com:mfem/mfem into complex-operator-gpu
Merging master into feature branch.
2020-07-08 14:37:12 -05:00
Tomov dcf2e20f86 Added limiting to the mixed mesh sample runs, switched to references
instead of pointer for the local integration rules.
2020-07-08 10:59:21 -07:00
Tzanio Kolev c8990d45db Merge branch 'master' into h1-hessian-dev 2020-07-08 09:24:49 -07:00
psocratis 19fac7ee7c make style 2020-07-07 19:03:56 -07:00
psocratis 3625d1cdb8 Merge branch 'master' into convergence-dev 2020-07-07 19:02:57 -07:00
Tomov 5e71900292 Sample runs with mixed 2D and 3D meshes. Fix in the normalization code. 2020-07-07 19:00:58 -07:00
Andreas Schafelner 4a17f07edf Fixed variable names. 2020-07-07 11:27:37 +02:00
Andreas Schafelner 1b5e10bd25 Fix a typo in CalCHessian documentation. 2020-07-07 10:41:22 +02:00
Andreas Schafelner 2f77370746 Merge branch 'master' into h1-hessian-dev 2020-07-07 10:40:55 +02:00
camierjs d9c9caa909 Merge branch 'master' into okina-mmu-mflags 2020-07-06 10:40:45 -07:00
Andreas Schafelner 5e436c109e make style 2020-07-06 09:23:23 +02:00
Stowell, Mark L 346af0560f Gmsh pyramid mappings 2020-07-03 14:56:33 -07:00
Stowell, Mark L 5cdbec35ff Use predefined mappings for orders 2 and 3 2020-07-02 14:26:24 -07:00
Stowell, Mark L f917dfb3c1 Gmsh wedge mappings 2020-07-02 14:01:52 -07:00
Stowell, Mark L 89ae6ad31c Adding new gmsh.[ch]pp files to cmake 2020-07-02 10:33:17 -07:00
Stowell, Mark L a7ba2b2dad Gmsh tetrahedron mapping 2020-07-01 17:51:01 -07:00
Tomov 69ea9d3dc4 Support for mixed meshes in TMOPNewtonSolver. 2020-07-01 15:39:53 -07:00
Stowell, Mark L bf24259fda Gmsh hexahedron mapping 2020-07-01 15:21:02 -07:00
Stowell, Mark L a0ac13f0ef Gmsh quadrilateral mapping (thanks @pazner!) 2020-07-01 15:20:42 -07:00
Stowell, Mark L fc430a2732 Gmsh triangle mapping (thanks @pazner) 2020-07-01 15:18:38 -07:00
Stefan Henneking a298f02b4c Enable block diagonal preconditioner for device computation. 2020-07-01 13:51:50 -07:00
Stefan Henneking ec8b00ea1e Merge branch 'blockop_cuda' of github.com:mfem/mfem into complex-operator-gpu
Merging support for BlockOperator on device from feature branch.
2020-07-01 13:24:56 -07:00
Stowell, Mark L ce12d60a57 Adding Gmsh specific high-order vertex mapping functions 2020-07-01 11:54:53 -07:00
Stowell, Mark L 25804821c9 Adding recognition of higher order element types (as well as Wedges and Pyramids). Still need mappings... 2020-07-01 00:51:32 -07:00
Stowell, Mark L 275ef2d826 Starting modifications to support orders up to 9 or 10 2020-06-30 22:16:05 -07:00
Dylan Copeland e77e7f592b Adding support for matrix coefficients in H(curl) mass diagonal assembly, with unit tests. 2020-06-30 15:10:55 -07:00
psocratis 8833320150 added relative error computation 2020-06-29 19:50:11 -07:00
psocratis 69e1c83478 Added Conv_rates to convergence and diffusion example. Removed ComputeEnergyError from gridFuncion class. Added energy error estimates to Convergence Class 2020-06-29 17:49:54 -07:00
stefanhenneking f9ed143f40 Removing typos. 2020-06-29 16:00:21 -05:00
Stefan Henneking e5570e9e4c Sync memory after recovering FEM solution on device. 2020-06-29 12:24:42 -07:00
camierjs a46473e463 Merge branch 'master' into okina-mmu-mflags 2020-06-29 10:29:06 -07:00
Stefan Henneking af900cf8d7 Merge branch 'master' of github.com:mfem/mfem into complex-operator-gpu
Merging master into feature branch.
2020-06-29 10:25:06 -07:00
Stefan Henneking a57a3eb070 Enabling device support for ComplexParLinearForm. 2020-06-29 10:23:07 -07:00
Stefan Henneking aea668a9f9 Adding MakeRef function to ParLinearForm. 2020-06-29 10:22:18 -07:00
Stefan Henneking a3ebecd8ac Minor change in function doc. 2020-06-29 09:49:17 -07:00
Tzanio f2c1441949 Merge branch 'master' into ho-gmsh-dev 2020-06-27 18:23:47 -07:00
Tzanio 4bae761338 make style 2020-06-27 18:23:43 -07:00
psocratis 6d23b31933 minor modification in makefile 2020-06-26 17:43:47 -07:00
psocratis 7d56d2ab30 Modified parallel projection test 2020-06-26 17:40:53 -07:00
psocratis 7d60795d20 Added serial projection example test 2020-06-26 17:40:10 -07:00
psocratis c614d384a3 Added relative L2 error 2020-06-26 17:39:38 -07:00
psocratis a8f9fcc65c Clean up in ComputeEnergyError 2020-06-26 17:38:48 -07:00
psocratis ee2e6d4f35 Small modification for 2D Hcurl LFCurlIntegrator 2020-06-26 17:37:59 -07:00
Dylan Copeland 65c4443b77 Implemented shared memory version of curl-curl diagonal assembly in 3D. 2020-06-26 17:10:40 -07:00
Stefan Henneking ac4aa43430 Enable device support for ParSesquilinearForm. 2020-06-26 15:16:41 -07:00
Stefan Henneking 47d3d7ead1 Enable device support for ParComplexGridFunction. 2020-06-26 14:35:07 -07:00
Stefan Henneking 03473d90fa Ensure vector is registered on device before using alias. 2020-06-26 14:33:26 -07:00
stefanhenneking e4529f82f7 Adding device option to ex22p. 2020-06-26 13:58:52 -05:00
stefanhenneking a883eb7287 Minor style change. 2020-06-26 11:53:34 -05:00
Stefan Henneking aaf321caab Fixing a few typos in documentation. 2020-06-26 09:49:53 -07:00
Stowell, Mark L 9a6954b957 Tweaks after double-checking high order hexahedron support 2020-06-26 09:42:56 -07:00
Stefan Henneking b9b7c7b046 Enabling device support for complex linear form. 2020-06-26 09:39:34 -07:00
psocratis 1f8c48ce73 Added ComputeEnergyError in ParGridFunction 2020-06-25 19:53:36 -07:00
Stefan Henneking 3a9bfe3c81 Enabling device support for ComplexGridFunction::Update(). 2020-06-25 15:39:12 -07:00
Stefan Henneking dce5bf5801 Enabling device support for example ex22. 2020-06-25 15:06:24 -07:00
Stefan Henneking 1fd05bf80d Enabling support for device computation for complex operator transpose mult. 2020-06-25 14:46:49 -07:00
Stefan Henneking 302886dda3 Enable device support for sesquilinear form and complex grid function. 2020-06-25 13:34:04 -07:00
Stefan Henneking c34f87aab7 Modifying complex operator mult for device support. 2020-06-25 13:11:58 -07:00
psocratis d79302db6b Added ComputeCurlError method for GridFunction (serial) 2020-06-24 19:41:47 -07:00
psocratis 4568e35898 Added ComputeDivError method in GridFunction (for serial) 2020-06-24 18:09:52 -07:00
Ketan Mittal 83f74fefca resolve conflict 2020-06-24 17:36:29 -07:00
Ketan Mittal 752d698ffb cleaning up 2020-06-24 17:31:00 -07:00
Tomov dd9643cabd WIP mixed meshes. 2020-06-24 15:03:51 -07:00
Stowell, Mark L 9d21df44c9 Adding option to shutoff the periodicity 2020-06-24 13:32:09 -07:00
Tomov cfdd39a066 Merge branch 'master' into tmop-el-type 2020-06-24 10:40:02 -07:00
Stowell, Mark L a0e9c74b9d Generalizing 2D .geo script for different orders and element types 2020-06-24 09:36:19 -07:00
Stowell, Mark L 634ae97901 Adding "order" parameter to .geo files 2020-06-24 09:04:31 -07:00
Stowell, Mark L 484dadbe4f Removing finalize calls 2020-06-24 09:04:05 -07:00
Stowell, Mark L 411ee11ffd Adding finalize topology 2020-06-23 22:54:46 -07:00
Stowell, Mark L 37d153a393 Adding 20 node tetrahedron support 2020-06-23 22:54:09 -07:00
Stowell, Mark L 13f1441e6c Adding 64 nodes hexahedron support 2020-06-23 22:19:39 -07:00
Stowell, Mark L 331b940373 Adding support for 27 node hexahedral elements 2020-06-23 20:55:57 -07:00
Stowell, Mark L 67c70dc827 Adding support for 10 node tetrahedra 2020-06-23 18:58:21 -07:00
Stowell, Mark L 93a7b6ae86 High order Gmsh support in 1D and 2D 2020-06-23 16:50:17 -07:00
psocratis 006d78c2c0 minor fix 2020-06-22 15:30:41 -07:00
psocratis e5bb4991a7 Initial commit for con_rates class 2020-06-22 15:13:36 -07:00
Tzanio a89750a63a Merge branch 'tests-convergence-dev' into convergence-dev
Conflicts:
	tests/convergence/makefile
2020-06-18 19:19:43 -07:00
Tzanio 4b925ab9b0 Adding convergence test from #1218 renamed to tests/convergence/(p)complex.cpp 2020-06-18 19:10:37 -07:00
Tzanio fdd67e17fe Adding convergence test from #1254 2020-06-18 19:05:15 -07:00
Tzanio 96ab53d665 Adding convergence test from https://github.com/mfem/mfem/pull/1460, renamed
from tests/convergence/bae.cpp to tests/convergence/projection.cpp
2020-06-18 18:55:58 -07:00
Ketan Mittal 2ff4dc87ed minor 2020-06-18 13:03:49 -07:00
Ketan Mittal 2c2947ebc1 merge with master and resolve conflict 2020-06-17 09:13:28 -07:00
Ketan Mittal b7661f38c2 field-interp working for hdiv and hcurl 2020-06-17 09:02:27 -07:00
Ketan Mittal 5e712c0329 debugging 2020-06-16 17:09:10 -07:00
Tomov a7cc1e74c3 wip on tmop with mixed meshes. 2020-06-16 16:41:59 -07:00
Ketan Mittal 477edc285e debugging grid to grid transfer for H(div) 2020-06-15 10:48:55 -07:00
Ketan Mittal f437641970 Merge branch 'field-interp' of https://github.com/mfem/mfem into findpts-crystalrouter 2020-06-05 14:37:30 -07:00
Ketan Mittal 12990ce20f Merge branch 'master' of https://github.com/mfem/mfem into findpts-crystalrouter 2020-06-05 14:36:59 -07:00
Ketan Mittal 6b871aecd9 minor changes to output at the end 2020-06-05 14:34:39 -07:00
Ketan Mittal 5f9dd70856 adding tests for more gridfunctions to pfindpts 2020-05-27 15:46:48 -07:00
Ketan Mittal 6cc67adfbb minor 2020-05-27 15:34:34 -07:00
Tzanio Kolev 0f54e013aa Merge branch 'master' into h1-hessian-dev 2020-05-19 09:31:42 -07:00
Ketan Mittal 85d6d808ea Merge branch 'master' of https://github.com/mfem/mfem into findpts-crystalrouter 2020-05-15 14:16:51 -07:00
Ketan Mittal 330fd509a6 support for non H1 gridfunctions 2020-05-15 11:13:23 -07:00
Andreas Schafelner 9b47fcf5cf Fixed a typo in the documentation of CalcHessian. 2020-05-11 10:31:14 +02:00
Andreas Schafelner 247fa3fa11 Added CalcHessian for H1-conforming tensor f.e.
Also added Poly_1D::Basis::Eval that computes the second derivative.
2020-05-11 10:30:31 +02:00
Ketan Mittal d7d58fa285 Merge branch 'findpts-serialpatch' of https://github.com/mfem/mfem into findpts-crystalrouter 2020-05-04 13:48:40 -07:00
camierjs 7acd97bf7f Merge branch 'master' into okina-mmu-mflags 2020-04-21 14:00:13 -07:00
camierjs 859bc2c483 Merge branch 'master' into okina-mmu-mflags 2020-04-16 15:43:36 -07:00
camierjs 475a876f56 Merge branch 'master' into okina-mmu-mflags 2020-03-30 10:05:15 -07:00
camierjs 05fb690baa Merge branch 'master' into okina-mmu-mflags 2020-03-20 14:37:47 -07:00
camierjs 41384afba5 Merge branch 'master' into okina-mmu-mflags 2020-03-18 17:23:49 -07:00
camierjs b37fcb9525 Merge branch 'master' into okina-mmu-mflags 2020-03-15 14:42:51 -07:00
Vladimir Tomov b737960971 Minor. 2020-03-06 16:10:22 -08:00
camierjs ffd086e263 Add initial memory flags h_rw and d_rw 2020-02-26 18:08:38 -08:00
Vladimir Tomov e39b468240 Solution transfer between grids. 2020-02-12 14:54:30 -08:00
Veselin Dobrev ac6275e096 A small fix in config/sample-runs.sh 2018-09-27 16:32:05 -07:00
Veselin Dobrev 7967070bde A small tweak in config/sample-runs.sh 2018-09-27 13:17:52 -07:00
Veselin Dobrev 1a560b9627 In the tests/ directory, add a test for the parallel mesh format.
Fixed an issue when loading VisItDataCollection with Load.
2018-09-18 14:31:17 -07:00
Veselin Dobrev 41c38fa6e5 Update config/sample-runs.sh:
Remove the "convergence" group from the "groups_serial" variable
because there are no serial tests in it.
2018-09-13 22:19:46 -07:00
Veselin Dobrev d2dae423e1 Create directory tests with one test: convergence/diffusion.cpp
Also, added the new test to the config/sample-runs.sh script.
2018-09-13 21:02:36 -07:00
254 changed files with 33827 additions and 25101 deletions
+8 -9
View File
@@ -175,6 +175,7 @@ miniapps/meshing/mesh-optimizer
miniapps/meshing/pmesh-optimizer
miniapps/meshing/minimal-surface
miniapps/meshing/pminimal-surface
miniapps/meshing/polar-nc
miniapps/meshing/mobius-strip.mesh
miniapps/meshing/klein-bottle.mesh
@@ -187,6 +188,7 @@ miniapps/meshing/extruder.mesh
miniapps/meshing/trimmer.mesh
miniapps/meshing/optimized*
miniapps/meshing/perturbed*
miniapps/meshing/polar-nc.mesh
miniapps/performance/ex1
miniapps/performance/ex1p
@@ -233,6 +235,7 @@ miniapps/nurbs/mode_*
miniapps/nurbs/Example1*
miniapps/gslib/field-diff
miniapps/gslib/field-interp
miniapps/gslib/findpts
miniapps/gslib/pfindpts
@@ -253,20 +256,16 @@ tests/unit/unit_tests
tests/unit/punit_tests
tests/unit/sedov_tests_*
tests/unit/psedov_tests_*
tests/unit/tmop_tests_*
tests/unit/ptmop_tests_*
tests/unit/cube.mesh
tests/unit/star.mesh
tests/unit/blade.mesh
tests/unit/square01.mesh
tests/unit/toroid-hex.mesh
tests/unit/beam-hex-nurbs.mesh
tests/unit/square-disc-nurbs.mesh
# Test script output
tests/scripts/*.err
tests/scripts/*.out
tests/scripts/*.msg
# Other tests
tests/convergence/rates
tests/convergence/prates
tests/par-mesh-format/ex1p
# VPATH builds
build-*/*
+17 -1
View File
@@ -71,6 +71,8 @@ stages:
- build
- test
- deallocate
- lassen_build
- lassen_test
- baseline_check
- baseline_publish
@@ -79,7 +81,11 @@ stages:
# TODO: updating tests and tpls is not necessary anymore since pipelines are
# now using unique directories so repo are never shared with another pipeline.
# This is not memory efficient (we keep a lot of data), hence this reminder.
.setup:
# Setup
setup:
tags:
- shell
- quartz
stage: setup
variables:
GIT_STRATEGY: none
@@ -100,6 +106,15 @@ stages:
before_script:
- module load gcc/6.1.0
# On lassen
.with_gcc_8_3_1:
variables:
TOOLCHAIN: gcc_8_3_1
CXX: g++
CC: gcc
before_script:
- module load gcc/8.3.1
.with_gcc_4_9_3:
variables:
TOOLCHAIN: gcc_4_9_3
@@ -290,3 +305,4 @@ stages:
# The list on jobs is defined in machine-specific files.
include:
- local: .gitlab/quartz.yml
- local: .gitlab/lassen.yml
+57
View File
@@ -0,0 +1,57 @@
# Copyright (c) 2010-2020, 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
.on_lassen:
tags:
- shell
- lassen
variables:
PLAT: lassen
# Build MFEM
build_mfem_ser_lassen:
extends: [.with_gcc_8_3_1, .on_lassen]
needs: [setup]
stage: lassen_build
script:
- mkdir -p ${BUILD_PATH}
- cp -r ${CI_PROJECT_DIR} ${BUILD_PATH}/${CI_PROJECT_NAME}_lassen_ser
- cd ${BUILD_PATH}/${CI_PROJECT_NAME}_lassen_ser
- lalloc 1 -W 5 -q pdebug make -j cuda CUDA_ARCH=sm_70
build_mfem_debug_ser_lassen:
extends: [.with_gcc_8_3_1, .on_lassen]
needs: [setup]
stage: lassen_build
script:
- mkdir -p ${BUILD_PATH}
- cp -r ${CI_PROJECT_DIR} ${BUILD_PATH}/${CI_PROJECT_NAME}_lassen_ser_debug
- cd ${BUILD_PATH}/${CI_PROJECT_NAME}_lassen_ser_debug
- lalloc 1 -W 5 -q pdebug make -j cuda MFEM_DEBUG="YES" CUDA_ARCH=sm_70
# Sanity check
sanitycheck_mfem_ser_lassen:
extends: [.with_gcc_8_3_1, .on_lassen]
stage: lassen_test
needs: [build_mfem_ser_lassen]
script:
- cd ${BUILD_PATH}/${CI_PROJECT_NAME}_lassen_ser
- lalloc 1 -W 15 -q pdebug make -j test
sanitycheck_mfem_debug_ser_lassen:
extends: [.with_gcc_8_3_1, .on_lassen]
stage: lassen_test
needs: [build_mfem_debug_ser_lassen]
script:
- cd ${BUILD_PATH}/${CI_PROJECT_NAME}_lassen_ser_debug
- lalloc 1 -W 30 -q pdebug make -j test
-4
View File
@@ -22,10 +22,6 @@
MAKE_PAR: 6
BASELINE_PAR: 18
# Setup
setup_quartz:
extends: [.setup, .on_quartz]
# Allocate
allocate_quartz:
variables:
+57 -13
View File
@@ -16,7 +16,12 @@ Meshing improvements
- The graph linear ordering library Gecko, previously an external dependency, is
now included directly in MFEM. As a result, Mesh::GetGeckoElementOrdering is
always available. The interface has also been improved, see for example the
mesh-explorer miniapp.
Mesh Explorer miniapp.
- Improved Gmsh reader (version 2.2), which now supports both high-order and
periodic meshes. Segments, triangles, quadrilaterals, and tetrahedra are
supported up to order 10. Wedges and hexahedra are supported up to order 9.
For sample periodic meshes, see the periodic*.msh files in the data directory.
- Added support for finite difference-based gradient and Hessian approximation
in the TMOP mesh optimization algorithms. This improves the accuracy of the
@@ -27,15 +32,17 @@ Meshing improvements
the user to specify different discrete functions for controlling the
size, aspect-ratio, orientation, and skew of elements in the mesh.
- Added TMOP capability for approximate tangential mesh relaxation.
- Added support for reading periodic meshes in Gmsh format (version 2.2). See
for example the periodic-annulus-sector and periodic-torus-sector files in
the data directory.
- Added TMOP capability for approximate tangential mesh relaxation. Added
support and examples for using TMOP on mixed meshes.
- Added complete action of the TMOP Integrator to account for the spatial
derivatives of discrete and analytic targets.
- Added support for initialization of (serial) non-conforming meshes. Hanging
nodes can be marked with Mesh::AddVertexParents when building the mesh with
the "init" constructor. The usage is demonstrated in a new meshing miniapp
(polar-nc) which generates meshes that are non-conforming from the start.
Performance improvements
------------------------
- Added support for explicit vectorization in the high-performance templated
@@ -50,11 +57,6 @@ Performance improvements
Improved GPU capabilities
-------------------------
- Added support for Chebyshev accelerated polynomial smoother on GPU.
- The TMOP mesh optimization algorithms were extended to GPU:
- QualityMetric #1, #2 and #7 are available in 2D, #302, #303 and #321 in 3D
- Both AnalyticAdaptTC and DiscreteAdaptTC TargetConstructor are available
- Kernels for normalization and limiting have been added
- The AdvectorCG now also support AssemblyLevel::PARTIAL
- Optimized AMD/HIP kernel support.
@@ -63,8 +65,14 @@ Improved GPU capabilities
compute a global sparse matrix. All integrators supported by element assembly
are also supported by full assembly. See the '-fa' option in Example 9.
- Added CUDA support for sparse matrix-vector multiplication with cuSPARSE.
- Added support for BlockOperator on GPU. See the updated Example 5.
- Added partial assembly and GPU support for complex operators, including the
classes ComplexOperator, [Par]ComplexGridFunction, [Par]ComplexLinearForm, and
[Par]SesquilinearForm. See the updated Example 22.
Discretization improvements
---------------------------
- Added support for matrix-free interpolation and restriction operators between
@@ -93,6 +101,14 @@ Discretization improvements
- Added support face integrals on the boundaries of NURBS meshes.
- Added support for interpolation of functions in L2, H(div) and H(curl)
spaces using GSLIB-FindPoints.
- Added support for computing asymptotic error estimates and convergence rates
for the whole de Rham sequence based on the new class ConvergenceStudy and new
member methods in GridFunction and ParGridFunction. See the rates.cpp file in
the tests/convergence directory for sample usage.
Linear and nonlinear solvers
----------------------------
- Added power method to iteratively estimate the largest eigenvalue and the
@@ -118,6 +134,12 @@ Linear and nonlinear solvers
- Added support for the SLEPc eigensolver package.
- Added partially assembled convergent diagonal preconditioner for adaptively
refined meshes (i.e. non-conforming finite element spaces), see Example 6/6p.
- Added an interface to the Intel MKL Parallel Direct Sparse Solver for
Clusters. An example usage of the interface is shown in Example 11p.
New and updated examples and miniapps
-------------------------------------
- Added a new example, Example 25/25p, to demonstrate the use of a Perfectly
@@ -154,6 +176,9 @@ New and updated examples and miniapps
- Added a new meshing miniapp, Minimal Surface, which solves Plateau's problem:
the Dirichlet problem for the minimal surface equation.
- Added a new meshing miniapp, Polar NC, which demonstrates the construction of
polar non-conforming meshes.
- Added partial assembly support to Example 4/4p and Example 5/5p, with diagonal
preconditioning.
@@ -168,28 +193,47 @@ New and updated examples and miniapps
mesh based on element attributes. Any newly exposed boundary elements are
assigned attribute numbers related to the trimmed element attributes.
- Added a new miniapp (field-interp) that demonstrates transfer of grid function
between different meshes using GSLIB-FindPoints.
- Added diagonal preconditioner in Example 6/6p for partial assembly with AMR.
- Added device support in Example 5/5p.
- Added partial assembly and device support to Example 22/22p, with diagonal
preconditioning.
- Added the option to plot a function in Mesh Explorer.
Improved testing
----------------
- Upgraded the Catch unit test framework from version 1.6.1 to version 2.13.0.
- Added a GitLab pipeline that automates PR testing on supercomputing systems
and Linux clusters at Lawrence Livermore National Lab (LLNL). This can be
triggered only by LLNL developers, see .gitlab-ci.yml, the .gitlab directory
and the updated CONTRIBUTING.md file.
- Added testing of the parallel mesh format in tests/par-mesh-format.
Miscellaneous
-------------
- Added support for ADIOS2 for parallel I/O with ParaView visualization. The
classes adios2stream and ADIOS2DataCollection are introduced in mfem as the
interfaces to generate ADIOS2 Binary Pack (BP4) directory datasets for the
entire spatial and temporal data. In addition, ADIOS2 allows for setting a
user-defined number of data substreams/subfiles. See examples 5, 9, 12, 16.
entire spatial and temporal node data. Cell centered data is accessible by
ADIOS2 data readers (e.g. Python), but currently not yet implement as of
ParaView v5.8.1. In addition, ADIOS2 allows for setting a user-defined number
of data substreams/subfiles at scale. See examples 5, 9, 12, 16.
- The integration order used in the ComputeLpError and ComputeElementLpError
methods of class GridFunction has been increased.
- Various other simplifications, extensions, and bugfixes in the code.
- Renamed "Backend::DEBUG" to "Backend::DEBUG_DEVICE" to avoid conflicts,
as DEBUG is sometimes used as a macro.
Version 4.1, released on March 10, 2020
=======================================
+38 -17
View File
@@ -89,8 +89,38 @@ enable_language(CXX)
if (MFEM_USE_CUDA)
# MFEM_USE_CUDA requires CMake 3.8 or newer (for direct CUDA support)
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
# Use ${CMAKE_CXX_COMPILER} as the cuda host compiler.
if (NOT CMAKE_CUDA_HOST_COMPILER)
set(CMAKE_CUDA_HOST_COMPILER ${CMAKE_CXX_COMPILER})
endif()
enable_language(CUDA)
set(CMAKE_CUDA_STANDARD 11)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_EXTENSIONS OFF)
set(CUDA_FLAGS "--expt-extended-lambda")
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}")
if (CMAKE_VERSION VERSION_LESS 3.12.0)
# CMake versions 3.8 and 3.9 require this to work; 3.10 and 3.11 are not
# tested and may not actually need this (but should be ok to keep).
set(CUDA_FLAGS "-ccbin=${CMAKE_CXX_COMPILER} ${CUDA_FLAGS}")
set(CMAKE_CUDA_HOST_LINK_LAUNCHER ${CMAKE_CXX_COMPILER})
endif()
set(CMAKE_CUDA_FLAGS "${CUDA_FLAGS}" CACHE STRING
"CUDA flags set for MFEM" FORCE)
set(CUSPARSE_FOUND TRUE)
set(CUSPARSE_LIBRARIES "cusparse")
endif()
if (XSDK_ENABLE_C)
@@ -296,22 +326,6 @@ if (MFEM_USE_HIOP)
# find_package updates HIOP_FOUND, HIOP_INCLUDE_DIRS, HIOP_LIBRARIES
endif()
# CUDA
if (MFEM_USE_CUDA)
set(CMAKE_CUDA_STANDARD 11)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_EXTENSIONS OFF)
set(CMAKE_CUDA_FLAGS "-arch=${CUDA_ARCH} --expt-extended-lambda"
CACHE STRING "CUDA flags set for MFEM" FORCE)
if (MFEM_USE_MPI)
set(CUDA_CCBIN_COMPILER ${MPI_CXX_COMPILER})
else()
set(CUDA_CCBIN_COMPILER ${CMAKE_CXX_COMPILER})
endif()
string(APPEND CMAKE_CUDA_FLAGS " -ccbin ${CUDA_CCBIN_COMPILER}")
set(CMAKE_CUDA_HOST_LINK_LAUNCHER ${CUDA_CCBIN_COMPILER})
endif()
# OCCA
if (MFEM_USE_OCCA)
find_package(OCCA REQUIRED)
@@ -332,6 +346,12 @@ if (MFEM_USE_ADIOS2)
find_package(ADIOS2 REQUIRED)
endif()
if (MFEM_USE_MKL_CPARDISO)
if (MFEM_USE_MPI)
find_package(MKL_CPARDISO REQUIRED MKL_SEQUENTIAL MKL_LP64 MKL_MPI_WRAPPER)
endif()
endif()
# MFEM_TIMER_TYPE
if (NOT DEFINED MFEM_TIMER_TYPE)
if (APPLE)
@@ -357,7 +377,8 @@ endif()
# be before SuiteSparse.
set(MFEM_TPLS MPI_CXX OPENMP BLAS LAPACK METIS HYPRE SuiteSparse SUNDIALS PETSC
SLEPC MESQUITE SuperLUDist STRUMPACK AXOM CONDUIT Ginkgo GNUTLS GSLIB NETCDF
MPFR PUMI HIOP POSIXCLOCKS MFEMBacktrace ZLIB OCCA CEED RAJA UMPIRE ADIOS2)
MPFR PUMI HIOP POSIXCLOCKS MFEMBacktrace ZLIB OCCA CEED RAJA UMPIRE ADIOS2
CUSPARSE MKL_CPARDISO)
# Add all *_FOUND libraries in the variable TPL_LIBRARIES.
set(TPL_LIBRARIES "")
set(TPL_INCLUDE_DIRS "")
+8 -1
View File
@@ -486,6 +486,13 @@ MFEM_USE_CEED = YES/NO
library for performant high-order operator evaluation developed by the Center
for Efficient Exascale Discretizations in the Exascale Computing Project.
MFEM_USE_MKL_CPARDISO = YES/NO
Enables the interface to the Intel MKL Parallel Direct Sparse Solver for
Clusters. Make sure to set the correct values for MKL_MPI_WRAPPER and
MKL_LIBRARY_SUBDIR as shown in defaults.mk. If you configure MFEM with
MFEM_USE_LAPACK=YES, verify that the MKL LAPACK libraries are used. The
OpenMP capabilities are disabled at link time.
MFEM_BUILD_TAG = (any value)
An optional tag to characterize the build. Exported to config/config.mk.
Can be used to identify the MFEM build from other makefiles.
@@ -663,7 +670,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.6, git-hash a970f63.
Versions: libCEED > 0.6, git-hash bdfed75.
- RAJA (optional), used when MFEM_USE_RAJA = YES.
Beginning with MFEM v4.1, only RAJA v0.10.0+ is supported.
+3
View File
@@ -156,4 +156,7 @@
// library.
#cmakedefine MFEM_USE_SIMMETRIX
// Enable interface to the MKL CPardiso library.
#cmakedefine MFEM_USE_MKL_CPARDISO
#endif // MFEM_CONFIG_HEADER
+13 -1
View File
@@ -38,7 +38,19 @@ if(NOT ADIOS2_FOUND)
endif()
find_path(ADIOS2_INCLUDE_DIR adios2.h ${ADIOS2_INCLUDE_OPTS})
find_library(ADIOS2_LIBRARY NAMES adios2 ${ADIOS2_LIBRARY_OPTS})
# adios2 version 2.5.0
find_library(ADIOS2_LIBRARY NAMES adios2 ${ADIOS2_LIBRARY_OPTS})
# adios2 version 2.6.0 and onwards
if(NOT ADIOS2_LIBRARY)
find_library(ADIOS2_CXX11_MPI_LIBRARY NAMES adios2_cxx11_mpi ${ADIOS2_LIBRARY_OPTS})
find_library(ADIOS2_CXX11_LIBRARY NAMES adios2_cxx11 ${ADIOS2_LIBRARY_OPTS})
set(ADIOS2_LIBRARY ${ADIOS2_CXX11_MPI_LIBRARY} ${ADIOS2_CXX11_LIBRARY})
if(MFEM_USE_MPI)
add_definitions(-DADIOS2_USE_MPI)
endif()
endif()
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(ADIOS2
+106
View File
@@ -0,0 +1,106 @@
# Copyright (c) 2010-2020, 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.
# Defines the following variables:
# - MKL_CPARDISO_FOUND
# - MKL_CPARDISO_LIBRARIES
# - MKL_CPARDISO_INCLUDE_DIRS
if(NOT MKL_MPI_WRAPPER_LIB)
message(FATAL_ERROR "MKL CPardiso enabled but no MKL MPI Wrapper lib specified")
endif()
if(NOT MKL_LIBRARY_DIR)
message(WARNING "Using default MKL library path. Double check the variable MKL_LIBRARY_DIR")
set(MKL_LIBRARY_DIR "lib")
endif()
include(MfemCmakeUtilities)
mfem_find_package(MKL_CPARDISO MKL_CPARDISO
MKL_CPARDISO_DIR "include" mkl_cluster_sparse_solver.h ${MKL_LIBRARY_DIR} mkl_core
"Paths to headers required by MKL CPardiso." "Libraries required by MKL CPARDISO."
ADD_COMPONENT MKL_LP64 "include" "" ${MKL_LIBRARY_DIR} mkl_intel_lp64
ADD_COMPONENT MKL_SEQUENTIAL "include" "" ${MKL_LIBRARY_DIR} mkl_sequential
ADD_COMPONENT MKL_MPI_WRAPPER "include" "" ${MKL_LIBRARY_DIR} ${MKL_MPI_WRAPPER_LIB}
CHECK_BUILD MKL_CPARDISO_VERSION_OK TRUE
"
#include <mpi.h>
#include <mkl.h>
#include <mkl_cluster_sparse_solver.h>
int main (void)
{
MKL_INT n = 5;
MKL_INT ia[6] = { 1, 4, 6, 9, 12, 14};
MKL_INT ja[13] = { 1, 2, 4, /* index of non-zeros in 1 row*/
1, 2, /* index of non-zeros in 2 row*/
3, 4, 5, /* index of non-zeros in 3 row*/
1, 3, 4, /* index of non-zeros in 4 row*/
2, 5 /* index of non-zeros in 5 row*/
};
double a[13] = {
1.0, -1.0, /*0*/ -3.0, /*0*/
-2.0, 5.0, /*0*/ /*0*/ /*0*/
/*0*/ 4.0, 6.0, 4.0, /*0*/
-4.0, /*0*/ 2.0, 7.0, /*0*/
/*0*/ 8.0, /*0*/ /*0*/ -5.0
};
MKL_INT mtype = 11; /* set matrix type to \"real unsymmetric matrix\" */
MKL_INT nrhs = 1; /* Number of right hand sides. */
double b[5], x[5], bs[5], res, res0; /* RHS and solution vectors. */
/* Internal solver memory pointer pt
* 32-bit: int pt[64] or void *pt[64];
* 64-bit: long int pt[64] or void *pt[64]; */
void *pt[64] = { 0 };
/* Cluster Sparse Solver control parameters. */
MKL_INT iparm[64] = { 0 };
MKL_INT maxfct, mnum, phase, msglvl, error;
/* Auxiliary variables. */
double ddum; /* Double dummy */
MKL_INT idum; /* Integer dummy. */
MKL_INT i, j;
int mpi_stat = 0;
int argc = 0;
int comm, rank;
char* uplo;
char** argv;
mpi_stat = MPI_Init( &argc, &argv );
mpi_stat = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
comm = MPI_Comm_c2f( MPI_COMM_WORLD );
iparm[ 0] = 1; /* Solver default parameters overriden with provided by iparm */
iparm[ 1] = 2; /* Use METIS for fill-in reordering */
iparm[ 5] = 0; /* Write solution into x */
iparm[ 7] = 2; /* Max number of iterative refinement steps */
iparm[ 9] = 13; /* Perturb the pivot elements with 1E-13 */
iparm[10] = 1; /* Use nonsymmetric permutation and scaling MPS */
iparm[12] = 1; /* Switch on Maximum Weighted Matching algorithm (default for non-symmetric) */
iparm[17] = -1; /* Output: Number of nonzeros in the factor LU */
iparm[18] = -1; /* Output: Mflops for LU factorization */
iparm[26] = 1; /* Check input data for correctness */
iparm[39] = 0; /* Input: matrix/rhs/solution stored on master */
maxfct = 1; /* Maximum number of numerical factorizations. */
mnum = 1; /* Which factorization to use. */
msglvl = 1; /* Print statistical information in file */
error = 0; /* Initialize error flag */
phase = 11;
cluster_sparse_solver ( pt, &maxfct, &mnum, &mtype, &phase,
&n, a, ia, ja, &idum, &nrhs, iparm, &msglvl, &ddum, &ddum, &comm, &error );
mpi_stat = MPI_Finalize();
return error;
}
")
@@ -128,7 +128,15 @@ function(add_mfem_miniapp MFEM_EXE_NAME)
if (MFEM_USE_CUDA)
set_property(SOURCE ${MAIN_LIST} ${EXTRA_SOURCES_LIST}
PROPERTY LANGUAGE CUDA)
list(TRANSFORM EXTRA_OPTIONS_LIST PREPEND "-Xcompiler=")
if (CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
list(TRANSFORM EXTRA_OPTIONS_LIST PREPEND "-Xcompiler=")
else()
set(LIST_)
foreach(item IN LISTS EXTRA_OPTIONS_LIST)
list(APPEND LIST_ "-Xcompiler=${item}")
endforeach()
set(EXTRA_OPTIONS_LIST ${LIST_})
endif()
endif()
# Actually add the executable
+6
View File
@@ -42,9 +42,15 @@
#ifdef MFEM_USE_SUPERLU
#error Building with SuperLU_DIST (MFEM_USE_SUPERLU=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#ifdef MFEM_USE_MUMPS
#error Building with MUMPS (MFEM_USE_MUMPS=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#ifdef MFEM_USE_STRUMPACK
#error Building with STRUMPACK (MFEM_USE_STRUMPACK=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#ifdef MFEM_USE_MKL_CPARDISO
#error Building with MKL CPARDISO (MFEM_USE_MKL_CPARDISO=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#ifdef MFEM_USE_PETSC
#error Building with PETSc (MFEM_USE_PETSC=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
+7
View File
@@ -94,6 +94,10 @@
// Enable MFEM functionality based on the SuperLU library.
// #define MFEM_USE_SUPERLU
// Enable MFEM functionality based on the MUMPS library.
// #define MFEM_USE_MUMPS
// #define MFEM_MUMPS_VERSION @MFEM_MUMPS_VERSION@
// Enable MFEM functionality based on the STRUMPACK library.
// #define MFEM_USE_STRUMPACK
@@ -163,4 +167,7 @@
// library.
// #define MFEM_USE_SIMMETRIX
// Enable interface to the MKL CPardiso library.
// #define MFEM_USE_MKL_CPARDISO
#endif // MFEM_CONFIG_HEADER
+2
View File
@@ -32,6 +32,7 @@ MFEM_USE_SUNDIALS = @MFEM_USE_SUNDIALS@
MFEM_USE_MESQUITE = @MFEM_USE_MESQUITE@
MFEM_USE_SUITESPARSE = @MFEM_USE_SUITESPARSE@
MFEM_USE_SUPERLU = @MFEM_USE_SUPERLU@
MFEM_USE_MUMPS = @MFEM_USE_MUMPS@
MFEM_USE_STRUMPACK = @MFEM_USE_STRUMPACK@
MFEM_USE_GINKGO = @MFEM_USE_GINKGO@
MFEM_USE_GNUTLS = @MFEM_USE_GNUTLS@
@@ -52,6 +53,7 @@ MFEM_USE_CEED = @MFEM_USE_CEED@
MFEM_USE_UMPIRE = @MFEM_USE_UMPIRE@
MFEM_USE_SIMD = @MFEM_USE_SIMD@
MFEM_USE_ADIOS2 = @MFEM_USE_ADIOS2@
MFEM_USE_MKL_CPARDISO = @MFEM_USE_MKL_CPARDISO@
# Compiler, compile options, and link options
MFEM_CXX = @MFEM_CXX@
+5
View File
@@ -52,6 +52,7 @@ option(MFEM_USE_CEED "Enable CEED" OFF)
option(MFEM_USE_UMPIRE "Enable Umpire" OFF)
option(MFEM_USE_SIMD "Enable use of SIMD intrinsics" OFF)
option(MFEM_USE_ADIOS2 "Enable ADIOS2" OFF)
option(MFEM_USE_MKL_CPARDISO "Enable MKL CPardiso" OFF)
set(MFEM_MPI_NP 4 CACHE STRING "Number of processes used for MPI tests")
@@ -180,6 +181,10 @@ set(HIOP_DIR "${MFEM_DIR}/../hiop/install" CACHE STRING
set(HIOP_REQUIRED_PACKAGES "BLAS" "LAPACK" CACHE STRING
"Packages that HiOp depends on.")
set(MKL_CPARDISO_DIR "" CACHE STRING "MKL installation path.")
set(MKL_MPI_WRAPPER_LIB "mkl_blacs_mpich_lp64" CACHE STRING "MKL MPI wrapper library")
set(MKL_LIBRARY_DIR "" CACHE STRING "Custom library subdirectory")
set(OCCA_DIR "${MFEM_DIR}/../occa" CACHE PATH "Path to OCCA")
set(RAJA_DIR "${MFEM_DIR}/../raja" CACHE PATH "Path to RAJA")
set(CEED_DIR "${MFEM_DIR}/../libCEED" CACHE PATH "Path to libCEED")
+17 -7
View File
@@ -120,6 +120,7 @@ MFEM_USE_SUNDIALS = NO
MFEM_USE_MESQUITE = NO
MFEM_USE_SUITESPARSE = NO
MFEM_USE_SUPERLU = NO
MFEM_USE_MUMPS = NO
MFEM_USE_STRUMPACK = NO
MFEM_USE_GINKGO = NO
MFEM_USE_GNUTLS = NO
@@ -138,9 +139,9 @@ MFEM_USE_RAJA = NO
MFEM_USE_OCCA = NO
MFEM_USE_CEED = NO
MFEM_USE_UMPIRE = NO
MFEM_USE_CAMP = NO
MFEM_USE_SIMD = NO
MFEM_USE_ADIOS2 = NO
MFEM_USE_MKL_CPARDISO = NO
# Compile and link options for zlib.
ZLIB_DIR =
@@ -157,7 +158,7 @@ HYPRE_OPT = -I$(HYPRE_DIR)/include
HYPRE_LIB = -L$(HYPRE_DIR)/lib -lHYPRE
# METIS library configuration
ifeq ($(MFEM_USE_SUPERLU)$(MFEM_USE_STRUMPACK),NONO)
ifeq ($(MFEM_USE_SUPERLU)$(MFEM_USE_STRUMPACK)$(MFEM_USE_MUMPS),NONONO)
ifeq ($(MFEM_USE_METIS_5),NO)
METIS_DIR = @MFEM_DIR@/../metis-4.0
METIS_OPT =
@@ -233,7 +234,7 @@ SCALAPACK_DIR = @MFEM_DIR@/../scalapack-2.0.2
SCALAPACK_OPT = -I$(SCALAPACK_DIR)/SRC
SCALAPACK_LIB = -L$(SCALAPACK_DIR)/lib -lscalapack $(LAPACK_LIB)
# MPI Fortran library, needed e.g. by STRUMPACK
# MPI Fortran library, needed e.g. by STRUMPACK or MUMPS
# MPICH:
MPI_FORTRAN_LIB = -lmpifort
# OpenMPI:
@@ -241,6 +242,11 @@ MPI_FORTRAN_LIB = -lmpifort
# Additional Fortan library:
# MPI_FORTRAN_LIB += -lgfortran
# MUMPS library configuration
MUMPS_DIR =
MUMPS_OPT = -I$(MUMPS_DIR)/include
MUMPS_LIB = -Wl,-rpath,$(MUMPS_DIR)/lib -L$(MUMPS_DIR)/lib -ldmumps -lmumps_common -lpord $(SCALAPACK_LIB) $(LAPACK_LIB) $(MPI_FORTRAN_LIB)
# STRUMPACK library configuration
STRUMPACK_DIR = @MFEM_DIR@/../STRUMPACK-build
STRUMPACK_OPT = -I$(STRUMPACK_DIR)/include $(SCOTCH_OPT)
@@ -373,10 +379,14 @@ UMPIRE_DIR = @MFEM_DIR@/../umpire
UMPIRE_OPT = -I$(UMPIRE_DIR)/include
UMPIRE_LIB = -L$(UMPIRE_DIR)/lib -lumpire
# CAMP library configuration
CAMP_DIR = @MFEM_DIR@/../camp
CAMP_OPT = -I$(CAMP_DIR)/include
CAMP_LIB = -L$(CAMP_DIR)/lib
# MKL CPardiso library configuration
MKL_CPARDISO_DIR ?=
MKL_MPI_WRAPPER ?= mkl_blacs_mpich_lp64
MKL_LIBRARY_SUBDIR ?= lib
MKL_CPARDISO_OPT = -I$(MKL_CPARDISO_DIR)/include
MKL_CPARDISO_LIB = -Wl,-rpath,$(MKL_CPARDISO_DIR)/$(MKL_LIBRARY_SUBDIR)\
-L$(MKL_CPARDISO_DIR)/$(MKL_LIBRARY_SUBDIR) -l$(MKL_MPI_WRAPPER)\
-lmkl_intel_lp64 -lmkl_sequential -lmkl_core
# If YES, enable some informational messages
VERBOSE = NO
+33
View File
@@ -0,0 +1,33 @@
// Copyright (c) 2010-2020, 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 "dmumps_c.h"
#include <string>
#include <iostream>
#include <algorithm>
// Macros to expand a macro as a string
#define STR_EXPAND(s) #s
#define STR(s) STR_EXPAND(s)
int main()
{
#ifdef MUMPS_VERSION
const char *ptr = STR(MUMPS_VERSION);
std::string s(ptr);
s.erase(std::remove(s.begin(), s.end(), '"'), s.end());
s.erase(std::remove(s.begin(), s.end(), '.'), s.end());
std::cout << s << "\n";
return 0;
#else
return -1;
#endif
}
+19 -2
View File
@@ -42,6 +42,10 @@ GHV_FLAGS = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(HYPRE_OPT))
SMX = $(if $(MFEM_USE_PUMI:NO=),MFEM_USE_SIMMETRIX)
SMX_PATH = $(PUMI_DIR)/include/gmi_sim.h
SMX_FILE = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(SMX_PATH))
MUMPS = $(MFEM_USE_MUMPS:NO=)
GMV_CXX ?= $(MFEM_CXX)
GMV = get_mumps_version
GMV_FLAGS = $(subst @MFEM_DIR@,$(if $(MFEM_DIR),$(MFEM_DIR),..),$(MUMPS_OPT))
$(GHV): $(SRC)$(GHV).cpp
$(call mfem-info, Determining HYPRE version ...)
@@ -50,6 +54,13 @@ $(GHV).out: $(GHV)
./$(GHV) > $(GHV).out
.INTERMEDIATE: $(GHV) $(GHV).out
$(GMV): $(SRC)$(GMV).cpp
$(call mfem-info, Determining MUMPS version ...)
$(GMV_CXX) ${GMV_FLAGS} $(SRC)$(GMV).cpp -o $(GMV)
$(GMV).out: $(GMV)
./$(GMV) > $(GMV).out
.INTERMEDIATE: $(GMV) $(GMV).out
get-hypre-version: $(GHV).out
$(eval MFEM_HYPRE_VERSION:=$(shell cat $(GHV).out))
$(if $(MFEM_HYPRE_VERSION),$(eval export MFEM_HYPRE_VERSION)\
@@ -62,10 +73,16 @@ check-smx:
$(call mfem-info, MFEM_USE_SIMMETRIX = $(MFEM_USE_SIMMETRIX))
$(eval export MFEM_USE_SIMMETRIX)
header: $(if $(MPI),get-hypre-version,) $(if $(SMX),check-smx)
get-mumps-version: $(GMV).out
$(eval MFEM_MUMPS_VERSION:=$(shell cat $(GMV).out))
$(if $(MFEM_MUMPS_VERSION),$(eval export MFEM_MUMPS_VERSION)\
$(info MUMPS version: $(MFEM_MUMPS_VERSION)),\
$(error Unable to determine MUMPS version))
header: $(if $(MPI),get-hypre-version,) $(if $(SMX),check-smx,) $(if $(MUMPS),get-mumps-version,)
$(call mfem-info, Writing $(CONFIG_HPP) ...)
@set -- && \
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION) $(SMX); do \
for def in $${MFEM_DEFINES} $(if $(MPI),MFEM_HYPRE_VERSION) $(SMX) $(if $(MUMPS),MFEM_MUMPS_VERSION); do \
eval var=\$$$$def && \
if [ "NO" != "$${var}" ]; then \
set -- "$$@" -e "s|// \(#define $${def} \)|\1|" && \
+50 -7
View File
@@ -78,6 +78,14 @@ groups_parallel=(
"miniapps/electromagnetics"
"joule.cpp"'
# "{volta,tesla,joule}.cpp"' # todo: multiline sample runs
'"convergence"
"Convergence tests:"
"tests/convergence"
"diffusion.cpp"'
'"par-mesh-format"
"Parallel mesh tests:"
"tests/par-mesh-format"
"ex1p.cpp"'
)
# All groups serial + parallel runs mixed in the same group:
groups_all=(
@@ -107,6 +115,14 @@ groups_all=(
"miniapps/electromagnetics"
"joule.cpp"'
# "{volta,tesla,joule}.cpp"' # todo: multiline sample runs
'"convergence"
"Convergence tests:"
"tests/convergence"
"diffusion.cpp"'
'"par-mesh-format"
"Parallel mesh tests:"
"tests/par-mesh-format"
"ex1p.cpp"'
)
make_all="all"
base_timeformat=$'real: %3Rs user: %3Us sys: %3Ss %%cpu: %P'
@@ -380,10 +396,15 @@ function timed_run()
# This function is used to execute the sample runs
function go()
{
local cmd=("$@")
# Strip leading and trailing spaces from $1 and store the result in cmd_line
shopt -s extglob
local cmd_line="${1##+( )}"
cmd_line="${cmd_line%%+( )}"
shopt -u extglob
eval local cmd=(${cmd_line})
local res=""
echo $sep
echo "<${group}>" "${cmd[@]}"
echo "<${group}>" "${cmd_line}"
echo $sep
if [ "${timing}" == "yes" ]; then
timed_run "${cmd[@]}"
@@ -395,15 +416,15 @@ function go()
else
res="${red}FAILED${none}"
fi
printf "[${res}] <${group}> ${cmd[*]}\n"
printf "[${res}] <${group}> ${cmd_line}\n"
if [ "${timing}" == "yes" ]; then
printf "Run time: %s\n" "${timer}"
timer=(${timer})
timer="${timer[1]}"
printf -v line "[$res](%8s) ${cmd[*]}" "$timer"
printf -v line "[$res](%8s) ${cmd_line}" "$timer"
summary=("${summary[@]}" "$line")
else
summary=("${summary[@]}" "[${res}] ${cmd[*]}")
summary=("${summary[@]}" "[${res}] ${cmd_line}")
fi
echo $sep
}
@@ -438,7 +459,7 @@ function go_group()
fi
for run in "${runs[@]}"; do
if [ "${run}" == "" ]; then continue; fi
eval go \${run_prefix} \${run} \${run_suffix} $output
eval go \"\${run_prefix} \${run} \${run_suffix}\" $output
done
done
${make} clean-exec
@@ -504,7 +525,7 @@ function echo_run()
{
echo " $@"
{ echo " $@"; echo "$sep";
"$@"
eval "$@"
echo "$sep"; } >> "$echo_log" 2>&1
}
@@ -524,6 +545,28 @@ function build_all()
echo_run ${make} config ${mfem_config} || exit 1
echo_run ${make} ${make_j} || exit 1
echo_run ${make} ${make_all} ${make_j} || exit 1
# Build groups in directories other than the directories built by 'make all':
for group_params in "${groups[@]}"; do
eval params=(${group_params})
group_dir="${params[2]}"
case "$group_dir" in
(examples*|miniapps*)
# Built by 'make all'
;;
(*)
if [ "${mfem_dir}" != "${mfem_build_dir}" ]; then
echo_run mkdir -p "${group_dir}" || exit 1
echo_run cd "${group_dir}" || exit 1
echo_run cp -af "${mfem_dir}/${group_dir}/makefile" . || exit 1
else
echo_run cd "${group_dir}" || exit 1
fi
echo_run ${make} clean || exit 1
echo_run ${make} MFEM_DIR="${mfem_dir}" ${make_j} || exit 1
echo_run cd "${mfem_build_dir}" || exit 1
;;
esac
done
}
# Function that runs all sample runs, given by the array variable "groups".
+57 -8
View File
@@ -1,13 +1,38 @@
SetFactory("OpenCASCADE");
// Select periodic mesh by setting this to either 0 - standard, 1 - periodic
periodic = 1;
// Set the geometry order (1, 2, ..., 9)
order = 3;
// Set the element type (3 - triangles, 4 - quadrilaterals)
type = 3;
// Number of radial elements
nrad = 2;
// Number of azimuthal elements on inner arc
nazm1 = 3;
// Number of azimuthal elements on outer arc
nazm2 = 5;
// Note: Using type = 4 with nazm1 != nazm2 can lead to mixed meshes
// containing both triangles and quadrilaterals.
// Inner and outer radii
R1 = 1.0;
R2 = 2.0;
// Angular size of the sector
Phi = Pi/3.0;
Point(1) = {0.0, 0, 0, 1.0};
Point(2) = {R1, 0, 0, 1.0};
Point(3) = {R2, 0, 0, 1.0};
Point(4) = {R1*Cos(Pi/3), R1*Sin(Pi/3), 0, 1.0};
Point(5) = {R2*Cos(Pi/3), R2*Sin(Pi/3), 0, 1.0};
Point(4) = {R1*Cos(Phi), R1*Sin(Phi), 0, 1.0};
Point(5) = {R2*Cos(Phi), R2*Sin(Phi), 0, 1.0};
Line(1) = {2, 3};
Line(2) = {4, 5};
Circle(3) = {2, 1, 4};
@@ -15,13 +40,23 @@ Circle(4) = {3, 1, 5};
Curve Loop(5) = {1, 4, -2, -3};
Plane Surface(1) = {5};
Transfinite Curve{1} = 7;
Transfinite Curve{2} = 7;
Transfinite Curve{3} = 4;
Transfinite Curve{4} = 10;
Transfinite Curve{1} = nrad+1;
Transfinite Curve{2} = nrad+1;
Transfinite Curve{3} = nazm1+1;
Transfinite Curve{4} = nazm2+1;
If (nazm1 == nazm2)
Transfinite Surface{1};
EndIf
If (type == 4)
Recombine Surface {1};
EndIf
// Set a rotation periodicity constraint:
Periodic Line{1} = {2} Rotate{{0,0,1}, {0,0,0}, -Pi/3};
If (periodic)
Periodic Line{1} = {2} Rotate{{0,0,1}, {0,0,0}, -Phi};
EndIf
// Tag surfaces and volumes with positive integers
Physical Curve(1) = {3};
@@ -30,8 +65,22 @@ Physical Curve(3) = {1};
Physical Curve(4) = {2};
Physical Surface(1) = {1};
// Optimize the high-order mesh
// See https://gmsh.info/doc/texinfo/gmsh.html#index-Mesh_002eHighOrderOptimize
// Mesh.ElementOrder = order;
// Mesh.HighOrderOptimize = 1;
// Generate 2D mesh
Mesh 2;
SetOrder order;
Mesh.MshFileVersion = 2.2;
Save "periodic-annulus-sector.msh";
// Check the element quality (the Plugin may be called AnalyseCurvedMesh)
// Plugin(AnalyseMeshQuality).JacobianDeterminant = 1;
// Plugin(AnalyseMeshQuality).Run;
If (periodic)
Save Sprintf("periodic-annulus-sector-t%01g-o%01g.msh", type, order);
Else
Save Sprintf("annulus-sector-t%01g-o%01g.msh", type, order);
EndIf
+168 -161
View File
@@ -2,184 +2,191 @@ $MeshFormat
2.2 0 8
$EndMeshFormat
$Nodes
55
136
1 1 0 0
2 2 0 0
3 0.5000000000000001 0.8660254037844386 0
4 1 1.732050807568877 0
5 1.166666666666667 0 0
6 1.333333333333333 0 0
7 1.5 0 0
5 1.5 0 0
6 1.166666666666667 0 0
7 1.333333333333333 0 0
8 1.666666666666667 0 0
9 1.833333333333333 0 0
10 0.5833333333333335 1.010362971081845 0
11 0.6666666666666667 1.154700538379251 0
12 0.7500000000000002 1.299038105676658 0
10 0.7500000000000002 1.299038105676658 0
11 0.5833333333333335 1.010362971081845 0
12 0.6666666666666667 1.154700538379251 0
13 0.8333333333333335 1.443375672974064 0
14 0.9166666666666669 1.587713240271471 0
15 0.9396926207859085 0.3420201433256683 0
16 0.7660444431189786 0.6427876096865386 0
17 1.986476715483886 0.2321858282504602 0
18 1.946089741159648 0.4612317414848793 0
19 1.879385241571817 0.6840402866513365 0
20 1.787265280646825 0.8975983604009234 0
21 1.670975622825874 1.09901795614161 0
22 1.532088886237958 1.285575219373077 0
23 1.372483275737469 1.454747283146095 0
24 1.194317183405575 1.604246385510085 0
25 1.425989114816062 0.1915326920916892 0
26 0.8788667344146573 1.13917645290495 0
27 1.630372059110754 0.7154531062316609 0
28 1.436395769298814 1.053728612482506 0
29 1.081023776188756 0.6241293681829633 0
30 1.168737372335971 1.428012728596308 0
31 1.821063986059922 0.298149890497067 0
32 1.234707097211386 0.3469796339295647 0
33 1.377747393186519 0.6200150626754309 0
34 1.457047681210906 0.3890895843559762 0
35 0.917846726184522 0.8957978954532204 0
36 1.218335619030348 0.9017812086952638 0
37 1.066623110765233 1.061857005744772 0
38 1.587029716281926 0.1355955181472859 0
39 1.744445799211916 0.1441515753740107 0
40 1.25 0.1443375672974065 0
41 1.453660070628011 0.8435769396609902 0
42 1.741367044061892 0.499612708014486 0
43 1.30550638526547 1.257610469847477 0
44 1.118213276932792 0.1666674689105279 0
45 0.9109440214958271 1.306610291787315 0
46 0.9970618258753989 1.438658589955562 0
47 0.7499999999999998 1.010362971081845 0
48 0.7034449005273667 0.8850673702175776 0
49 1.605449512513618 0.9269067082200894 0
50 1.561654019115059 0.5298592532912715 0
51 1.229782222487711 1.096820457143683 0
52 1.617066998712459 0.3090202662210922 0
53 1.079645953234324 1.246963713711438 0
54 1.877063966817811 0.1348974588243076 0
55 1.055356609656722 1.558136350380461 0
17 0.993238357741943 0.1160929141252301 0
18 0.9730448705798238 0.2306158707424401 0
19 0.8936326403234125 0.4487991802004617 0
20 0.8354878114129367 0.5495089780708056 0
21 0.6862416378687343 0.7273736415730481 0
22 0.597158591702787 0.8021231927550432 0
23 1.956295201467611 0.4158233816355181 0
24 1.827090915285202 0.8134732861515996 0
25 1.618033988749896 1.175570504584944 0
26 1.338261212717719 1.486289650954786 0
27 1.995128100519648 0.1395129474882505 0
28 1.980536137483141 0.278346201920131 0
29 1.922523391876638 0.551274711633998 0
30 1.879385241571817 0.6840402866513373 0
31 1.765895185717855 0.9389431255717802 0
32 1.696096192312853 1.059838528466408 0
33 1.532088886237958 1.285575219373077 0
34 1.438679600677305 1.389316740917992 0
35 1.231322950651319 1.576021507213442 0
36 1.118385806941496 1.658075145110082 0
37 1.162276263405681 0.6710405135499813 0
38 1.248615852873337 1.079531485311822 0
39 1.559209616901855 0.5415673055003691 0
40 1.478306597054007 0.8535007117539289 0
41 0.9210953433941653 0.9653302893212266 0
42 1.296548225291847 0.3150268220262836 0
43 1.055002035226811 1.358510675893086 0
44 1.704005774249187 0.2344032256041583 0
45 0.6403651144647218 0.8991270322967013 0
46 0.7807302289294435 0.9322286608089638 0
47 0.864063562262777 1.07656622810637 0
48 0.8070317811313885 1.187802166891514 0
49 0.7236984477980553 1.043464599594108 0
50 1.432182741763949 0.1050089406754279 0
51 1.364365483527898 0.2100178813508558 0
52 1.197698816861231 0.2100178813508558 0
53 1.098849408430616 0.1050089406754279 0
54 1.265516075097282 0.1050089406754278 0
55 0.8177280765440409 0.7503018362314346 0
56 0.869411709969103 0.8578160627763305 0
57 0.7348318576552288 0.8316090412164392 0
58 1.177596357123201 0.3240245957927452 0
59 1.058644488954555 0.3330223695592067 0
60 1.087610484537871 0.2205785356313179 0
61 1.267619707955123 0.7318605796179638 0
62 1.372963152504565 0.7926806456859463 0
63 1.40174301566045 0.9288443029398934 0
64 1.325179434266893 1.004187894125858 0
65 1.219835989717452 0.9433678280578752 0
66 1.191056126561566 0.8072041708039283 0
67 1.296399571111008 0.8680242368719107 0
68 1.532241943619239 0.645545107584889 0
69 1.505274270336623 0.7495229096694089 0
70 1.294587381237739 0.6278827775334439 0
71 1.426898499069797 0.5847250415169065 0
72 1.399930825787181 0.6887028436014264 0
73 1.139442349713613 1.041464419981624 0
74 1.030268846553889 1.003397354651425 0
75 1.001488983398004 0.8672336973974781 0
76 1.081882623401843 0.7691371054737297 0
77 1.110662486557728 0.9053007627276766 0
78 1.207033584034403 0.5523692830420821 0
79 1.251790904663125 0.4336980525341829 0
80 1.384102022495183 0.3905403165176455 0
81 1.471655819698519 0.4660538110090073 0
82 1.339344701866461 0.5092115470255447 0
83 1.73779714915742 0.7228379592678562 0
84 1.648503383029637 0.6322026323841127 0
85 1.691571478423774 0.4996526642120855 0
86 1.823933339945692 0.4577380229238018 0
87 1.787039416783436 0.5922941012619014 0
88 1.308379426102925 1.350703595740465 0
89 1.278497639488131 1.215117540526144 0
90 1.371755231498856 1.111544491736196 0
91 1.494894610124376 1.14355749816057 0
92 1.4064614465962 1.25147448186763 0
93 1.013887168325833 0.451693600067106 0
94 1.088081715865757 0.5613670568085436 0
95 1.03019898997678 0.6616228789288338 0
96 0.8981217165478794 0.6522052443076862 0
97 0.9637989050473432 0.5564495572737495 0
98 1.432367408277627 0.2881522898855752 0
99 1.568186591263407 0.2612777577448668 0
100 1.655740388466743 0.3367912522362286 0
101 1.607475002684299 0.4391792788682989 0
102 1.519921205480963 0.3636657843769371 0
103 1.184077913657828 1.17252454883891 0
104 1.119539974442319 1.265517612365998 0
105 1.010366471282595 1.2274505470358 0
106 0.9657309073383804 1.096390418178513 0
107 1.074904410498104 1.134457483508712 0
108 1.901335258083062 0.07813440853471942 0
109 1.802670516166124 0.1562688170694388 0
110 1.636003849499458 0.156268817069439 0
111 1.568001924749729 0.07813440853471942 0
112 1.734668591416396 0.07813440853471944 0
113 0.8516673450756037 1.318862295748801 0
114 0.9533346901512071 1.338686485820944 0
115 1.03666802348454 1.48302405311835 0
116 1.01833401174227 1.607537430343614 0
117 0.9350006784089369 1.463199863046207 0
118 1.710829475874804 0.8268157613523761 0
119 1.594568036464405 0.8401582365531526 0
120 1.621535709747021 0.7361804344686326 0
121 1.52488239428597 0.9608573093642675 0
122 1.571458191517933 1.068213906974606 0
123 1.448318812892413 1.036200900550232 0
124 0.908699126206992 1.207626356963657 0
125 1.500184666513678 0.1831433492101474 0
126 1.646765991694905 0.9507607885973723 0
127 0.9498053499729417 0.7597194708525821 0
128 1.132839036494479 0.4426958263006443 0
129 1.149421761057113 1.40110366758032 0
130 1.243841486887416 1.443696659267553 0
131 1.134903597606542 1.530869109405537 0
132 1.872198725728137 0.3553499962917315 0
133 1.788102249988661 0.2948766109479449 0
134 1.893223337417325 0.2174207916708467 0
135 1.213959700272622 1.308110604053232 0
136 1.739836864206217 0.3972646375800152 0
$EndNodes
$Elements
108
1 1 2 3 1 1 5
2 1 2 3 1 5 6
3 1 2 3 1 6 7
4 1 2 3 1 7 8
5 1 2 3 1 8 9
6 1 2 3 1 9 2
7 1 2 4 2 3 10
8 1 2 4 2 10 11
9 1 2 4 2 11 12
10 1 2 4 2 12 13
11 1 2 4 2 13 14
12 1 2 4 2 14 4
13 1 2 1 3 1 15
14 1 2 1 3 15 16
15 1 2 1 3 16 3
16 1 2 2 4 2 17
17 1 2 2 4 17 18
18 1 2 2 4 18 19
19 1 2 2 4 19 20
20 1 2 2 4 20 21
21 1 2 2 4 21 22
22 1 2 2 4 22 23
23 1 2 2 4 23 24
24 1 2 2 4 24 4
25 2 2 1 1 32 40 25
26 2 2 1 1 25 34 32
27 2 2 1 1 33 41 36
28 2 2 1 1 38 52 25
29 2 2 1 1 33 36 29
30 2 2 1 1 26 47 35
31 2 2 1 1 35 37 26
32 2 2 1 1 25 52 34
33 2 2 1 1 32 44 40
34 2 2 1 1 15 32 29
35 2 2 1 1 15 29 16
36 2 2 1 1 36 41 28
37 2 2 1 1 32 33 29
38 2 2 1 1 50 52 42
39 2 2 1 1 32 34 33
40 2 2 1 1 42 52 31
41 2 2 1 1 43 53 51
42 2 2 1 1 27 41 33
43 2 2 1 1 26 53 45
44 2 2 1 1 18 31 17
45 2 2 1 1 29 35 16
46 2 2 1 1 29 36 35
47 2 2 1 1 24 30 23
48 2 2 1 1 30 53 43
49 2 2 1 1 17 54 2
50 2 2 1 1 4 55 24
51 2 2 1 1 28 51 36
52 2 2 1 1 47 48 35
53 2 2 1 1 36 37 35
54 2 2 1 1 37 53 26
55 2 2 1 1 22 28 21
56 2 2 1 1 20 27 19
57 2 2 1 1 33 50 27
58 2 2 1 1 15 44 32
59 2 2 1 1 18 42 31
60 2 2 1 1 30 43 23
61 2 2 1 1 35 48 16
62 2 2 1 1 31 54 17
63 2 2 1 1 9 39 8
64 2 2 1 1 8 38 7
65 2 2 1 1 7 25 6
66 2 2 1 1 22 43 28
67 2 2 1 1 23 43 22
68 2 2 1 1 39 54 31
69 2 2 1 1 19 42 18
70 2 2 1 1 24 55 30
71 2 2 1 1 27 42 19
72 2 2 1 1 13 46 14
73 2 2 1 1 51 53 37
74 2 2 1 1 39 52 38
75 2 2 1 1 6 40 5
76 2 2 1 1 34 52 50
77 2 2 1 1 12 45 13
78 2 2 1 1 30 55 46
79 2 2 1 1 10 47 11
80 2 2 1 1 8 39 38
81 2 2 1 1 28 49 21
82 2 2 1 1 7 38 25
83 2 2 1 1 41 49 28
84 2 2 1 1 20 49 27
85 2 2 1 1 11 26 12
86 2 2 1 1 27 49 41
87 2 2 1 1 31 52 39
88 2 2 1 1 25 40 6
89 2 2 1 1 2 54 9
90 2 2 1 1 14 55 4
91 2 2 1 1 45 53 46
92 2 2 1 1 45 46 13
93 2 2 1 1 5 44 1
94 2 2 1 1 21 49 20
95 2 2 1 1 46 53 30
96 2 2 1 1 3 48 10
97 2 2 1 1 34 50 33
98 2 2 1 1 36 51 37
99 2 2 1 1 26 45 12
100 2 2 1 1 11 47 26
101 2 2 1 1 27 50 42
102 2 2 1 1 40 44 5
103 2 2 1 1 43 51 28
104 2 2 1 1 10 48 47
105 2 2 1 1 9 54 39
106 2 2 1 1 46 55 14
107 2 2 1 1 1 44 15
108 2 2 1 1 16 48 3
38
1 26 2 3 1 1 5 6 7
2 26 2 3 1 5 2 8 9
3 26 2 4 2 3 10 11 12
4 26 2 4 2 10 4 13 14
5 26 2 1 3 1 15 17 18
6 26 2 1 3 15 16 19 20
7 26 2 1 3 16 3 21 22
8 26 2 2 4 2 23 27 28
9 26 2 2 4 23 24 29 30
10 26 2 2 4 24 25 31 32
11 26 2 2 4 25 26 33 34
12 26 2 2 4 26 4 35 36
13 21 2 1 1 3 41 10 45 46 47 48 12 11 49
14 21 2 1 1 5 42 1 50 51 52 53 6 7 54
15 21 2 1 1 16 41 3 55 56 46 45 22 21 57
16 21 2 1 1 1 42 15 53 52 58 59 18 17 60
17 21 2 1 1 37 40 38 61 62 63 64 65 66 67
18 21 2 1 1 39 40 37 68 69 62 61 70 71 72
19 21 2 1 1 38 41 37 73 74 75 76 66 65 77
20 21 2 1 1 37 42 39 78 79 80 81 71 70 82
21 21 2 1 1 24 39 23 83 84 85 86 29 30 87
22 21 2 1 1 26 38 25 88 89 90 91 33 34 92
23 21 2 1 1 15 37 16 93 94 95 96 20 19 97
24 21 2 1 1 42 44 39 98 99 100 101 81 80 102
25 21 2 1 1 38 43 41 103 104 105 106 74 73 107
26 21 2 1 1 2 44 5 108 109 110 111 8 9 112
27 21 2 1 1 10 43 4 113 114 115 116 14 13 117
28 21 2 1 1 24 40 39 118 119 69 68 84 83 120
29 21 2 1 1 38 40 25 64 63 121 122 91 90 123
30 21 2 1 1 41 43 10 106 105 114 113 48 47 124
31 21 2 1 1 5 44 42 111 110 99 98 51 50 125
32 21 2 1 1 25 40 24 122 121 119 118 31 32 126
33 21 2 1 1 37 41 16 76 75 56 55 96 95 127
34 21 2 1 1 15 42 37 59 58 79 78 94 93 128
35 21 2 1 1 4 43 26 116 115 129 130 35 36 131
36 21 2 1 1 23 44 2 132 133 109 108 27 28 134
37 21 2 1 1 26 43 38 130 129 104 103 89 88 135
38 21 2 1 1 39 44 23 101 100 133 132 86 85 136
$EndElements
$Periodic
1
1 1 2
Affine 0.5000000000000001 0.8660254037844386 0 0 -0.8660254037844386 0.5000000000000001 0 0 0 0 1 0 0 0 0 1
7
9 14
6 11
8 13
3
5 10
7 12
2 4
1 3
2 4
$EndPeriodic
+129 -13
View File
@@ -1,25 +1,141 @@
SetFactory("OpenCASCADE");
// Select periodic mesh by setting this to either 0 - standard, 1 - periodic
periodic = 1;
R = 1.5;
r = 0.5;
// Set the geometry order (1, 2, ..., 10 for tetrahedra or 9 for other types)
order = 3;
Torus(1) = {0,0,0, R, r, Pi/3};
// Set the element type (4 - tetrahedra, 6 - wedges, 8 - hexahedra)
type = 8;
pts() = PointsOf{ Volume{1}; };
// Minor and major radii
R1 = 1.0;
R2 = 2.0;
Characteristic Length{ pts() } = 0.25;
// Side length of interior square
A1 = 0.8;
// Angular size of the sector
Phi = Pi/3.0;
// Number of azimuthal elements
nazm = 3;
// Number of elements around a quarter of the circle
narc = 2;
// Number of elements between surface and interior square
nshl = 1;
lc = 0.5;
a1 = A1 / Sqrt(2.0);
Point(1) = {R2+R1, 0, 0, lc};
Point(2) = {R2, 0, R1, lc};
Point(3) = {R2-R1, 0, 0, lc};
Point(4) = {R2, 0, -R1, lc};
Point(5) = {R2, 0, 0, lc};
Point(6) = {R2+a1, 0, 0, lc};
Point(7) = {R2, 0, a1, lc};
Point(8) = {R2-a1, 0, 0, lc};
Point(9) = {R2, 0, -a1, lc};
Circle(1) = {1,5,2};
Circle(2) = {2,5,3};
Circle(3) = {3,5,4};
Circle(4) = {4,5,1};
Line(5) = {6,1};
Line(6) = {7,2};
Line(7) = {8,3};
Line(8) = {9,4};
Line(9) = {6, 7};
Line(10) = {7, 8};
Line(11) = {8, 9};
Line(12) = {9, 6};
Line Loop(101) = {1, -6, -9, 5};
Line Loop(102) = {2, -7, -10, 6};
Line Loop(103) = {3, -8, -11, 7};
Line Loop(104) = {4, -5, -12, 8};
Line Loop(105) = {9, 10, 11, 12};
Plane Surface(201) = {101};
Plane Surface(202) = {102};
Plane Surface(203) = {103};
Plane Surface(204) = {104};
Plane Surface(205) = {105};
Transfinite Curve{1} = narc+1;
Transfinite Curve{2} = narc+1;
Transfinite Curve{3} = narc+1;
Transfinite Curve{4} = narc+1;
Transfinite Curve{5} = nshl+1;
Transfinite Curve{6} = nshl+1;
Transfinite Curve{7} = nshl+1;
Transfinite Curve{8} = nshl+1;
Transfinite Curve{9} = narc+1;
Transfinite Curve{10} = narc+1;
Transfinite Curve{11} = narc+1;
Transfinite Curve{12} = narc+1;
If (type == 8)
Recombine Surface {201};
Recombine Surface {202};
Recombine Surface {203};
Recombine Surface {204};
Recombine Surface {205};
Transfinite Surface {201} = {1,2,7,6};
Transfinite Surface {202} = {2,3,8,7};
Transfinite Surface {203} = {3,4,9,8};
Transfinite Surface {204} = {4,1,6,9};
Transfinite Surface {205} = {6,7,8,9};
EndIf
If (type == 4)
Extrude { {0,0,1} , {0,0,0} , Phi} {
Surface{201,202,203,204,205}; Layers{nazm};
}
Else
Extrude { {0,0,1} , {0,0,0} , Phi} {
Surface{201,202,203,204,205}; Layers{nazm}; Recombine;
}
EndIf
// Set a rotation periodicity constraint:
Periodic Surface{3} = {2} Rotate{{0,0,1}, {0,0,0}, Pi/3};
If (periodic)
Periodic Surface{227} = {201} Rotate{{0,0,1}, {0,0,0}, Phi};
Periodic Surface{249} = {202} Rotate{{0,0,1}, {0,0,0}, Phi};
Periodic Surface{271} = {203} Rotate{{0,0,1}, {0,0,0}, Phi};
Periodic Surface{293} = {204} Rotate{{0,0,1}, {0,0,0}, Phi};
Periodic Surface{315} = {205} Rotate{{0,0,1}, {0,0,0}, Phi};
EndIf
// Tag surfaces and volumes with positive integers
Physical Surface(1) = {1};
Physical Surface(2) = {2};
Physical Surface(3) = {3};
Physical Volume(1) = {1};
Physical Surface(1) = {201,202,203,204,205};
Physical Surface(2) = {227,249,271,293,315};
Physical Surface(3) = {214,236,258,280};
Physical Volume(1) = {1,2,3,4,5};
// Optimize the high-order mesh
// See https://gmsh.info/doc/texinfo/gmsh.html#index-Mesh_002eHighOrderOptimize
// Mesh.ElementOrder = order;
// Mesh.HighOrderOptimize = 1;
// Generate 3D mesh
Mesh 3;
SetOrder order;
Mesh.MshFileVersion = 2.2;
Save "periodic-torus-sector.msh";
// Check the element quality (the Plugin may be called AnalyseCurvedMesh)
// Plugin(AnalyseMeshQuality).JacobianDeterminant = 1;
// Plugin(AnalyseMeshQuality).Run;
If (periodic)
Save Sprintf("periodic-torus-sector-t%01g-o%01g.msh", type, order);
Else
Save Sprintf("torus-sector-t%01g-o%01g.msh", type, order);
EndIf
File diff suppressed because it is too large Load Diff
+118
View File
@@ -0,0 +1,118 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
2
elements
20
1 3 0 1 6 5
1 3 1 2 7 6
1 3 2 3 8 7
1 3 3 4 9 8
1 3 5 6 11 10
1 2 6 7 11
1 2 7 12 11
1 2 7 8 13
1 2 7 13 12
1 3 8 9 14 13
1 3 10 11 16 15
1 2 11 12 17
1 2 11 17 16
1 2 12 13 17
1 2 13 18 17
1 3 13 14 19 18
1 3 15 16 21 20
1 3 16 17 22 21
1 3 17 18 23 22
1 3 18 19 24 23
boundary
16
2 1 0 1
2 1 1 2
2 1 2 3
2 1 3 4
2 1 21 20
2 1 22 21
2 1 23 22
2 1 24 23
1 1 5 0
1 1 10 5
1 1 15 10
1 1 20 15
1 1 4 9
1 1 9 14
1 1 14 19
1 1 19 24
vertices
25
nodes
FiniteElementSpace
FiniteElementCollection: H1_2D_P1
VDim: 2
Ordering: 0
0
0.25
0.5
0.75
1
0
0.25
0.5
0.75
1
0
0.25
0.5
0.75
1
0
0.25
0.5
0.75
1
0
0.25
0.5
0.75
1
0
0
0
0
0
0.25
0.25
0.25
0.25
0.25
0.5
0.5
0.5
0.5
0.5
0.75
0.75
0.75
0.75
0.75
1
1
1
1
1
+3 -2
View File
@@ -144,12 +144,12 @@ namespace mfem {
* - <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="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="mobius-strip_8cpp_source.html">Mobius Strip</a>: generate various Mobius strip-like meshes
* - <a class="el" href="klein-bottle_8cpp_source.html">Klein Bottle</a>: generate three types of Klein bottle surfaces
* - <a class="el" href="toroid_8cpp_source.html">Toroid</a>: generate simple toroidal meshes
* - <a class="el" href="twist_8cpp_source.html">Twist</a>: generate simple periodic meshes
* - <a class="el" href="minimal-surface_8cpp_source.html">Minimal Surface</a>: compute minimal surfaces, <a class="el" href="minimal-surface_8cpp_source.html">serial</a> and <a class="el" href="pminimal-surface_8cpp_source.html">parallel</a> versions
* - <a class="el" href="polar-nc_8cpp_source.html">Polar NC</a>: generate polar non-conforming meshes
* - <a class="el" href="shaper_8cpp_source.html">Shaper</a>: resolve material interfaces by mesh refinement
* - <a class="el" href="extruder_8cpp_source.html">Extruder</a>: extrude a low-dimensional mesh into a higher dimension
* - <a class="el" href="mesh-explorer_8cpp_source.html">Mesh Explorer</a>: visualize and manipulate meshes
@@ -162,6 +162,7 @@ namespace mfem {
* - <a class="el" href="lor-transfer_8cpp_source.html">LOR Transfer</a>: map functions between high-order and low-order refined spaces
* - <a class="el" href="findpts_8cpp_source.html">Find Points</a>: evaluate grid function in physical space, <a class="el" href="findpts_8cpp_source.html">serial</a> and <a class="el" href="pfindpts_8cpp_source.html">parallel</a> versions
* - <a class="el" href="field-diff_8cpp_source.html">Field Diff</a>: compare grid functions on different meshes
* - <a class="el" href="field-interp_8cpp_source.html">Field Interp</a>: transfer a grid functions betwen meshes
* - <a class="el" href="miniapps_2performance_2ex1_8cpp_source.html">HPC Example 1</a>: high-performance nodal H1 FEM for the Laplace problem
* - <a class="el" href="miniapps_2performance_2ex1p_8cpp_source.html">HPC Example 1p</a>: high-performance parallel nodal H1 FEM for the Laplace problem
*
+1 -1
View File
@@ -19,7 +19,7 @@ html: $(DOXYGEN_CONF)
@# Generate the html documentation
@doxygen $(DOXYGEN_CONF)
@echo "<meta http-equiv=\"REFRESH\" content=\"0;URL=CodeDocumentation/html/index.html\">" > CodeDocumentation.html
@cat warnings.log
@cat warnings.log 1>&2
@# Generate the log of undocumented methods
@( cat $(DOXYGEN_CONF) ; echo "GENERATE_HTML=NO" ; echo "EXTRACT_ALL=NO" ; echo "WARN_LOGFILE=undoc.log" ; echo "QUIET=YES" ) | doxygen - &> /dev/null
+20 -2
View File
@@ -72,6 +72,7 @@ int main(int argc, char *argv[])
int seed = 75;
bool slu_solver = false;
bool sp_solver = false;
bool pardiso_solver = false;
bool visualization = 1;
OptionsParser args(argc, argv);
@@ -95,6 +96,14 @@ int main(int argc, char *argv[])
#ifdef MFEM_USE_STRUMPACK
args.AddOption(&sp_solver, "-sp", "--strumpack", "-no-sp",
"--no-strumpack", "Use the STRUMPACK Solver.");
#endif
#ifdef MFEM_USE_MKL_CPARDISO
args.AddOption(&pardiso_solver,
"-pardiso",
"--pardiso",
"-no-pardiso",
"--no-pardiso",
"Use the MKL Cluster Pardiso Solver.");
#endif
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
@@ -236,7 +245,7 @@ int main(int argc, char *argv[])
// preconditioner for A to be used within the solver. Set the matrices
// which define the generalized eigenproblem A x = lambda M x.
Solver * precond = NULL;
if (!slu_solver && !sp_solver)
if (!slu_solver && !sp_solver && !pardiso_solver)
{
HypreBoomerAMG * amg = new HypreBoomerAMG(*A);
amg->SetPrintLevel(0);
@@ -268,10 +277,19 @@ int main(int argc, char *argv[])
strumpack->SetFromCommandLine();
precond = strumpack;
}
#endif
#ifdef MFEM_USE_MKL_CPARDISO
if (pardiso_solver)
{
auto pardiso = new CPardisoSolver(A->GetComm());
pardiso->SetMatrixType(CPardisoSolver::MatType::REAL_STRUCTURE_SYMMETRIC);
pardiso->SetPrintLevel(1);
pardiso->SetOperator(*A);
precond = pardiso;
}
#endif
}
HypreLOBPCG * lobpcg = new HypreLOBPCG(MPI_COMM_WORLD);
lobpcg->SetNumModes(nev);
lobpcg->SetRandomSeed(seed);
+234
View File
@@ -0,0 +1,234 @@
// MFEM Example 1 - Parallel Version
//
// Compile with: make ex1p
//
// Sample runs: mpirun -np 4 ex1p -m ../data/square-disc.mesh
//
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
int main(int argc, char *argv[])
{
// 1. Initialize MPI.
int num_procs, myid;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
// 2. Parse command-line options.
const char *mesh_file = "../data/inline-quad.mesh";
int order = 1;
bool static_cond = false;
bool visualization = true;
int sr = 1;
int pr = 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(&sr, "-sr", "--serial_ref",
"Number of serial refinements");
args.AddOption(&pr, "-pr", "--parallel_ref",
"Number of parallel refinements");
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
"--no-static-condensation", "Enable static condensation.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.Parse();
if (!args.Good())
{
if (myid == 0)
{
args.PrintUsage(cout);
}
MPI_Finalize();
return 1;
}
if (myid == 0)
{
args.PrintOptions(cout);
}
// 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.
{
for (int l = 0; l < sr; 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();
{
for (int l = 0; l < pr; 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 = new H1_FECollection(order, dim);
ParFiniteElementSpace fespace(&pmesh, fec);
HYPRE_Int 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);
a.AddDomainIntegrator(new DiffusionIntegrator(one));
if (static_cond) { a.EnableStaticCondensation(); }
a.Assemble();
HypreParMatrix A;
Vector B, X;
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
// // 13. Solve the linear system A X = B.
// // * With full assembly, use the BoomerAMG preconditioner from hypre.
// // * With partial assembly, use Jacobi smoothing, for now.
StopWatch chrono;
chrono.Clear();
chrono.Start();
HypreBoomerAMG *prec = new HypreBoomerAMG;
prec->SetPrintLevel(0);
CGSolver cg(MPI_COMM_WORLD);
cg.SetRelTol(1e-13);
cg.SetMaxIter(2000);
cg.SetPrintLevel(0);
if (prec) { cg.SetPreconditioner(*prec); }
cg.SetOperator(A);
cg.Mult(B, X);
delete prec;
if (myid == 0)
{
cout << "PCG-AMG time: " << chrono.RealTime() << endl;
}
chrono.Clear();
chrono.Start();
{
MUMPSSolver MA;
MA.SetMatrixSymType(0);
MA.SetOperator(A);
Vector Y(X.Size());
MA.Mult(B,Y);
Y-=X;
cout << "Mumps Diff norm = " << Y.Norml2() << endl;
}
if (myid == 0)
{
cout << "mumps time: " << chrono.RealTime() << endl;
}
chrono.Clear();
chrono.Start();
{
CPardisoSolver pardiso(A.GetComm());
// pardiso.SetMatrixType(CPardisoSolver::MatType::REAL_STRUCTURE_SYMMETRIC);
pardiso.SetMatrixType(CPardisoSolver::MatType::REAL_UNSYMMETRIC);
pardiso.SetPrintLevel(0);
pardiso.SetOperator(A);
Vector Y(X.Size());
pardiso.Mult(B, Y);
Y-=X;
cout << "Pardiso Diff norm = " << Y.Norml2() << endl;
}
if (myid == 0)
{
cout << "pardiso time: " << chrono.RealTime() << endl;
}
{
SuperLURowLocMatrix SA(A);
SuperLUSolver superlu(MPI_COMM_WORLD);
superlu.SetPrintStatistics(false);
superlu.SetSymmetricPattern(false);
superlu.SetColumnPermutation(superlu::PARMETIS);
superlu.SetOperator(SA);
Vector Y(X.Size());
superlu.Mult(B, Y);
Y-=X;
cout << "Superlu Diff norm = " << Y.Norml2() << endl;
}
if (myid == 0)
{
cout << "superlu time: " << chrono.RealTime() << endl;
}
a.RecoverFEMSolution(X, b, x);
// 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.
delete fec;
MPI_Finalize();
return 0;
}
+30 -21
View File
@@ -6,17 +6,19 @@
// ex22 -m ../data/inline-tri.mesh -o 3
// ex22 -m ../data/inline-quad.mesh -o 3
// ex22 -m ../data/inline-quad.mesh -o 3 -p 1
// ex22 -m ../data/inline-quad.mesh -o 3 -p 1 -pa
// ex22 -m ../data/inline-quad.mesh -o 3 -p 2
// ex22 -m ../data/inline-tet.mesh -o 2
// ex22 -m ../data/inline-hex.mesh -o 2
// ex22 -m ../data/inline-hex.mesh -o 2 -p 1
// ex22 -m ../data/inline-hex.mesh -o 2 -p 2
// ex22 -m ../data/inline-hex.mesh -o 2 -p 2 -pa
// ex22 -m ../data/star.mesh -r 1 -o 2 -sigma 10.0
//
// With partial assembly:
// ex22 -m ../data/inline-quad.mesh -o 3 -p 1 -pa
// ex22 -m ../data/inline-hex.mesh -o 2 -p 2 -pa
// ex22 -m ../data/star.mesh -r 1 -o 2 -sigma 10.0 -pa
// Device sample runs:
// ex22 -m ../data/inline-quad.mesh -o 3 -p 1 -pa -d cuda
// ex22 -m ../data/inline-hex.mesh -o 2 -p 2 -pa -d cuda
// ex22 -m ../data/star.mesh -r 1 -o 2 -sigma 10.0 -pa -d cuda
//
// Description: This example code demonstrates the use of MFEM to define and
// solve simple complex-valued linear systems. It implements three
@@ -82,6 +84,7 @@ int main(int argc, char *argv[])
bool herm_conv = true;
bool exact_sol = true;
bool pa = false;
const char *device_config = "cpu";
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
@@ -114,6 +117,8 @@ int main(int argc, char *argv[])
"Enable or disable GLVis visualization.");
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
"--no-partial-assembly", "Enable Partial Assembly.");
args.AddOption(&device_config, "-d", "--device",
"Device configuration string, see Device::Configure().");
args.Parse();
if (!args.Good())
{
@@ -143,13 +148,18 @@ int main(int argc, char *argv[])
ComplexOperator::Convention conv =
herm_conv ? ComplexOperator::HERMITIAN : ComplexOperator::BLOCK_SYMMETRIC;
// 2. Read the mesh from the given mesh file. We can handle triangular,
// 2. 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.Print();
// 3. Read the mesh from the given mesh file. We can handle triangular,
// quadrilateral, tetrahedral, hexahedral, surface and volume meshes
// with the same code.
Mesh *mesh = new Mesh(mesh_file, 1, 1);
int dim = mesh->Dimension();
// 3. Refine the mesh to increase resolution. In this example we do
// 4. Refine the mesh to increase resolution. In this example we do
// 'ref_levels' of uniform refinement where the user specifies
// the number of levels with the '-r' option.
for (int l = 0; l < ref_levels; l++)
@@ -157,7 +167,7 @@ int main(int argc, char *argv[])
mesh->UniformRefinement();
}
// 4. Define a finite element space on the mesh. Here we use continuous
// 5. Define a finite element space on the mesh. Here we use continuous
// Lagrange, Nedelec, or Raviart-Thomas finite elements of the specified
// order.
if (dim == 1 && prob != 0 )
@@ -179,7 +189,7 @@ int main(int argc, char *argv[])
cout << "Number of finite element unknowns: " << fespace->GetTrueVSize()
<< endl;
// 5. Determine the list of true (i.e. conforming) essential boundary dofs.
// 6. Determine the list of true (i.e. conforming) essential boundary dofs.
// In this example, the boundary conditions are defined based on the type
// of mesh and the problem type.
Array<int> ess_tdof_list;
@@ -191,12 +201,12 @@ int main(int argc, char *argv[])
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
// 6. Set up the linear form b(.) which corresponds to the right-hand side of
// 7. Set up the linear form b(.) which corresponds to the right-hand side of
// the FEM linear system.
ComplexLinearForm b(fespace, conv);
b.Vector::operator=(0.0);
// 7. Define the solution vector u as a complex finite element grid function
// 8. Define the solution vector u as a complex finite element grid function
// corresponding to fespace. Initialize u with initial guess of 1+0i or
// the exact solution if it is known.
ComplexGridFunction u(fespace);
@@ -218,7 +228,6 @@ int main(int argc, char *argv[])
VectorConstantCoefficient zeroVecCoef(zeroVec);
VectorConstantCoefficient oneVecCoef(oneVec);
u = 0.0;
switch (prob)
{
case 0:
@@ -271,7 +280,7 @@ int main(int argc, char *argv[])
<< "window_title 'Exact: Imaginary Part'" << flush;
}
// 8. Set up the sesquilinear form a(.,.) on the finite element space
// 9. Set up the sesquilinear form a(.,.) on the finite element space
// corresponding to the damped harmonic oscillator operator of the
// appropriate type:
//
@@ -314,7 +323,7 @@ int main(int argc, char *argv[])
default: break; // This should be unreachable
}
// 8a. Set up the bilinear form for the preconditioner corresponding to the
// 9a. Set up the bilinear form for the preconditioner corresponding to the
// appropriate operator
//
// 0) A scalar H1 field
@@ -349,9 +358,9 @@ int main(int argc, char *argv[])
default: break; // This should be unreachable
}
// 9. Assemble the form and the corresponding linear system, applying any
// necessary transformations such as: assembly, eliminating boundary
// conditions, conforming constraints for non-conforming AMR, etc.
// 10. Assemble the form and the corresponding linear system, applying any
// necessary transformations such as: assembly, eliminating boundary
// conditions, conforming constraints for non-conforming AMR, etc.
a->Assemble();
pcOp->Assemble();
@@ -362,7 +371,7 @@ int main(int argc, char *argv[])
cout << "Size of linear system: " << A->Width() << endl << endl;
// 10. Define and apply a GMRES solver for AU=B with a block diagonal
// 11. Define and apply a GMRES solver for AU=B with a block diagonal
// preconditioner based on the appropriate sparse smoother.
{
Array<int> blockOffsets;
@@ -419,7 +428,7 @@ int main(int argc, char *argv[])
gmres.Mult(B, U);
}
// 11. Recover the solution as a finite element grid function and compute the
// 12. Recover the solution as a finite element grid function and compute the
// errors if the exact solution is known.
a->RecoverFEMSolution(U, b, u);
@@ -451,7 +460,7 @@ int main(int argc, char *argv[])
cout << endl;
}
// 12. Save the refined mesh and the solution. This output can be viewed
// 13. Save the refined mesh and the solution. This output can be viewed
// later using GLVis: "glvis -m mesh -g sol".
{
ofstream mesh_ofs("refined.mesh");
@@ -466,7 +475,7 @@ int main(int argc, char *argv[])
u.imag().Save(sol_i_ofs);
}
// 13. Send the solution by socket to a GLVis server.
// 14. Send the solution by socket to a GLVis server.
if (visualization)
{
char vishost[] = "localhost";
@@ -525,7 +534,7 @@ int main(int argc, char *argv[])
}
}
// 14. Free the used memory.
// 15. Free the used memory.
delete a;
delete u_exact;
delete pcOp;
+31 -23
View File
@@ -7,16 +7,18 @@
// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 3
// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 3 -p 1
// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 3 -p 2
// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 1 -p 1 -pa
// mpirun -np 4 ex22p -m ../data/inline-tet.mesh -o 2
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2 -p 1
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2 -p 2
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 1 -p 2 -pa
// mpirun -np 4 ex22p -m ../data/star.mesh -o 2 -sigma 10.0
//
// With partial assembly:
// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 1 -p 1 -pa
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 1 -p 2 -pa
// mpirun -np 4 ex22p -m ../data/star.mesh -o 2 -sigma 10.0 -pa
// Device sample runs:
// mpirun -np 4 ex22p -m ../data/inline-quad.mesh -o 1 -p 1 -pa -d cuda
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 1 -p 2 -pa -d cuda
// mpirun -np 4 ex22p -m ../data/star.mesh -o 2 -sigma 10.0 -pa -d cuda
//
// Description: This example code demonstrates the use of MFEM to define and
// solve simple complex-valued linear systems. It implements three
@@ -46,7 +48,6 @@
// We recommend viewing examples 1, 3 and 4 before viewing this
// example.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
@@ -90,6 +91,7 @@ int main(int argc, char *argv[])
bool herm_conv = true;
bool exact_sol = true;
bool pa = false;
const char *device_config = "cpu";
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
@@ -124,6 +126,8 @@ int main(int argc, char *argv[])
"Enable or disable GLVis visualization.");
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
"--no-partial-assembly", "Enable Partial Assembly.");
args.AddOption(&device_config, "-d", "--device",
"Device configuration string, see Device::Configure().");
args.Parse();
if (!args.Good())
{
@@ -160,19 +164,24 @@ int main(int argc, char *argv[])
ComplexOperator::Convention conv =
herm_conv ? ComplexOperator::HERMITIAN : ComplexOperator::BLOCK_SYMMETRIC;
// 3. Read the (serial) mesh from the given mesh file on all processors. We
// 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);
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 = new Mesh(mesh_file, 1, 1);
int dim = mesh->Dimension();
// 4. Refine the serial mesh on all processors to increase the resolution.
// 5. Refine the serial mesh on all processors to increase the resolution.
for (int l = 0; l < ser_ref_levels; l++)
{
mesh->UniformRefinement();
}
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
// 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 = new ParMesh(MPI_COMM_WORLD, *mesh);
@@ -182,7 +191,7 @@ int main(int argc, char *argv[])
pmesh->UniformRefinement();
}
// 6. Define a parallel finite element space on the parallel mesh. Here we
// 7. Define a parallel finite element space on the parallel mesh. Here we
// use continuous Lagrange, Nedelec, or Raviart-Thomas finite elements of
// the specified order.
if (dim == 1 && prob != 0 )
@@ -210,7 +219,7 @@ int main(int argc, char *argv[])
cout << "Number of finite element unknowns: " << size << endl;
}
// 7. Determine the list of true (i.e. parallel conforming) essential
// 8. Determine the list of true (i.e. parallel conforming) essential
// boundary dofs. In this example, the boundary conditions are defined
// based on the type of mesh and the problem type.
Array<int> ess_tdof_list;
@@ -222,14 +231,14 @@ int main(int argc, char *argv[])
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
// 8. Set up the parallel linear form b(.) which corresponds to the
// 9. Set up the parallel linear form b(.) which corresponds to the
// right-hand side of the FEM linear system.
ParComplexLinearForm b(fespace, conv);
b.Vector::operator=(0.0);
// 9. Define the solution vector u as a parallel complex finite element grid
// function corresponding to fespace. Initialize u with initial guess of
// 1+0i or the exact solution if it is known.
// 10. Define the solution vector u as a parallel complex finite element grid
// function corresponding to fespace. Initialize u with initial guess of
// 1+0i or the exact solution if it is known.
ParComplexGridFunction u(fespace);
ParComplexGridFunction * u_exact = NULL;
if (exact_sol) { u_exact = new ParComplexGridFunction(fespace); }
@@ -249,7 +258,6 @@ int main(int argc, char *argv[])
VectorConstantCoefficient zeroVecCoef(zeroVec);
VectorConstantCoefficient oneVecCoef(oneVec);
u = 0.0;
switch (prob)
{
case 0:
@@ -304,7 +312,7 @@ int main(int argc, char *argv[])
<< "window_title 'Exact: Imaginary Part'" << flush;
}
// 10. Set up the parallel sesquilinear form a(.,.) on the finite element
// 11. Set up the parallel sesquilinear form a(.,.) on the finite element
// space corresponding to the damped harmonic oscillator operator of the
// appropriate type:
//
@@ -347,7 +355,7 @@ int main(int argc, char *argv[])
default: break; // This should be unreachable
}
// 10a. Set up the parallel bilinear form for the preconditioner
// 11a. Set up the parallel bilinear form for the preconditioner
// corresponding to the appropriate operator
//
// 0) A scalar H1 field
@@ -381,7 +389,7 @@ int main(int argc, char *argv[])
default: break; // This should be unreachable
}
// 11. Assemble the parallel bilinear form and the corresponding linear
// 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, etc.
@@ -399,7 +407,7 @@ int main(int argc, char *argv[])
<< 2 * fespace->GlobalTrueVSize() << endl << endl;
}
// 12. Define and apply a parallel FGMRES solver for AU=B with a block
// 13. Define and apply a parallel FGMRES solver for AU=B with a block
// diagonal preconditioner based on the appropriate multigrid
// preconditioner from hypre.
{
@@ -460,7 +468,7 @@ int main(int argc, char *argv[])
fgmres.SetPrintLevel(1);
fgmres.Mult(B, U);
}
// 13. Recover the parallel grid function corresponding to U. This is the
// 14. Recover the parallel grid function corresponding to U. This is the
// local finite element solution on each processor.
a->RecoverFEMSolution(U, b, u);
@@ -495,7 +503,7 @@ int main(int argc, char *argv[])
}
}
// 14. Save the refined mesh and the solution in parallel. This output can be
// 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;
@@ -515,7 +523,7 @@ int main(int argc, char *argv[])
u.imag().Save(sol_i_ofs);
}
// 15. Send the solution by socket to a GLVis server.
// 16. Send the solution by socket to a GLVis server.
if (visualization)
{
char vishost[] = "localhost";
@@ -580,7 +588,7 @@ int main(int argc, char *argv[])
}
}
// 16. Free the used memory.
// 17. Free the used memory.
delete a;
delete u_exact;
delete pcOp;
+1 -1
View File
@@ -70,7 +70,7 @@ int main(int argc, char *argv[])
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&prob, "-p", "--problem-type",
"Choose between 0: H(Curl) or 1: H(Div)");
"Choose between 0: grad, 1: curl, 2: div");
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
"--no-static-condensation", "Enable static condensation.");
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
+1 -1
View File
@@ -76,7 +76,7 @@ int main(int argc, char *argv[])
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&prob, "-p", "--problem-type",
"Choose between 0: H(Curl) or 1: H(Div)");
"Choose between 0: grad, 1: curl, 2: div");
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
"--no-static-condensation", "Enable static condensation.");
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
+47 -53
View File
@@ -82,24 +82,24 @@ public:
};
// Class for returning the PML coefficients of the bilinear form
class PMLMatrixCoefficient : public MatrixCoefficient
class PMLDiagMatrixCoefficient : public VectorCoefficient
{
private:
CartesianPML * pml = nullptr;
void (*Function)(const Vector &, CartesianPML * , DenseMatrix &);
void (*Function)(const Vector &, CartesianPML * , Vector &);
public:
PMLMatrixCoefficient(int dim, void(*F)(const Vector &, CartesianPML *,
DenseMatrix &),
CartesianPML * pml_)
: MatrixCoefficient(dim), pml(pml_), Function(F)
PMLDiagMatrixCoefficient(int dim, void(*F)(const Vector &, CartesianPML *,
Vector &),
CartesianPML * pml_)
: VectorCoefficient(dim), pml(pml_), Function(F)
{}
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
virtual void Eval(Vector &K, ElementTransformation &T,
const IntegrationPoint &ip)
{
double x[3];
Vector transip(x, 3);
T.Transform(ip, transip);
K.SetSize(height, width);
K.SetSize(vdim);
(*Function)(transip, pml, K);
}
};
@@ -116,13 +116,13 @@ void source(const Vector &x, Vector & f);
// Functions for computing the necessary coefficients after PML stretching.
// J is the Jacobian matrix of the stretching function
void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, Vector &D);
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, Vector &D);
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, Vector &D);
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, Vector &D);
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, Vector &D);
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, Vector &D);
Array2D<double> comp_domain_bdr;
Array2D<double> domain_bdr;
@@ -365,19 +365,19 @@ int main(int argc, char *argv[])
a.AddDomainIntegrator(new VectorFEMassIntegrator(restr_omeg),NULL);
int cdim = (dim == 2) ? 1 : dim;
PMLMatrixCoefficient pml_c1_Re(cdim,detJ_inv_JT_J_Re, pml);
PMLMatrixCoefficient pml_c1_Im(cdim,detJ_inv_JT_J_Im, pml);
ScalarMatrixProductCoefficient c1_Re(muinv,pml_c1_Re);
ScalarMatrixProductCoefficient c1_Im(muinv,pml_c1_Im);
MatrixRestrictedCoefficient restr_c1_Re(c1_Re,attrPML);
MatrixRestrictedCoefficient restr_c1_Im(c1_Im,attrPML);
PMLDiagMatrixCoefficient pml_c1_Re(cdim,detJ_inv_JT_J_Re, pml);
PMLDiagMatrixCoefficient pml_c1_Im(cdim,detJ_inv_JT_J_Im, pml);
ScalarVectorProductCoefficient c1_Re(muinv,pml_c1_Re);
ScalarVectorProductCoefficient c1_Im(muinv,pml_c1_Im);
VectorRestrictedCoefficient restr_c1_Re(c1_Re,attrPML);
VectorRestrictedCoefficient restr_c1_Im(c1_Im,attrPML);
PMLMatrixCoefficient pml_c2_Re(dim, detJ_JT_J_inv_Re,pml);
PMLMatrixCoefficient pml_c2_Im(dim, detJ_JT_J_inv_Im,pml);
ScalarMatrixProductCoefficient c2_Re(omeg,pml_c2_Re);
ScalarMatrixProductCoefficient c2_Im(omeg,pml_c2_Im);
MatrixRestrictedCoefficient restr_c2_Re(c2_Re,attrPML);
MatrixRestrictedCoefficient restr_c2_Im(c2_Im,attrPML);
PMLDiagMatrixCoefficient pml_c2_Re(dim, detJ_JT_J_inv_Re,pml);
PMLDiagMatrixCoefficient pml_c2_Im(dim, detJ_JT_J_inv_Im,pml);
ScalarVectorProductCoefficient c2_Re(omeg,pml_c2_Re);
ScalarVectorProductCoefficient c2_Im(omeg,pml_c2_Im);
VectorRestrictedCoefficient restr_c2_Re(c2_Re,attrPML);
VectorRestrictedCoefficient restr_c2_Im(c2_Im,attrPML);
// Integrators inside the PML region
a.AddDomainIntegrator(new CurlCurlIntegrator(restr_c1_Re),
@@ -419,13 +419,13 @@ int main(int argc, char *argv[])
prec.AddDomainIntegrator(new CurlCurlIntegrator(restr_muinv));
prec.AddDomainIntegrator(new VectorFEMassIntegrator(restr_absomeg));
PMLMatrixCoefficient pml_c1_abs(cdim,detJ_inv_JT_J_abs, pml);
ScalarMatrixProductCoefficient c1_abs(muinv,pml_c1_abs);
MatrixRestrictedCoefficient restr_c1_abs(c1_abs,attrPML);
PMLDiagMatrixCoefficient pml_c1_abs(cdim,detJ_inv_JT_J_abs, pml);
ScalarVectorProductCoefficient c1_abs(muinv,pml_c1_abs);
VectorRestrictedCoefficient restr_c1_abs(c1_abs,attrPML);
PMLMatrixCoefficient pml_c2_abs(dim, detJ_JT_J_inv_abs,pml);
ScalarMatrixProductCoefficient c2_abs(absomeg,pml_c2_abs);
MatrixRestrictedCoefficient restr_c2_abs(c2_abs,attrPML);
PMLDiagMatrixCoefficient pml_c2_abs(dim, detJ_JT_J_inv_abs,pml);
ScalarVectorProductCoefficient c2_abs(absomeg,pml_c2_abs);
VectorRestrictedCoefficient restr_c2_abs(c2_abs,attrPML);
prec.AddDomainIntegrator(new CurlCurlIntegrator(restr_c1_abs));
prec.AddDomainIntegrator(new VectorFEMassIntegrator(restr_c2_abs));
@@ -763,7 +763,7 @@ void E_bdr_data_Im(const Vector &x, Vector &E)
}
}
void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det(1.0, 0.0);
@@ -774,14 +774,13 @@ void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M)
det *= dxs[i];
}
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = (det / pow(dxs[i], 2)).real();
D(i) = (det / pow(dxs[i], 2)).real();
}
}
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
@@ -792,14 +791,13 @@ void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M)
det *= dxs[i];
}
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = (det / pow(dxs[i], 2)).imag();
D(i) = (det / pow(dxs[i], 2)).imag();
}
}
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
@@ -810,14 +808,13 @@ void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M)
det *= dxs[i];
}
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = abs(det / pow(dxs[i], 2));
D(i) = abs(det / pow(dxs[i], 2));
}
}
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det(1.0, 0.0);
@@ -831,19 +828,18 @@ void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M)
// in the 2D case the coefficient is scalar 1/det(J)
if (dim == 2)
{
M = (1.0 / det).real();
D = (1.0 / det).real();
}
else
{
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = (pow(dxs[i], 2) / det).real();
D(i) = (pow(dxs[i], 2) / det).real();
}
}
}
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
@@ -856,19 +852,18 @@ void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M)
if (dim == 2)
{
M = (1.0 / det).imag();
D = (1.0 / det).imag();
}
else
{
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = (pow(dxs[i], 2) / det).imag();
D(i) = (pow(dxs[i], 2) / det).imag();
}
}
}
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, Vector &D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
@@ -881,14 +876,13 @@ void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M)
if (dim == 2)
{
M = abs(1.0 / det);
D = abs(1.0 / det);
}
else
{
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = abs(pow(dxs[i], 2) / det);
D(i) = abs(pow(dxs[i], 2) / det);
}
}
}
+47 -53
View File
@@ -82,24 +82,24 @@ public:
};
// Class for returning the PML coefficients of the bilinear form
class PMLMatrixCoefficient : public MatrixCoefficient
class PMLDiagMatrixCoefficient : public VectorCoefficient
{
private:
CartesianPML * pml = nullptr;
void (*Function)(const Vector &, CartesianPML * , DenseMatrix &);
void (*Function)(const Vector &, CartesianPML * , Vector &);
public:
PMLMatrixCoefficient(int dim, void(*F)(const Vector &, CartesianPML *,
DenseMatrix &),
CartesianPML * pml_)
: MatrixCoefficient(dim), pml(pml_), Function(F)
PMLDiagMatrixCoefficient(int dim, void(*F)(const Vector &, CartesianPML *,
Vector &),
CartesianPML * pml_)
: VectorCoefficient(dim), pml(pml_), Function(F)
{}
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
virtual void Eval(Vector &K, ElementTransformation &T,
const IntegrationPoint &ip)
{
double x[3];
Vector transip(x, 3);
T.Transform(ip, transip);
K.SetSize(height, width);
K.SetSize(vdim);
(*Function)(transip, pml, K);
}
};
@@ -116,13 +116,13 @@ void source(const Vector &x, Vector & f);
// Functions for computing the necessary coefficients after PML stretching.
// J is the Jacobian matrix of the stretching function
void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, Vector & D);
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, Vector & D);
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, Vector & D);
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M);
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, Vector & D);
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, Vector & D);
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, Vector & D);
Array2D<double> comp_domain_bdr;
Array2D<double> domain_bdr;
@@ -393,19 +393,19 @@ int main(int argc, char *argv[])
a.AddDomainIntegrator(new VectorFEMassIntegrator(restr_omeg),NULL);
int cdim = (dim == 2) ? 1 : dim;
PMLMatrixCoefficient pml_c1_Re(cdim,detJ_inv_JT_J_Re, pml);
PMLMatrixCoefficient pml_c1_Im(cdim,detJ_inv_JT_J_Im, pml);
ScalarMatrixProductCoefficient c1_Re(muinv,pml_c1_Re);
ScalarMatrixProductCoefficient c1_Im(muinv,pml_c1_Im);
MatrixRestrictedCoefficient restr_c1_Re(c1_Re,attrPML);
MatrixRestrictedCoefficient restr_c1_Im(c1_Im,attrPML);
PMLDiagMatrixCoefficient pml_c1_Re(cdim,detJ_inv_JT_J_Re, pml);
PMLDiagMatrixCoefficient pml_c1_Im(cdim,detJ_inv_JT_J_Im, pml);
ScalarVectorProductCoefficient c1_Re(muinv,pml_c1_Re);
ScalarVectorProductCoefficient c1_Im(muinv,pml_c1_Im);
VectorRestrictedCoefficient restr_c1_Re(c1_Re,attrPML);
VectorRestrictedCoefficient restr_c1_Im(c1_Im,attrPML);
PMLMatrixCoefficient pml_c2_Re(dim, detJ_JT_J_inv_Re,pml);
PMLMatrixCoefficient pml_c2_Im(dim, detJ_JT_J_inv_Im,pml);
ScalarMatrixProductCoefficient c2_Re(omeg,pml_c2_Re);
ScalarMatrixProductCoefficient c2_Im(omeg,pml_c2_Im);
MatrixRestrictedCoefficient restr_c2_Re(c2_Re,attrPML);
MatrixRestrictedCoefficient restr_c2_Im(c2_Im,attrPML);
PMLDiagMatrixCoefficient pml_c2_Re(dim, detJ_JT_J_inv_Re,pml);
PMLDiagMatrixCoefficient pml_c2_Im(dim, detJ_JT_J_inv_Im,pml);
ScalarVectorProductCoefficient c2_Re(omeg,pml_c2_Re);
ScalarVectorProductCoefficient c2_Im(omeg,pml_c2_Im);
VectorRestrictedCoefficient restr_c2_Re(c2_Re,attrPML);
VectorRestrictedCoefficient restr_c2_Im(c2_Im,attrPML);
// Integrators inside the PML region
a.AddDomainIntegrator(new CurlCurlIntegrator(restr_c1_Re),
@@ -453,13 +453,13 @@ int main(int argc, char *argv[])
prec.AddDomainIntegrator(new CurlCurlIntegrator(restr_muinv));
prec.AddDomainIntegrator(new VectorFEMassIntegrator(restr_absomeg));
PMLMatrixCoefficient pml_c1_abs(cdim,detJ_inv_JT_J_abs, pml);
ScalarMatrixProductCoefficient c1_abs(muinv,pml_c1_abs);
MatrixRestrictedCoefficient restr_c1_abs(c1_abs,attrPML);
PMLDiagMatrixCoefficient pml_c1_abs(cdim,detJ_inv_JT_J_abs, pml);
ScalarVectorProductCoefficient c1_abs(muinv,pml_c1_abs);
VectorRestrictedCoefficient restr_c1_abs(c1_abs,attrPML);
PMLMatrixCoefficient pml_c2_abs(dim, detJ_JT_J_inv_abs,pml);
ScalarMatrixProductCoefficient c2_abs(absomeg,pml_c2_abs);
MatrixRestrictedCoefficient restr_c2_abs(c2_abs,attrPML);
PMLDiagMatrixCoefficient pml_c2_abs(dim, detJ_JT_J_inv_abs,pml);
ScalarVectorProductCoefficient c2_abs(absomeg,pml_c2_abs);
VectorRestrictedCoefficient restr_c2_abs(c2_abs,attrPML);
prec.AddDomainIntegrator(new CurlCurlIntegrator(restr_c1_abs));
prec.AddDomainIntegrator(new VectorFEMassIntegrator(restr_c2_abs));
@@ -819,7 +819,7 @@ void E_bdr_data_Im(const Vector &x, Vector &E)
}
}
void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det(1.0, 0.0);
@@ -830,14 +830,13 @@ void detJ_JT_J_inv_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M)
det *= dxs[i];
}
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = (det / pow(dxs[i], 2)).real();
D(i) = (det / pow(dxs[i], 2)).real();
}
}
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
@@ -848,14 +847,13 @@ void detJ_JT_J_inv_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M)
det *= dxs[i];
}
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = (det / pow(dxs[i], 2)).imag();
D(i) = (det / pow(dxs[i], 2)).imag();
}
}
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
@@ -866,14 +864,13 @@ void detJ_JT_J_inv_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M)
det *= dxs[i];
}
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = abs(det / pow(dxs[i], 2));
D(i) = abs(det / pow(dxs[i], 2));
}
}
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det(1.0, 0.0);
@@ -887,19 +884,18 @@ void detJ_inv_JT_J_Re(const Vector &x, CartesianPML * pml, DenseMatrix &M)
// in the 2D case the coefficient is scalar 1/det(J)
if (dim == 2)
{
M = (1.0 / det).real();
D = (1.0 / det).real();
}
else
{
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = (pow(dxs[i], 2) / det).real();
D(i) = (pow(dxs[i], 2) / det).real();
}
}
}
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
@@ -912,19 +908,18 @@ void detJ_inv_JT_J_Im(const Vector &x, CartesianPML * pml, DenseMatrix &M)
if (dim == 2)
{
M = (1.0 / det).imag();
D = (1.0 / det).imag();
}
else
{
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = (pow(dxs[i], 2) / det).imag();
D(i) = (pow(dxs[i], 2) / det).imag();
}
}
}
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M)
void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, Vector & D)
{
vector<complex<double>> dxs(dim);
complex<double> det = 1.0;
@@ -937,14 +932,13 @@ void detJ_inv_JT_J_abs(const Vector &x, CartesianPML * pml, DenseMatrix &M)
if (dim == 2)
{
M = abs(1.0 / det);
D = abs(1.0 / det);
}
else
{
M = 0.0;
for (int i = 0; i < dim; ++i)
{
M(i, i) = abs(pow(dxs[i], 2) / det);
D(i) = abs(pow(dxs[i], 2) / det);
}
}
}
+12 -2
View File
@@ -60,6 +60,7 @@ int main(int argc, char *argv[])
bool static_cond = false;
bool visualization = 1;
bool amg_elast = 0;
bool reorder_space = false;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
@@ -75,6 +76,8 @@ int main(int argc, char *argv[])
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&reorder_space, "-nodes", "--by-nodes", "-vdim", "--by-vdim",
"Use byNODES ordering of vector space instead of byVDIM");
args.Parse();
if (!args.Good())
{
@@ -156,7 +159,14 @@ int main(int argc, char *argv[])
else
{
fec = new H1_FECollection(order, dim);
fespace = new ParFiniteElementSpace(pmesh, fec, dim, Ordering::byVDIM);
if (reorder_space)
{
fespace = new ParFiniteElementSpace(pmesh, fec, dim, Ordering::byNODES);
}
else
{
fespace = new ParFiniteElementSpace(pmesh, fec, dim, Ordering::byVDIM);
}
}
HYPRE_Int size = fespace->GlobalTrueVSize();
if (myid == 0)
@@ -249,7 +259,7 @@ int main(int argc, char *argv[])
}
else
{
amg->SetSystemsOptions(dim);
amg->SetSystemsOptions(dim, reorder_space);
}
HyprePCG *pcg = new HyprePCG(A);
pcg->SetTol(1e-8);
+8 -3
View File
@@ -108,7 +108,11 @@ int main(int argc, char *argv[])
// the Laplace problem -\Delta u = 1. We don't assemble the discrete
// problem yet, this will be done in the main loop.
BilinearForm a(&fespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
if (pa)
{
a.SetAssemblyLevel(AssemblyLevel::PARTIAL);
a.SetDiagonalPolicy(Operator::DIAG_ONE);
}
LinearForm b(&fespace);
ConstantCoefficient one(1.0);
@@ -199,9 +203,10 @@ int main(int argc, char *argv[])
umf_solver.Mult(B, X);
#endif
}
else // No preconditioning for now in partial assembly mode.
else // Diagonal preconditioning in partial assembly mode.
{
CG(*A, B, X, 3, 2000, 1e-12, 0.0);
OperatorJacobiSmoother M(a, ess_tdof_list);
PCG(*A, M, B, X, 3, 2000, 1e-12, 0.0);
}
// 18. After solving the linear system, reconstruct the solution as a
+19 -6
View File
@@ -129,7 +129,11 @@ int main(int argc, char *argv[])
// the Laplace problem -\Delta u = 1. We don't assemble the discrete
// problem yet, this will be done in the main loop.
ParBilinearForm a(&fespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
if (pa)
{
a.SetAssemblyLevel(AssemblyLevel::PARTIAL);
a.SetDiagonalPolicy(Operator::DIAG_ONE);
}
ParLinearForm b(&fespace);
ConstantCoefficient one(1.0);
@@ -220,17 +224,26 @@ int main(int argc, char *argv[])
// 17. Solve the linear system A X = B.
// * With full assembly, use the BoomerAMG preconditioner from hypre.
// * With partial assembly, use no preconditioner, for now.
HypreBoomerAMG *amg = NULL;
if (!pa) { amg = new HypreBoomerAMG; amg->SetPrintLevel(0); }
// * With partial assembly, use a diagonal preconditioner.
Solver *M = NULL;
if (pa)
{
M = new OperatorJacobiSmoother(a, ess_tdof_list);
}
else
{
HypreBoomerAMG *amg = new HypreBoomerAMG;
amg->SetPrintLevel(0);
M = amg;
}
CGSolver cg(MPI_COMM_WORLD);
cg.SetRelTol(1e-6);
cg.SetMaxIter(2000);
cg.SetPrintLevel(3); // print the first and the last iterations only
if (amg) { cg.SetPreconditioner(*amg); }
cg.SetPreconditioner(*M);
cg.SetOperator(*A);
cg.Mult(B, X);
delete amg;
delete M;
// 18. Switch back to the host and extract the parallel grid function
// corresponding to the finite element approximation X. This is the
+5
View File
@@ -119,6 +119,11 @@ ex11p-test-superlu: ex11p
@$(call mfem-test,$<, $(RUN_MPI), SuperLU_DIST example,--superlu)
test-par-YES: ex11p-test-superlu
endif
ifeq ($(MFEM_USE_MKL_CPARDISO),YES)
ex11p-test-superlu: ex11p
@$(call mfem-test,$<, $(RUN_MPI), MKL_CPARDISO example,--pardiso)
test-par-YES: ex11p-test-pardiso
endif
# Testing: "test" target and mfem-test* variables are defined in config/test.mk
+2 -37
View File
@@ -31,6 +31,7 @@ set(SRCS
bilininteg_vecmass.cpp
coefficient.cpp
complex_fem.cpp
convergence.cpp
datacollection.cpp
eltrans.cpp
estimators.cpp
@@ -50,43 +51,10 @@ set(SRCS
fespacehierarchy.cpp
nonlininteg_vectorconvection.cpp
quadinterpolator.cpp
quadinterpolator_det.cpp
quadinterpolator_eval_by_nodes.cpp
quadinterpolator_eval_by_vdim.cpp
quadinterpolator_grad_by_nodes.cpp
quadinterpolator_grad_by_vdim.cpp
quadinterpolator_grad_phys_by_nodes.cpp
quadinterpolator_grad_phys_by_vdim.cpp
quadinterpolator_face.cpp
restriction.cpp
staticcond.cpp
tmop.cpp
tmop_pa.cpp
tmop_pa_h2d.cpp
tmop_pa_h2d_c0.cpp
tmop_pa_h2m.cpp
tmop_pa_h2m_c0.cpp
tmop_pa_h2s.cpp
tmop_pa_h2s_c0.cpp
tmop_pa_h3d.cpp
tmop_pa_h3d_c0.cpp
tmop_pa_h3m.cpp
tmop_pa_h3m_c0.cpp
tmop_pa_h3s.cpp
tmop_pa_h3s_c0.cpp
tmop_pa_jp2.cpp
tmop_pa_jp3.cpp
tmop_pa_jt2_tc.cpp
tmop_pa_jt3_datc.cpp
tmop_pa_jt3_tc.cpp
tmop_pa_p2.cpp
tmop_pa_p2_c0.cpp
tmop_pa_p3.cpp
tmop_pa_p3_c0.cpp
tmop_pa_w2.cpp
tmop_pa_w2_c0.cpp
tmop_pa_w3.cpp
tmop_pa_w3_c0.cpp
tmop_tools.cpp
gslib.cpp
transfer.cpp
@@ -98,6 +66,7 @@ set(HDRS
bilininteg.hpp
coefficient.hpp
complex_fem.hpp
convergence.hpp
datacollection.hpp
eltrans.hpp
estimators.hpp
@@ -116,10 +85,7 @@ set(HDRS
nonlinearform_ext.hpp
nonlininteg.hpp
quadinterpolator.hpp
quadinterpolator_eval.hpp
quadinterpolator_face.hpp
quadinterpolator_grad.hpp
quadinterpolator_grad_phys.hpp
restriction.hpp
fespacehierarchy.hpp
staticcond.hpp
@@ -132,7 +98,6 @@ set(HDRS
tfespace.hpp
tintrules.hpp
tmop.hpp
tmop_pa.hpp
tmop_tools.hpp
gslib.hpp
transfer.hpp
+27
View File
@@ -627,6 +627,33 @@ void BilinearForm::AssembleDiagonal(Vector &diag) const
MFEM_ASSERT(diag.Size() == fes->GetTrueVSize(),
"Vector for holding diagonal has wrong size!");
const Operator *P = fes->GetProlongationMatrix();
// For an AMR mesh, a convergent diagonal is assembled with |P^T| d_e,
// where |P^T| has the entry-wise absolute values of the conforming
// prolongation transpose operator.
if (P && !fes->Conforming())
{
Vector local_diag(P->Height());
ext->AssembleDiagonal(local_diag);
const SparseMatrix *SP = dynamic_cast<const SparseMatrix*>(P);
#ifdef MFEM_USE_MPI
const HypreParMatrix *HP = dynamic_cast<const HypreParMatrix*>(P);
#endif
if (SP)
{
SP->AbsMultTranspose(local_diag, diag);
}
#ifdef MFEM_USE_MPI
else if (HP)
{
HP->AbsMultTranspose(1.0, local_diag, 0.0, diag);
}
#endif
else
{
MFEM_ABORT("Prolongation matrix has unexpected type.");
}
return;
}
if (!IsIdentityProlongation(P))
{
Vector local_diag(P->Height());
+16 -6
View File
@@ -96,6 +96,9 @@ void PABilinearFormExtension::Assemble()
integrators[i]->AssemblePA(*a->FESpace());
}
MFEM_VERIFY(a->GetBBFI()->Size() == 0,
"Partial assembly does not support AddBoundaryIntegrator yet.");
Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
const int intFaceIntegratorCount = intFaceIntegrators.Size();
for (int i = 0; i < intFaceIntegratorCount; ++i)
@@ -307,19 +310,21 @@ void EABilinearFormExtension::Assemble()
ea_data.SetSize(ne*elemDofs*elemDofs, Device::GetMemoryType());
ea_data.UseDevice(true);
ea_data = 0.0;
Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
const int integratorCount = integrators.Size();
for (int i = 0; i < integratorCount; ++i)
{
integrators[i]->AssembleEA(*a->FESpace(), ea_data);
integrators[i]->AssembleEA(*a->FESpace(), ea_data, i);
}
faceDofs = trialFes ->
GetTraceElement(0, trialFes->GetMesh()->GetFaceBaseGeometry(0)) ->
GetDof();
MFEM_VERIFY(a->GetBBFI()->Size() == 0,
"Element assembly does not support AddBoundaryIntegrator yet.");
Array<BilinearFormIntegrator*> &intFaceIntegrators = *a->GetFBFI();
const int intFaceIntegratorCount = intFaceIntegrators.Size();
if (intFaceIntegratorCount>0)
@@ -327,14 +332,13 @@ void EABilinearFormExtension::Assemble()
nf_int = trialFes->GetNFbyType(FaceType::Interior);
ea_data_int.SetSize(2*nf_int*faceDofs*faceDofs, Device::GetMemoryType());
ea_data_ext.SetSize(2*nf_int*faceDofs*faceDofs, Device::GetMemoryType());
ea_data_int = 0.0;
ea_data_ext = 0.0;
}
for (int i = 0; i < intFaceIntegratorCount; ++i)
{
intFaceIntegrators[i]->AssembleEAInteriorFaces(*a->FESpace(),
ea_data_int,
ea_data_ext);
ea_data_ext,
i);
}
Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
@@ -347,7 +351,7 @@ void EABilinearFormExtension::Assemble()
}
for (int i = 0; i < boundFaceIntegratorCount; ++i)
{
bdrFaceIntegrators[i]->AssembleEABoundaryFaces(*a->FESpace(),ea_data_bdr);
bdrFaceIntegrators[i]->AssembleEABoundaryFaces(*a->FESpace(),ea_data_bdr,i);
}
if (factorize_face_terms && int_face_restrict_lex)
@@ -794,6 +798,12 @@ void PAMixedBilinearFormExtension::Assemble()
{
integrators[i]->AssemblePA(*trialFes, *testFes);
}
MFEM_VERIFY(a->GetBBFI()->Size() == 0,
"Partial assembly does not support AddBoundaryIntegrator yet.");
MFEM_VERIFY(a->GetTFBFI()->Size() == 0,
"Partial assembly does not support AddTraceFaceIntegrator yet.");
MFEM_VERIFY(a->GetBTFBFI()->Size() == 0,
"Partial assembly does not support AddBdrTraceFaceIntegrator yet.");
}
void PAMixedBilinearFormExtension::Update()
+14 -3
View File
@@ -52,7 +52,8 @@ void BilinearFormIntegrator::AssembleDiagonalPA(Vector &)
}
void BilinearFormIntegrator::AssembleEA(const FiniteElementSpace &fes,
Vector &emat)
Vector &emat,
const bool add)
{
mfem_error ("BilinearFormIntegrator::AssembleEA(...)\n"
" is not implemented for this class.");
@@ -61,7 +62,8 @@ void BilinearFormIntegrator::AssembleEA(const FiniteElementSpace &fes,
void BilinearFormIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace
&fes,
Vector &ea_data_int,
Vector &ea_data_ext)
Vector &ea_data_ext,
const bool add)
{
mfem_error ("BilinearFormIntegrator::AssembleEAInteriorFaces(...)\n"
" is not implemented for this class.");
@@ -69,7 +71,8 @@ void BilinearFormIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace
void BilinearFormIntegrator::AssembleEABoundaryFaces(const FiniteElementSpace
&fes,
Vector &ea_data_bdr)
Vector &ea_data_bdr,
const bool add)
{
mfem_error ("BilinearFormIntegrator::AssembleEABoundaryFaces(...)\n"
" is not implemented for this class.");
@@ -1522,6 +1525,7 @@ void CurlCurlIntegrator::AssembleElementMatrix
double w;
#ifdef MFEM_THREAD_SAFE
Vector D;
DenseMatrix curlshape(nd,dimc), curlshape_dFt(nd,dimc), M;
#else
curlshape.SetSize(nd,dimc);
@@ -1529,6 +1533,7 @@ void CurlCurlIntegrator::AssembleElementMatrix
#endif
elmat.SetSize(nd);
if (MQ) { M.SetSize(dimc); }
if (DQ) { D.SetSize(dimc); }
const IntegrationRule *ir = IntRule;
if (ir == NULL)
@@ -1572,6 +1577,12 @@ void CurlCurlIntegrator::AssembleElementMatrix
Mult(curlshape_dFt, M, curlshape);
AddMultABt(curlshape, curlshape_dFt, elmat);
}
else if (DQ)
{
DQ->Eval(D, Trans, ip);
D *= w;
AddMultADAt(curlshape_dFt, D, elmat);
}
else if (Q)
{
w *= Q->Eval(Trans, ip);
+47 -17
View File
@@ -20,6 +20,13 @@
namespace mfem
{
// Local maximum size of dofs and quads in 1D
constexpr int HCURL_MAX_D1D = 5;
constexpr int HCURL_MAX_Q1D = 6;
constexpr int HDIV_MAX_D1D = 5;
constexpr int HDIV_MAX_Q1D = 6;
/// Abstract base class BilinearFormIntegrator
class BilinearFormIntegrator : public NonlinearFormIntegrator
{
@@ -79,9 +86,10 @@ public:
virtual void AddMultTransposePA(const Vector &x, Vector &y) const;
/// Method defining element assembly.
/** The result of the element assembly is added and stored in the @a emat
Vector. */
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat);
/** The result of the element assembly is added to the @a emat Vector if
@a add is true. Otherwise, if @a add is false, we set @a emat. */
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat,
const bool add = true);
/** Used with BilinearFormIntegrators that have different spaces. */
// virtual void AssembleEA(const FiniteElementSpace &trial_fes,
// const FiniteElementSpace &test_fes,
@@ -89,10 +97,12 @@ public:
virtual void AssembleEAInteriorFaces(const FiniteElementSpace &fes,
Vector &ea_data_int,
Vector &ea_data_ext);
Vector &ea_data_ext,
const bool add = true);
virtual void AssembleEABoundaryFaces(const FiniteElementSpace &fes,
Vector &ea_data_bdr);
Vector &ea_data_bdr,
const bool add = true);
/// Given a particular Finite Element computes the element matrix elmat.
virtual void AssembleElementMatrix(const FiniteElement &el,
@@ -255,14 +265,17 @@ public:
bfi->AddMultTransposePA(x, y);
}
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat);
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat,
const bool add);
virtual void AssembleEAInteriorFaces(const FiniteElementSpace &fes,
Vector &ea_data_int,
Vector &ea_data_ext);
Vector &ea_data_ext,
const bool add);
virtual void AssembleEABoundaryFaces(const FiniteElementSpace &fes,
Vector &ea_data_bdr);
Vector &ea_data_bdr,
const bool add);
virtual ~TransposeIntegrator() { if (own_bfi) { delete bfi; } }
};
@@ -1945,7 +1958,8 @@ public:
virtual void AssemblePA(const FiniteElementSpace &fes);
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat);
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat,
const bool add);
virtual void AssembleDiagonalPA(Vector &diag);
@@ -2020,7 +2034,8 @@ public:
virtual void AssemblePA(const FiniteElementSpace &fes);
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat);
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat,
const bool add);
virtual void AssembleDiagonalPA(Vector &diag);
@@ -2076,7 +2091,8 @@ public:
virtual void AssemblePA(const FiniteElementSpace&);
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat);
virtual void AssembleEA(const FiniteElementSpace &fes, Vector &emat,
const bool add);
virtual void AddMultPA(const Vector&, Vector&) const;
@@ -2293,12 +2309,14 @@ class CurlCurlIntegrator: public BilinearFormIntegrator
private:
Vector vec, pointflux;
#ifndef MFEM_THREAD_SAFE
Vector D;
DenseMatrix curlshape, curlshape_dFt, M;
DenseMatrix vshape, projcurl;
#endif
protected:
Coefficient *Q;
VectorCoefficient *DQ;
MatrixCoefficient *MQ;
// PA extension
@@ -2307,12 +2325,17 @@ protected:
const DofToQuad *mapsC; ///< Not owned. DOF-to-quad map, closed.
const GeometricFactors *geom; ///< Not owned
int dim, ne, nq, dofs1D, quad1D;
bool symmetric = true; ///< False if using a nonsymmetric matrix coefficient
public:
CurlCurlIntegrator() { Q = NULL; MQ = NULL; }
CurlCurlIntegrator() { Q = NULL; DQ = NULL; MQ = NULL; }
/// Construct a bilinear form integrator for Nedelec elements
CurlCurlIntegrator(Coefficient &q) : Q(&q) { MQ = NULL; }
CurlCurlIntegrator(MatrixCoefficient &m) : MQ(&m) { Q = NULL; }
CurlCurlIntegrator(Coefficient &q, const IntegrationRule *ir = NULL) :
BilinearFormIntegrator(ir), Q(&q) { DQ = NULL; MQ = NULL; }
CurlCurlIntegrator(VectorCoefficient &dq, const IntegrationRule *ir = NULL) :
BilinearFormIntegrator(ir), DQ(&dq) { Q = NULL; MQ = NULL; }
CurlCurlIntegrator(MatrixCoefficient &mq, const IntegrationRule *ir = NULL) :
BilinearFormIntegrator(ir), MQ(&mq) { Q = NULL; DQ = NULL; }
/* Given a particular Finite Element, compute the
element curl-curl matrix elmat */
@@ -2390,8 +2413,11 @@ protected:
Vector pa_data;
const DofToQuad *mapsO; ///< Not owned. DOF-to-quad map, open.
const DofToQuad *mapsC; ///< Not owned. DOF-to-quad map, closed.
const DofToQuad *mapsOtest; ///< Not owned. DOF-to-quad map, open.
const DofToQuad *mapsCtest; ///< Not owned. DOF-to-quad map, closed.
const GeometricFactors *geom; ///< Not owned
int dim, ne, nq, dofs1D, quad1D, fetype;
int dim, ne, nq, dofs1D, dofs1Dtest, quad1D, trial_fetype, test_fetype;
bool symmetric = true; ///< False if using a nonsymmetric matrix coefficient
public:
VectorFEMassIntegrator() { Init(NULL, NULL, NULL); }
@@ -2412,6 +2438,8 @@ public:
using BilinearFormIntegrator::AssemblePA;
virtual void AssemblePA(const FiniteElementSpace &fes);
virtual void AssemblePA(const FiniteElementSpace &trial_fes,
const FiniteElementSpace &test_fes);
virtual void AddMultPA(const Vector &x, Vector &y) const;
virtual void AssembleDiagonalPA(Vector& diag);
};
@@ -2641,10 +2669,12 @@ public:
virtual void AssembleEAInteriorFaces(const FiniteElementSpace& fes,
Vector &ea_data_int,
Vector &ea_data_ext);
Vector &ea_data_ext,
const bool add);
virtual void AssembleEABoundaryFaces(const FiniteElementSpace& fes,
Vector &ea_data_bdr);
Vector &ea_data_bdr,
const bool add);
static const IntegrationRule &GetRule(Geometry::Type geom, int order,
FaceElementTransformations &T);
+58 -30
View File
@@ -22,6 +22,7 @@ static void EAConvectionAssemble1D(const int NE,
const Array<double> &g,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -54,7 +55,14 @@ static void EAConvectionAssemble1D(const int NE,
{
val += r_Bj[k1] * D(k1, e) * r_Gi[k1];
}
A(i1, j1, e) += val;
if (add)
{
A(i1, j1, e) += val;
}
else
{
A(i1, j1, e) = val;
}
}
}
});
@@ -66,6 +74,7 @@ static void EAConvectionAssemble2D(const int NE,
const Array<double> &g,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -121,7 +130,14 @@ static void EAConvectionAssemble2D(const int NE,
* r_B[k1][j1]* r_B[k2][j2];
}
}
A(i1, i2, j1, j2, e) += val;
if (add)
{
A(i1, i2, j1, j2, e) += val;
}
else
{
A(i1, i2, j1, j2, e) = val;
}
}
}
}
@@ -135,6 +151,7 @@ static void EAConvectionAssemble3D(const int NE,
const Array<double> &g,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -191,7 +208,14 @@ static void EAConvectionAssemble3D(const int NE,
}
}
}
A(i1, i2, i3, j1, j2, j3, e) += val;
if (add)
{
A(i1, i2, i3, j1, j2, j3, e) += val;
}
else
{
A(i1, i2, i3, j1, j2, j3, e) = val;
}
}
}
}
@@ -202,7 +226,8 @@ static void EAConvectionAssemble3D(const int NE,
}
void ConvectionIntegrator::AssembleEA(const FiniteElementSpace &fes,
Vector &ea_data)
Vector &ea_data,
const bool add)
{
AssemblePA(fes);
const int ne = fes.GetMesh()->GetNE();
@@ -212,44 +237,47 @@ void ConvectionIntegrator::AssembleEA(const FiniteElementSpace &fes,
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x22: return EAConvectionAssemble1D<2,2>(ne,B,G,pa_data,ea_data);
case 0x33: return EAConvectionAssemble1D<3,3>(ne,B,G,pa_data,ea_data);
case 0x44: return EAConvectionAssemble1D<4,4>(ne,B,G,pa_data,ea_data);
case 0x55: return EAConvectionAssemble1D<5,5>(ne,B,G,pa_data,ea_data);
case 0x66: return EAConvectionAssemble1D<6,6>(ne,B,G,pa_data,ea_data);
case 0x77: return EAConvectionAssemble1D<7,7>(ne,B,G,pa_data,ea_data);
case 0x88: return EAConvectionAssemble1D<8,8>(ne,B,G,pa_data,ea_data);
case 0x99: return EAConvectionAssemble1D<9,9>(ne,B,G,pa_data,ea_data);
default: return EAConvectionAssemble1D(ne,B,G,pa_data,ea_data,dofs1D,quad1D);
case 0x22: return EAConvectionAssemble1D<2,2>(ne,B,G,pa_data,ea_data,add);
case 0x33: return EAConvectionAssemble1D<3,3>(ne,B,G,pa_data,ea_data,add);
case 0x44: return EAConvectionAssemble1D<4,4>(ne,B,G,pa_data,ea_data,add);
case 0x55: return EAConvectionAssemble1D<5,5>(ne,B,G,pa_data,ea_data,add);
case 0x66: return EAConvectionAssemble1D<6,6>(ne,B,G,pa_data,ea_data,add);
case 0x77: return EAConvectionAssemble1D<7,7>(ne,B,G,pa_data,ea_data,add);
case 0x88: return EAConvectionAssemble1D<8,8>(ne,B,G,pa_data,ea_data,add);
case 0x99: return EAConvectionAssemble1D<9,9>(ne,B,G,pa_data,ea_data,add);
default: return EAConvectionAssemble1D(ne,B,G,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
else if (dim == 2)
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x22: return EAConvectionAssemble2D<2,2>(ne,B,G,pa_data,ea_data);
case 0x33: return EAConvectionAssemble2D<3,3>(ne,B,G,pa_data,ea_data);
case 0x44: return EAConvectionAssemble2D<4,4>(ne,B,G,pa_data,ea_data);
case 0x55: return EAConvectionAssemble2D<5,5>(ne,B,G,pa_data,ea_data);
case 0x66: return EAConvectionAssemble2D<6,6>(ne,B,G,pa_data,ea_data);
case 0x77: return EAConvectionAssemble2D<7,7>(ne,B,G,pa_data,ea_data);
case 0x88: return EAConvectionAssemble2D<8,8>(ne,B,G,pa_data,ea_data);
case 0x99: return EAConvectionAssemble2D<9,9>(ne,B,G,pa_data,ea_data);
default: return EAConvectionAssemble2D(ne,B,G,pa_data,ea_data,dofs1D,quad1D);
case 0x22: return EAConvectionAssemble2D<2,2>(ne,B,G,pa_data,ea_data,add);
case 0x33: return EAConvectionAssemble2D<3,3>(ne,B,G,pa_data,ea_data,add);
case 0x44: return EAConvectionAssemble2D<4,4>(ne,B,G,pa_data,ea_data,add);
case 0x55: return EAConvectionAssemble2D<5,5>(ne,B,G,pa_data,ea_data,add);
case 0x66: return EAConvectionAssemble2D<6,6>(ne,B,G,pa_data,ea_data,add);
case 0x77: return EAConvectionAssemble2D<7,7>(ne,B,G,pa_data,ea_data,add);
case 0x88: return EAConvectionAssemble2D<8,8>(ne,B,G,pa_data,ea_data,add);
case 0x99: return EAConvectionAssemble2D<9,9>(ne,B,G,pa_data,ea_data,add);
default: return EAConvectionAssemble2D(ne,B,G,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
else if (dim == 3)
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x23: return EAConvectionAssemble3D<2,3>(ne,B,G,pa_data,ea_data);
case 0x34: return EAConvectionAssemble3D<3,4>(ne,B,G,pa_data,ea_data);
case 0x45: return EAConvectionAssemble3D<4,5>(ne,B,G,pa_data,ea_data);
case 0x56: return EAConvectionAssemble3D<5,6>(ne,B,G,pa_data,ea_data);
case 0x67: return EAConvectionAssemble3D<6,7>(ne,B,G,pa_data,ea_data);
case 0x78: return EAConvectionAssemble3D<7,8>(ne,B,G,pa_data,ea_data);
case 0x89: return EAConvectionAssemble3D<8,9>(ne,B,G,pa_data,ea_data);
default: return EAConvectionAssemble3D(ne,B,G,pa_data,ea_data,dofs1D,quad1D);
case 0x23: return EAConvectionAssemble3D<2,3>(ne,B,G,pa_data,ea_data,add);
case 0x34: return EAConvectionAssemble3D<3,4>(ne,B,G,pa_data,ea_data,add);
case 0x45: return EAConvectionAssemble3D<4,5>(ne,B,G,pa_data,ea_data,add);
case 0x56: return EAConvectionAssemble3D<5,6>(ne,B,G,pa_data,ea_data,add);
case 0x67: return EAConvectionAssemble3D<6,7>(ne,B,G,pa_data,ea_data,add);
case 0x78: return EAConvectionAssemble3D<7,8>(ne,B,G,pa_data,ea_data,add);
case 0x89: return EAConvectionAssemble3D<8,9>(ne,B,G,pa_data,ea_data,add);
default: return EAConvectionAssemble3D(ne,B,G,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
MFEM_ABORT("Unknown kernel.");
+73 -275
View File
@@ -13,10 +13,6 @@
#include "bilininteg.hpp"
#include "gridfunc.hpp"
#include "restriction.hpp"
#include "tmop_pa.hpp"
#include "../linalg/kernels.hpp"
using namespace std;
namespace mfem
@@ -72,53 +68,47 @@ static void PAConvectionSetup3D(const int Q1D,
const double alpha,
Vector &op)
{
const auto W = Reshape(w.Read(), Q1D,Q1D,Q1D);
const auto J = Reshape(j.Read(), Q1D,Q1D,Q1D,3,3,NE);
const int NQ = Q1D*Q1D*Q1D;
auto W = w.Read();
auto J = Reshape(j.Read(), NQ, 3, 3, NE);
const bool const_v = vel.Size() == 3;
const auto V = const_v ?
Reshape(vel.Read(), 3,1,1,1,1) :
Reshape(vel.Read(), 3,Q1D,Q1D,Q1D,NE);
auto y = Reshape(op.Write(), Q1D,Q1D,Q1D,3,NE);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
auto V =
const_v ? Reshape(vel.Read(), 3,1,1) : Reshape(vel.Read(), 3,NQ,NE);
auto y = Reshape(op.Write(), NQ, 3, NE);
MFEM_FORALL(e, NE,
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
for (int q = 0; q < NQ; ++q)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
const double J11 = J(qx,qy,qz,0,0,e);
const double J12 = J(qx,qy,qz,0,1,e);
const double J13 = J(qx,qy,qz,0,2,e);
const double J21 = J(qx,qy,qz,1,0,e);
const double J22 = J(qx,qy,qz,1,1,e);
const double J23 = J(qx,qy,qz,1,2,e);
const double J31 = J(qx,qy,qz,2,0,e);
const double J32 = J(qx,qy,qz,2,1,e);
const double J33 = J(qx,qy,qz,2,2,e);
const double w = alpha * W(qx,qy,qz);
const double v0 = const_v ? V(0,0,0,0,0) : V(0,qx,qy,qz,e);
const double v1 = const_v ? V(1,0,0,0,0) : V(1,qx,qy,qz,e);
const double v2 = const_v ? V(2,0,0,0,0) : V(2,qx,qy,qz,e);
const double wx = w * v0;
const double wy = w * v1;
const double wz = w * v2;
// adj(J)
const double A11 = (J22 * J33) - (J23 * J32);
const double A12 = (J32 * J13) - (J12 * J33);
const double A13 = (J12 * J23) - (J22 * J13);
const double A21 = (J31 * J23) - (J21 * J33);
const double A22 = (J11 * J33) - (J13 * J31);
const double A23 = (J21 * J13) - (J11 * J23);
const double A31 = (J21 * J32) - (J31 * J22);
const double A32 = (J31 * J12) - (J11 * J32);
const double A33 = (J11 * J22) - (J12 * J21);
// q . J^{-1} = q . adj(J)
y(qx,qy,qz,0,e) = wx * A11 + wy * A12 + wz * A13;
y(qx,qy,qz,1,e) = wx * A21 + wy * A22 + wz * A23;
y(qx,qy,qz,2,e) = wx * A31 + wy * A32 + wz * A33;
}
}
const double J11 = J(q,0,0,e);
const double J21 = J(q,1,0,e);
const double J31 = J(q,2,0,e);
const double J12 = J(q,0,1,e);
const double J22 = J(q,1,1,e);
const double J32 = J(q,2,1,e);
const double J13 = J(q,0,2,e);
const double J23 = J(q,1,2,e);
const double J33 = J(q,2,2,e);
const double w = alpha * W[q];
const double v0 = const_v ? V(0,0,0) : V(0,q,e);
const double v1 = const_v ? V(1,0,0) : V(1,q,e);
const double v2 = const_v ? V(2,0,0) : V(2,q,e);
const double wx = w * v0;
const double wy = w * v1;
const double wz = w * v2;
// adj(J)
const double A11 = (J22 * J33) - (J23 * J32);
const double A12 = (J32 * J13) - (J12 * J33);
const double A13 = (J12 * J23) - (J22 * J13);
const double A21 = (J31 * J23) - (J21 * J33);
const double A22 = (J11 * J33) - (J13 * J31);
const double A23 = (J21 * J13) - (J11 * J23);
const double A31 = (J21 * J32) - (J31 * J22);
const double A32 = (J31 * J12) - (J11 * J32);
const double A33 = (J11 * J22) - (J12 * J21);
// q . J^{-1} = q . adj(J)
y(q,0,e) = wx * A11 + wy * A12 + wz * A13;
y(q,1,e) = wx * A21 + wy * A22 + wz * A23;
y(q,2,e) = wx * A31 + wy * A32 + wz * A33;
}
});
}
@@ -194,8 +184,8 @@ void PAConvectionApply2D(const int ne,
Gu[dy][qx] = 0.0;
for (int dx = 0; dx < D1D; ++dx)
{
const double bx = B(qx,dx);
const double gx = G(qx,dx);
const double bx = B(qx,dx);
const double gx = G(qx,dx);
const double x = u[dy][dx];
Bu[dy][qx] += bx * x;
Gu[dy][qx] += gx * x;
@@ -212,8 +202,8 @@ void PAConvectionApply2D(const int ne,
BGu[qy][qx] = 0.0;
for (int dy = 0; dy < D1D; ++dy)
{
const double bx = B(qy,dy);
const double gx = G(qy,dy);
const double bx = B(qy,dy);
const double gx = G(qy,dy);
GBu[qy][qx] += gx * Bu[dy][qx];
BGu[qy][qx] += bx * Gu[dy][qx];
}
@@ -242,7 +232,7 @@ void PAConvectionApply2D(const int ne,
BDGu[dy][qx] = 0.0;
for (int qy = 0; qy < Q1D; ++qy)
{
const double w = Bt(dy,qy);
const double w = Bt(dy,qy);
BDGu[dy][qx] += w * DGu[qy][qx];
}
}
@@ -254,7 +244,7 @@ void PAConvectionApply2D(const int ne,
double BBDGu = 0.0;
for (int qx = 0; qx < Q1D; ++qx)
{
const double w = Bt(dx,qx);
const double w = Bt(dx,qx);
BBDGu += w * BDGu[dy][qx];
}
y(dx,dy,e) += BBDGu;
@@ -320,7 +310,7 @@ void SmemPAConvectionApply2D(const int ne,
{
const double bx = B(qx,dx);
const double gx = G(qx,dx);
const double x = u[tidz][dy][dx];
const double x = u[tidz][dy][dx];
Bu[tidz][dy][qx] += bx * x;
Gu[tidz][dy][qx] += gx * x;
}
@@ -337,8 +327,8 @@ void SmemPAConvectionApply2D(const int ne,
BGu[tidz][qy][qx] = 0.0;
for (int dy = 0; dy < D1D; ++dy)
{
const double bx = B(qy,dy);
const double gx = G(qy,dy);
const double bx = B(qy,dy);
const double gx = G(qy,dy);
GBu[tidz][qy][qx] += gx * Bu[tidz][dy][qx];
BGu[tidz][qy][qx] += bx * Gu[tidz][dy][qx];
}
@@ -369,7 +359,7 @@ void SmemPAConvectionApply2D(const int ne,
BDGu[tidz][dy][qx] = 0.0;
for (int qy = 0; qy < Q1D; ++qy)
{
const double w = Bt(dy,qy);
const double w = Bt(dy,qy);
BDGu[tidz][dy][qx] += w * DGu[tidz][qy][qx];
}
}
@@ -382,7 +372,7 @@ void SmemPAConvectionApply2D(const int ne,
double BBDGu = 0.0;
for (int qx = 0; qx < Q1D; ++qx)
{
const double w = Bt(dx,qx);
const double w = Bt(dx,qx);
BBDGu += w * BDGu[tidz][dy][qx];
}
y(dx,dy,e) += BBDGu;
@@ -446,8 +436,8 @@ void PAConvectionApply3D(const int ne,
Gu[dz][dy][qx] = 0.0;
for (int dx = 0; dx < D1D; ++dx)
{
const double bx = B(qx,dx);
const double gx = G(qx,dx);
const double bx = B(qx,dx);
const double gx = G(qx,dx);
const double x = u[dz][dy][dx];
Bu[dz][dy][qx] += bx * x;
Gu[dz][dy][qx] += gx * x;
@@ -469,8 +459,8 @@ void PAConvectionApply3D(const int ne,
BGu[dz][qy][qx] = 0.0;
for (int dy = 0; dy < D1D; ++dy)
{
const double bx = B(qy,dy);
const double gx = G(qy,dy);
const double bx = B(qy,dy);
const double gx = G(qy,dy);
BBu[dz][qy][qx] += bx * Bu[dz][dy][qx];
GBu[dz][qy][qx] += gx * Bu[dz][dy][qx];
BGu[dz][qy][qx] += bx * Gu[dz][dy][qx];
@@ -492,8 +482,8 @@ void PAConvectionApply3D(const int ne,
BBGu[qz][qy][qx] = 0.0;
for (int dz = 0; dz < D1D; ++dz)
{
const double bx = B(qz,dz);
const double gx = G(qz,dz);
const double bx = B(qz,dz);
const double gx = G(qz,dz);
GBBu[qz][qy][qx] += gx * BBu[dz][qy][qx];
BGBu[qz][qy][qx] += bx * GBu[dz][qy][qx];
BBGu[qz][qy][qx] += bx * BGu[dz][qy][qx];
@@ -531,7 +521,7 @@ void PAConvectionApply3D(const int ne,
BDGu[dz][qy][qx] = 0.0;
for (int qz = 0; qz < Q1D; ++qz)
{
const double w = Bt(dz,qz);
const double w = Bt(dz,qz);
BDGu[dz][qy][qx] += w * DGu[qz][qy][qx];
}
}
@@ -547,7 +537,7 @@ void PAConvectionApply3D(const int ne,
BBDGu[dz][dy][qx] = 0.0;
for (int qy = 0; qy < Q1D; ++qy)
{
const double w = Bt(dy,qy);
const double w = Bt(dy,qy);
BBDGu[dz][dy][qx] += w * BDGu[dz][qy][qx];
}
}
@@ -562,7 +552,7 @@ void PAConvectionApply3D(const int ne,
double BBBDGu = 0.0;
for (int qx = 0; qx < Q1D; ++qx)
{
const double w = Bt(dx,qx);
const double w = Bt(dx,qx);
BBBDGu += w * BBDGu[dz][dy][qx];
}
y(dx,dy,dz,e) += BBBDGu;
@@ -635,8 +625,8 @@ void SmemPAConvectionApply3D(const int ne,
double Gu_ = 0.0;
for (int dx = 0; dx < D1D; ++dx)
{
const double bx = B(qx,dx);
const double gx = G(qx,dx);
const double bx = B(qx,dx);
const double gx = G(qx,dx);
const double x = u[dz][dy][dx];
Bu_ += bx * x;
Gu_ += gx * x;
@@ -661,8 +651,8 @@ void SmemPAConvectionApply3D(const int ne,
double BGu_ = 0.0;
for (int dy = 0; dy < D1D; ++dy)
{
const double bx = B(qy,dy);
const double gx = G(qy,dy);
const double bx = B(qy,dy);
const double gx = G(qy,dy);
BBu_ += bx * Bu[dz][dy][qx];
GBu_ += gx * Bu[dz][dy][qx];
BGu_ += bx * Gu[dz][dy][qx];
@@ -688,8 +678,8 @@ void SmemPAConvectionApply3D(const int ne,
double BBGu_ = 0.0;
for (int dz = 0; dz < D1D; ++dz)
{
const double bx = B(qz,dz);
const double gx = G(qz,dz);
const double bx = B(qz,dz);
const double gx = G(qz,dz);
GBBu_ += gx * BBu[dz][qy][qx];
BGBu_ += bx * GBu[dz][qy][qx];
BBGu_ += bx * BGu[dz][qy][qx];
@@ -731,7 +721,7 @@ void SmemPAConvectionApply3D(const int ne,
double BDGu_ = 0.0;
for (int qz = 0; qz < Q1D; ++qz)
{
const double w = Bt(dz,qz);
const double w = Bt(dz,qz);
BDGu_ += w * DGu[qz][qy][qx];
}
BDGu[dz][qy][qx] = BDGu_;
@@ -749,7 +739,7 @@ void SmemPAConvectionApply3D(const int ne,
double BBDGu_ = 0.0;
for (int qy = 0; qy < Q1D; ++qy)
{
const double w = Bt(dy,qy);
const double w = Bt(dy,qy);
BBDGu_ += w * BDGu[dz][qy][qx];
}
BBDGu[dz][dy][qx] = BBDGu_;
@@ -766,7 +756,7 @@ void SmemPAConvectionApply3D(const int ne,
double BBBDGu = 0.0;
for (int qx = 0; qx < Q1D; ++qx)
{
const double w = Bt(dx,qx);
const double w = Bt(dx,qx);
BBBDGu += w * BBDGu[dz][dy][qx];
}
y(dx,dy,dz,e) = BBBDGu;
@@ -776,117 +766,6 @@ void SmemPAConvectionApply3D(const int ne,
});
}
template<int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0, int T_MAX = 0>
static void QEvalVGF2D(const int NE,
const double *b_,
const double *x_,
double *y_,
const int vdim = 1,
const int d1d = 0,
const int q1d = 0)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
const auto b = Reshape(b_, Q1D, D1D);
const auto X = Reshape(x_, D1D, D1D, VDIM, NE);
auto C = Reshape(y_, VDIM, Q1D, Q1D, NE);
MFEM_FORALL_2D(e, NE, Q1D, Q1D, 1,
{
constexpr int NBZ = 1;
constexpr int MQ1 = T_Q1D ? T_Q1D : T_MAX;
constexpr int MD1 = T_D1D ? T_D1D : T_MAX;
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
MFEM_SHARED double B[MQ1*MD1];
mfem::kernels::LoadB<MD1,MQ1>(D1D,Q1D,b,B);
MFEM_SHARED double DD[NBZ][MD1*MD1];
MFEM_SHARED double DQ[NBZ][MD1*MQ1];
MFEM_SHARED double QQ[NBZ][MQ1*MQ1];
for (int c = 0; c < VDIM; c++)
{
mfem::kernels::LoadX<MD1,NBZ>(e,D1D,c,X,DD);
mfem::kernels::EvalX<MD1,MQ1,NBZ>(D1D,Q1D,B,DD,DQ);
mfem::kernels::EvalY<MD1,MQ1,NBZ>(D1D,Q1D,B,DQ,QQ);
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
double G;
mfem::kernels::PullEval<MQ1,NBZ>(qx,qy,QQ,G);
C(c,qx,qy,e) = G;
}
}
MFEM_SYNC_THREAD;
}
});
}
template<int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0, int T_MAX = 0>
static void QEvalVGF3D(const int NE,
const double *b_,
const double *x_,
double *y_,
const int vdim = 1,
const int d1d = 0,
const int q1d = 0)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
const auto b = Reshape(b_, Q1D, D1D);
const auto X = Reshape(x_, D1D, D1D, D1D, VDIM, NE);
auto C = Reshape(y_, VDIM, Q1D, Q1D, Q1D, NE);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
constexpr int MQ1 = T_Q1D ? T_Q1D : T_MAX;
constexpr int MD1 = T_D1D ? T_D1D : T_MAX;
MFEM_SHARED double B[MQ1*MD1];
mfem::kernels::LoadB<MD1,MQ1>(D1D,Q1D,b,B);
MFEM_SHARED double DDD[MD1*MD1*MD1];
MFEM_SHARED double DDQ[MD1*MD1*MQ1];
MFEM_SHARED double DQQ[MD1*MQ1*MQ1];
MFEM_SHARED double QQQ[MQ1*MQ1*MQ1];
for (int c = 0; c < VDIM; c++)
{
mfem::kernels::LoadX<MD1>(e,D1D,c,X,DDD);
mfem::kernels::EvalX<MD1,MQ1>(D1D,Q1D,B,DDD,DDQ);
mfem::kernels::EvalY<MD1,MQ1>(D1D,Q1D,B,DDQ,DQQ);
mfem::kernels::EvalZ<MD1,MQ1>(D1D,Q1D,B,DQQ,QQQ);
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
double G;
mfem::kernels::PullEval<MQ1>(qx,qy,qz,QQQ,G);
C(c,qx,qy,qz,e) = G;
}
}
}
MFEM_SYNC_THREAD;
}
});
}
void ConvectionIntegrator::AssemblePA(const FiniteElementSpace &fes)
{
// Assumes tensor-product elements
@@ -899,90 +778,16 @@ void ConvectionIntegrator::AssemblePA(const FiniteElementSpace &fes)
const int nq = ir->GetNPoints();
dim = mesh->Dimension();
ne = fes.GetNE();
const DofToQuad::Mode mode = DofToQuad::TENSOR;
#ifdef MFEM_USE_UMPIRE
const MemoryType temp_type = Device::GetDeviceMemoryType() == MemoryType::DEVICE_UMPIRE
? MemoryType::DEVICE_UMPIRE_2 : Device::GetDeviceMemoryType();
#else
const MemoryType temp_type = Device::GetDeviceMemoryType();
#endif
geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS, mode, temp_type);
maps = &el.GetDofToQuad(*ir, mode);
geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS);
maps = &el.GetDofToQuad(*ir, DofToQuad::TENSOR);
dofs1D = maps->ndof;
quad1D = maps->nqpt;
pa_data.SetSize(symmDims * nq * ne, temp_type);
pa_data.SetSize(symmDims * nq * ne, Device::GetMemoryType());
Vector vel;
if (VectorConstantCoefficient *cQ =
dynamic_cast<VectorConstantCoefficient*>(Q))
if (VectorConstantCoefficient *cQ = dynamic_cast<VectorConstantCoefficient*>(Q))
{
vel = cQ->GetVec();
}
else if (VectorGridFunctionCoefficient *vgfQ =
dynamic_cast<VectorGridFunctionCoefficient*>(Q))
{
Vector xe;
vel.SetSize(dim * nq * ne, temp_type);
const GridFunction *gf = vgfQ->GetGridFunction();
const ElementDofOrdering ordering = ElementDofOrdering::LEXICOGRAPHIC;
const FiniteElementSpace &gf_fes = *gf->FESpace();
const int vdim = gf_fes.GetVDim();
const Operator *R = gf_fes.GetElementRestriction(ordering);
const FiniteElement &el_gf = *gf_fes.GetFE(0);
const DofToQuad *maps_gf = &el_gf.GetDofToQuad(*ir, mode);
const int D1D = maps_gf->ndof;
const int Q1D = maps_gf->nqpt;
MFEM_VERIFY(R,"");
MFEM_VERIFY(vdim == dim, "");
MFEM_VERIFY(dim==2 || dim==3,"");
xe.SetSize(R->Height(), Device::GetMemoryType());
xe.UseDevice(true);
R->Mult(*gf, xe);
const auto B = maps_gf->B.Read();
const auto x = xe.Read();
auto y = vel.Write();
const int id = (D1D << 4 ) | Q1D;
if (dim == 2)
{
switch (id)
{
case 0x22: QEvalVGF2D<2,2,2>(ne,B,x,y); break;
case 0x33: QEvalVGF2D<2,3,3>(ne,B,x,y); break;
case 0x34: QEvalVGF2D<2,3,4>(ne,B,x,y); break;
default:
{
constexpr int MAX_DQ = 8;
MFEM_VERIFY(D1D <= MAX_DQ, "");
MFEM_VERIFY(Q1D <= MAX_DQ, "");
QEvalVGF2D<0,0,0,MAX_DQ>(ne,B,x,y,vdim,D1D,Q1D);
}
}
}
if (dim == 3)
{
switch (id)
{
case 0x23: QEvalVGF3D<3,2,3>(ne,B,x,y); break;
case 0x34: QEvalVGF3D<3,3,4>(ne,B,x,y); break;
case 0x35: QEvalVGF3D<3,3,5>(ne,B,x,y); break;
case 0x46: QEvalVGF3D<3,4,6>(ne,B,x,y); break;
case 0x48: QEvalVGF3D<3,4,8>(ne,B,x,y); break;
default:
{
constexpr int MAX_DQ = 6;
MFEM_VERIFY(D1D <= MAX_DQ, "");
MFEM_VERIFY(Q1D <= MAX_DQ, "");
QEvalVGF3D<0,0,0,MAX_DQ>(ne,B,x,y,vdim,D1D,Q1D);
}
}
}
}
else if (VectorQuadratureFunctionCoefficient* cQ =
dynamic_cast<VectorQuadratureFunctionCoefficient*>(Q))
{
@@ -1036,12 +841,9 @@ static void PAConvectionApply(const int dim,
switch ((D1D << 4 ) | Q1D)
{
case 0x22: return SmemPAConvectionApply2D<2,2,8>(NE,B,G,Bt,Gt,op,x,y);
case 0x33: return SmemPAConvectionApply2D<3,3,4>(NE,B,G,Bt,Gt,op,x,y);
case 0x34: return SmemPAConvectionApply2D<3,4,4>(NE,B,G,Bt,Gt,op,x,y);
case 0x44: return SmemPAConvectionApply2D<4,4,4>(NE,B,G,Bt,Gt,op,x,y);
case 0x46: return SmemPAConvectionApply2D<4,6,4>(NE,B,G,Bt,Gt,op,x,y);
case 0x33: return SmemPAConvectionApply2D<3,3,3>(NE,B,G,Bt,Gt,op,x,y);
case 0x44: return SmemPAConvectionApply2D<4,4,2>(NE,B,G,Bt,Gt,op,x,y);
case 0x55: return SmemPAConvectionApply2D<5,5,2>(NE,B,G,Bt,Gt,op,x,y);
case 0x58: return SmemPAConvectionApply2D<5,8,2>(NE,B,G,Bt,Gt,op,x,y);
case 0x66: return SmemPAConvectionApply2D<6,6,1>(NE,B,G,Bt,Gt,op,x,y);
case 0x77: return SmemPAConvectionApply2D<7,7,1>(NE,B,G,Bt,Gt,op,x,y);
case 0x88: return SmemPAConvectionApply2D<8,8,1>(NE,B,G,Bt,Gt,op,x,y);
@@ -1054,12 +856,8 @@ static void PAConvectionApply(const int dim,
switch ((D1D << 4 ) | Q1D)
{
case 0x23: return SmemPAConvectionApply3D<2,3>(NE,B,G,Bt,Gt,op,x,y);
case 0x24: return SmemPAConvectionApply3D<2,4>(NE,B,G,Bt,Gt,op,x,y);
case 0x26: return SmemPAConvectionApply3D<2,6>(NE,B,G,Bt,Gt,op,x,y);
case 0x34: return SmemPAConvectionApply3D<3,4>(NE,B,G,Bt,Gt,op,x,y);
case 0x35: return SmemPAConvectionApply3D<3,5>(NE,B,G,Bt,Gt,op,x,y);
case 0x45: return SmemPAConvectionApply3D<4,5>(NE,B,G,Bt,Gt,op,x,y);
case 0x48: return SmemPAConvectionApply3D<4,8>(NE,B,G,Bt,Gt,op,x,y);
case 0x56: return SmemPAConvectionApply3D<5,6>(NE,B,G,Bt,Gt,op,x,y);
case 0x67: return SmemPAConvectionApply3D<6,7>(NE,B,G,Bt,Gt,op,x,y);
case 0x78: return SmemPAConvectionApply3D<7,8>(NE,B,G,Bt,Gt,op,x,y);
+114 -55
View File
@@ -20,7 +20,8 @@ static void EADGTraceAssemble1DInt(const int NF,
const Array<double> &basis,
const Vector &padata,
Vector &eadata_int,
Vector &eadata_ext)
Vector &eadata_ext,
const bool add)
{
auto D = Reshape(padata.Read(), 2, 2, NF);
auto A_int = Reshape(eadata_int.ReadWrite(), 2, NF);
@@ -32,23 +33,41 @@ static void EADGTraceAssemble1DInt(const int NF,
val_ext10 = D(1, 0, f);
val_ext01 = D(0, 1, f);
val_int1 = D(1, 1, f);
A_int(0, f) += val_int0;
A_int(1, f) += val_int1;
A_ext(0, f) += val_ext01;
A_ext(1, f) += val_ext10;
if (add)
{
A_int(0, f) += val_int0;
A_int(1, f) += val_int1;
A_ext(0, f) += val_ext01;
A_ext(1, f) += val_ext10;
}
else
{
A_int(0, f) = val_int0;
A_int(1, f) = val_int1;
A_ext(0, f) = val_ext01;
A_ext(1, f) = val_ext10;
}
});
}
static void EADGTraceAssemble1DBdr(const int NF,
const Array<double> &basis,
const Vector &padata,
Vector &eadata_bdr)
Vector &eadata_bdr,
const bool add)
{
auto D = Reshape(padata.Read(), 2, 2, NF);
auto A_bdr = Reshape(eadata_bdr.ReadWrite(), NF);
MFEM_FORALL(f, NF,
{
A_bdr(f) += D(0, 0, f);
if (add)
{
A_bdr(f) += D(0, 0, f);
}
else
{
A_bdr(f) = D(0, 0, f);
}
});
}
@@ -58,6 +77,7 @@ static void EADGTraceAssemble2DInt(const int NF,
const Vector &padata,
Vector &eadata_int,
Vector &eadata_ext,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -88,10 +108,20 @@ static void EADGTraceAssemble2DInt(const int NF,
val_ext10 += B(k1,i1) * B(k1,j1) * D(k1, 1, 0, f);
val_int1 += B(k1,i1) * B(k1,j1) * D(k1, 1, 1, f);
}
A_int(i1, j1, 0, f) += val_int0;
A_int(i1, j1, 1, f) += val_int1;
A_ext(i1, j1, 0, f) += val_ext01;
A_ext(i1, j1, 1, f) += val_ext10;
if (add)
{
A_int(i1, j1, 0, f) += val_int0;
A_int(i1, j1, 1, f) += val_int1;
A_ext(i1, j1, 0, f) += val_ext01;
A_ext(i1, j1, 1, f) += val_ext10;
}
else
{
A_int(i1, j1, 0, f) = val_int0;
A_int(i1, j1, 1, f) = val_int1;
A_ext(i1, j1, 0, f) = val_ext01;
A_ext(i1, j1, 1, f) = val_ext10;
}
}
}
});
@@ -102,6 +132,7 @@ static void EADGTraceAssemble2DBdr(const int NF,
const Array<double> &basis,
const Vector &padata,
Vector &eadata_bdr,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -125,7 +156,14 @@ static void EADGTraceAssemble2DBdr(const int NF,
{
val_bdr += B(k1,i1) * B(k1,j1) * D(k1, 0, 0, f);
}
A_bdr(i1, j1, f) += val_bdr;
if (add)
{
A_bdr(i1, j1, f) += val_bdr;
}
else
{
A_bdr(i1, j1, f) = val_bdr;
}
}
}
});
@@ -137,6 +175,7 @@ static void EADGTraceAssemble3DInt(const int NF,
const Vector &padata,
Vector &eadata_int,
Vector &eadata_ext,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -207,10 +246,20 @@ static void EADGTraceAssemble3DInt(const int NF,
* s_D[k1][k2][1][0];
}
}
A_int(i1, i2, j1, j2, 0, f) += val_int0;
A_int(i1, i2, j1, j2, 1, f) += val_int1;
A_ext(i1, i2, j1, j2, 0, f) += val_ext01;
A_ext(i1, i2, j1, j2, 1, f) += val_ext10;
if (add)
{
A_int(i1, i2, j1, j2, 0, f) += val_int0;
A_int(i1, i2, j1, j2, 1, f) += val_int1;
A_ext(i1, i2, j1, j2, 0, f) += val_ext01;
A_ext(i1, i2, j1, j2, 1, f) += val_ext10;
}
else
{
A_int(i1, i2, j1, j2, 0, f) = val_int0;
A_int(i1, i2, j1, j2, 1, f) = val_int1;
A_ext(i1, i2, j1, j2, 0, f) = val_ext01;
A_ext(i1, i2, j1, j2, 1, f) = val_ext10;
}
}
}
}
@@ -223,6 +272,7 @@ static void EADGTraceAssemble3DBdr(const int NF,
const Array<double> &basis,
const Vector &padata,
Vector &eadata_bdr,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -280,7 +330,14 @@ static void EADGTraceAssemble3DBdr(const int NF,
* s_D[k1][k2][0][0];
}
}
A_bdr(i1, i2, j1, j2, f) += val_bdr;
if (add)
{
A_bdr(i1, i2, j1, j2, f) += val_bdr;
}
else
{
A_bdr(i1, i2, j1, j2, f) = val_bdr;
}
}
}
}
@@ -290,7 +347,8 @@ static void EADGTraceAssemble3DBdr(const int NF,
void DGTraceIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace& fes,
Vector &ea_data_int,
Vector &ea_data_ext)
Vector &ea_data_ext,
const bool add)
{
SetupPA(fes, FaceType::Interior);
nf = fes.GetNFbyType(FaceType::Interior);
@@ -298,7 +356,7 @@ void DGTraceIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace& fes,
const Array<double> &B = maps->B;
if (dim == 1)
{
return EADGTraceAssemble1DInt(nf,B,pa_data,ea_data_int,ea_data_ext);
return EADGTraceAssemble1DInt(nf,B,pa_data,ea_data_int,ea_data_ext,add);
}
else if (dim == 2)
{
@@ -306,31 +364,31 @@ void DGTraceIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace& fes,
{
case 0x22:
return EADGTraceAssemble2DInt<2,2>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x33:
return EADGTraceAssemble2DInt<3,3>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x44:
return EADGTraceAssemble2DInt<4,4>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x55:
return EADGTraceAssemble2DInt<5,5>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x66:
return EADGTraceAssemble2DInt<6,6>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x77:
return EADGTraceAssemble2DInt<7,7>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x88:
return EADGTraceAssemble2DInt<8,8>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x99:
return EADGTraceAssemble2DInt<9,9>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
default:
return EADGTraceAssemble2DInt(nf,B,pa_data,ea_data_int,
ea_data_ext,dofs1D,quad1D);
ea_data_ext,add,dofs1D,quad1D);
}
}
else if (dim == 3)
@@ -339,35 +397,36 @@ void DGTraceIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace& fes,
{
case 0x23:
return EADGTraceAssemble3DInt<2,3>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x34:
return EADGTraceAssemble3DInt<3,4>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x45:
return EADGTraceAssemble3DInt<4,5>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x56:
return EADGTraceAssemble3DInt<5,6>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x67:
return EADGTraceAssemble3DInt<6,7>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x78:
return EADGTraceAssemble3DInt<7,8>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
case 0x89:
return EADGTraceAssemble3DInt<8,9>(nf,B,pa_data,ea_data_int,
ea_data_ext);
ea_data_ext,add);
default:
return EADGTraceAssemble3DInt(nf,B,pa_data,ea_data_int,
ea_data_ext,dofs1D,quad1D);
ea_data_ext,add,dofs1D,quad1D);
}
}
MFEM_ABORT("Unknown kernel.");
}
void DGTraceIntegrator::AssembleEABoundaryFaces(const FiniteElementSpace& fes,
Vector &ea_data_bdr)
Vector &ea_data_bdr,
const bool add)
{
SetupPA(fes, FaceType::Boundary);
nf = fes.GetNFbyType(FaceType::Boundary);
@@ -375,37 +434,37 @@ void DGTraceIntegrator::AssembleEABoundaryFaces(const FiniteElementSpace& fes,
const Array<double> &B = maps->B;
if (dim == 1)
{
return EADGTraceAssemble1DBdr(nf,B,pa_data,ea_data_bdr);
return EADGTraceAssemble1DBdr(nf,B,pa_data,ea_data_bdr,add);
}
else if (dim == 2)
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x22: return EADGTraceAssemble2DBdr<2,2>(nf,B,pa_data,ea_data_bdr);
case 0x33: return EADGTraceAssemble2DBdr<3,3>(nf,B,pa_data,ea_data_bdr);
case 0x44: return EADGTraceAssemble2DBdr<4,4>(nf,B,pa_data,ea_data_bdr);
case 0x55: return EADGTraceAssemble2DBdr<5,5>(nf,B,pa_data,ea_data_bdr);
case 0x66: return EADGTraceAssemble2DBdr<6,6>(nf,B,pa_data,ea_data_bdr);
case 0x77: return EADGTraceAssemble2DBdr<7,7>(nf,B,pa_data,ea_data_bdr);
case 0x88: return EADGTraceAssemble2DBdr<8,8>(nf,B,pa_data,ea_data_bdr);
case 0x99: return EADGTraceAssemble2DBdr<9,9>(nf,B,pa_data,ea_data_bdr);
case 0x22: return EADGTraceAssemble2DBdr<2,2>(nf,B,pa_data,ea_data_bdr,add);
case 0x33: return EADGTraceAssemble2DBdr<3,3>(nf,B,pa_data,ea_data_bdr,add);
case 0x44: return EADGTraceAssemble2DBdr<4,4>(nf,B,pa_data,ea_data_bdr,add);
case 0x55: return EADGTraceAssemble2DBdr<5,5>(nf,B,pa_data,ea_data_bdr,add);
case 0x66: return EADGTraceAssemble2DBdr<6,6>(nf,B,pa_data,ea_data_bdr,add);
case 0x77: return EADGTraceAssemble2DBdr<7,7>(nf,B,pa_data,ea_data_bdr,add);
case 0x88: return EADGTraceAssemble2DBdr<8,8>(nf,B,pa_data,ea_data_bdr,add);
case 0x99: return EADGTraceAssemble2DBdr<9,9>(nf,B,pa_data,ea_data_bdr,add);
default:
return EADGTraceAssemble2DBdr(nf,B,pa_data,ea_data_bdr,dofs1D,quad1D);
return EADGTraceAssemble2DBdr(nf,B,pa_data,ea_data_bdr,add,dofs1D,quad1D);
}
}
else if (dim == 3)
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x23: return EADGTraceAssemble3DBdr<2,3>(nf,B,pa_data,ea_data_bdr);
case 0x34: return EADGTraceAssemble3DBdr<3,4>(nf,B,pa_data,ea_data_bdr);
case 0x45: return EADGTraceAssemble3DBdr<4,5>(nf,B,pa_data,ea_data_bdr);
case 0x56: return EADGTraceAssemble3DBdr<5,6>(nf,B,pa_data,ea_data_bdr);
case 0x67: return EADGTraceAssemble3DBdr<6,7>(nf,B,pa_data,ea_data_bdr);
case 0x78: return EADGTraceAssemble3DBdr<7,8>(nf,B,pa_data,ea_data_bdr);
case 0x89: return EADGTraceAssemble3DBdr<8,9>(nf,B,pa_data,ea_data_bdr);
case 0x23: return EADGTraceAssemble3DBdr<2,3>(nf,B,pa_data,ea_data_bdr,add);
case 0x34: return EADGTraceAssemble3DBdr<3,4>(nf,B,pa_data,ea_data_bdr,add);
case 0x45: return EADGTraceAssemble3DBdr<4,5>(nf,B,pa_data,ea_data_bdr,add);
case 0x56: return EADGTraceAssemble3DBdr<5,6>(nf,B,pa_data,ea_data_bdr,add);
case 0x67: return EADGTraceAssemble3DBdr<6,7>(nf,B,pa_data,ea_data_bdr,add);
case 0x78: return EADGTraceAssemble3DBdr<7,8>(nf,B,pa_data,ea_data_bdr,add);
case 0x89: return EADGTraceAssemble3DBdr<8,9>(nf,B,pa_data,ea_data_bdr,add);
default:
return EADGTraceAssemble3DBdr(nf,B,pa_data,ea_data_bdr,dofs1D,quad1D);
return EADGTraceAssemble3DBdr(nf,B,pa_data,ea_data_bdr,add,dofs1D,quad1D);
}
}
MFEM_ABORT("Unknown kernel.");
+59 -31
View File
@@ -22,6 +22,7 @@ static void EADiffusionAssemble1D(const int NE,
const Array<double> &g,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -53,7 +54,14 @@ static void EADiffusionAssemble1D(const int NE,
{
val += r_Gj[k1] * D(k1, e) * r_Gi[k1];
}
A(i1, j1, e) += val;
if (add)
{
A(i1, j1, e) += val;
}
else
{
A(i1, j1, e) = val;
}
}
}
});
@@ -65,6 +73,7 @@ static void EADiffusionAssemble2D(const int NE,
const Array<double> &g,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -120,7 +129,14 @@ static void EADiffusionAssemble2D(const int NE,
+ gbi * D11 * gbj;
}
}
A(i1, i2, j1, j2, e) += val;
if (add)
{
A(i1, i2, j1, j2, e) += val;
}
else
{
A(i1, i2, j1, j2, e) = val;
}
}
}
}
@@ -130,10 +146,11 @@ static void EADiffusionAssemble2D(const int NE,
template<int T_D1D = 0, int T_Q1D = 0>
static void EADiffusionAssemble3D(const int NE,
const Array<double> &g,
const Array<double> &b,
const Array<double> &g,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -208,7 +225,14 @@ static void EADiffusionAssemble3D(const int NE,
}
}
}
A(i1, i2, i3, j1, j2, j3, e) += val;
if (add)
{
A(i1, i2, i3, j1, j2, j3, e) += val;
}
else
{
A(i1, i2, i3, j1, j2, j3, e) = val;
}
}
}
}
@@ -219,7 +243,8 @@ static void EADiffusionAssemble3D(const int NE,
}
void DiffusionIntegrator::AssembleEA(const FiniteElementSpace &fes,
Vector &ea_data)
Vector &ea_data,
const bool add)
{
AssemblePA(fes);
const int ne = fes.GetMesh()->GetNE();
@@ -229,44 +254,47 @@ void DiffusionIntegrator::AssembleEA(const FiniteElementSpace &fes,
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x22: return EADiffusionAssemble1D<2,2>(ne,B,G,pa_data,ea_data);
case 0x33: return EADiffusionAssemble1D<3,3>(ne,B,G,pa_data,ea_data);
case 0x44: return EADiffusionAssemble1D<4,4>(ne,B,G,pa_data,ea_data);
case 0x55: return EADiffusionAssemble1D<5,5>(ne,B,G,pa_data,ea_data);
case 0x66: return EADiffusionAssemble1D<6,6>(ne,B,G,pa_data,ea_data);
case 0x77: return EADiffusionAssemble1D<7,7>(ne,B,G,pa_data,ea_data);
case 0x88: return EADiffusionAssemble1D<8,8>(ne,B,G,pa_data,ea_data);
case 0x99: return EADiffusionAssemble1D<9,9>(ne,B,G,pa_data,ea_data);
default: return EADiffusionAssemble1D(ne,B,G,pa_data,ea_data,dofs1D,quad1D);
case 0x22: return EADiffusionAssemble1D<2,2>(ne,B,G,pa_data,ea_data,add);
case 0x33: return EADiffusionAssemble1D<3,3>(ne,B,G,pa_data,ea_data,add);
case 0x44: return EADiffusionAssemble1D<4,4>(ne,B,G,pa_data,ea_data,add);
case 0x55: return EADiffusionAssemble1D<5,5>(ne,B,G,pa_data,ea_data,add);
case 0x66: return EADiffusionAssemble1D<6,6>(ne,B,G,pa_data,ea_data,add);
case 0x77: return EADiffusionAssemble1D<7,7>(ne,B,G,pa_data,ea_data,add);
case 0x88: return EADiffusionAssemble1D<8,8>(ne,B,G,pa_data,ea_data,add);
case 0x99: return EADiffusionAssemble1D<9,9>(ne,B,G,pa_data,ea_data,add);
default: return EADiffusionAssemble1D(ne,B,G,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
else if (dim == 2)
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x22: return EADiffusionAssemble2D<2,2>(ne,B,G,pa_data,ea_data);
case 0x33: return EADiffusionAssemble2D<3,3>(ne,B,G,pa_data,ea_data);
case 0x44: return EADiffusionAssemble2D<4,4>(ne,B,G,pa_data,ea_data);
case 0x55: return EADiffusionAssemble2D<5,5>(ne,B,G,pa_data,ea_data);
case 0x66: return EADiffusionAssemble2D<6,6>(ne,B,G,pa_data,ea_data);
case 0x77: return EADiffusionAssemble2D<7,7>(ne,B,G,pa_data,ea_data);
case 0x88: return EADiffusionAssemble2D<8,8>(ne,B,G,pa_data,ea_data);
case 0x99: return EADiffusionAssemble2D<9,9>(ne,B,G,pa_data,ea_data);
default: return EADiffusionAssemble2D(ne,B,G,pa_data,ea_data,dofs1D,quad1D);
case 0x22: return EADiffusionAssemble2D<2,2>(ne,B,G,pa_data,ea_data,add);
case 0x33: return EADiffusionAssemble2D<3,3>(ne,B,G,pa_data,ea_data,add);
case 0x44: return EADiffusionAssemble2D<4,4>(ne,B,G,pa_data,ea_data,add);
case 0x55: return EADiffusionAssemble2D<5,5>(ne,B,G,pa_data,ea_data,add);
case 0x66: return EADiffusionAssemble2D<6,6>(ne,B,G,pa_data,ea_data,add);
case 0x77: return EADiffusionAssemble2D<7,7>(ne,B,G,pa_data,ea_data,add);
case 0x88: return EADiffusionAssemble2D<8,8>(ne,B,G,pa_data,ea_data,add);
case 0x99: return EADiffusionAssemble2D<9,9>(ne,B,G,pa_data,ea_data,add);
default: return EADiffusionAssemble2D(ne,B,G,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
else if (dim == 3)
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x23: return EADiffusionAssemble3D<2,3>(ne,B,G,pa_data,ea_data);
case 0x34: return EADiffusionAssemble3D<3,4>(ne,B,G,pa_data,ea_data);
case 0x45: return EADiffusionAssemble3D<4,5>(ne,B,G,pa_data,ea_data);
case 0x56: return EADiffusionAssemble3D<5,6>(ne,B,G,pa_data,ea_data);
case 0x67: return EADiffusionAssemble3D<6,7>(ne,B,G,pa_data,ea_data);
case 0x78: return EADiffusionAssemble3D<7,8>(ne,B,G,pa_data,ea_data);
case 0x89: return EADiffusionAssemble3D<8,9>(ne,B,G,pa_data,ea_data);
default: return EADiffusionAssemble3D(ne,B,G,pa_data,ea_data,dofs1D,quad1D);
case 0x23: return EADiffusionAssemble3D<2,3>(ne,B,G,pa_data,ea_data,add);
case 0x34: return EADiffusionAssemble3D<3,4>(ne,B,G,pa_data,ea_data,add);
case 0x45: return EADiffusionAssemble3D<4,5>(ne,B,G,pa_data,ea_data,add);
case 0x56: return EADiffusionAssemble3D<5,6>(ne,B,G,pa_data,ea_data,add);
case 0x67: return EADiffusionAssemble3D<6,7>(ne,B,G,pa_data,ea_data,add);
case 0x78: return EADiffusionAssemble3D<7,8>(ne,B,G,pa_data,ea_data,add);
case 0x89: return EADiffusionAssemble3D<8,9>(ne,B,G,pa_data,ea_data,add);
default: return EADiffusionAssemble3D(ne,B,G,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
MFEM_ABORT("Unknown kernel.");
+48 -47
View File
@@ -96,26 +96,28 @@ void PADiffusionSetup2D<2>(const int Q1D,
const Vector &c,
Vector &d)
{
const int NQ = Q1D*Q1D;
const bool const_c = c.Size() == 1;
auto W = w.Read();
auto J = Reshape(j.Read(), NQ, 2, 2, NE);
auto C = const_c ? Reshape(c.Read(), 1, 1) : Reshape(c.Read(), NQ, NE);
auto D = Reshape(d.Write(), NQ, 3, NE);
MFEM_FORALL(e, NE,
const auto W = Reshape(w.Read(), Q1D,Q1D);
const auto J = Reshape(j.Read(), Q1D,Q1D,2,2,NE);
const auto C = const_c ? Reshape(c.Read(), 1,1,1) :
Reshape(c.Read(), Q1D,Q1D,NE);
auto D = Reshape(d.Write(), Q1D,Q1D, 3, NE);
MFEM_FORALL_2D(e, NE, Q1D,Q1D,1,
{
for (int q = 0; q < NQ; ++q)
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
const double J11 = J(q,0,0,e);
const double J21 = J(q,1,0,e);
const double J12 = J(q,0,1,e);
const double J22 = J(q,1,1,e);
const double coeff = const_c ? C(0,0) : C(q,e);
const double c_detJ = W[q] * coeff / ((J11*J22)-(J21*J12));
D(q,0,e) = c_detJ * (J12*J12 + J22*J22); // 1,1
D(q,1,e) = -c_detJ * (J12*J11 + J22*J21); // 1,2
D(q,2,e) = c_detJ * (J11*J11 + J21*J21); // 2,2
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
const double J11 = J(qx,qy,0,0,e);
const double J21 = J(qx,qy,1,0,e);
const double J12 = J(qx,qy,0,1,e);
const double J22 = J(qx,qy,1,1,e);
const double coeff = const_c ? C(0,0,0) : C(qx,qy,e);
const double c_detJ = W(qx,qy) * coeff / ((J11*J22)-(J21*J12));
D(qx,qy,0,e) = c_detJ * (J12*J12 + J22*J22); // 1,1
D(qx,qy,1,e) = -c_detJ * (J12*J11 + J22*J21); // 1,2
D(qx,qy,2,e) = c_detJ * (J11*J11 + J21*J21); // 2,2
}
}
});
}
@@ -131,33 +133,35 @@ void PADiffusionSetup2D<3>(const int Q1D,
{
constexpr int DIM = 2;
constexpr int SDIM = 3;
const int NQ = Q1D*Q1D;
const bool const_c = c.Size() == 1;
auto W = w.Read();
auto J = Reshape(j.Read(), NQ, SDIM, DIM, NE);
auto C = const_c ? Reshape(c.Read(), 1, 1) : Reshape(c.Read(), NQ, NE);
auto D = Reshape(d.Write(), NQ, 3, NE);
MFEM_FORALL(e, NE,
const auto W = Reshape(w.Read(), Q1D,Q1D);
const auto J = Reshape(j.Read(), Q1D,Q1D,SDIM,DIM,NE);
const auto C = const_c ? Reshape(c.Read(), 1,1,1) :
Reshape(c.Read(), Q1D,Q1D,NE);
auto D = Reshape(d.Write(), Q1D,Q1D, 3, NE);
MFEM_FORALL_2D(e, NE, Q1D,Q1D,1,
{
for (int q = 0; q < NQ; ++q)
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
const double wq = W[q];
const double J11 = J(q,0,0,e);
const double J21 = J(q,1,0,e);
const double J31 = J(q,2,0,e);
const double J12 = J(q,0,1,e);
const double J22 = J(q,1,1,e);
const double J32 = J(q,2,1,e);
const double E = J11*J11 + J21*J21 + J31*J31;
const double G = J12*J12 + J22*J22 + J32*J32;
const double F = J11*J12 + J21*J22 + J31*J32;
const double iw = 1.0 / sqrt(E*G - F*F);
const double coeff = const_c ? C(0,0) : C(q,e);
const double alpha = wq * coeff * iw;
D(q,0,e) = alpha * G; // 1,1
D(q,1,e) = -alpha * F; // 1,2
D(q,2,e) = alpha * E; // 2,2
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
const double wq = W(qx,qy);
const double J11 = J(qx,qy,0,0,e);
const double J21 = J(qx,qy,1,0,e);
const double J31 = J(qx,qy,2,0,e);
const double J12 = J(qx,qy,0,1,e);
const double J22 = J(qx,qy,1,1,e);
const double J32 = J(qx,qy,2,1,e);
const double E = J11*J11 + J21*J21 + J31*J31;
const double G = J12*J12 + J22*J22 + J32*J32;
const double F = J11*J12 + J21*J22 + J31*J32;
const double iw = 1.0 / sqrt(E*G - F*F);
const double coeff = const_c ? C(0,0,0) : C(qx,qy,e);
const double alpha = wq * coeff * iw;
D(qx,qy,0,e) = alpha * G; // 1,1
D(qx,qy,1,e) = -alpha * F; // 1,2
D(qx,qy,2,e) = alpha * E; // 2,2
}
}
});
}
@@ -282,10 +286,9 @@ void DiffusionIntegrator::SetupPA(const FiniteElementSpace &fes)
const int nq = ir->GetNPoints();
dim = mesh->Dimension();
ne = fes.GetNE();
const DofToQuad::Mode mode = DofToQuad::TENSOR;
geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS, mode);
geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS);
const int sdim = mesh->SpaceDimension();
maps = &el.GetDofToQuad(*ir, mode);
maps = &el.GetDofToQuad(*ir, DofToQuad::TENSOR);
dofs1D = maps->ndof;
quad1D = maps->nqpt;
pa_data.SetSize(symmDims * nq * ne, Device::GetDeviceMemoryType());
@@ -740,7 +743,6 @@ static void PADiffusionAssembleDiagonal(const int dim,
case 0x23: return SmemPADiffusionDiagonal3D<2,3>(NE,B,G,D,Y);
case 0x34: return SmemPADiffusionDiagonal3D<3,4>(NE,B,G,D,Y);
case 0x45: return SmemPADiffusionDiagonal3D<4,5>(NE,B,G,D,Y);
case 0x46: return SmemPADiffusionDiagonal3D<4,6>(NE,B,G,D,Y);
case 0x56: return SmemPADiffusionDiagonal3D<5,6>(NE,B,G,D,Y);
case 0x67: return SmemPADiffusionDiagonal3D<6,7>(NE,B,G,D,Y);
case 0x78: return SmemPADiffusionDiagonal3D<7,8>(NE,B,G,D,Y);
@@ -1678,7 +1680,7 @@ static void PADiffusionApply(const int dim,
MFEM_ABORT("OCCA PADiffusionApply unknown kernel!");
}
#endif // MFEM_USE_OCCA
const int ID = (D1D << 4 ) | Q1D;
const int ID = (D1D << 4) | Q1D;
if (dim == 2)
{
@@ -1701,7 +1703,6 @@ static void PADiffusionApply(const int dim,
switch (ID)
{
case 0x23: return SmemPADiffusionApply3D<2,3>(NE,B,G,D,X,Y);
case 0x24: return SmemPADiffusionApply3D<2,4>(NE,B,G,D,X,Y);
case 0x34: return SmemPADiffusionApply3D<3,4>(NE,B,G,D,X,Y);
case 0x45: return SmemPADiffusionApply3D<4,5>(NE,B,G,D,X,Y);
case 0x46: return SmemPADiffusionApply3D<4,6>(NE,B,G,D,X,Y);
+2088 -348
View File
File diff suppressed because it is too large Load Diff
-5
View File
@@ -23,11 +23,6 @@ using namespace std;
namespace mfem
{
// Local maximum size of dofs and quads in 1D
constexpr int HDIV_MAX_D1D = 5;
constexpr int HDIV_MAX_Q1D = 6;
// PA H(div) Mass Assemble 2D kernel
void PAHdivSetup2D(const int Q1D,
const int NE,
+58 -30
View File
@@ -21,6 +21,7 @@ static void EAMassAssemble1D(const int NE,
const Array<double> &basis,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -52,7 +53,14 @@ static void EAMassAssemble1D(const int NE,
{
val += r_Bi[k1] * r_Bj[k1] * D(k1, e);
}
M(i1, j1, e) += val;
if (add)
{
M(i1, j1, e) += val;
}
else
{
M(i1, j1, e) = val;
}
}
}
});
@@ -63,6 +71,7 @@ static void EAMassAssemble2D(const int NE,
const Array<double> &basis,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -114,7 +123,14 @@ static void EAMassAssemble2D(const int NE,
* s_D[k1][k2];
}
}
M(i1, i2, j1, j2, e) += val;
if (add)
{
M(i1, i2, j1, j2, e) += val;
}
else
{
M(i1, i2, j1, j2, e) = val;
}
}
}
}
@@ -127,6 +143,7 @@ static void EAMassAssemble3D(const int NE,
const Array<double> &basis,
const Vector &padata,
Vector &eadata,
const bool add,
const int d1d = 0,
const int q1d = 0)
{
@@ -189,7 +206,14 @@ static void EAMassAssemble3D(const int NE,
}
}
}
M(i1, i2, i3, j1, j2, j3, e) += val;
if (add)
{
M(i1, i2, i3, j1, j2, j3, e) += val;
}
else
{
M(i1, i2, i3, j1, j2, j3, e) = val;
}
}
}
}
@@ -200,7 +224,8 @@ static void EAMassAssemble3D(const int NE,
}
void MassIntegrator::AssembleEA(const FiniteElementSpace &fes,
Vector &ea_data)
Vector &ea_data,
const bool add)
{
AssemblePA(fes);
const int ne = fes.GetMesh()->GetNE();
@@ -209,44 +234,47 @@ void MassIntegrator::AssembleEA(const FiniteElementSpace &fes,
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x22: return EAMassAssemble1D<2,2>(ne,B,pa_data,ea_data);
case 0x33: return EAMassAssemble1D<3,3>(ne,B,pa_data,ea_data);
case 0x44: return EAMassAssemble1D<4,4>(ne,B,pa_data,ea_data);
case 0x55: return EAMassAssemble1D<5,5>(ne,B,pa_data,ea_data);
case 0x66: return EAMassAssemble1D<6,6>(ne,B,pa_data,ea_data);
case 0x77: return EAMassAssemble1D<7,7>(ne,B,pa_data,ea_data);
case 0x88: return EAMassAssemble1D<8,8>(ne,B,pa_data,ea_data);
case 0x99: return EAMassAssemble1D<9,9>(ne,B,pa_data,ea_data);
default: return EAMassAssemble1D(ne,B,pa_data,ea_data,dofs1D,quad1D);
case 0x22: return EAMassAssemble1D<2,2>(ne,B,pa_data,ea_data,add);
case 0x33: return EAMassAssemble1D<3,3>(ne,B,pa_data,ea_data,add);
case 0x44: return EAMassAssemble1D<4,4>(ne,B,pa_data,ea_data,add);
case 0x55: return EAMassAssemble1D<5,5>(ne,B,pa_data,ea_data,add);
case 0x66: return EAMassAssemble1D<6,6>(ne,B,pa_data,ea_data,add);
case 0x77: return EAMassAssemble1D<7,7>(ne,B,pa_data,ea_data,add);
case 0x88: return EAMassAssemble1D<8,8>(ne,B,pa_data,ea_data,add);
case 0x99: return EAMassAssemble1D<9,9>(ne,B,pa_data,ea_data,add);
default: return EAMassAssemble1D(ne,B,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
else if (dim == 2)
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x22: return EAMassAssemble2D<2,2>(ne,B,pa_data,ea_data);
case 0x33: return EAMassAssemble2D<3,3>(ne,B,pa_data,ea_data);
case 0x44: return EAMassAssemble2D<4,4>(ne,B,pa_data,ea_data);
case 0x55: return EAMassAssemble2D<5,5>(ne,B,pa_data,ea_data);
case 0x66: return EAMassAssemble2D<6,6>(ne,B,pa_data,ea_data);
case 0x77: return EAMassAssemble2D<7,7>(ne,B,pa_data,ea_data);
case 0x88: return EAMassAssemble2D<8,8>(ne,B,pa_data,ea_data);
case 0x99: return EAMassAssemble2D<9,9>(ne,B,pa_data,ea_data);
default: return EAMassAssemble2D(ne,B,pa_data,ea_data,dofs1D,quad1D);
case 0x22: return EAMassAssemble2D<2,2>(ne,B,pa_data,ea_data,add);
case 0x33: return EAMassAssemble2D<3,3>(ne,B,pa_data,ea_data,add);
case 0x44: return EAMassAssemble2D<4,4>(ne,B,pa_data,ea_data,add);
case 0x55: return EAMassAssemble2D<5,5>(ne,B,pa_data,ea_data,add);
case 0x66: return EAMassAssemble2D<6,6>(ne,B,pa_data,ea_data,add);
case 0x77: return EAMassAssemble2D<7,7>(ne,B,pa_data,ea_data,add);
case 0x88: return EAMassAssemble2D<8,8>(ne,B,pa_data,ea_data,add);
case 0x99: return EAMassAssemble2D<9,9>(ne,B,pa_data,ea_data,add);
default: return EAMassAssemble2D(ne,B,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
else if (dim == 3)
{
switch ((dofs1D << 4 ) | quad1D)
{
case 0x23: return EAMassAssemble3D<2,3>(ne,B,pa_data,ea_data);
case 0x34: return EAMassAssemble3D<3,4>(ne,B,pa_data,ea_data);
case 0x45: return EAMassAssemble3D<4,5>(ne,B,pa_data,ea_data);
case 0x56: return EAMassAssemble3D<5,6>(ne,B,pa_data,ea_data);
case 0x67: return EAMassAssemble3D<6,7>(ne,B,pa_data,ea_data);
case 0x78: return EAMassAssemble3D<7,8>(ne,B,pa_data,ea_data);
case 0x89: return EAMassAssemble3D<8,9>(ne,B,pa_data,ea_data);
default: return EAMassAssemble3D(ne,B,pa_data,ea_data,dofs1D,quad1D);
case 0x23: return EAMassAssemble3D<2,3>(ne,B,pa_data,ea_data,add);
case 0x34: return EAMassAssemble3D<3,4>(ne,B,pa_data,ea_data,add);
case 0x45: return EAMassAssemble3D<4,5>(ne,B,pa_data,ea_data,add);
case 0x56: return EAMassAssemble3D<5,6>(ne,B,pa_data,ea_data,add);
case 0x67: return EAMassAssemble3D<6,7>(ne,B,pa_data,ea_data,add);
case 0x78: return EAMassAssemble3D<7,8>(ne,B,pa_data,ea_data,add);
case 0x89: return EAMassAssemble3D<8,9>(ne,B,pa_data,ea_data,add);
default: return EAMassAssemble3D(ne,B,pa_data,ea_data,add,
dofs1D,quad1D);
}
}
MFEM_ABORT("Unknown kernel.");
+41 -69
View File
@@ -25,7 +25,6 @@ namespace mfem
void MassIntegrator::SetupPA(const FiniteElementSpace &fes)
{
// Assuming the same element type
fespace = &fes;
Mesh *mesh = fes.GetMesh();
@@ -46,38 +45,22 @@ void MassIntegrator::SetupPA(const FiniteElementSpace &fes)
dim = mesh->Dimension();
ne = fes.GetMesh()->GetNE();
nq = ir->GetNPoints();
const DofToQuad::Mode mode = DofToQuad::TENSOR;
const int flags = GeometricFactors::JACOBIANS |
GeometricFactors::COORDINATES;
#ifdef MFEM_USE_UMPIRE
const MemoryType temp_type = Device::GetDeviceMemoryType() == MemoryType::DEVICE_UMPIRE
? MemoryType::DEVICE_UMPIRE_2 : Device::GetDeviceMemoryType();
#else
const MemoryType temp_type = Device::GetDeviceMemoryType();
#endif
geom = mesh->GetGeometricFactors(*ir, flags, mode, temp_type);
maps = &el.GetDofToQuad(*ir, mode);
geom = mesh->GetGeometricFactors(*ir, GeometricFactors::COORDINATES |
GeometricFactors::JACOBIANS);
maps = &el.GetDofToQuad(*ir, DofToQuad::TENSOR);
dofs1D = maps->ndof;
quad1D = maps->nqpt;
pa_data.SetSize(ne*nq, Device::GetDeviceMemoryType());
Vector *coeff{nullptr};
bool own_coeff{true};
Vector coeff;
if (Q == nullptr)
{
coeff = new Vector;
coeff->SetSize(1);
(*coeff)(0) = 1.0;
coeff.SetSize(1);
coeff(0) = 1.0;
}
else if (ConstantCoefficient* cQ = dynamic_cast<ConstantCoefficient*>(Q))
{
coeff = new Vector;
coeff->SetSize(1);
(*coeff)(0) = cQ->constant;
}
else if (QuadratureCoefficient* cQ = dynamic_cast<QuadratureCoefficient*>(Q))
{
coeff = cQ->Data();
own_coeff = false;
coeff.SetSize(1);
coeff(0) = cQ->constant;
}
else if (QuadratureFunctionCoefficient* cQ =
dynamic_cast<QuadratureFunctionCoefficient*>(Q))
@@ -90,13 +73,12 @@ void MassIntegrator::SetupPA(const FiniteElementSpace &fes)
"IntegrationRule used within integrator and in"
" QuadratureFunction appear to be different");
qFun.Read();
coeff->MakeRef(const_cast<QuadratureFunction &>(qFun),0);
coeff.MakeRef(const_cast<QuadratureFunction &>(qFun),0);
}
else
{
coeff = new Vector;
coeff->SetSize(nq * ne);
auto C = Reshape(coeff->HostWrite(), nq, ne);
coeff.SetSize(nq * ne);
auto C = Reshape(coeff.HostWrite(), nq, ne);
for (int e = 0; e < ne; ++e)
{
ElementTransformation& T = *fes.GetElementTransformation(e);
@@ -110,24 +92,27 @@ void MassIntegrator::SetupPA(const FiniteElementSpace &fes)
if (dim==2)
{
const int NE = ne;
const int NQ = nq;
const bool const_c = coeff->Size() == 1;
auto w = ir->GetWeights().Read();
auto J = Reshape(geom->J.Read(), NQ,2,2,NE);
auto C =
const_c ? Reshape(coeff->Read(), 1,1) : Reshape(coeff->Read(), NQ,NE);
auto v = Reshape(pa_data.Write(), NQ, NE);
MFEM_FORALL(e, NE,
const int Q1D = quad1D;
const bool const_c = coeff.Size() == 1;
const auto W = Reshape(ir->GetWeights().Read(), Q1D,Q1D);
const auto J = Reshape(geom->J.Read(), Q1D,Q1D,2,2,NE);
const auto C = const_c ? Reshape(coeff.Read(), 1,1,1) :
Reshape(coeff.Read(), Q1D,Q1D,NE);
auto v = Reshape(pa_data.Write(), Q1D,Q1D, NE);
MFEM_FORALL_2D(e, NE, Q1D,Q1D,1,
{
for (int q = 0; q < NQ; ++q)
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
const double J11 = J(q,0,0,e);
const double J12 = J(q,1,0,e);
const double J21 = J(q,0,1,e);
const double J22 = J(q,1,1,e);
const double detJ = (J11*J22)-(J21*J12);
const double coeff = const_c ? C(0,0) : C(q,e);
v(q,e) = w[q] * coeff * detJ;
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
const double J11 = J(qx,qy,0,0,e);
const double J12 = J(qx,qy,1,0,e);
const double J21 = J(qx,qy,0,1,e);
const double J22 = J(qx,qy,1,1,e);
const double detJ = (J11*J22)-(J21*J12);
const double coeff = const_c ? C(0,0,0) : C(qx,qy,e);
v(qx,qy,e) = W(qx,qy) * coeff * detJ;
}
}
});
}
@@ -135,13 +120,12 @@ void MassIntegrator::SetupPA(const FiniteElementSpace &fes)
{
const int NE = ne;
const int Q1D = quad1D;
const bool const_c = coeff->Size() == 1;
const auto W = Reshape(ir->GetWeights().Read(),Q1D,Q1D,Q1D);
const bool const_c = coeff.Size() == 1;
const auto W = Reshape(ir->GetWeights().Read(), Q1D,Q1D,Q1D);
const auto J = Reshape(geom->J.Read(), Q1D,Q1D,Q1D,3,3,NE);
const auto C = const_c ?
Reshape(coeff->Read(), 1,1,1,1) :
Reshape(coeff->Read(), Q1D,Q1D,Q1D,NE);
auto V = Reshape(pa_data.Write(), Q1D,Q1D,Q1D,NE);
const auto C = const_c ? Reshape(coeff.Read(), 1,1,1,1) :
Reshape(coeff.Read(), Q1D,Q1D,Q1D,NE);
auto v = Reshape(pa_data.Write(), Q1D,Q1D,Q1D,NE);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
@@ -151,26 +135,24 @@ void MassIntegrator::SetupPA(const FiniteElementSpace &fes)
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
const double J11 = J(qx,qy,qz,0,0,e);
const double J12 = J(qx,qy,qz,0,1,e);
const double J13 = J(qx,qy,qz,0,2,e);
const double J21 = J(qx,qy,qz,1,0,e);
const double J22 = J(qx,qy,qz,1,1,e);
const double J23 = J(qx,qy,qz,1,2,e);
const double J31 = J(qx,qy,qz,2,0,e);
const double J12 = J(qx,qy,qz,0,1,e);
const double J22 = J(qx,qy,qz,1,1,e);
const double J32 = J(qx,qy,qz,2,1,e);
const double J13 = J(qx,qy,qz,0,2,e);
const double J23 = J(qx,qy,qz,1,2,e);
const double J33 = J(qx,qy,qz,2,2,e);
const double detJ = J11 * (J22 * J33 - J32 * J23) -
/* */ J21 * (J12 * J33 - J32 * J13) +
/* */ J31 * (J12 * J23 - J22 * J13);
const double coeff = const_c ? C(0,0,0,0) : C(qx,qy,qz,e);
V(qx,qy,qz,e) = W(qx,qy,qz) * coeff * detJ;
v(qx,qy,qz,e) = W(qx,qy,qz) * coeff * detJ;
}
}
}
});
}
if (own_coeff) { delete coeff; }
}
void MassIntegrator::AssemblePA(const FiniteElementSpace &fes)
@@ -472,12 +454,8 @@ static void PAMassAssembleDiagonal(const int dim, const int D1D,
switch ((D1D << 4 ) | Q1D)
{
case 0x23: return SmemPAMassAssembleDiagonal3D<2,3>(NE,B,D,Y);
case 0x24: return SmemPAMassAssembleDiagonal3D<2,4>(NE,B,D,Y);
case 0x26: return SmemPAMassAssembleDiagonal3D<2,6>(NE,B,D,Y);
case 0x34: return SmemPAMassAssembleDiagonal3D<3,4>(NE,B,D,Y);
case 0x35: return SmemPAMassAssembleDiagonal3D<3,5>(NE,B,D,Y);
case 0x45: return SmemPAMassAssembleDiagonal3D<4,5>(NE,B,D,Y);
case 0x48: return SmemPAMassAssembleDiagonal3D<4,8>(NE,B,D,Y);
case 0x56: return SmemPAMassAssembleDiagonal3D<5,6>(NE,B,D,Y);
case 0x67: return SmemPAMassAssembleDiagonal3D<6,7>(NE,B,D,Y);
case 0x78: return SmemPAMassAssembleDiagonal3D<7,8>(NE,B,D,Y);
@@ -1211,13 +1189,10 @@ static void PAMassApply(const int dim,
case 0x24: return SmemPAMassApply2D<2,4,16>(NE,B,Bt,D,X,Y);
case 0x33: return SmemPAMassApply2D<3,3,16>(NE,B,Bt,D,X,Y);
case 0x34: return SmemPAMassApply2D<3,4,16>(NE,B,Bt,D,X,Y);
case 0x35: return SmemPAMassApply2D<3,5,16>(NE,B,Bt,D,X,Y);
case 0x36: return SmemPAMassApply2D<3,6,16>(NE,B,Bt,D,X,Y);
case 0x44: return SmemPAMassApply2D<4,4,8>(NE,B,Bt,D,X,Y);
case 0x46: return SmemPAMassApply2D<4,6,8>(NE,B,Bt,D,X,Y);
case 0x48: return SmemPAMassApply2D<4,8,4>(NE,B,Bt,D,X,Y);
case 0x55: return SmemPAMassApply2D<5,5,8>(NE,B,Bt,D,X,Y);
case 0x57: return SmemPAMassApply2D<5,7,8>(NE,B,Bt,D,X,Y);
case 0x58: return SmemPAMassApply2D<5,8,2>(NE,B,Bt,D,X,Y);
case 0x66: return SmemPAMassApply2D<6,6,4>(NE,B,Bt,D,X,Y);
case 0x77: return SmemPAMassApply2D<7,7,4>(NE,B,Bt,D,X,Y);
@@ -1225,7 +1200,6 @@ static void PAMassApply(const int dim,
case 0x99: return SmemPAMassApply2D<9,9,2>(NE,B,Bt,D,X,Y);
default: return PAMassApply2D(NE,B,Bt,D,X,Y,D1D,Q1D);
}
mfem::out << "Unknown 2D kernel 0x" << std::hex << id << std::endl;
}
else if (dim == 3)
{
@@ -1234,9 +1208,7 @@ static void PAMassApply(const int dim,
case 0x23: return SmemPAMassApply3D<2,3>(NE,B,Bt,D,X,Y);
case 0x24: return SmemPAMassApply3D<2,4>(NE,B,Bt,D,X,Y);
case 0x34: return SmemPAMassApply3D<3,4>(NE,B,Bt,D,X,Y);
case 0x35: return SmemPAMassApply3D<3,5>(NE,B,Bt,D,X,Y);
case 0x36: return SmemPAMassApply3D<3,6>(NE,B,Bt,D,X,Y);
case 0x37: return SmemPAMassApply3D<3,7>(NE,B,Bt,D,X,Y);
case 0x45: return SmemPAMassApply3D<4,5>(NE,B,Bt,D,X,Y);
case 0x46: return SmemPAMassApply3D<4,6>(NE,B,Bt,D,X,Y);
case 0x48: return SmemPAMassApply3D<4,8>(NE,B,Bt,D,X,Y);
@@ -1248,8 +1220,8 @@ static void PAMassApply(const int dim,
case 0x9A: return SmemPAMassApply3D<9,10>(NE,B,Bt,D,X,Y);
default: return PAMassApply3D(NE,B,Bt,D,X,Y,D1D,Q1D);
}
mfem::out << "Unknown 3D kernel 0x" << std::hex << id << std::endl;
}
mfem::out << "Unknown kernel 0x" << std::hex << id << std::endl;
MFEM_ABORT("Unknown kernel.");
}
+139 -56
View File
@@ -16,88 +16,171 @@ namespace mfem
{
void TransposeIntegrator::AssembleEA(const FiniteElementSpace &fes,
Vector &ea_data)
Vector &ea_data, const bool add)
{
Vector ea_data_tmp(ea_data.Size());
ea_data_tmp = 0.0;
bfi->AssembleEA(fes, ea_data_tmp);
const int ne = fes.GetNE();
if (ne == 0) { return; }
const int dofs = fes.GetFE(0)->GetDof();
auto A = Reshape(ea_data_tmp.Write(), dofs, dofs, ne);
auto AT = Reshape(ea_data.ReadWrite(), dofs, dofs, ne);
MFEM_FORALL(e, ne,
if (add)
{
for (int i = 0; i < dofs; i++)
Vector ea_data_tmp(ea_data.Size());
bfi->AssembleEA(fes, ea_data_tmp, false);
const int ne = fes.GetNE();
if (ne == 0) { return; }
const int dofs = fes.GetFE(0)->GetDof();
auto A = Reshape(ea_data_tmp.Read(), dofs, dofs, ne);
auto AT = Reshape(ea_data.ReadWrite(), dofs, dofs, ne);
MFEM_FORALL(e, ne,
{
for (int j = 0; j < dofs; j++)
for (int i = 0; i < dofs; i++)
{
const double a = A(i, j, e);
AT(j, i, e) += a;
for (int j = 0; j < dofs; j++)
{
const double a = A(i, j, e);
AT(j, i, e) += a;
}
}
}
});
});
}
else
{
bfi->AssembleEA(fes, ea_data, false);
const int ne = fes.GetNE();
if (ne == 0) { return; }
const int dofs = fes.GetFE(0)->GetDof();
auto A = Reshape(ea_data.ReadWrite(), dofs, dofs, ne);
MFEM_FORALL(e, ne,
{
for (int i = 0; i < dofs; i++)
{
for (int j = i+1; j < dofs; j++)
{
const double aij = A(i, j, e);
const double aji = A(j, i, e);
A(j, i, e) = aij;
A(i, j, e) = aji;
}
}
});
}
}
void TransposeIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace& fes,
Vector &ea_data_int,
Vector &ea_data_ext)
Vector &ea_data_ext,
const bool add)
{
const int nf = fes.GetNFbyType(FaceType::Interior);
if (nf == 0) { return; }
Vector ea_data_int_tmp(ea_data_int.Size());
Vector ea_data_ext_tmp(ea_data_ext.Size());
ea_data_int_tmp = 0.0;
ea_data_ext_tmp = 0.0;
bfi->AssembleEAInteriorFaces(fes, ea_data_int_tmp, ea_data_ext_tmp);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof();
auto A_int = Reshape(ea_data_int_tmp.Read(), faceDofs, faceDofs, 2, nf);
auto A_ext = Reshape(ea_data_ext_tmp.Read(), faceDofs, faceDofs, 2, nf);
auto AT_int = Reshape(ea_data_int.ReadWrite(), faceDofs, faceDofs, 2, nf);
auto AT_ext = Reshape(ea_data_ext.ReadWrite(), faceDofs, faceDofs, 2, nf);
MFEM_FORALL(f, nf,
if (add)
{
for (int i = 0; i < faceDofs; i++)
Vector ea_data_int_tmp(ea_data_int.Size());
Vector ea_data_ext_tmp(ea_data_ext.Size());
bfi->AssembleEAInteriorFaces(fes, ea_data_int_tmp, ea_data_ext_tmp, false);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof();
auto A_int = Reshape(ea_data_int_tmp.Read(), faceDofs, faceDofs, 2, nf);
auto A_ext = Reshape(ea_data_ext_tmp.Read(), faceDofs, faceDofs, 2, nf);
auto AT_int = Reshape(ea_data_int.ReadWrite(), faceDofs, faceDofs, 2, nf);
auto AT_ext = Reshape(ea_data_ext.ReadWrite(), faceDofs, faceDofs, 2, nf);
MFEM_FORALL(f, nf,
{
for (int j = 0; j < faceDofs; j++)
for (int i = 0; i < faceDofs; i++)
{
const double a_int0 = A_int(i, j, 0, f);
const double a_int1 = A_int(i, j, 1, f);
const double a_ext0 = A_ext(i, j, 0, f);
const double a_ext1 = A_ext(i, j, 1, f);
AT_int(j, i, 0, f) += a_int0;
AT_int(j, i, 1, f) += a_int1;
AT_ext(j, i, 0, f) += a_ext1;
AT_ext(j, i, 1, f) += a_ext0;
for (int j = 0; j < faceDofs; j++)
{
const double a_int0 = A_int(i, j, 0, f);
const double a_int1 = A_int(i, j, 1, f);
const double a_ext0 = A_ext(i, j, 0, f);
const double a_ext1 = A_ext(i, j, 1, f);
AT_int(j, i, 0, f) += a_int0;
AT_int(j, i, 1, f) += a_int1;
AT_ext(j, i, 0, f) += a_ext1;
AT_ext(j, i, 1, f) += a_ext0;
}
}
}
});
});
}
else
{
bfi->AssembleEAInteriorFaces(fes, ea_data_int, ea_data_ext, false);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof();
auto A_int = Reshape(ea_data_int.ReadWrite(), faceDofs, faceDofs, 2, nf);
auto A_ext = Reshape(ea_data_ext.ReadWrite(), faceDofs, faceDofs, 2, nf);
MFEM_FORALL(f, nf,
{
for (int i = 0; i < faceDofs; i++)
{
for (int j = i+1; j < faceDofs; j++)
{
const double aij_int0 = A_int(i, j, 0, f);
const double aij_int1 = A_int(i, j, 1, f);
const double aji_int0 = A_int(j, i, 0, f);
const double aji_int1 = A_int(j, i, 1, f);
A_int(j, i, 0, f) = aij_int0;
A_int(j, i, 1, f) = aij_int1;
A_int(i, j, 0, f) = aji_int0;
A_int(i, j, 1, f) = aji_int1;
}
}
for (int i = 0; i < faceDofs; i++)
{
for (int j = 0; j < faceDofs; j++)
{
const double aij_ext0 = A_ext(i, j, 0, f);
const double aji_ext1 = A_ext(j, i, 1, f);
A_ext(j, i, 1, f) = aij_ext0;
A_ext(i, j, 0, f) = aji_ext1;
}
}
});
}
}
void TransposeIntegrator::AssembleEABoundaryFaces(const FiniteElementSpace& fes,
Vector &ea_data_bdr)
Vector &ea_data_bdr,
const bool add)
{
const int nf = fes.GetNFbyType(FaceType::Boundary);
if (nf == 0) { return; }
Vector ea_data_bdr_tmp(ea_data_bdr.Size());
ea_data_bdr_tmp = 0.0;
bfi->AssembleEABoundaryFaces(fes, ea_data_bdr_tmp);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof();
auto A_bdr = Reshape(ea_data_bdr_tmp.Read(), faceDofs, faceDofs, nf);
auto AT_bdr = Reshape(ea_data_bdr.ReadWrite(), faceDofs, faceDofs, nf);
MFEM_FORALL(f, nf,
if (add)
{
for (int i = 0; i < faceDofs; i++)
Vector ea_data_bdr_tmp(ea_data_bdr.Size());
bfi->AssembleEABoundaryFaces(fes, ea_data_bdr_tmp, false);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof();
auto A_bdr = Reshape(ea_data_bdr_tmp.Read(), faceDofs, faceDofs, nf);
auto AT_bdr = Reshape(ea_data_bdr.ReadWrite(), faceDofs, faceDofs, nf);
MFEM_FORALL(f, nf,
{
for (int j = 0; j < faceDofs; j++)
for (int i = 0; i < faceDofs; i++)
{
const double a_bdr = A_bdr(i, j, f);
AT_bdr(j, i, f) += a_bdr;
for (int j = 0; j < faceDofs; j++)
{
const double a_bdr = A_bdr(i, j, f);
AT_bdr(j, i, f) += a_bdr;
}
}
}
});
});
}
else
{
bfi->AssembleEABoundaryFaces(fes, ea_data_bdr, false);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof();
auto A_bdr = Reshape(ea_data_bdr.ReadWrite(), faceDofs, faceDofs, nf);
MFEM_FORALL(f, nf,
{
for (int i = 0; i < faceDofs; i++)
{
for (int j = i+1; j < faceDofs; j++)
{
const double aij_bdr = A_bdr(i, j, f);
const double aji_bdr = A_bdr(j, i, f);
A_bdr(j, i, f) = aij_bdr;
A_bdr(i, j, f) = aji_bdr;
}
}
});
}
}
}
File diff suppressed because it is too large Load Diff
+25 -8
View File
@@ -12,7 +12,6 @@
// Implementation of Coefficient class
#include "fem.hpp"
#include "../linalg/dtensor.hpp"
#include <cmath>
#include <limits>
@@ -22,13 +21,6 @@ namespace mfem
using namespace std;
double QuadratureCoefficient::Eval(ElementTransformation & T,
const IntegrationPoint & ip)
{
auto coeff = mfem::Reshape(qData->HostRead(), nip, NE);
return coeff(ip.index, T.ElementNo);
}
double PWConstCoefficient::Eval(ElementTransformation & T,
const IntegrationPoint & ip)
{
@@ -327,6 +319,31 @@ void MatrixFunctionCoefficient::Eval(DenseMatrix &K, ElementTransformation &T,
}
}
void MatrixFunctionCoefficient::EvalSymmetric(Vector &K,
ElementTransformation &T,
const IntegrationPoint &ip)
{
MFEM_VERIFY(symmetric && height == width && height < 4 && SymmFunction,
"MatrixFunctionCoefficient is not symmetric");
double x[3];
Vector transip(x, 3);
T.Transform(ip, transip);
K.SetSize((width * (width + 1)) / 2); // 1x1: 1, 2x2: 3, 3x3: 6
if (SymmFunction)
{
(*SymmFunction)(transip, K);
}
if (Q)
{
K *= Q->Eval(T, ip, GetTime());
}
}
MatrixArrayCoefficient::MatrixArrayCoefficient (int dim)
: MatrixCoefficient (dim)
{
+34 -29
View File
@@ -87,33 +87,6 @@ public:
{ return (constant); }
};
/// class for quadrature coefficient
class QuadratureCoefficient : public Coefficient
{
private:
const int nip;
const int NE;
public:
Vector *qData{nullptr};
//Set external data
QuadratureCoefficient(Vector *Data, int in_nip, int in_NE)
: qData(Data), nip(in_nip), NE(in_NE)
{ }
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip);
Vector *Data()
{
return qData;
}
};
/// class for piecewise constant coefficient
/** @brief A piecewise constant coefficient with the constants keyed
off the element attribute numbers. */
class PWConstCoefficient : public Coefficient
@@ -722,13 +695,16 @@ class MatrixCoefficient
protected:
int height, width;
double time;
bool symmetric;
public:
/// Construct a dim x dim matrix coefficient.
explicit MatrixCoefficient(int dim) { height = width = dim; time = 0.; }
explicit MatrixCoefficient(int dim, bool symm=false)
{ height = width = dim; time = 0.; symmetric = symm; }
/// Construct a h x w matrix coefficient.
MatrixCoefficient(int h, int w) : height(h), width(w), time(0.) { }
MatrixCoefficient(int h, int w, bool symm=false) :
height(h), width(w), time(0.), symmetric(symm) { }
/// Set the time for time dependent coefficients
void SetTime(double t) { time = t; }
@@ -745,6 +721,9 @@ public:
/// For backward compatibility get the width of the matrix.
int GetVDim() const { return width; }
void SetSymmetric(bool s) { symmetric = s; }
bool IsSymmetric() const { return symmetric; }
/** @brief Evaluate the matrix coefficient in the element described by @a T
at the point @a ip, storing the result in @a K. */
/** @note When this method is called, the caller must make sure that the
@@ -753,6 +732,15 @@ public:
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip) = 0;
/** @brief Evaluate the upper triangular entries of the matrix coefficient
in the symmetric case, similarly to Eval. Matrix entry (i,j) is stored
in K[j - i + os_i] for 0 <= i <= j < width, os_0 = 0,
os_{i+1} = os_i + width - i. That is, K = {M(0,0), ..., M(0,w-1),
M(1,1), ..., M(1,w-1), ..., M(w-1,w-1) with w = width. */
virtual void EvalSymmetric(Vector &K, ElementTransformation &T,
const IntegrationPoint &ip)
{ mfem_error("MatrixCoefficient::EvalSymmetric"); }
virtual ~MatrixCoefficient() { }
};
@@ -780,6 +768,7 @@ class MatrixFunctionCoefficient : public MatrixCoefficient
{
private:
void (*Function)(const Vector &, DenseMatrix &);
void (*SymmFunction)(const Vector &, Vector &);
void (*TDFunction)(const Vector &, double, DenseMatrix &);
Coefficient *Q;
DenseMatrix mat;
@@ -817,10 +806,26 @@ public:
mat.SetSize(0);
}
/// Construct a symmetric square matrix coefficient from a C-function
/// defining a vector function used by EvalSymmetric
MatrixFunctionCoefficient(int dim, void (*F)(const Vector &, Vector &),
Coefficient *q = NULL)
: MatrixCoefficient(dim, true), Q(q)
{
SymmFunction = F;
Function = NULL;
TDFunction = NULL;
mat.SetSize(0);
}
/// Evaluate the matrix coefficient at @a ip.
virtual void Eval(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip);
/// Evaluate the symmetric matrix coefficient at @a ip.
virtual void EvalSymmetric(Vector &K, ElementTransformation &T,
const IntegrationPoint &ip);
virtual ~MatrixFunctionCoefficient() { }
};
+326 -159
View File
@@ -10,6 +10,7 @@
// CONTRIBUTING.md for details.
#include "complex_fem.hpp"
#include "../general/forall.hpp"
using namespace std;
@@ -19,16 +20,21 @@ namespace mfem
ComplexGridFunction::ComplexGridFunction(FiniteElementSpace *fes)
: Vector(2*(fes->GetVSize()))
{
gfr = new GridFunction(fes, data);
gfi = new GridFunction(fes, &data[fes->GetVSize()]);
UseDevice(true);
this->Vector::operator=(0.0);
gfr = new GridFunction();
gfr->MakeRef(fes, *this, 0);
gfi = new GridFunction();
gfi->MakeRef(fes, *this, fes->GetVSize());
}
void
ComplexGridFunction::Update()
{
FiniteElementSpace * fes = gfr->FESpace();
int vsize = fes->GetVSize();
FiniteElementSpace *fes = gfr->FESpace();
const int vsize = fes->GetVSize();
const Operator *T = fes->GetUpdateOperator();
if (T)
@@ -40,30 +46,36 @@ ComplexGridFunction::Update()
// Our data array now contains old data as well as being the wrong size so
// reallocate it.
UseDevice(true);
this->SetSize(2 * vsize);
this->Vector::operator=(0.0);
// Create temporary vectors which point to the new data array
Vector gf_r(data, vsize);
Vector gf_i((data) ? &data[vsize] : data, vsize);
Vector gf_r; gf_r.MakeRef(*this, 0, vsize);
Vector gf_i; gf_i.MakeRef(*this, vsize, vsize);
// Copy the updated GridFunctions into the new data array
gf_r = *gfr;
gf_i = *gfi;
gf_r.SyncAliasMemory(*this);
gf_i.SyncAliasMemory(*this);
// Replace the individual data arrays with pointers into the new data
// array
gfr->NewDataAndSize(data, vsize);
gfi->NewDataAndSize((data) ? &data[vsize] : data, vsize);
gfr->MakeRef(*this, 0, vsize);
gfi->MakeRef(*this, vsize, vsize);
}
else
{
// The existing data will not be transferred to the new GridFunctions so
// delete it a allocate a new array
// delete it and allocate a new array
UseDevice(true);
this->SetSize(2 * vsize);
this->Vector::operator=(0.0);
// Point the individual GridFunctions to the new data array
gfr->NewDataAndSize(data, vsize);
gfi->NewDataAndSize((data) ? &data[vsize] : data, vsize);
gfr->MakeRef(*this, 0, vsize);
gfi->MakeRef(*this, vsize, vsize);
// These updates will only set the proper 'sequence' value within the
// individual GridFunction objects because their sizes are already correct
@@ -76,16 +88,24 @@ void
ComplexGridFunction::ProjectCoefficient(Coefficient &real_coeff,
Coefficient &imag_coeff)
{
gfr->SyncMemory(*this);
gfi->SyncMemory(*this);
gfr->ProjectCoefficient(real_coeff);
gfi->ProjectCoefficient(imag_coeff);
gfr->SyncAliasMemory(*this);
gfi->SyncAliasMemory(*this);
}
void
ComplexGridFunction::ProjectCoefficient(VectorCoefficient &real_vcoeff,
VectorCoefficient &imag_vcoeff)
{
gfr->SyncMemory(*this);
gfi->SyncMemory(*this);
gfr->ProjectCoefficient(real_vcoeff);
gfi->ProjectCoefficient(imag_vcoeff);
gfr->SyncAliasMemory(*this);
gfi->SyncAliasMemory(*this);
}
void
@@ -93,8 +113,12 @@ ComplexGridFunction::ProjectBdrCoefficient(Coefficient &real_coeff,
Coefficient &imag_coeff,
Array<int> &attr)
{
gfr->SyncMemory(*this);
gfi->SyncMemory(*this);
gfr->ProjectBdrCoefficient(real_coeff, attr);
gfi->ProjectBdrCoefficient(imag_coeff, attr);
gfr->SyncAliasMemory(*this);
gfi->SyncAliasMemory(*this);
}
void
@@ -102,8 +126,12 @@ ComplexGridFunction::ProjectBdrCoefficientNormal(VectorCoefficient &real_vcoeff,
VectorCoefficient &imag_vcoeff,
Array<int> &attr)
{
gfr->SyncMemory(*this);
gfi->SyncMemory(*this);
gfr->ProjectBdrCoefficientNormal(real_vcoeff, attr);
gfi->ProjectBdrCoefficientNormal(imag_vcoeff, attr);
gfr->SyncAliasMemory(*this);
gfi->SyncAliasMemory(*this);
}
void
@@ -113,18 +141,28 @@ ComplexGridFunction::ProjectBdrCoefficientTangent(VectorCoefficient
&imag_vcoeff,
Array<int> &attr)
{
gfr->SyncMemory(*this);
gfi->SyncMemory(*this);
gfr->ProjectBdrCoefficientTangent(real_vcoeff, attr);
gfi->ProjectBdrCoefficientTangent(imag_vcoeff, attr);
gfr->SyncAliasMemory(*this);
gfi->SyncAliasMemory(*this);
}
ComplexLinearForm::ComplexLinearForm(FiniteElementSpace *f,
ComplexLinearForm::ComplexLinearForm(FiniteElementSpace *fes,
ComplexOperator::Convention convention)
: Vector(2*(f->GetVSize())),
: Vector(2*(fes->GetVSize())),
conv(convention)
{
lfr = new LinearForm(f, data);
lfi = new LinearForm(f, &data[f->GetVSize()]);
UseDevice(true);
this->Vector::operator=(0.0);
lfr = new LinearForm();
lfr->MakeRef(fes, *this, 0);
lfi = new LinearForm();
lfi->MakeRef(fes, *this, fes->GetVSize());
}
ComplexLinearForm::ComplexLinearForm(FiniteElementSpace *fes,
@@ -133,8 +171,14 @@ ComplexLinearForm::ComplexLinearForm(FiniteElementSpace *fes,
: Vector(2*(fes->GetVSize())),
conv(convention)
{
lfr = new LinearForm(fes, lf_r); lfr->SetData(data);
lfi = new LinearForm(fes, lf_i); lfi->SetData(&data[fes->GetVSize()]);
UseDevice(true);
this->Vector::operator=(0.0);
lfr = new LinearForm(fes, lf_r);
lfi = new LinearForm(fes, lf_i);
lfr->MakeRef(fes, *this, 0);
lfi->MakeRef(fes, *this, fes->GetVSize());
}
ComplexLinearForm::~ComplexLinearForm()
@@ -189,42 +233,43 @@ void
ComplexLinearForm::Update()
{
FiniteElementSpace *fes = lfr->FESpace();
this->Update(fes);
}
void
ComplexLinearForm::Update(FiniteElementSpace *fes)
{
int vsize = fes->GetVSize();
SetSize(2 * vsize);
UseDevice(true);
SetSize(2 * fes->GetVSize());
this->Vector::operator=(0.0);
Vector vlfr(data, vsize);
Vector vlfi((data) ? &data[vsize] : data, vsize);
lfr->Update(fes, vlfr, 0);
lfi->Update(fes, vlfi, 0);
lfr->MakeRef(fes, *this, 0);
lfi->MakeRef(fes, *this, fes->GetVSize());
}
void
ComplexLinearForm::Assemble()
{
lfr->SyncMemory(*this);
lfi->SyncMemory(*this);
lfr->Assemble();
lfi->Assemble();
if (conv == ComplexOperator::BLOCK_SYMMETRIC)
{
*lfi *= -1.0;
}
if (conv == ComplexOperator::BLOCK_SYMMETRIC) { *lfi *= -1.0; }
lfr->SyncAliasMemory(*this);
lfi->SyncAliasMemory(*this);
}
complex<double>
ComplexLinearForm::operator()(const ComplexGridFunction &gf) const
{
double s = (conv == ComplexOperator::HERMITIAN)?1.0:-1.0;
double s = (conv == ComplexOperator::HERMITIAN) ? 1.0 : -1.0;
lfr->SyncMemory(*this);
lfi->SyncMemory(*this);
return complex<double>((*lfr)(gf.real()) - s * (*lfi)(gf.imag()),
(*lfr)(gf.imag()) + s * (*lfi)(gf.real()));
}
bool SesquilinearForm::RealInteg()
{
int nint = blfr->GetFBFI()->Size() + blfr->GetDBFI()->Size() +
@@ -341,34 +386,45 @@ SesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
Vector &X, Vector &B,
int ci)
{
FiniteElementSpace * fes = blfr->FESpace();
int vsize = fes->GetVSize();
FiniteElementSpace *fes = blfr->FESpace();
const int vsize = fes->GetVSize();
// Allocate temporary vectors
Vector b_0(vsize); b_0 = 0.0;
// Allocate temporary vector
Vector b_0;
b_0.UseDevice(true);
b_0.SetSize(vsize);
b_0 = 0.0;
// Extract the real and imaginary parts of the input vectors
MFEM_ASSERT(x.Size() == 2 * vsize, "Input GridFunction of incorrect size!");
Vector x_r(x.GetData(), vsize);
Vector x_i(&(x.GetData())[vsize], vsize);
x.Read();
Vector x_r; x_r.MakeRef(x, 0, vsize);
Vector x_i; x_i.MakeRef(x, vsize, vsize);
MFEM_ASSERT(b.Size() == 2 * vsize, "Input LinearForm of incorrect size!");
Vector b_r(b.GetData(), vsize);
Vector b_i(&(b.GetData())[vsize], vsize);
b.Read();
Vector b_r; b_r.MakeRef(b, 0, vsize);
Vector b_i; b_i.MakeRef(b, vsize, vsize);
if (conv == ComplexOperator::BLOCK_SYMMETRIC) { b_i *= -1.0; }
int tvsize = fes->GetTrueVSize();
const int tvsize = fes->GetTrueVSize();
OperatorHandle A_r, A_i;
X.UseDevice(true);
X.SetSize(2 * tvsize);
B.SetSize(2 * tvsize);
X = 0.0;
Vector X_0(tvsize), B_0(tvsize);
Vector X_r(X.GetData(),tvsize);
Vector X_i(&(X.GetData())[tvsize], tvsize);
Vector B_r(B.GetData(), tvsize);
Vector B_i(&(B.GetData())[tvsize], tvsize);
B.UseDevice(true);
B.SetSize(2 * tvsize);
B = 0.0;
Vector X_r; X_r.MakeRef(X, 0, tvsize);
Vector X_i; X_i.MakeRef(X, tvsize, tvsize);
Vector B_r; B_r.MakeRef(B, 0, tvsize);
Vector B_i; B_i.MakeRef(B, tvsize, tvsize);
Vector X_0, B_0;
if (RealInteg())
{
@@ -418,13 +474,18 @@ SesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
// conform with standard essential BC treatment
if (A_i.Is<ConstrainedOperator>())
{
int n = ess_tdof_list.Size();
for (int k = 0; k < n; k++)
const int n = ess_tdof_list.Size();
auto d_B_r = B_r.Write();
auto d_B_i = B_i.Write();
auto d_X_r = X_r.Read();
auto d_X_i = X_i.Read();
auto d_idx = ess_tdof_list.Read();
MFEM_FORALL(i, n,
{
int j = ess_tdof_list[k];
B_r(j) = X_r(j);
B_i(j) = X_i(j);
}
const int j = d_idx[i];
d_B_r[j] = d_X_r[j];
d_B_i[j] = d_X_i[j];
});
A_i.As<ConstrainedOperator>()->SetDiagonalPolicy
(mfem::Operator::DiagonalPolicy::DIAG_ZERO);
}
@@ -436,6 +497,16 @@ SesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
b_i *= -1.0;
}
x_r.SyncAliasMemory(x);
x_i.SyncAliasMemory(x);
b_r.SyncAliasMemory(b);
b_i.SyncAliasMemory(b);
X_r.SyncAliasMemory(X);
X_i.SyncAliasMemory(X);
B_r.SyncAliasMemory(B);
B_i.SyncAliasMemory(B);
// A = A_r + i A_i
A.Clear();
if ( A_r.Type() == Operator::MFEM_SPARSEMAT ||
@@ -528,29 +599,32 @@ void
SesquilinearForm::RecoverFEMSolution(const Vector &X, const Vector &b,
Vector &x)
{
FiniteElementSpace * fes = blfr->FESpace();
FiniteElementSpace *fes = blfr->FESpace();
const SparseMatrix *P = fes->GetConformingProlongation();
int vsize = fes->GetVSize();
int tvsize = X.Size() / 2;
Vector X_r(X.GetData(), tvsize);
Vector X_i(&(X.GetData())[tvsize], tvsize);
Vector x_r(x.GetData(), vsize);
Vector x_i(&(x.GetData())[vsize], vsize);
if (!P)
{
x = X;
return;
}
else
{
// Apply conforming prolongation
P->Mult(X_r, x_r);
P->Mult(X_i, x_i);
}
const int vsize = fes->GetVSize();
const int tvsize = X.Size() / 2;
X.Read();
Vector X_r; X_r.MakeRef(const_cast<Vector&>(X), 0, tvsize);
Vector X_i; X_i.MakeRef(const_cast<Vector&>(X), tvsize, tvsize);
x.Write();
Vector x_r; x_r.MakeRef(x, 0, vsize);
Vector x_i; x_i.MakeRef(x, vsize, vsize);
// Apply conforming prolongation
P->Mult(X_r, x_r);
P->Mult(X_i, x_i);
x_r.SyncAliasMemory(x);
x_i.SyncAliasMemory(x);
}
void
@@ -566,16 +640,21 @@ SesquilinearForm::Update(FiniteElementSpace *nfes)
ParComplexGridFunction::ParComplexGridFunction(ParFiniteElementSpace *pfes)
: Vector(2*(pfes->GetVSize()))
{
pgfr = new ParGridFunction(pfes, data);
pgfi = new ParGridFunction(pfes, (data) ? &data[pfes->GetVSize()]:data);
UseDevice(true);
this->Vector::operator=(0.0);
pgfr = new ParGridFunction();
pgfr->MakeRef(pfes, *this, 0);
pgfi = new ParGridFunction();
pgfi->MakeRef(pfes, *this, pfes->GetVSize());
}
void
ParComplexGridFunction::Update()
{
ParFiniteElementSpace * pfes = pgfr->ParFESpace();
int vsize = pfes->GetVSize();
ParFiniteElementSpace *pfes = pgfr->ParFESpace();
const int vsize = pfes->GetVSize();
const Operator *T = pfes->GetUpdateOperator();
if (T)
@@ -587,30 +666,34 @@ ParComplexGridFunction::Update()
// Our data array now contains old data as well as being the wrong size so
// reallocate it.
UseDevice(true);
this->SetSize(2 * vsize);
this->Vector::operator=(0.0);
// Create temporary vectors which point to the new data array
Vector gf_r(data, vsize);
Vector gf_i((data) ? &data[vsize] : data, vsize);
Vector gf_r; gf_r.MakeRef(*this, 0, vsize);
Vector gf_i; gf_i.MakeRef(*this, vsize, vsize);
// Copy the updated GridFunctions into the new data array
gf_r = *pgfr;
gf_i = *pgfi;
gf_r = *pgfr; gf_r.SyncAliasMemory(*this);
gf_i = *pgfi; gf_i.SyncAliasMemory(*this);
// Replace the individual data arrays with pointers into the new data
// array
pgfr->NewDataAndSize(data, vsize);
pgfi->NewDataAndSize((data) ? &data[vsize] : data, vsize);
pgfr->MakeRef(*this, 0, vsize);
pgfi->MakeRef(*this, vsize, vsize);
}
else
{
// The existing data will not be transferred to the new GridFunctions so
// delete it a allocate a new array
// delete it and allocate a new array
UseDevice(true);
this->SetSize(2 * vsize);
this->Vector::operator=(0.0);
// Point the individual GridFunctions to the new data array
pgfr->NewDataAndSize(data, vsize);
pgfi->NewDataAndSize((data) ? &data[vsize] : data, vsize);
pgfr->MakeRef(*this, 0, vsize);
pgfi->MakeRef(*this, vsize, vsize);
// These updates will only set the proper 'sequence' value within the
// individual GridFunction objects because their sizes are already correct
@@ -623,16 +706,24 @@ void
ParComplexGridFunction::ProjectCoefficient(Coefficient &real_coeff,
Coefficient &imag_coeff)
{
pgfr->SyncMemory(*this);
pgfi->SyncMemory(*this);
pgfr->ProjectCoefficient(real_coeff);
pgfi->ProjectCoefficient(imag_coeff);
pgfr->SyncAliasMemory(*this);
pgfi->SyncAliasMemory(*this);
}
void
ParComplexGridFunction::ProjectCoefficient(VectorCoefficient &real_vcoeff,
VectorCoefficient &imag_vcoeff)
{
pgfr->SyncMemory(*this);
pgfi->SyncMemory(*this);
pgfr->ProjectCoefficient(real_vcoeff);
pgfi->ProjectCoefficient(imag_vcoeff);
pgfr->SyncAliasMemory(*this);
pgfi->SyncAliasMemory(*this);
}
void
@@ -640,8 +731,12 @@ ParComplexGridFunction::ProjectBdrCoefficient(Coefficient &real_coeff,
Coefficient &imag_coeff,
Array<int> &attr)
{
pgfr->SyncMemory(*this);
pgfi->SyncMemory(*this);
pgfr->ProjectBdrCoefficient(real_coeff, attr);
pgfi->ProjectBdrCoefficient(imag_coeff, attr);
pgfr->SyncAliasMemory(*this);
pgfi->SyncAliasMemory(*this);
}
void
@@ -651,8 +746,12 @@ ParComplexGridFunction::ProjectBdrCoefficientNormal(VectorCoefficient
&imag_vcoeff,
Array<int> &attr)
{
pgfr->SyncMemory(*this);
pgfi->SyncMemory(*this);
pgfr->ProjectBdrCoefficientNormal(real_vcoeff, attr);
pgfi->ProjectBdrCoefficientNormal(imag_vcoeff, attr);
pgfr->SyncAliasMemory(*this);
pgfi->SyncAliasMemory(*this);
}
void
@@ -662,36 +761,51 @@ ParComplexGridFunction::ProjectBdrCoefficientTangent(VectorCoefficient
&imag_vcoeff,
Array<int> &attr)
{
pgfr->SyncMemory(*this);
pgfi->SyncMemory(*this);
pgfr->ProjectBdrCoefficientTangent(real_vcoeff, attr);
pgfi->ProjectBdrCoefficientTangent(imag_vcoeff, attr);
pgfr->SyncAliasMemory(*this);
pgfi->SyncAliasMemory(*this);
}
void
ParComplexGridFunction::Distribute(const Vector *tv)
{
ParFiniteElementSpace * pfes = pgfr->ParFESpace();
HYPRE_Int size = pfes->GetTrueVSize();
ParFiniteElementSpace *pfes = pgfr->ParFESpace();
const int tvsize = pfes->GetTrueVSize();
double * tvd = tv->GetData();
Vector tvr(tvd, size);
Vector tvi((tvd) ? &tvd[size] : tvd, size);
tv->Read();
Vector tvr; tvr.MakeRef(const_cast<Vector&>(*tv), 0, tvsize);
Vector tvi; tvi.MakeRef(const_cast<Vector&>(*tv), tvsize, tvsize);
pgfr->SyncMemory(*this);
pgfi->SyncMemory(*this);
pgfr->Distribute(tvr);
pgfi->Distribute(tvi);
pgfr->SyncAliasMemory(*this);
pgfi->SyncAliasMemory(*this);
}
void
ParComplexGridFunction::ParallelProject(Vector &tv) const
{
ParFiniteElementSpace * pfes = pgfr->ParFESpace();
HYPRE_Int size = pfes->GetTrueVSize();
ParFiniteElementSpace *pfes = pgfr->ParFESpace();
const int tvsize = pfes->GetTrueVSize();
double * tvd = tv.GetData();
Vector tvr(tvd, size);
Vector tvi((tvd) ? &tvd[size] : tvd, size);
tv.Write();
Vector tvr; tvr.MakeRef(tv, 0, tvsize);
Vector tvi; tvi.MakeRef(tv, tvsize, tvsize);
pgfr->SyncMemory(*this);
pgfi->SyncMemory(*this);
pgfr->ParallelProject(tvr);
pgfi->ParallelProject(tvi);
pgfr->SyncAliasMemory(*this);
pgfi->SyncAliasMemory(*this);
tvr.SyncAliasMemory(tv);
tvi.SyncAliasMemory(tv);
}
@@ -701,10 +815,16 @@ ParComplexLinearForm::ParComplexLinearForm(ParFiniteElementSpace *pfes,
: Vector(2*(pfes->GetVSize())),
conv(convention)
{
plfr = new ParLinearForm(pfes, data);
plfi = new ParLinearForm(pfes, (data) ? &data[pfes->GetVSize()]:data);
UseDevice(true);
this->Vector::operator=(0.0);
HYPRE_Int * tdof_offsets_fes = pfes->GetTrueDofOffsets();
plfr = new ParLinearForm();
plfr->MakeRef(pfes, *this, 0);
plfi = new ParLinearForm();
plfi->MakeRef(pfes, *this, pfes->GetVSize());
HYPRE_Int *tdof_offsets_fes = pfes->GetTrueDofOffsets();
int n = (HYPRE_AssumedPartitionCheck()) ? 2 : pfes->GetNRanks();
tdof_offsets = new HYPRE_Int[n+1];
@@ -724,12 +844,16 @@ ParComplexLinearForm::ParComplexLinearForm(ParFiniteElementSpace *pfes,
: Vector(2*(pfes->GetVSize())),
conv(convention)
{
plfr = new ParLinearForm(pfes, plf_r);
plfr->SetData(data);
plfi = new ParLinearForm(pfes, plf_i);
plfi->SetData((data) ? &data[pfes->GetVSize()]:data);
UseDevice(true);
this->Vector::operator=(0.0);
HYPRE_Int * tdof_offsets_fes = pfes->GetTrueDofOffsets();
plfr = new ParLinearForm(pfes, plf_r);
plfi = new ParLinearForm(pfes, plf_i);
plfr->MakeRef(pfes, *this, 0);
plfi->MakeRef(pfes, *this, pfes->GetVSize());
HYPRE_Int *tdof_offsets_fes = pfes->GetTrueDofOffsets();
int n = (HYPRE_AssumedPartitionCheck()) ? 2 : pfes->GetNRanks();
tdof_offsets = new HYPRE_Int[n+1];
@@ -792,58 +916,71 @@ ParComplexLinearForm::AddBdrFaceIntegrator(LinearFormIntegrator *lfi_real,
void
ParComplexLinearForm::Update(ParFiniteElementSpace *pf)
{
ParFiniteElementSpace *pfes = (pf!=NULL)?pf:plfr->ParFESpace();
int vsize = pfes->GetVSize();
SetSize(2 * vsize);
ParFiniteElementSpace *pfes = (pf != NULL) ? pf : plfr->ParFESpace();
Vector vplfr(data, vsize);
Vector vplfi((data) ? &data[vsize] : data, vsize);
UseDevice(true);
SetSize(2 * pfes->GetVSize());
this->Vector::operator=(0.0);
plfr->Update(pfes, vplfr, 0);
plfi->Update(pfes, vplfi, 0);
plfr->MakeRef(pfes, *this, 0);
plfi->MakeRef(pfes, *this, pfes->GetVSize());
}
void
ParComplexLinearForm::Assemble()
{
plfr->SyncMemory(*this);
plfi->SyncMemory(*this);
plfr->Assemble();
plfi->Assemble();
if (conv == ComplexOperator::BLOCK_SYMMETRIC)
{
*plfi *= -1.0;
}
if (conv == ComplexOperator::BLOCK_SYMMETRIC) { *plfi *= -1.0; }
plfr->SyncAliasMemory(*this);
plfi->SyncAliasMemory(*this);
}
void
ParComplexLinearForm::ParallelAssemble(Vector &tv)
{
HYPRE_Int size = plfr->ParFESpace()->GetTrueVSize();
const int tvsize = plfr->ParFESpace()->GetTrueVSize();
double * tvd = tv.GetData();
Vector tvr(tvd, size);
Vector tvi((tvd) ? &tvd[size] : tvd, size);
tv.Write();
Vector tvr; tvr.MakeRef(tv, 0, tvsize);
Vector tvi; tvi.MakeRef(tv, tvsize, tvsize);
plfr->SyncMemory(*this);
plfi->SyncMemory(*this);
plfr->ParallelAssemble(tvr);
plfi->ParallelAssemble(tvi);
plfr->SyncAliasMemory(*this);
plfi->SyncAliasMemory(*this);
tvr.SyncAliasMemory(tv);
tvi.SyncAliasMemory(tv);
}
HypreParVector *
ParComplexLinearForm::ParallelAssemble()
{
const ParFiniteElementSpace * pfes = plfr->ParFESpace();
const ParFiniteElementSpace *pfes = plfr->ParFESpace();
const int tvsize = pfes->GetTrueVSize();
HypreParVector * tv = new HypreParVector(pfes->GetComm(),
2*(pfes->GlobalTrueVSize()),
tdof_offsets);
HypreParVector *tv = new HypreParVector(pfes->GetComm(),
2*(pfes->GlobalTrueVSize()),
tdof_offsets);
HYPRE_Int size = pfes->GetTrueVSize();
double * tvd = tv->GetData();
Vector tvr(tvd, size);
Vector tvi((tvd) ? &tvd[size] : tvd, size);
tv->Write();
Vector tvr; tvr.MakeRef(*tv, 0, tvsize);
Vector tvi; tvi.MakeRef(*tv, tvsize, tvsize);
plfr->SyncMemory(*this);
plfi->SyncMemory(*this);
plfr->ParallelAssemble(tvr);
plfi->ParallelAssemble(tvi);
plfr->SyncAliasMemory(*this);
plfi->SyncAliasMemory(*this);
tvr.SyncAliasMemory(*tv);
tvi.SyncAliasMemory(*tv);
return tv;
}
@@ -851,13 +988,14 @@ ParComplexLinearForm::ParallelAssemble()
complex<double>
ParComplexLinearForm::operator()(const ParComplexGridFunction &gf) const
{
double s = (conv == ComplexOperator::HERMITIAN)?1.0:-1.0;
plfr->SyncMemory(*this);
plfi->SyncMemory(*this);
double s = (conv == ComplexOperator::HERMITIAN) ? 1.0 : -1.0;
return complex<double>((*plfr)(gf.real()) - s * (*plfi)(gf.imag()),
(*plfr)(gf.imag()) + s * (*plfi)(gf.real()));
}
bool ParSesquilinearForm::RealInteg()
{
int nint = pblfr->GetFBFI()->Size() + pblfr->GetDBFI()->Size() +
@@ -964,7 +1102,6 @@ ParSesquilinearForm::ParallelAssemble()
return new ComplexHypreParMatrix(pblfr->ParallelAssemble(),
pblfi->ParallelAssemble(),
true, true, conv);
}
void
@@ -974,35 +1111,45 @@ ParSesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
Vector &X, Vector &B,
int ci)
{
ParFiniteElementSpace * pfes = pblfr->ParFESpace();
int vsize = pfes->GetVSize();
ParFiniteElementSpace *pfes = pblfr->ParFESpace();
const int vsize = pfes->GetVSize();
// Allocate temporary vectors
Vector b_0(vsize); b_0 = 0.0;
// Allocate temporary vector
Vector b_0;
b_0.UseDevice(true);
b_0.SetSize(vsize);
b_0 = 0.0;
// Extract the real and imaginary parts of the input vectors
MFEM_ASSERT(x.Size() == 2 * vsize, "Input GridFunction of incorrect size!");
Vector x_r(x.GetData(), vsize);
Vector x_i(&(x.GetData())[vsize], vsize);
x.Read();
Vector x_r; x_r.MakeRef(x, 0, vsize);
Vector x_i; x_i.MakeRef(x, vsize, vsize);
MFEM_ASSERT(b.Size() == 2 * vsize, "Input LinearForm of incorrect size!");
Vector b_r(b.GetData(), vsize);
Vector b_i(&(b.GetData())[vsize], vsize);
b.Read();
Vector b_r; b_r.MakeRef(b, 0, vsize);
Vector b_i; b_i.MakeRef(b, vsize, vsize);
if (conv == ComplexOperator::BLOCK_SYMMETRIC) { b_i *= -1.0; }
int tvsize = pfes->GetTrueVSize();
const int tvsize = pfes->GetTrueVSize();
OperatorHandle A_r, A_i;
X.UseDevice(true);
X.SetSize(2 * tvsize);
B.SetSize(2 * tvsize);
X = 0.0;
Vector X_0(tvsize), B_0(tvsize);
Vector X_r(X.GetData(),tvsize);
Vector X_i(&(X.GetData())[tvsize], tvsize);
Vector B_r(B.GetData(), tvsize);
Vector B_i(&(B.GetData())[tvsize], tvsize);
B.UseDevice(true);
B.SetSize(2 * tvsize);
B = 0.0;
Vector X_r; X_r.MakeRef(X, 0, tvsize);
Vector X_i; X_i.MakeRef(X, tvsize, tvsize);
Vector B_r; B_r.MakeRef(B, 0, tvsize);
Vector B_i; B_i.MakeRef(B, tvsize, tvsize);
Vector X_0, B_0;
if (RealInteg())
{
@@ -1042,24 +1189,29 @@ ParSesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
if (RealInteg() && ImagInteg())
{
int n = ess_tdof_list.Size();
// Modify RHS to conform with standard essential BC treatment
for (int k = 0; k < n; k++)
const int n = ess_tdof_list.Size();
auto d_B_r = B_r.Write();
auto d_B_i = B_i.Write();
auto d_X_r = X_r.Read();
auto d_X_i = X_i.Read();
auto d_idx = ess_tdof_list.Read();
MFEM_FORALL(i, n,
{
int j=ess_tdof_list[k];
B_r(j) = X_r(j);
B_i(j) = X_i(j);
}
const int j = d_idx[i];
d_B_r[j] = d_X_r[j];
d_B_i[j] = d_X_i[j];
});
// Modify offdiagonal blocks (imaginary parts of the matrix) to conform
// with standard essential BC treatment
if ( A_i.Type() == Operator::Hypre_ParCSR )
if (A_i.Type() == Operator::Hypre_ParCSR)
{
HypreParMatrix * Ah;
A_i.Get(Ah);
hypre_ParCSRMatrix *Aih = *Ah;
for (int k = 0; k < n; k++)
{
int j = ess_tdof_list[k];
const int j = ess_tdof_list[k];
Aih->diag->data[Aih->diag->i[j]] = 0.0;
}
}
@@ -1076,6 +1228,16 @@ ParSesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
b_i *= -1.0;
}
x_r.SyncAliasMemory(x);
x_i.SyncAliasMemory(x);
b_r.SyncAliasMemory(b);
b_i.SyncAliasMemory(b);
X_r.SyncAliasMemory(X);
X_i.SyncAliasMemory(X);
B_r.SyncAliasMemory(B);
B_i.SyncAliasMemory(B);
// A = A_r + i A_i
A.Clear();
if ( A_r.Type() == Operator::Hypre_ParCSR ||
@@ -1175,22 +1337,27 @@ void
ParSesquilinearForm::RecoverFEMSolution(const Vector &X, const Vector &b,
Vector &x)
{
ParFiniteElementSpace * pfes = pblfr->ParFESpace();
ParFiniteElementSpace *pfes = pblfr->ParFESpace();
const Operator &P = *pfes->GetProlongationMatrix();
int vsize = pfes->GetVSize();
int tvsize = X.Size() / 2;
const int vsize = pfes->GetVSize();
const int tvsize = X.Size() / 2;
Vector X_r(X.GetData(), tvsize);
Vector X_i(&(X.GetData())[tvsize], tvsize);
X.Read();
Vector X_r; X_r.MakeRef(const_cast<Vector&>(X), 0, tvsize);
Vector X_i; X_i.MakeRef(const_cast<Vector&>(X), tvsize, tvsize);
Vector x_r(x.GetData(), vsize);
Vector x_i(&(x.GetData())[vsize], vsize);
x.Write();
Vector x_r; x_r.MakeRef(x, 0, vsize);
Vector x_i; x_i.MakeRef(x, vsize, vsize);
// Apply conforming prolongation
P.Mult(X_r, x_r);
P.Mult(X_i, x_i);
x_r.SyncAliasMemory(x);
x_i.SyncAliasMemory(x);
}
void
+44 -11
View File
@@ -38,8 +38,8 @@ protected:
void Destroy() { delete gfr; delete gfi; }
public:
/* @brief Construct a ComplexGridFunction associated with the
FiniteElementSpace @a *f. */
/** @brief Construct a ComplexGridFunction associated with the
FiniteElementSpace @a *f. */
ComplexGridFunction(FiniteElementSpace *f);
void Update();
@@ -71,6 +71,14 @@ public:
const GridFunction & real() const { return *gfr; }
const GridFunction & imag() const { return *gfi; }
/// Update the memory location of the real and imaginary GridFunction @a gfr
/// and @a gfi to match the ComplexGridFunction.
void Sync() { gfr->SyncMemory(*this); gfi->SyncMemory(*this); }
/// Update the alias memory location of the real and imaginary GridFunction
/// @a gfr and @a gfi to match the ComplexGridFunction.
void SyncAlias() { gfr->SyncAliasMemory(*this); gfi->SyncAliasMemory(*this); }
/// Destroys the grid function.
virtual ~ComplexGridFunction() { Destroy(); }
@@ -99,8 +107,8 @@ public:
ComplexOperator::Convention
convention = ComplexOperator::HERMITIAN);
/** @brief Create a ComplexLinearForm on the FiniteElementSpace @a f, using
the same integrators as the LinearForms @a lfr (real) and @a lfi (imag) .
/** @brief Create a ComplexLinearForm on the FiniteElementSpace @a fes, using
the same integrators as the LinearForms @a lf_r (real) and @a lf_i (imag).
The pointer @a fes is not owned by the newly constructed object.
@@ -157,6 +165,14 @@ public:
const LinearForm & real() const { return *lfr; }
const LinearForm & imag() const { return *lfi; }
/// Update the memory location of the real and imaginary LinearForm @a lfr
/// and @a lfi to match the ComplexLinearForm.
void Sync() { lfr->SyncMemory(*this); lfi->SyncMemory(*this); }
/// Update the alias memory location of the real and imaginary LinearForm @a
/// lfr and @a lfi to match the ComplexLinearForm.
void SyncAlias() { lfr->SyncAliasMemory(*this); lfi->SyncAliasMemory(*this); }
void Update();
void Update(FiniteElementSpace *f);
@@ -195,8 +211,8 @@ private:
BilinearForm *blfr;
BilinearForm *blfi;
/* These methods check if the real/imag parts of the sesqulinear form are not
empty */
/* These methods check if the real/imag parts of the sesquilinear form are
not empty */
bool RealInteg();
bool ImagInteg();
@@ -204,7 +220,7 @@ public:
SesquilinearForm(FiniteElementSpace *fes,
ComplexOperator::Convention
convention = ComplexOperator::HERMITIAN);
/** @brief Create a SesquilinearForm on the FiniteElementSpace @a f, using
/** @brief Create a SesquilinearForm on the FiniteElementSpace @a fes, using
the same integrators as the BilinearForms @a bfr and @a bfi .
The pointer @a fes is not owned by the newly constructed object.
@@ -323,8 +339,8 @@ protected:
public:
/* @brief Construct a ParComplexGridFunction associated with the
ParFiniteElementSpace @a *f. */
/** @brief Construct a ParComplexGridFunction associated with the
ParFiniteElementSpace @a *pf. */
ParComplexGridFunction(ParFiniteElementSpace *pf);
void Update();
@@ -365,6 +381,15 @@ public:
const ParGridFunction & real() const { return *pgfr; }
const ParGridFunction & imag() const { return *pgfi; }
/// Update the memory location of the real and imaginary ParGridFunction @a
/// pgfr and @a pgfi to match the ParComplexGridFunction.
void Sync() { pgfr->SyncMemory(*this); pgfi->SyncMemory(*this); }
/// Update the alias memory location of the real and imaginary
/// ParGridFunction @a pgfr and @a pgfi to match the ParComplexGridFunction.
void SyncAlias() { pgfr->SyncAliasMemory(*this); pgfi->SyncAliasMemory(*this); }
virtual double ComputeL2Error(Coefficient &exsolr, Coefficient &exsoli,
const IntegrationRule *irs[] = NULL) const
{
@@ -416,8 +441,8 @@ public:
convention = ComplexOperator::HERMITIAN);
/** @brief Create a ParComplexLinearForm on the ParFiniteElementSpace @a pf,
using the same integrators as the LinearForms @a plfr (real) and @a plfi
(imag) .
using the same integrators as the LinearForms @a plf_r (real) and
@a plf_i (imag).
The pointer @a fes is not owned by the newly constructed object.
@@ -475,6 +500,14 @@ public:
const ParLinearForm & real() const { return *plfr; }
const ParLinearForm & imag() const { return *plfi; }
/// Update the memory location of the real and imaginary ParLinearForm @a lfr
/// and @a lfi to match the ParComplexLinearForm.
void Sync() { plfr->SyncMemory(*this); plfi->SyncMemory(*this); }
/// Update the alias memory location of the real and imaginary ParLinearForm
/// @a plfr and @a plfi to match the ParComplexLinearForm.
void SyncAlias() { plfr->SyncAliasMemory(*this); plfi->SyncAliasMemory(*this); }
void Update(ParFiniteElementSpace *pf = NULL);
/// Assembles the linear form i.e. sums over all domain/bdr integrators.
+297
View File
@@ -0,0 +1,297 @@
#include "convergence.hpp"
using namespace std;
namespace mfem
{
void ConvergenceStudy::Reset()
{
counter=0;
dcounter=0;
fcounter=0;
cont_type=-1;
print_flag=1;
L2Errors.SetSize(0);
L2Rates.SetSize(0);
DErrors.SetSize(0);
DRates.SetSize(0);
EnErrors.SetSize(0);
EnRates.SetSize(0);
DGFaceErrors.SetSize(0);
DGFaceRates.SetSize(0);
ndofs.SetSize(0);
}
double ConvergenceStudy::GetNorm(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *vector_u)
{
bool norm_set = false;
double norm=0.0;
int order = gf->FESpace()->GetOrder(0);
int order_quad = std::max(2, 2*order+1);
const IntegrationRule *irs[Geometry::NumGeom];
for (int i=0; i < Geometry::NumGeom; ++i)
{
irs[i] = &(IntRules.Get(i, order_quad));
}
#ifdef MFEM_USE_MPI
ParGridFunction *pgf = dynamic_cast<ParGridFunction *>(gf);
if (pgf)
{
ParMesh *pmesh = pgf->ParFESpace()->GetParMesh();
if (scalar_u)
{
norm = ComputeGlobalLpNorm(2.0,*scalar_u,*pmesh,irs);
}
else if (vector_u)
{
norm = ComputeGlobalLpNorm(2.0,*vector_u,*pmesh,irs);
}
norm_set = true;
}
#endif
if (!norm_set)
{
Mesh *mesh = gf->FESpace()->GetMesh();
if (scalar_u)
{
norm = ComputeLpNorm(2.0,*scalar_u,*mesh,irs);
}
else if (vector_u)
{
norm = ComputeLpNorm(2.0,*vector_u,*mesh,irs);
}
}
return norm;
}
void ConvergenceStudy::AddL2Error(GridFunction *gf,
Coefficient *scalar_u, VectorCoefficient *vector_u)
{
int tdofs=0;
#ifdef MFEM_USE_MPI
ParGridFunction *pgf = dynamic_cast<ParGridFunction *>(gf);
if (pgf)
{
MPI_Comm comm = pgf->ParFESpace()->GetComm();
int rank;
MPI_Comm_rank(comm, &rank);
print_flag = 0;
if (rank==0) { print_flag = 1; }
tdofs = pgf->ParFESpace()->GlobalTrueVSize();
}
#endif
if (!tdofs) { tdofs = gf->FESpace()->GetTrueVSize(); }
ndofs.Append(tdofs);
double L2Err;
if (scalar_u)
{
L2Err = gf->ComputeL2Error(*scalar_u);
CoeffNorm = GetNorm(gf,scalar_u,nullptr);
}
else if (vector_u)
{
L2Err = gf->ComputeL2Error(*vector_u);
CoeffNorm = GetNorm(gf,nullptr,vector_u);
}
else
{
MFEM_ABORT("Exact Solution Coefficient pointer is NULL");
}
L2Errors.Append(L2Err);
// Compute the rate of convergence by:
// rate = log (||u - u_h|| / ||u - u_{h/2}||)/log(2)
double val = (counter) ? log(L2Errors[counter-1]/L2Err)/log(2.0) : 0.0;
L2Rates.Append(val);
counter++;
}
void ConvergenceStudy::AddGf(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *grad,
Coefficient *ell_coeff, double Nu)
{
cont_type = gf->FESpace()->FEColl()->GetContType();
MFEM_VERIFY((cont_type == mfem::FiniteElementCollection::CONTINUOUS) ||
(cont_type == mfem::FiniteElementCollection::DISCONTINUOUS),
"This constructor is intended for H1 or L2 Elements")
AddL2Error(gf,scalar_u, nullptr);
if (grad)
{
double GradErr = gf->ComputeGradError(grad);
DErrors.Append(GradErr);
double err = sqrt(L2Errors[counter-1]*L2Errors[counter-1]+GradErr*GradErr);
EnErrors.Append(err);
// Compute the rate of convergence by:
// rate = log (||u - u_h|| / ||u - u_{h/2}||)/log(2)
double val = (dcounter) ? log(DErrors[dcounter-1]/GradErr)/log(2.0) : 0.0;
double eval = (dcounter) ? log(EnErrors[dcounter-1]/err)/log(2.0) : 0.0;
DRates.Append(val);
EnRates.Append(eval);
CoeffDNorm = GetNorm(gf,nullptr,grad);
dcounter++;
MFEM_VERIFY(counter == dcounter,
"Number of added solutions and derivatives do not match")
}
if (cont_type == mfem::FiniteElementCollection::DISCONTINUOUS && ell_coeff)
{
double DGErr = gf->ComputeDGFaceJumpError(scalar_u,ell_coeff,Nu);
DGFaceErrors.Append(DGErr);
// Compute the rate of convergence by:
// rate = log (||u - u_h|| / ||u - u_{h/2}||)/log(2)
double val=(fcounter) ? log(DGFaceErrors[fcounter-1]/DGErr)/log(2.0):0.;
DGFaceRates.Append(val);
fcounter++;
MFEM_VERIFY(fcounter == counter, "Number of added solutions mismatch");
}
}
void ConvergenceStudy::AddGf(GridFunction *gf, VectorCoefficient *vector_u,
VectorCoefficient *curl, Coefficient *div)
{
cont_type = gf->FESpace()->FEColl()->GetContType();
AddL2Error(gf,nullptr,vector_u);
double DErr = 0.0;
bool derivative = false;
if (curl)
{
DErr = gf->ComputeCurlError(curl);
CoeffDNorm = GetNorm(gf,nullptr,curl);
derivative = true;
}
else if (div)
{
DErr = gf->ComputeDivError(div);
// update coefficient norm
CoeffDNorm = GetNorm(gf,div,nullptr);
derivative = true;
}
if (derivative)
{
double err = sqrt(L2Errors[counter-1]*L2Errors[counter-1] + DErr*DErr);
DErrors.Append(DErr);
EnErrors.Append(err);
// Compute the rate of convergence by:
// rate = log (||u - u_h|| / ||u - u_{h/2}||)/log(2)
double val = (dcounter) ? log(DErrors[dcounter-1]/DErr)/log(2.0) : 0.0;
double eval = (dcounter) ? log(EnErrors[dcounter-1]/err)/log(2.0) : 0.0;
DRates.Append(val);
EnRates.Append(eval);
dcounter++;
MFEM_VERIFY(counter == dcounter,
"Number of added solutions and derivatives do not match")
}
}
void ConvergenceStudy::Print(bool relative, std::ostream &out)
{
if (print_flag)
{
std::string title = (relative) ? "Relative " : "Absolute ";
out << "\n";
out << " -------------------------------------------" << "\n";
out << std::setw(21) << title << "L2 Error " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::right<< std::setw(11)<< "DOFs "<< std::setw(13) << "Error ";
out << std::setw(15) << "Rate " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::setprecision(4);
double d = (relative) ? CoeffNorm : 1.0;
for (int i =0; i<counter; i++)
{
out << std::right << std::setw(10)<< ndofs[i] << std::setw(16)
<< std::scientific << L2Errors[i]/d << std::setw(13)
<< std::fixed << L2Rates[i] << "\n";
}
out << "\n";
if (dcounter == counter)
{
std::string dname;
switch (cont_type)
{
case 0: dname = "Grad"; break;
case 1: dname = "Curl"; break;
case 2: dname = "Div"; break;
case 3: dname = "DG Grad"; break;
default: break;
}
out << " -------------------------------------------" << "\n";
out << std::setw(21) << title << dname << " Error " << "\n";
out << " -------------------------------------------" << "\n";
out << std::right<<std::setw(11)<< "DOFs "<< std::setw(13) << "Error";
out << std::setw(15) << "Rate " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::setprecision(4);
d = (relative) ? CoeffDNorm : 1.0;
for (int i =0; i<dcounter; i++)
{
out << std::right << std::setw(10)<< ndofs[i] << std::setw(16)
<< std::scientific << DErrors[i]/d << std::setw(13)
<< std::fixed << DRates[i] << "\n";
}
out << "\n";
switch (cont_type)
{
case 0: dname = "H1"; break;
case 1: dname = "H(Curl)"; break;
case 2: dname = "H(Div)"; break;
case 3: dname = "DG H1"; break;
default: break;
}
if (dcounter)
{
d = (relative) ?
sqrt(CoeffNorm*CoeffNorm + CoeffDNorm*CoeffDNorm):1.0;
out << " -------------------------------------------" << "\n";
out << std::setw(21) << title << dname << " Error " << "\n";
out << " -------------------------------------------" << "\n";
out << std::right<< std::setw(11)<< "DOFs "<< std::setw(13);
out << "Error ";
out << std::setw(15) << "Rate " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::setprecision(4);
for (int i =0; i<dcounter; i++)
{
out << std::right << std::setw(10)<< ndofs[i] << std::setw(16)
<< std::scientific << EnErrors[i]/d << std::setw(13)
<< std::fixed << EnRates[i] << "\n";
}
out << "\n";
}
if (cont_type == 3 && fcounter)
{
out << " -------------------------------------------" << "\n";
out << " DG Face Jump Error " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::right<< std::setw(11)<< "DOFs "<< std::setw(13);
out << "Error ";
out << std::setw(15) << "Rate " << "\n";
out << " -------------------------------------------"
<< "\n";
out << std::setprecision(4);
for (int i =0; i<fcounter; i++)
{
out << std::right << std::setw(10)<< ndofs[i] << std::setw(16)
<< std::scientific << DGFaceErrors[i] << std::setw(13)
<< std::fixed << DGFaceRates[i] << "\n";
}
out << "\n";
}
}
}
}
} // namespace mfem
+149
View File
@@ -0,0 +1,149 @@
// Copyright (c) 2010-2020, 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.
#ifndef MFEM_CONVERGENCE
#define MFEM_CONVERGENCE
#include "../linalg/linalg.hpp"
#include "gridfunc.hpp"
#ifdef MFEM_USE_MPI
#include "pgridfunc.hpp"
#endif
namespace mfem
{
/** @brief Class to compute error and convergence rates.
It supports H1, H(curl) (ND elements), H(div) (RT elements) and L2 (DG).
For "smooth enough" solutions the Galerkin error measured in the appropriate
norm satisfies || u - u_h || ~ h^k
Here, k is called the asymptotic rate of convergence
For successive uniform h-refinements the rate can be estimated by
k = log(||u - u_h|| / ||u - u_{h/2}||)/log(2)
*/
class ConvergenceStudy
{
private:
// counters for solutions/derivatives
int counter=0;
int dcounter=0;
int fcounter=0;
// space continuity type
int cont_type=-1;
// printing flag for helpful for MPI calls
int print_flag=1;
// exact solution and derivatives
double CoeffNorm;
double CoeffDNorm;
// Arrays to store error/rates
Array<double> L2Errors, DGFaceErrors, DErrors, EnErrors;
Array<double> L2Rates, DGFaceRates, DRates, EnRates;
Array<int> ndofs;
void AddL2Error(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *vector_u);
void AddGf(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *grad=nullptr,
Coefficient *ell_coeff=nullptr, double Nu=1.0);
void AddGf(GridFunction *gf, VectorCoefficient *vector_u,
VectorCoefficient *curl, Coefficient *div);
// returns the L2-norm of scalar_u or vector_u
double GetNorm(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *vector_u);
public:
/// Clear any internal data
void Reset();
/// Add L2 GridFunction, the exact solution and possibly its gradient and/or
/// DG face jumps parameters
void AddL2GridFunction(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *grad=nullptr,
Coefficient *ell_coeff=nullptr, double Nu=1.0)
{
AddGf(gf, scalar_u, grad, ell_coeff, Nu);
}
/// Add H1 GridFunction, the exact solution and possibly its gradient
void AddH1GridFunction(GridFunction *gf, Coefficient *scalar_u,
VectorCoefficient *grad=nullptr)
{
AddGf(gf, scalar_u, grad);
}
/// Add H(curl) GridFunction, the exact solution and possibly its curl
void AddHcurlGridFunction(GridFunction *gf, VectorCoefficient *vector_u,
VectorCoefficient *curl=nullptr)
{
AddGf(gf, vector_u, curl, nullptr);
}
/// Add H(div) GridFunction, the exact solution and possibly its div
void AddHdivGridFunction(GridFunction *gf, VectorCoefficient *vector_u,
Coefficient *div=nullptr)
{
AddGf(gf,vector_u, nullptr, div);
}
/// Get the L2 error at step n
double GetL2Error(int n)
{
MFEM_VERIFY( n <= counter,"Step out of bounds")
return L2Errors[n];
}
/// Get all L2 errors
void GetL2Errors(Array<double> & L2Errors_)
{
L2Errors_ = L2Errors;
}
/// Get the Grad/Curl/Div error at step n
double GetDError(int n)
{
MFEM_VERIFY(n <= dcounter,"Step out of bounds")
return DErrors[n];
}
/// Get all Grad/Curl/Div errors
void GetDErrors(Array<double> & DErrors_)
{
DErrors_ = DErrors;
}
/// Get the DGFaceJumps error at step n
double GetDGFaceJumpsError(int n)
{
MFEM_VERIFY(n<= fcounter,"Step out of bounds")
return DGFaceErrors[n];
}
/// Get all DGFaceJumps errors
void GetDGFaceJumpsErrors(Array<double> & DGFaceErrors_)
{
DGFaceErrors_ = DGFaceErrors;
}
/// Print rates and errors
void Print(bool relative = false, std::ostream &out = mfem::out);
};
} // namespace mfem
#endif // MFEM_CONVERGENCE
+2
View File
@@ -563,6 +563,8 @@ void VisItDataCollection::LoadVisItRootFile(const std::string& root_name)
void VisItDataCollection::LoadMesh()
{
// GetMeshFileName() uses 'serial', so we need to set it in advance.
serial = (format == SERIAL_FORMAT);
std::string mesh_fname = GetMeshFileName();
named_ifgzstream file(mesh_fname);
// TODO: in parallel, check for errors on all processors
+17 -3
View File
@@ -77,6 +77,9 @@ public:
ElementTransformation();
/** @brief Force the reevaluation of the Jacobian in the next call. */
void Reset() { EvalState = 0; }
/** @brief Set the integration point @a ip that weights and Jacobians will
be evaluated at. */
void SetIntPoint(const IntegrationPoint *ip)
@@ -357,9 +360,17 @@ private:
// Evaluate the Hessian of the transformation at the IntPoint and store it
// in d2Fdx2.
virtual const DenseMatrix &EvalHessian();
public:
IsoparametricTransformation() : FElem(NULL) {}
/// Set the element that will be used to compute the transformations
void SetFE(const FiniteElement *FE) { FElem = FE; geom = FE->GetGeomType(); }
void SetFE(const FiniteElement *FE)
{
MFEM_ASSERT(FE != NULL, "Must provide a valid FiniteElement object!");
EvalState = (FE != FElem) ? 0 : EvalState;
FElem = FE; geom = FE->GetGeomType();
}
/// Get the current element used to compute the transformations
const FiniteElement* GetFE() const { return FElem; }
@@ -374,12 +385,15 @@ public:
the column-vector of all basis functions evaluated at \f$ \hat x \f$ .
The columns of @a P represent the control points in physical space
defining the transformation. */
void SetPointMat(const DenseMatrix &pm) { PointMat = pm; }
void SetPointMat(const DenseMatrix &pm) { PointMat = pm; EvalState = 0; }
/// Return the stored point matrix.
const DenseMatrix &GetPointMat() const { return PointMat; }
/// Write access to the stored point matrix. Use with caution.
/// @brief Write access to the stored point matrix. Use with caution.
/** If the point matrix is altered using this member function the Reset
function should also be called to force the reevaluation of the
Jacobian, etc.. */
DenseMatrix &GetPointMat() { return PointMat; }
/// Set the FiniteElement Geometry for the reference elements being used.
+203
View File
@@ -139,6 +139,12 @@ void FiniteElement::Project (
mfem_error ("FiniteElement::Project (...) (vector) is not overloaded !");
}
void FiniteElement::ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{
mfem_error ("FiniteElement::ProjectFromNodes() (vector) is not overloaded!");
}
void FiniteElement::ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{
@@ -925,6 +931,23 @@ void VectorFiniteElement::Project_RT(
}
}
void VectorFiniteElement::Project_RT(
const double *nk, const Array<int> &d2n,
Vector &vc, ElementTransformation &Trans, Vector &dofs) const
{
const int sdim = Trans.GetSpaceDim();
const bool square_J = (dim == sdim);
for (int k = 0; k < dof; k++)
{
Trans.SetIntPoint(&Nodes.IntPoint(k));
// dof_k = nk^t adj(J) xk
Vector vk(vc.GetData()+k*sdim, sdim);
dofs(k) = Trans.AdjugateJacobian().InnerProduct(vk, nk + d2n[k]*dim);
if (!square_J) { dofs(k) /= Trans.Weight(); }
}
}
void VectorFiniteElement::ProjectMatrixCoefficient_RT(
const double *nk, const Array<int> &d2n,
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
@@ -1101,6 +1124,19 @@ void VectorFiniteElement::Project_ND(
}
}
void VectorFiniteElement::Project_ND(
const double *tk, const Array<int> &d2t,
Vector &vc, ElementTransformation &Trans, Vector &dofs) const
{
for (int k = 0; k < dof; k++)
{
Trans.SetIntPoint(&Nodes.IntPoint(k));
Vector vk(vc.GetData()+k*dim, dim);
// dof_k = xk^t J tk
dofs(k) = Trans.Jacobian().InnerProduct(tk + d2t[k]*dim, vk);
}
}
void VectorFiniteElement::ProjectMatrixCoefficient_ND(
const double *tk, const Array<int> &d2t,
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
@@ -7034,6 +7070,95 @@ void Poly_1D::Basis::Eval(const double y, Vector &u, Vector &d) const
}
}
void Poly_1D::Basis::Eval(const double y, Vector &u, Vector &d,
Vector &d2) const
{
MFEM_VERIFY(etype == Barycentric,
"Basis::Eval with second order derivatives not implemented for"
" etype = " << etype);
switch (etype)
{
case ChangeOfBasis:
{
CalcBasis(Ai.Width() - 1, y, x, w);
Ai.Mult(x, u);
Ai.Mult(w, d);
// set d2 (not implemented yet)
break;
}
case Barycentric:
{
int i, k, p = x.Size() - 1;
double l, lp, lp2, lk, sk, si, sk2;
if (p == 0)
{
u(0) = 1.0;
d(0) = 0.0;
d2(0) = 0.0;
return;
}
lk = 1.0;
for (k = 0; k < p; k++)
{
if (y >= (x(k) + x(k+1))/2)
{
lk *= y - x(k);
}
else
{
for (i = k+1; i <= p; i++)
{
lk *= y - x(i);
}
break;
}
}
l = lk * (y - x(k));
sk = 0.0;
sk2 = 0.0;
for (i = 0; i < k; i++)
{
si = 1.0/(y - x(i));
sk += si;
sk2 -= si * si;
u(i) = l * si * w(i);
}
u(k) = lk * w(k);
for (i++; i <= p; i++)
{
si = 1.0/(y - x(i));
sk += si;
sk2 -= si * si;
u(i) = l * si * w(i);
}
lp = l * sk + lk;
lp2 = lp * sk + l * sk2 + sk * lk;
for (i = 0; i < k; i++)
{
d(i) = (lp * w(i) - u(i))/(y - x(i));
d2(i) = (lp2 * w(i) - 2 * d(i))/(y - x(i));
}
d(k) = sk * u(k);
d2(k) = sk2 * u(k) + sk * d(k);
for (i++; i <= p; i++)
{
d(i) = (lp * w(i) - u(i))/(y - x(i));
d2(i) = (lp2 * w(i) - 2 * d(i))/(y - x(i));
}
break;
}
case Positive:
CalcBernstein(x.Size() - 1, y, u, d);
break;
default: break;
}
}
const int *Poly_1D::Binom(const int p)
{
if (binom.NumCols() <= p)
@@ -7589,6 +7714,7 @@ H1_SegmentElement::H1_SegmentElement(const int p, const int btype)
#ifndef MFEM_THREAD_SAFE
shape_x.SetSize(p+1);
dshape_x.SetSize(p+1);
d2shape_x.SetSize(p+1);
#endif
Nodes.IntPoint(0).x = cp[0];
@@ -7637,6 +7763,25 @@ void H1_SegmentElement::CalcDShape(const IntegrationPoint &ip,
}
}
void H1_SegmentElement::CalcHessian(const IntegrationPoint &ip,
DenseMatrix &Hessian) const
{
const int p = order;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p+1), dshape_x(p+1), d2shape_x(p+1);
#endif
basis1d.Eval(ip.x, shape_x, dshape_x, d2shape_x);
Hessian(0,0) = d2shape_x(0);
Hessian(1,0) = d2shape_x(p);
for (int i = 1; i < p; i++)
{
Hessian(i+1,0) = d2shape_x(i);
}
}
void H1_SegmentElement::ProjectDelta(int vertex, Vector &dofs) const
{
const int p = order;
@@ -7677,6 +7822,8 @@ H1_QuadrilateralElement::H1_QuadrilateralElement(const int p, const int btype)
shape_y.SetSize(p1);
dshape_x.SetSize(p1);
dshape_y.SetSize(p1);
d2shape_x.SetSize(p1);
d2shape_y.SetSize(p1);
#endif
int o = 0;
@@ -7730,6 +7877,30 @@ void H1_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
}
}
void H1_QuadrilateralElement::CalcHessian(const IntegrationPoint &ip,
DenseMatrix &Hessian) const
{
const int p = order;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1),
d2shape_x(p+1), d2shape_y(p+1);
#endif
basis1d.Eval(ip.x, shape_x, dshape_x, d2shape_x);
basis1d.Eval(ip.y, shape_y, dshape_y, d2shape_y);
for (int o = 0, j = 0; j <= p; j++)
{
for (int i = 0; i <= p; i++)
{
Hessian(dof_map[o],0) = d2shape_x(i)* shape_y(j);
Hessian(dof_map[o],1) = dshape_x(i)* dshape_y(j);
Hessian(dof_map[o],2) = shape_x(i)*d2shape_y(j); o++;
}
}
}
void H1_QuadrilateralElement::ProjectDelta(int vertex, Vector &dofs) const
{
const int p = order;
@@ -7793,6 +7964,9 @@ H1_HexahedronElement::H1_HexahedronElement(const int p, const int btype)
dshape_x.SetSize(p1);
dshape_y.SetSize(p1);
dshape_z.SetSize(p1);
d2shape_x.SetSize(p1);
d2shape_y.SetSize(p1);
d2shape_z.SetSize(p1);
#endif
int o = 0;
@@ -7849,6 +8023,35 @@ void H1_HexahedronElement::CalcDShape(const IntegrationPoint &ip,
}
}
void H1_HexahedronElement::CalcHessian(const IntegrationPoint &ip,
DenseMatrix &Hessian) const
{
const int p = order;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p+1), shape_y(p+1), shape_z(p+1);
Vector dshape_x(p+1), dshape_y(p+1), dshape_z(p+1);
Vector d2shape_x(p+1), d2shape_y(p+1), ds2hape_z(p+1);
#endif
basis1d.Eval(ip.x, shape_x, dshape_x, d2shape_x);
basis1d.Eval(ip.y, shape_y, dshape_y, d2shape_y);
basis1d.Eval(ip.z, shape_z, dshape_z, d2shape_z);
for (int o = 0, k = 0; k <= p; k++)
for (int j = 0; j <= p; j++)
for (int i = 0; i <= p; i++)
{
Hessian(dof_map[o],0) = d2shape_x(i)* shape_y(j)* shape_z(k);
Hessian(dof_map[o],1) = dshape_x(i)* dshape_y(j)* shape_z(k);
Hessian(dof_map[o],2) = dshape_x(i)* shape_y(j)* dshape_z(k);
Hessian(dof_map[o],3) = shape_x(i)*d2shape_y(j)* shape_z(k);
Hessian(dof_map[o],4) = shape_x(i)* dshape_y(j)* dshape_z(k);
Hessian(dof_map[o],5) = shape_x(i)* shape_y(j)*d2shape_z(k);
o++;
}
}
void H1_HexahedronElement::ProjectDelta(int vertex, Vector &dofs) const
{
const int p = order;
+60 -10
View File
@@ -446,7 +446,7 @@ public:
/** Each row of the result DenseMatrix @a Hessian contains upper triangular
part of the Hessian of one shape function.
The order in 2D is {u_xx, u_xy, u_yy}.
The size (#dof x (#dim (#dim-1)/2) of @a Hessian must be set in advance.*/
The size (#dof x (#dim (#dim+1)/2) of @a Hessian must be set in advance.*/
virtual void CalcHessian (const IntegrationPoint &ip,
DenseMatrix &Hessian) const;
@@ -504,14 +504,21 @@ public:
/** @brief Given a coefficient and a transformation, compute its projection
(approximation) in the local finite dimensional space in terms
of the degrees of freedom. */
virtual void Project (Coefficient &coeff,
ElementTransformation &Trans, Vector &dofs) const;
virtual void Project(Coefficient &coeff,
ElementTransformation &Trans, Vector &dofs) const;
/** @brief Given a vector coefficient and a transformation, compute its
projection (approximation) in the local finite dimensional space
in terms of the degrees of freedom. (VectorFiniteElements) */
virtual void Project (VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const;
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const;
/** @brief Given a vector of values at the finite element nodes and a
transformation, compute its projection (approximation) in the local
finite dimensional space in terms of the degrees of freedom. Valid for
VectorFiniteElements. */
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const;
/** @brief Given a matrix coefficient and a transformation, compute an
approximation ("projection") in the local finite dimensional space in
@@ -797,7 +804,12 @@ protected:
VectorCoefficient &vc, ElementTransformation &Trans,
Vector &dofs) const;
// project the rows of the matrix coefficient in an RT space
/// Projects the vector of values given at FE nodes to RT space
void Project_RT(const double *nk, const Array<int> &d2n,
Vector &vc, ElementTransformation &Trans,
Vector &dofs) const;
/// Project the rows of the matrix coefficient in an RT space
void ProjectMatrixCoefficient_RT(
const double *nk, const Array<int> &d2n,
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const;
@@ -825,7 +837,12 @@ protected:
VectorCoefficient &vc, ElementTransformation &Trans,
Vector &dofs) const;
/// project the rows of the matrix coefficient in an ND space
/// Projects the vector of values given at FE nodes to ND space
void Project_ND(const double *tk, const Array<int> &d2t,
Vector &vc, ElementTransformation &Trans,
Vector &dofs) const;
/// Project the rows of the matrix coefficient in an ND space
void ProjectMatrixCoefficient_ND(
const double *tk, const Array<int> &d2t,
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const;
@@ -1850,6 +1867,7 @@ public:
Basis(const int p, const double *nodes, EvalType etype = Barycentric);
void Eval(const double x, Vector &u) const;
void Eval(const double x, Vector &u, Vector &d) const;
void Eval(const double x, Vector &u, Vector &d, Vector &d2) const;
};
private:
@@ -2100,7 +2118,7 @@ class H1_SegmentElement : public NodalTensorFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
mutable Vector shape_x, dshape_x;
mutable Vector shape_x, dshape_x, d2shape_x;
#endif
public:
@@ -2109,6 +2127,8 @@ public:
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
virtual void CalcHessian(const IntegrationPoint &ip,
DenseMatrix &Hessian) const;
virtual void ProjectDelta(int vertex, Vector &dofs) const;
};
@@ -2118,7 +2138,7 @@ class H1_QuadrilateralElement : public NodalTensorFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
mutable Vector shape_x, shape_y, dshape_x, dshape_y;
mutable Vector shape_x, shape_y, dshape_x, dshape_y, d2shape_x, d2shape_y;
#endif
public:
@@ -2128,6 +2148,8 @@ public:
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
virtual void CalcHessian(const IntegrationPoint &ip,
DenseMatrix &Hessian) const;
virtual void ProjectDelta(int vertex, Vector &dofs) const;
};
@@ -2137,7 +2159,8 @@ class H1_HexahedronElement : public NodalTensorFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
mutable Vector shape_x, shape_y, shape_z, dshape_x, dshape_y, dshape_z;
mutable Vector shape_x, shape_y, shape_z, dshape_x, dshape_y, dshape_z,
d2shape_x, d2shape_y, d2shape_z;
#endif
public:
@@ -2146,6 +2169,8 @@ public:
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
virtual void CalcHessian(const IntegrationPoint &ip,
DenseMatrix &Hessian) const;
virtual void ProjectDelta(int vertex, Vector &dofs) const;
};
@@ -2681,6 +2706,9 @@ public:
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); }
@@ -2739,6 +2767,9 @@ public:
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); }
@@ -2790,6 +2821,9 @@ public:
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); }
@@ -2847,6 +2881,9 @@ public:
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); }
@@ -2906,6 +2943,10 @@ public:
ElementTransformation &Trans, Vector &dofs) const
{ Project_ND(tk, dof2tk, vc, Trans, dofs); }
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{ Project_ND(tk, dof2tk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); }
@@ -2965,6 +3006,9 @@ public:
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const
{ Project_ND(tk, dof2tk, vc, Trans, dofs); }
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{ Project_ND(tk, dof2tk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); }
@@ -3016,6 +3060,9 @@ public:
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const
{ Project_ND(tk, dof2tk, vc, Trans, dofs); }
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{ Project_ND(tk, dof2tk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); }
@@ -3072,6 +3119,9 @@ public:
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const
{ Project_ND(tk, dof2tk, vc, Trans, dofs); }
virtual void ProjectFromNodes(Vector &vc, ElementTransformation &Trans,
Vector &dofs) const
{ Project_ND(tk, dof2tk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_ND(tk, dof2tk, mc, T, dofs); }
+1
View File
@@ -19,6 +19,7 @@
#include "eltrans.hpp"
#include "coefficient.hpp"
#include "complex_fem.hpp"
#include "convergence.hpp"
#include "lininteg.hpp"
#include "nonlininteg.hpp"
#include "bilininteg.hpp"
+9 -6
View File
@@ -440,6 +440,7 @@ void FiniteElementSpace::MarkerToList(const Array<int> &marker,
if (marker[i]) { num_marked++; }
}
list.SetSize(0);
list.HostWrite();
list.Reserve(num_marked);
for (int i = 0; i < marker.Size(); i++)
{
@@ -451,7 +452,9 @@ void FiniteElementSpace::MarkerToList(const Array<int> &marker,
void FiniteElementSpace::ListToMarker(const Array<int> &list, int marker_size,
Array<int> &marker, int mark_val)
{
list.HostRead(); // make sure we can read the array on host
marker.SetSize(marker_size);
marker.HostWrite();
marker = 0;
for (int i = 0; i < list.Size(); i++)
{
@@ -944,7 +947,7 @@ const Operator *FiniteElementSpace::GetFaceRestriction(
}
const QuadratureInterpolator *FiniteElementSpace::GetQuadratureInterpolator(
const IntegrationRule &ir, const DofToQuad::Mode mode) const
const IntegrationRule &ir) const
{
for (int i = 0; i < E2Q_array.Size(); i++)
{
@@ -952,13 +955,13 @@ const QuadratureInterpolator *FiniteElementSpace::GetQuadratureInterpolator(
if (qi->IntRule == &ir) { return qi; }
}
QuadratureInterpolator *qi = new QuadratureInterpolator(*this, ir, mode);
QuadratureInterpolator *qi = new QuadratureInterpolator(*this, ir);
E2Q_array.Append(qi);
return qi;
}
const QuadratureInterpolator *FiniteElementSpace::GetQuadratureInterpolator(
const QuadratureSpace &qs, const DofToQuad::Mode mode) const
const QuadratureSpace &qs) const
{
for (int i = 0; i < E2Q_array.Size(); i++)
{
@@ -966,7 +969,7 @@ const QuadratureInterpolator *FiniteElementSpace::GetQuadratureInterpolator(
if (qi->qspace == &qs) { return qi; }
}
QuadratureInterpolator *qi = new QuadratureInterpolator(*this, qs, mode);
QuadratureInterpolator *qi = new QuadratureInterpolator(*this, qs);
E2Q_array.Append(qi);
return qi;
}
@@ -983,8 +986,8 @@ const FaceQuadratureInterpolator
if (qi->IntRule == &ir) { return qi; }
}
FaceQuadratureInterpolator *qi =
new FaceQuadratureInterpolator(*this, ir, type);
FaceQuadratureInterpolator *qi = new FaceQuadratureInterpolator(*this, ir,
type);
E2IFQ_array.Append(qi);
return qi;
}
+2 -2
View File
@@ -367,7 +367,7 @@ public:
All elements will use the same IntegrationRule, @a ir as the target
quadrature points. */
const QuadratureInterpolator *GetQuadratureInterpolator(
const IntegrationRule &ir, const DofToQuad::Mode = DofToQuad::FULL) const;
const IntegrationRule &ir) const;
/** @brief Return a QuadratureInterpolator that interpolates E-vectors to
quadrature point values and/or derivatives (Q-vectors). */
@@ -378,7 +378,7 @@ public:
The target quadrature points in the elements are described by the given
QuadratureSpace, @a qs. */
const QuadratureInterpolator *GetQuadratureInterpolator(
const QuadratureSpace &qs, const DofToQuad::Mode = DofToQuad::FULL) const;
const QuadratureSpace &qs) const;
/** @brief Return a FaceQuadratureInterpolator that interpolates E-vectors to
quadrature point values and/or derivatives (Q-vectors). */
+247 -126
View File
@@ -199,8 +199,7 @@ void GridFunction::MakeRef(FiniteElementSpace *f, Vector &v, int v_offset)
if (f != fes) { Destroy(); }
fes = f;
v.UseDevice(true);
NewMemoryAndSize(Memory<double>(v.GetMemory(), v_offset, fes->GetVSize()),
fes->GetVSize(), true);
this->Vector::MakeRef(v, v_offset, fes->GetVSize());
sequence = fes->GetSequence();
}
@@ -1834,6 +1833,19 @@ void GridFunction::ImposeBounds(int i, const Vector &weights,
ImposeBounds(i, weights, minv, maxv);
}
void GridFunction::RestrictConforming()
{
const SparseMatrix *R = fes->GetRestrictionMatrix();
const Operator *P = fes->GetProlongationMatrix();
if (P && R)
{
Vector tmp(R->Height());
R->Mult(*this, tmp);
P->Mult(tmp, *this);
}
}
void GridFunction::GetNodalValues(Vector &nval, int vdim) const
{
int i, j;
@@ -2602,11 +2614,7 @@ double GridFunction::ComputeL2Error(
}
}
if (error < 0.0)
{
return -sqrt(-error);
}
return sqrt(error);
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
double GridFunction::ComputeL2Error(
@@ -2647,94 +2655,199 @@ double GridFunction::ComputeL2Error(
}
}
if (error < 0.0)
{
return -sqrt(-error);
}
return sqrt(error);
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
double GridFunction::ComputeH1Error(
Coefficient *exsol, VectorCoefficient *exgrad,
Coefficient *ell_coeff, double Nu, int norm_type) const
double GridFunction::ComputeGradError(VectorCoefficient *exgrad,
const IntegrationRule *irs[]) const
{
// assuming vdim is 1
int i, fdof, dim, intorder, j, k;
double error = 0.0;
const FiniteElement *fe;
ElementTransformation *Tr;
Array<int> dofs;
Vector grad;
int intorder;
int dim = fes->GetMesh()->SpaceDimension();
Vector vec(dim);
for (int i = 0; i < fes->GetNE(); i++)
{
fe = fes->GetFE(i);
Tr = fes->GetElementTransformation(i);
intorder = 2*fe->GetOrder() + 3; // <--------
const IntegrationRule *ir;
if (irs)
{
ir = irs[fe->GetGeomType()];
}
else
{
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
fes->GetElementDofs(i, dofs);
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
Tr->SetIntPoint(&ip);
GetGradient(*Tr,grad);
exgrad->Eval(vec,*Tr,ip);
vec-=grad;
error += ip.weight * Tr->Weight() * (vec * vec);
}
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
double GridFunction::ComputeCurlError(VectorCoefficient *excurl,
const IntegrationRule *irs[]) const
{
double error = 0.0;
const FiniteElement *fe;
ElementTransformation *Tr;
Array<int> dofs;
Vector curl;
int intorder;
int dim = fes->GetMesh()->SpaceDimension();
int n = (dim == 3) ? dim : 1;
Vector vec(n);
for (int i = 0; i < fes->GetNE(); i++)
{
fe = fes->GetFE(i);
Tr = fes->GetElementTransformation(i);
intorder = 2*fe->GetOrder() + 3;
const IntegrationRule *ir;
if (irs)
{
ir = irs[fe->GetGeomType()];
}
else
{
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
fes->GetElementDofs(i, dofs);
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
Tr->SetIntPoint(&ip);
GetCurl(*Tr,curl);
excurl->Eval(vec,*Tr,ip);
vec-=curl;
error += ip.weight * Tr->Weight() * ( vec * vec );
}
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
double GridFunction::ComputeDivError(
Coefficient *exdiv, const IntegrationRule *irs[]) const
{
double error = 0.0, a;
const FiniteElement *fe;
ElementTransformation *Tr;
Array<int> dofs;
int intorder;
for (int i = 0; i < fes->GetNE(); i++)
{
fe = fes->GetFE(i);
Tr = fes->GetElementTransformation(i);
intorder = 2*fe->GetOrder() + 3;
const IntegrationRule *ir;
if (irs)
{
ir = irs[fe->GetGeomType()];
}
else
{
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
fes->GetElementDofs(i, dofs);
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
Tr->SetIntPoint (&ip);
a = GetDivergence(*Tr) - exdiv->Eval(*Tr, ip);
error += ip.weight * Tr->Weight() * a * a;
}
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
double GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff, double Nu,
const IntegrationRule *irs[]) const
{
int fdof, dim, intorder, k;
Mesh *mesh;
const FiniteElement *fe;
ElementTransformation *transf;
FaceElementTransformations *face_elem_transf;
Vector e_grad, a_grad, shape, el_dofs, err_val, ell_coeff_val;
DenseMatrix dshape, dshapet, Jinv;
Vector shape, el_dofs, err_val, ell_coeff_val;
Array<int> vdofs;
IntegrationPoint eip;
double error = 0.0;
mesh = fes->GetMesh();
dim = mesh->Dimension();
e_grad.SetSize(dim);
a_grad.SetSize(dim);
Jinv.SetSize(dim);
if (norm_type & 1)
for (i = 0; i < mesh->GetNE(); i++)
{
fe = fes->GetFE(i);
fdof = fe->GetDof();
transf = mesh->GetElementTransformation(i);
el_dofs.SetSize(fdof);
dshape.SetSize(fdof, dim);
dshapet.SetSize(fdof, dim);
intorder = 2 * fe->GetOrder(); // <----------
const IntegrationRule &ir = IntRules.Get(fe->GetGeomType(), intorder);
fes->GetElementVDofs(i, vdofs);
for (k = 0; k < fdof; k++)
if (vdofs[k] >= 0)
{
el_dofs(k) = (*this)(vdofs[k]);
}
else
{
el_dofs(k) = - (*this)(-1-vdofs[k]);
}
for (j = 0; j < ir.GetNPoints(); j++)
for (int i = 0; i < mesh->GetNumFaces(); i++)
{
face_elem_transf = mesh->GetFaceElementTransformations(i, 5);
int i1 = face_elem_transf->Elem1No;
int i2 = face_elem_transf->Elem2No;
intorder = fes->GetFE(i1)->GetOrder();
if (i2 >= 0)
if ( (k = fes->GetFE(i2)->GetOrder()) > intorder )
{
const IntegrationPoint &ip = ir.IntPoint(j);
fe->CalcDShape(ip, dshape);
transf->SetIntPoint(&ip);
exgrad->Eval(e_grad, *transf, ip);
CalcInverse(transf->Jacobian(), Jinv);
Mult(dshape, Jinv, dshapet);
dshapet.MultTranspose(el_dofs, a_grad);
e_grad -= a_grad;
error += (ip.weight * transf->Weight() *
ell_coeff->Eval(*transf, ip) *
(e_grad * e_grad));
intorder = k;
}
}
if (norm_type & 2)
for (i = 0; i < mesh->GetNFaces(); i++)
intorder = 2 * intorder; // <-------------
const IntegrationRule *ir;
if (irs)
{
face_elem_transf = mesh->GetFaceElementTransformations(i, 5);
int i1 = face_elem_transf->Elem1No;
int i2 = face_elem_transf->Elem2No;
intorder = fes->GetFE(i1)->GetOrder();
if (i2 >= 0)
if ( (k = fes->GetFE(i2)->GetOrder()) > intorder )
{
intorder = k;
}
intorder = 2 * intorder; // <-------------
const IntegrationRule &ir =
IntRules.Get(face_elem_transf->GetGeometryType(), intorder);
err_val.SetSize(ir.GetNPoints());
ell_coeff_val.SetSize(ir.GetNPoints());
// side 1
transf = face_elem_transf->Elem1;
fe = fes->GetFE(i1);
ir = irs[face_elem_transf->GetGeometryType()];
}
else
{
ir = &(IntRules.Get(face_elem_transf->GetGeometryType(), intorder));
}
err_val.SetSize(ir->GetNPoints());
ell_coeff_val.SetSize(ir->GetNPoints());
// side 1
transf = face_elem_transf->Elem1;
fe = fes->GetFE(i1);
fdof = fe->GetDof();
fes->GetElementVDofs(i1, vdofs);
shape.SetSize(fdof);
el_dofs.SetSize(fdof);
for (k = 0; k < fdof; k++)
if (vdofs[k] >= 0)
{
el_dofs(k) = (*this)(vdofs[k]);
}
else
{
el_dofs(k) = - (*this)(-1-vdofs[k]);
}
for (int j = 0; j < ir->GetNPoints(); j++)
{
face_elem_transf->Loc1.Transform(ir->IntPoint(j), eip);
fe->CalcShape(eip, shape);
transf->SetIntPoint(&eip);
ell_coeff_val(j) = ell_coeff->Eval(*transf, eip);
err_val(j) = exsol->Eval(*transf, eip) - (shape * el_dofs);
}
if (i2 >= 0)
{
// side 2
face_elem_transf = mesh->GetFaceElementTransformations(i, 10);
transf = face_elem_transf->Elem2;
fe = fes->GetFE(i2);
fdof = fe->GetDof();
fes->GetElementVDofs(i1, vdofs);
fes->GetElementVDofs(i2, vdofs);
shape.SetSize(fdof);
el_dofs.SetSize(fdof);
for (k = 0; k < fdof; k++)
@@ -2746,60 +2859,69 @@ double GridFunction::ComputeH1Error(
{
el_dofs(k) = - (*this)(-1-vdofs[k]);
}
for (j = 0; j < ir.GetNPoints(); j++)
for (int j = 0; j < ir->GetNPoints(); j++)
{
face_elem_transf->Loc1.Transform(ir.IntPoint(j), eip);
face_elem_transf->Loc2.Transform(ir->IntPoint(j), eip);
fe->CalcShape(eip, shape);
transf->SetIntPoint(&eip);
ell_coeff_val(j) = ell_coeff->Eval(*transf, eip);
err_val(j) = exsol->Eval(*transf, eip) - (shape * el_dofs);
}
if (i2 >= 0)
{
// side 2
face_elem_transf = mesh->GetFaceElementTransformations(i, 10);
transf = face_elem_transf->Elem2;
fe = fes->GetFE(i2);
fdof = fe->GetDof();
fes->GetElementVDofs(i2, vdofs);
shape.SetSize(fdof);
el_dofs.SetSize(fdof);
for (k = 0; k < fdof; k++)
if (vdofs[k] >= 0)
{
el_dofs(k) = (*this)(vdofs[k]);
}
else
{
el_dofs(k) = - (*this)(-1-vdofs[k]);
}
for (j = 0; j < ir.GetNPoints(); j++)
{
face_elem_transf->Loc2.Transform(ir.IntPoint(j), eip);
fe->CalcShape(eip, shape);
transf->SetIntPoint(&eip);
ell_coeff_val(j) += ell_coeff->Eval(*transf, eip);
ell_coeff_val(j) *= 0.5;
err_val(j) -= (exsol->Eval(*transf, eip) - (shape * el_dofs));
}
}
face_elem_transf = mesh->GetFaceElementTransformations(i, 16);
transf = face_elem_transf;
for (j = 0; j < ir.GetNPoints(); j++)
{
const IntegrationPoint &ip = ir.IntPoint(j);
transf->SetIntPoint(&ip);
error += (ip.weight * Nu * ell_coeff_val(j) *
pow(transf->Weight(), 1.0-1.0/(dim-1)) *
err_val(j) * err_val(j));
ell_coeff_val(j) += ell_coeff->Eval(*transf, eip);
ell_coeff_val(j) *= 0.5;
err_val(j) -= (exsol->Eval(*transf, eip) - (shape * el_dofs));
}
}
if (error < 0.0)
{
return -sqrt(-error);
face_elem_transf = mesh->GetFaceElementTransformations(i, 16);
transf = face_elem_transf;
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
transf->SetIntPoint(&ip);
error += (ip.weight * Nu * ell_coeff_val(j) *
pow(transf->Weight(), 1.0-1.0/(dim-1)) *
err_val(j) * err_val(j));
}
}
return sqrt(error);
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
double GridFunction::ComputeH1Error(Coefficient *exsol,
VectorCoefficient *exgrad,
Coefficient *ell_coef, double Nu,
int norm_type) const
{
double error1 = 0.0;
double error2 = 0.0;
if (norm_type & 1) { error1 = GridFunction::ComputeGradError(exgrad); }
if (norm_type & 2) { error2 = GridFunction::ComputeDGFaceJumpError(exsol,ell_coef,Nu); }
return sqrt(error1 * error1 + error2 * error2);
}
double GridFunction::ComputeH1Error(Coefficient *exsol,
VectorCoefficient *exgrad,
const IntegrationRule *irs[]) const
{
double L2error = GridFunction::ComputeLpError(2.0,*exsol,NULL,irs);
double GradError = ComputeGradError(exgrad,irs);
return sqrt(L2error*L2error + GradError*GradError);
}
double GridFunction::ComputeHDivError(VectorCoefficient *exsol,
Coefficient *exdiv,
const IntegrationRule *irs[]) const
{
double L2error = GridFunction::ComputeLpError(2.0,*exsol,NULL,NULL,irs);
double DivError = ComputeDivError(exdiv,irs);
return sqrt(L2error*L2error + DivError*DivError);
}
double GridFunction::ComputeHCurlError(VectorCoefficient *exsol,
VectorCoefficient *excurl,
const IntegrationRule *irs[]) const
{
double L2error = GridFunction::ComputeLpError(2.0,*exsol,NULL,NULL,irs);
double CurlError = ComputeCurlError(excurl,irs);
return sqrt(L2error*L2error + CurlError*CurlError);
}
double GridFunction::ComputeMaxError(
@@ -2855,7 +2977,6 @@ double GridFunction::ComputeMaxError(
}
}
}
return error;
}
+46
View File
@@ -334,6 +334,11 @@ public:
void ImposeBounds(int i, const Vector &weights,
double _min = 0.0, double _max = infinity());
/** On a non-conforming mesh, make sure the function lies in the conforming
space by multiplying with R and then with P, the conforming restriction
and prolongation matrices of the space, respectively. */
void RestrictConforming();
/** @brief Project the @a src GridFunction to @a this GridFunction, both of
which must be on the same mesh. */
/** The current implementation assumes that all elements use the same
@@ -422,6 +427,7 @@ public:
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
Array<int> &bdr_attr);
virtual double ComputeL2Error(Coefficient &exsol,
const IntegrationRule *irs[] = NULL) const
{ return ComputeLpError(2.0, exsol, NULL, irs); }
@@ -433,10 +439,50 @@ public:
const IntegrationRule *irs[] = NULL,
Array<int> *elems = NULL) const;
/// Returns ||grad u_ex - grad u_h||_L2 for H1 or L2 elements
virtual double ComputeGradError(VectorCoefficient *exgrad,
const IntegrationRule *irs[] = NULL) const;
/// Returns ||curl u_ex - curl u_h||_L2 for ND elements
virtual double ComputeCurlError(VectorCoefficient *excurl,
const IntegrationRule *irs[] = NULL) const;
/// Returns ||div u_ex - div u_h||_L2 for RT elements
virtual double ComputeDivError(Coefficient *exdiv,
const IntegrationRule *irs[] = NULL) const;
/// Returns the Face Jumps error for L2 elements
virtual double ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
double Nu,
const IntegrationRule *irs[] = NULL)
const;
/** This method is kept for backward compatibility.
Returns either the H1-seminorm, or the DG face jumps error, or both
depending on norm_type = 1, 2, 3. Additional arguments for the DG face
jumps norm: ell_coeff: mesh-depended coefficient (weight) Nu: scalar
constant weight */
virtual double ComputeH1Error(Coefficient *exsol, VectorCoefficient *exgrad,
Coefficient *ell_coef, double Nu,
int norm_type) const;
/// Returns the error measured in H1-norm for H1 elements or in "broken"
/// H1-norm for L2 elements
virtual double ComputeH1Error(Coefficient *exsol, VectorCoefficient *exgrad,
const IntegrationRule *irs[] = NULL) const;
/// Returns the error measured in H(div)-norm for RT elements
virtual double ComputeHDivError(VectorCoefficient *exsol,
Coefficient *exdiv,
const IntegrationRule *irs[] = NULL) const;
/// Returns the error measured in H(curl)-norm for ND elements
virtual double ComputeHCurlError(VectorCoefficient *exsol,
VectorCoefficient *excurl,
const IntegrationRule *irs[] = NULL) const;
virtual double ComputeMaxError(Coefficient &exsol,
const IntegrationRule *irs[] = NULL) const
{
+403 -86
View File
@@ -29,10 +29,13 @@ namespace mfem
{
FindPointsGSLIB::FindPointsGSLIB()
: mesh(NULL), ir_simplex(NULL), fdata2D(NULL), fdata3D(NULL),
dim(-1), gsl_mesh(), gsl_ref(), gsl_dist(), setupflag(false)
: mesh(NULL), meshsplit(NULL), ir_simplex(NULL),
fdata2D(NULL), fdata3D(NULL), cr(NULL), gsl_comm(NULL),
dim(-1), points_cnt(0), setupflag(false), default_interp_value(0),
avgtype(AvgType::ARITHMETIC)
{
gsl_comm = new comm;
cr = new crystal;
#ifdef MFEM_USE_MPI
int initialized;
MPI_Initialized(&initialized);
@@ -47,15 +50,20 @@ FindPointsGSLIB::FindPointsGSLIB()
FindPointsGSLIB::~FindPointsGSLIB()
{
delete gsl_comm;
delete cr;
delete ir_simplex;
delete meshsplit;
}
#ifdef MFEM_USE_MPI
FindPointsGSLIB::FindPointsGSLIB(MPI_Comm _comm)
: mesh(NULL), ir_simplex(NULL), fdata2D(NULL), fdata3D(NULL),
dim(-1), gsl_mesh(), gsl_ref(), gsl_dist(), setupflag(false)
: mesh(NULL), meshsplit(NULL), ir_simplex(NULL),
fdata2D(NULL), fdata3D(NULL), cr(NULL), gsl_comm(NULL),
dim(-1), points_cnt(0), setupflag(false), default_interp_value(0),
avgtype(AvgType::ARITHMETIC)
{
gsl_comm = new comm;
cr = new crystal;
comm_init(gsl_comm, _comm);
}
#endif
@@ -70,6 +78,7 @@ void FindPointsGSLIB::Setup(Mesh &m, const double bb_t, const double newt_tol,
// call FreeData if FindPointsGSLIB::Setup has been called already
if (setupflag) { FreeData(); }
crystal_init(cr, gsl_comm);
mesh = &m;
dim = mesh->Dimension();
const FiniteElement *fe = mesh->GetNodalFESpace()->GetFE(0);
@@ -113,14 +122,16 @@ void FindPointsGSLIB::Setup(Mesh &m, const double bb_t, const double newt_tol,
setupflag = true;
}
void FindPointsGSLIB::FindPoints(const Vector &point_pos,
Array<unsigned int> &codes,
Array<unsigned int> &proc_ids,
Array<unsigned int> &elem_ids,
Vector &ref_pos, Vector &dist)
void FindPointsGSLIB::FindPoints(const Vector &point_pos)
{
MFEM_VERIFY(setupflag, "Use FindPointsGSLIB::Setup before finding points.");
const int points_cnt = point_pos.Size() / dim;
points_cnt = point_pos.Size() / dim;
gsl_code.SetSize(points_cnt);
gsl_proc.SetSize(points_cnt);
gsl_elem.SetSize(points_cnt);
gsl_ref.SetSize(points_cnt * dim);
gsl_dist.SetSize(points_cnt);
if (dim == 2)
{
const double *xv_base[2];
@@ -129,11 +140,11 @@ void FindPointsGSLIB::FindPoints(const Vector &point_pos,
unsigned xv_stride[2];
xv_stride[0] = sizeof(double);
xv_stride[1] = sizeof(double);
findpts_2(codes.GetData(), sizeof(unsigned int),
proc_ids.GetData(), sizeof(unsigned int),
elem_ids.GetData(), sizeof(unsigned int),
ref_pos.GetData(), sizeof(double) * dim,
dist.GetData(), sizeof(double),
findpts_2(gsl_code.GetData(), sizeof(unsigned int),
gsl_proc.GetData(), sizeof(unsigned int),
gsl_elem.GetData(), sizeof(unsigned int),
gsl_ref.GetData(), sizeof(double) * dim,
gsl_dist.GetData(), sizeof(double),
xv_base, xv_stride, points_cnt, fdata2D);
}
else
@@ -146,25 +157,27 @@ void FindPointsGSLIB::FindPoints(const Vector &point_pos,
xv_stride[0] = sizeof(double);
xv_stride[1] = sizeof(double);
xv_stride[2] = sizeof(double);
findpts_3(codes.GetData(), sizeof(unsigned int),
proc_ids.GetData(), sizeof(unsigned int),
elem_ids.GetData(), sizeof(unsigned int),
ref_pos.GetData(), sizeof(double) * dim,
dist.GetData(), sizeof(double),
findpts_3(gsl_code.GetData(), sizeof(unsigned int),
gsl_proc.GetData(), sizeof(unsigned int),
gsl_elem.GetData(), sizeof(unsigned int),
gsl_ref.GetData(), sizeof(double) * dim,
gsl_dist.GetData(), sizeof(double),
xv_base, xv_stride, points_cnt, fdata3D);
}
}
void FindPointsGSLIB::FindPoints(const Vector &point_pos)
{
const int points_cnt = point_pos.Size() / dim;
gsl_code.SetSize(points_cnt);
gsl_proc.SetSize(points_cnt);
gsl_elem.SetSize(points_cnt);
gsl_ref.SetSize(points_cnt * dim);
gsl_dist.SetSize(points_cnt);
// Set the element number and reference position to 0 for points not found
for (int i = 0; i < points_cnt; i++)
{
if (gsl_code[i] == 2)
{
gsl_elem[i] = 0;
for (int d = 0; d < dim; d++) { gsl_ref(i*dim + d) = -1.; }
}
}
FindPoints(point_pos, gsl_code, gsl_proc, gsl_elem, gsl_ref, gsl_dist);
// Map element number for simplices, and ref_pos from [-1,1] to [0,1] for
// both simplices and quads.
MapRefPosAndElemIndices();
}
void FindPointsGSLIB::FindPoints(Mesh &m, const Vector &point_pos,
@@ -178,72 +191,24 @@ void FindPointsGSLIB::FindPoints(Mesh &m, const Vector &point_pos,
FindPoints(point_pos);
}
void FindPointsGSLIB::Interpolate(Array<unsigned int> &codes,
Array<unsigned int> &proc_ids,
Array<unsigned int> &elem_ids,
Vector &ref_pos, const GridFunction &field_in,
Vector &field_out)
{
FiniteElementSpace ind_fes(mesh, field_in.FESpace()->FEColl());
GridFunction field_in_scalar(&ind_fes);
Vector node_vals;
const int ncomp = field_in.FESpace()->GetVDim(),
points_fld = field_in.Size() / ncomp,
points_cnt = codes.Size();
field_out.SetSize(points_cnt*ncomp);
for (int i = 0; i < ncomp; i++)
{
const int dataptrin = i*points_fld,
dataptrout = i*points_cnt;
field_in_scalar.NewDataAndSize(field_in.GetData()+dataptrin, points_fld);
GetNodeValues(field_in_scalar, node_vals);
if (dim==2)
{
findpts_eval_2(field_out.GetData()+dataptrout, sizeof(double),
codes.GetData(), sizeof(unsigned int),
proc_ids.GetData(), sizeof(unsigned int),
elem_ids.GetData(), sizeof(unsigned int),
ref_pos.GetData(), sizeof(double) * dim,
points_cnt, node_vals.GetData(), fdata2D);
}
else
{
findpts_eval_3(field_out.GetData()+dataptrout, sizeof(double),
codes.GetData(), sizeof(unsigned int),
proc_ids.GetData(), sizeof(unsigned int),
elem_ids.GetData(), sizeof(unsigned int),
ref_pos.GetData(), sizeof(double) * dim,
points_cnt, node_vals.GetData(), fdata3D);
}
}
}
void FindPointsGSLIB::Interpolate(const GridFunction &field_in,
Vector &field_out)
{
Interpolate(gsl_code, gsl_proc, gsl_elem, gsl_ref, field_in, field_out);
}
void FindPointsGSLIB::Interpolate(const Vector &point_pos,
const GridFunction &field_in, Vector &field_out)
{
FindPoints(point_pos);
Interpolate(gsl_code, gsl_proc, gsl_elem, gsl_ref, field_in, field_out);
Interpolate(field_in, field_out);
}
void FindPointsGSLIB::Interpolate(Mesh &m, const Vector &point_pos,
const GridFunction &field_in, Vector &field_out)
{
FindPoints(m, point_pos);
Interpolate(gsl_code, gsl_proc, gsl_elem, gsl_ref, field_in, field_out);
Interpolate(field_in, field_out);
}
void FindPointsGSLIB::FreeData()
{
if (!setupflag) { return; }
crystal_free(cr);
if (dim == 2)
{
findpts_free_2(fdata2D);
@@ -252,13 +217,13 @@ void FindPointsGSLIB::FreeData()
{
findpts_free_3(fdata3D);
}
setupflag = false;
gsl_code.DeleteAll();
gsl_proc.DeleteAll();
gsl_elem.DeleteAll();
gsl_mesh.Destroy();
gsl_ref.Destroy();
gsl_dist.Destroy();
setupflag = false;
}
void FindPointsGSLIB::GetNodeValues(const GridFunction &gf_in,
@@ -358,9 +323,8 @@ void FindPointsGSLIB::GetSimplexNodalCoordinates()
const FiniteElement *fe = mesh->GetNodalFESpace()->GetFE(0);
const Geometry::Type gt = fe->GetGeomType();
const GridFunction *nodes = mesh->GetNodes();
Mesh *meshsplit = NULL;
const int NE = mesh->GetNE();
int NEsplit = -1;
int NEsplit = 0;
// Split the reference element into a reference submesh of quads or hexes.
if (gt == Geometry::TRIANGLE)
@@ -516,8 +480,361 @@ void FindPointsGSLIB::GetSimplexNodalCoordinates()
pt_id++;
}
}
}
delete meshsplit;
void FindPointsGSLIB::MapRefPosAndElemIndices()
{
gsl_mfem_ref = gsl_ref;
gsl_mfem_elem = gsl_elem;
const FiniteElement *fe = mesh->GetNodalFESpace()->GetFE(0);
const Geometry::Type gt = fe->GetGeomType();
int NEsplit = 0;
gsl_mfem_ref -= -1.; // map [-1, 1] to
gsl_mfem_ref *= 0.5; // [0, 1]
if (gt == Geometry::SQUARE || gt == Geometry::CUBE) { return; }
H1_FECollection feclin(1, dim);
FiniteElementSpace nodal_fes_lin(meshsplit, &feclin, dim);
GridFunction gf_lin(&nodal_fes_lin);
if (gt == Geometry::TRIANGLE)
{
const double quad_v[7][2] =
{
{0, 0}, {0.5, 0}, {1, 0}, {0, 0.5},
{1./3., 1./3.}, {0.5, 0.5}, {0, 1}
};
for (int k = 0; k < dim; k++)
{
for (int j = 0; j < gf_lin.Size()/dim; j++)
{
gf_lin(j+k*gf_lin.Size()/dim) = quad_v[j][k];
}
}
NEsplit = 3;
}
else if (gt == Geometry::TETRAHEDRON)
{
const double hex_v[15][3] =
{
{0, 0, 0.}, {1, 0., 0.}, {0., 1., 0.}, {0, 0., 1.},
{0.5, 0., 0.}, {0.5, 0.5, 0.}, {0., 0.5, 0.},
{0., 0., 0.5}, {0.5, 0., 0.5}, {0., 0.5, 0.5},
{1./3., 0., 1./3.}, {1./3., 1./3., 1./3.}, {0, 1./3., 1./3.},
{1./3., 1./3., 0}, {0.25, 0.25, 0.25}
};
for (int k = 0; k < dim; k++)
{
for (int j = 0; j < gf_lin.Size()/dim; j++)
{
gf_lin(j+k*gf_lin.Size()/dim) = hex_v[j][k];
}
}
NEsplit = 4;
}
else if (gt == Geometry::PRISM)
{
const double hex_v[14][3] =
{
{0, 0, 0}, {0.5, 0, 0}, {1, 0, 0}, {0, 0.5, 0},
{1./3., 1./3., 0}, {0.5, 0.5, 0}, {0, 1, 0},
{0, 0, 1}, {0.5, 0, 1}, {1, 0, 1}, {0, 0.5, 1},
{1./3., 1./3., 1}, {0.5, 0.5, 1}, {0, 1, 1}
};
for (int k = 0; k < dim; k++)
{
for (int j = 0; j < gf_lin.Size()/dim; j++)
{
gf_lin(j+k*gf_lin.Size()/dim) = hex_v[j][k];
}
}
NEsplit = 3;
}
else
{
MFEM_ABORT("Element type not currently supported.");
}
// Simplices are split into quads/hexes for GSLIB. For MFEM, we need to find
// the original element number and map the rst from micro to macro element.
for (int i = 0; i < points_cnt; i++)
{
if (gsl_code[i] == 2) { continue; }
int local_elem = gsl_elem[i]%NEsplit;
gsl_mfem_elem[i] = (gsl_elem[i] - local_elem)/NEsplit; // macro element number
IntegrationPoint ip;
Vector mfem_ref(gsl_mfem_ref.GetData()+i*dim, dim);
ip.Set2(mfem_ref.GetData());
if (dim == 3) { ip.z = mfem_ref(2); }
gf_lin.GetVectorValue(local_elem, ip, mfem_ref); // map to rst of macro element
}
}
void FindPointsGSLIB::Interpolate(const GridFunction &field_in,
Vector &field_out)
{
const int gf_order = field_in.FESpace()->GetFE(0)->GetOrder(),
mesh_order = mesh->GetNodalFESpace()->GetFE(0)->GetOrder();
const FiniteElementCollection *fec_in = field_in.FESpace()->FEColl();
const H1_FECollection *fec_h1 = dynamic_cast<const H1_FECollection *>(fec_in);
const L2_FECollection *fec_l2 = dynamic_cast<const L2_FECollection *>(fec_in);
if (fec_h1 && gf_order == mesh_order &&
fec_h1->GetBasisType() == BasisType::GaussLobatto)
{
InterpolateH1(field_in, field_out);
return;
}
else
{
InterpolateGeneral(field_in, field_out);
if (!fec_l2 || avgtype == AvgType::NONE) { return; }
}
// For points on element borders, project the L2 GridFunction to H1 and
// re-interpolate.
if (fec_l2)
{
Array<int> indl2;
for (int i = 0; i < points_cnt; i++)
{
if (gsl_code[i] == 1) { indl2.Append(i); }
}
if (indl2.Size() == 0) { return; } // no points on element borders
Vector field_out_l2(field_out.Size());
VectorGridFunctionCoefficient field_in_dg(&field_in);
int gf_order_h1 = std::max(gf_order, 1); // H1 should be at least order 1
H1_FECollection fec(gf_order_h1, dim);
const int ncomp = field_in.FESpace()->GetVDim();
FiniteElementSpace fes(mesh, &fec, ncomp);
GridFunction field_in_h1(&fes);
if (avgtype == AvgType::ARITHMETIC)
{
field_in_h1.ProjectDiscCoefficient(field_in_dg, GridFunction::ARITHMETIC);
}
else if (avgtype == AvgType::HARMONIC)
{
field_in_h1.ProjectDiscCoefficient(field_in_dg, GridFunction::HARMONIC);
}
else
{
MFEM_ABORT("Invalid averaging type.");
}
if (gf_order_h1 == mesh_order) // basis is GaussLobatto by default
{
InterpolateH1(field_in_h1, field_out_l2);
}
else
{
InterpolateGeneral(field_in_h1, field_out_l2);
}
// Copy interpolated values for the points on element border
for (int j = 0; j < ncomp; j++)
{
for (int i = 0; i < indl2.Size(); i++)
{
int idx = indl2[i] + j*points_cnt;
field_out(idx) = field_out_l2(idx);
}
}
}
}
void FindPointsGSLIB::InterpolateH1(const GridFunction &field_in,
Vector &field_out)
{
FiniteElementSpace ind_fes(mesh, field_in.FESpace()->FEColl());
GridFunction field_in_scalar(&ind_fes);
Vector node_vals;
const int ncomp = field_in.FESpace()->GetVDim(),
points_fld = field_in.Size() / ncomp,
points_cnt = gsl_code.Size();
field_out.SetSize(points_cnt*ncomp);
field_out = default_interp_value;
for (int i = 0; i < ncomp; i++)
{
const int dataptrin = i*points_fld,
dataptrout = i*points_cnt;
field_in_scalar.NewDataAndSize(field_in.GetData()+dataptrin, points_fld);
GetNodeValues(field_in_scalar, node_vals);
if (dim==2)
{
findpts_eval_2(field_out.GetData()+dataptrout, sizeof(double),
gsl_code.GetData(), sizeof(unsigned int),
gsl_proc.GetData(), sizeof(unsigned int),
gsl_elem.GetData(), sizeof(unsigned int),
gsl_ref.GetData(), sizeof(double) * dim,
points_cnt, node_vals.GetData(), fdata2D);
}
else
{
findpts_eval_3(field_out.GetData()+dataptrout, sizeof(double),
gsl_code.GetData(), sizeof(unsigned int),
gsl_proc.GetData(), sizeof(unsigned int),
gsl_elem.GetData(), sizeof(unsigned int),
gsl_ref.GetData(), sizeof(double) * dim,
points_cnt, node_vals.GetData(), fdata3D);
}
}
}
void FindPointsGSLIB::InterpolateGeneral(const GridFunction &field_in,
Vector &field_out)
{
int ncomp = field_in.VectorDim(),
nptorig = points_cnt,
npt = points_cnt;
field_out.SetSize(points_cnt*ncomp);
field_out = default_interp_value;
if (gsl_comm->np == 1) // serial
{
for (int index = 0; index < npt; index++)
{
if (gsl_code[index] == 2) { continue; }
IntegrationPoint ip;
ip.Set2(gsl_mfem_ref.GetData()+index*dim);
if (dim == 3) { ip.z = gsl_mfem_ref(index*dim + 2); }
Vector localval(ncomp);
field_in.GetVectorValue(gsl_mfem_elem[index], ip, localval);
for (int i = 0; i < ncomp; i++)
{
field_out(index + i*npt) = localval(i);
}
}
}
else // parallel
{
// Determine number of points to be sent
int nptsend = 0;
for (int index = 0; index < npt; index++)
{
if (gsl_code[index] != 2) { nptsend +=1; }
}
// Pack data to send via crystal router
struct array *outpt = new array;
struct out_pt { double r[3], ival; uint index, el, proc; };
struct out_pt *pt;
array_init(struct out_pt, outpt, nptsend);
outpt->n=nptsend;
pt = (struct out_pt *)outpt->ptr;
for (int index = 0; index < npt; index++)
{
if (gsl_code[index] == 2) { continue; }
for (int d = 0; d < dim; ++d) { pt->r[d]= gsl_mfem_ref(index*dim + d); }
pt->index = index;
pt->proc = gsl_proc[index];
pt->el = gsl_mfem_elem[index];
++pt;
}
// Transfer data to target MPI ranks
sarray_transfer(struct out_pt, outpt, proc, 1, cr);
if (ncomp == 1)
{
// Interpolate the grid function
npt = outpt->n;
pt = (struct out_pt *)outpt->ptr;
for (int index = 0; index < npt; index++)
{
IntegrationPoint ip;
ip.Set3(&pt->r[0]);
pt->ival = field_in.GetValue(pt->el, ip, 1);
++pt;
}
// Transfer data back to source MPI rank
sarray_transfer(struct out_pt, outpt, proc, 1, cr);
npt = outpt->n;
pt = (struct out_pt *)outpt->ptr;
for (int index = 0; index < npt; index++)
{
field_out(pt->index) = pt->ival;
++pt;
}
array_free(outpt);
delete outpt;
}
else // ncomp > 1
{
// Interpolate data and store in a Vector
npt = outpt->n;
pt = (struct out_pt *)outpt->ptr;
Vector vec_int_vals(npt*ncomp);
for (int index = 0; index < npt; index++)
{
IntegrationPoint ip;
ip.Set3(&pt->r[0]);
Vector localval(vec_int_vals.GetData()+index*ncomp, ncomp);
field_in.GetVectorValue(pt->el, ip, localval);
++pt;
}
// Save index and proc data in a struct
struct array *savpt = new array;
struct sav_pt { uint index, proc; };
struct sav_pt *spt;
array_init(struct sav_pt, savpt, npt);
savpt->n=npt;
spt = (struct sav_pt *)savpt->ptr;
pt = (struct out_pt *)outpt->ptr;
for (int index = 0; index < npt; index++)
{
spt->index = pt->index;
spt->proc = pt->proc;
++pt; ++spt;
}
array_free(outpt);
delete outpt;
// Copy data from save struct to send struct and send component wise
struct array *sendpt = new array;
struct send_pt { double ival; uint index, proc; };
struct send_pt *sdpt;
for (int j = 0; j < ncomp; j++)
{
array_init(struct send_pt, sendpt, npt);
sendpt->n=npt;
spt = (struct sav_pt *)savpt->ptr;
sdpt = (struct send_pt *)sendpt->ptr;
for (int index = 0; index < npt; index++)
{
sdpt->index = spt->index;
sdpt->proc = spt->proc;
sdpt->ival = vec_int_vals(j + index*ncomp);
++sdpt; ++spt;
}
sarray_transfer(struct send_pt, sendpt, proc, 1, cr);
sdpt = (struct send_pt *)sendpt->ptr;
for (int index = 0; index < nptorig; index++)
{
int idx = sdpt->index + j*nptorig;
field_out(idx) = sdpt->ival;
++sdpt;
}
array_free(sendpt);
}
array_free(savpt);
delete sendpt;
delete savpt;
} // ncomp > 1
} // parallel
}
} // namespace mfem
+93 -45
View File
@@ -20,28 +20,66 @@
struct comm;
struct findpts_data_2;
struct findpts_data_3;
struct array;
struct crystal;
namespace mfem
{
/** \brief FindPointsGSLIB can robustly evaluate a GridFunction on an arbitrary
* collection of points. There are three key functions in FindPointsGSLIB:
*
* 1. Setup - constructs the internal data structures of gslib.
*
* 2. FindPoints - for any given arbitrary set of points in physical space,
* gslib finds the element number, MPI rank, and the reference space
* coordinates inside the element that each point is located in. gslib also
* returns a code that indicates whether the point was found inside an
* element, on element border, or not found in the domain.
*
* 3. Interpolate - Interpolates any grid function at the points found using 2.
*
* FindPointsGSLIB provides interface to use these functions individually or
* using a single call.
*/
class FindPointsGSLIB
{
public:
enum AvgType {NONE, ARITHMETIC, HARMONIC}; // Average type for L2 functions
protected:
Mesh *mesh;
IntegrationRule *ir_simplex;
struct findpts_data_2 *fdata2D;
struct findpts_data_3 *fdata3D;
int dim;
Array<unsigned int> gsl_code, gsl_proc, gsl_elem;
Vector gsl_mesh, gsl_ref, gsl_dist;
bool setupflag;
struct comm *gsl_comm;
Mesh *mesh, *meshsplit;
IntegrationRule *ir_simplex; // IntegrationRule to split quads/hex -> simplex
struct findpts_data_2 *fdata2D; // gslib's internal data
struct findpts_data_3 *fdata3D; // gslib's internal data
struct crystal *cr; // gslib's internal data
struct comm *gsl_comm; // gslib's internal data
int dim, points_cnt;
Array<unsigned int> gsl_code, gsl_proc, gsl_elem, gsl_mfem_elem;
Vector gsl_mesh, gsl_ref, gsl_dist, gsl_mfem_ref;
bool setupflag; // flag to indicate whether gslib data has been setup
double default_interp_value; // used for points that are not found in the mesh
AvgType avgtype; // average type used for L2 functions
/// Get GridFunction from MFEM format to GSLIB format
void GetNodeValues(const GridFunction &gf_in, Vector &node_vals);
/// Get nodal coordinates from mesh to the format expected by GSLIB for quads
/// and hexes
void GetQuadHexNodalCoordinates();
/// Convert simplices to quad/hexes and then get nodal coordinates for each
/// split element into format expected by GSLIB
void GetSimplexNodalCoordinates();
/// Use GSLIB for communication and interpolation
void InterpolateH1(const GridFunction &field_in, Vector &field_out);
/// Uses GSLIB Crystal Router for communication followed by MFEM's
/// interpolation functions
void InterpolateGeneral(const GridFunction &field_in, Vector &field_out);
/// Map {r,s,t} coordinates from [-1,1] to [0,1] for MFEM. For simplices mesh
/// find the original element number (that was split into micro quads/hexes
/// by GetSimplexNodalCoordinates())
void MapRefPosAndElemIndices();
public:
FindPointsGSLIB();
@@ -64,45 +102,37 @@ public:
void Setup(Mesh &m, const double bb_t = 0.1, const double newt_tol = 1.0e-12,
const int npt_max = 256);
/** Searches positions given in physical space by @a point_pos. All output
Arrays and Vectors are expected to have the correct size.
@param[in] point_pos Positions to be found. Must by ordered by nodes
(XXX...,YYY...,ZZZ).
@param[out] codes Return codes for each point: inside element (0),
element boundary (1), not found (2).
@param[out] proc_ids MPI proc ids where the points were found.
@param[out] elem_ids Element ids where the points were found.
@param[out] ref_pos Reference coordinates of the found point. Ordered
by vdim (XYZ,XYZ,XYZ...).
Note: the gslib reference frame is [-1,1].
@param[out] dist Distance between the sought and the found point
in physical space. */
void FindPoints(const Vector &point_pos, Array<unsigned int> &codes,
Array<unsigned int> &proc_ids, Array<unsigned int> &elem_ids,
Vector &ref_pos, Vector &dist);
/** Searches positions given in physical space by @a point_pos. These positions
must by ordered by nodes: (XXX...,YYY...,ZZZ).
This function populates the following member variables:
#gsl_code Return codes for each point: inside element (0),
element boundary (1), not found (2).
#gsl_proc MPI proc ids where the points were found.
#gsl_elem Element ids where the points were found.
Defaults to 0 for points that were not found.
#gsl_mfem_elem Element ids corresponding to MFEM-mesh where the points
were found. #gsl_mfem_elem != #gsl_elem for simplices
Defaults to 0 for points that were not found.
#gsl_ref Reference coordinates of the found point.
Ordered by vdim (XYZ,XYZ,XYZ...). Defaults to -1 for
points that were not found. Note: the gslib reference
frame is [-1,1].
#gsl_mfem_ref Reference coordinates #gsl_ref mapped to [0,1].
Defaults to 0 for points that were not found.
#gsl_dist Distance between the sought and the found point
in physical space. */
void FindPoints(const Vector &point_pos);
/// Setup FindPoints and search positions
void FindPoints(Mesh &m, const Vector &point_pos, const double bb_t = 0.1,
const double newt_tol = 1.0e-12, const int npt_max = 256);
/** Interpolation of field values at prescribed reference space positions.
@param[in] codes Return codes for each point: inside element (0),
element boundary (1), not found (2).
@param[in] proc_ids MPI proc ids where the points were found.
@param[in] elem_ids Element ids where the points were found.
@param[in] ref_pos Reference coordinates of the found point. Ordered
by vdim (XYZ,XYZ,XYZ...).
Note: the gslib reference frame is [-1,1].
@param[in] field_in Function values that will be interpolated on the
reference positions. Note: it is assumed that
@a field_in is in H1 and in the same space as the
mesh that was given to Setup().
@param[out] field_out Interpolated values. */
void Interpolate(Array<unsigned int> &codes, Array<unsigned int> &proc_ids,
Array<unsigned int> &elem_ids, Vector &ref_pos,
const GridFunction &field_in, Vector &field_out);
@param[out] field_out Interpolated values. For points that are not found
the value is set to #default_interp_value. */
void Interpolate(const GridFunction &field_in, Vector &field_out);
/** Search positions and interpolate */
void Interpolate(const Vector &point_pos, const GridFunction &field_in,
@@ -111,27 +141,45 @@ public:
void Interpolate(Mesh &m, const Vector &point_pos,
const GridFunction &field_in, Vector &field_out);
/// Average type to be used for L2 functions in-case a point is located at
/// an element boundary where the function might be multi-valued.
void SetL2AvgType(AvgType avgtype_) { avgtype = avgtype_; }
/// Set the default interpolation value for points that are not found in the
/// mesh.
void SetDefaultInterpolationValue(double interp_value_)
{
default_interp_value = interp_value_;
}
/** Cleans up memory allocated internally by gslib.
Note that in parallel, this must be called before MPI_Finalize(), as
it calls MPI_Comm_free() for internal gslib communicators. */
Note that in parallel, this must be called before MPI_Finalize(), as it
calls MPI_Comm_free() for internal gslib communicators. */
void FreeData();
/// Return code for each point searched by FindPoints: inside element (0), on
/// element boundary (1), or not found (2).
const Array<unsigned int> &GetCode() const { return gsl_code; }
/// Return element number for each point found by FindPoints.
const Array<unsigned int> &GetElem() const { return gsl_elem; }
const Array<unsigned int> &GetElem() const { return gsl_mfem_elem; }
/// Return MPI rank on which each point was found by FindPoints.
const Array<unsigned int> &GetProc() const { return gsl_proc; }
/// Return reference coordinates for each point found by FindPoints.
const Vector &GetReferencePosition() const { return gsl_ref; }
const Vector &GetReferencePosition() const { return gsl_mfem_ref; }
/// Return distance Distance between the sought and the found point
/// in physical space, for each point found by FindPoints.
const Vector &GetDist() const { return gsl_dist; }
/// Return element number for each point found by FindPoints corresponding to
/// GSLIB mesh. gsl_mfem_elem != gsl_elem for mesh with simplices.
const Array<unsigned int> &GetGSLIBElem() const { return gsl_elem; }
/// Return reference coordinates in [-1,1] (internal range in GSLIB) for each
/// point found by FindPoints.
const Vector &GetGSLIBReferencePosition() const { return gsl_ref; }
};
} // namespace mfem
#endif //MFEM_USE_GSLIB
#endif // MFEM_USE_GSLIB
#endif //MFEM_GSLIB guard
#endif // MFEM_GSLIB
-1465
View File
File diff suppressed because it is too large Load Diff
+149 -25
View File
@@ -35,6 +35,9 @@ extern Ceed ceed;
std::string ceed_path;
extern CeedBasisMap ceed_basis_map;
extern CeedRestrMap ceed_restr_map;
}
void InitCeedCoeff(Coefficient* Q, CeedData* ptr)
@@ -81,10 +84,9 @@ static CeedElemTopology GetCeedTopology(Geometry::Type geom)
}
}
static void InitCeedNonTensorBasisAndRestriction(const FiniteElementSpace &fes,
const IntegrationRule &ir,
Ceed ceed, CeedBasis *basis,
CeedElemRestriction *restr)
static void InitCeedNonTensorBasis(const FiniteElementSpace &fes,
const IntegrationRule &ir,
Ceed ceed, CeedBasis *basis)
{
Mesh *mesh = fes.GetMesh();
const FiniteElement *fe = fes.GetFE(0);
@@ -97,7 +99,73 @@ static void InitCeedNonTensorBasisAndRestriction(const FiniteElementSpace &fes,
Vector qweight(Q);
Vector shape_i(P);
DenseMatrix grad_i(P, dim);
const Table &el_dof = fes.GetElementToDofTable();
Array<int> tp_el_dof(el_dof.Size_of_connections());
const TensorBasisElement * tfe =
dynamic_cast<const TensorBasisElement *>(fe);
if (tfe) // Lexicographic ordering using dof_map
{
const Array<int>& dof_map = tfe->GetDofMap();
for (int i = 0; i < Q; i++)
{
const IntegrationPoint &ip = ir.IntPoint(i);
qref(0,i) = ip.x;
if (dim>1) { qref(1,i) = ip.y; }
if (dim>2) { qref(2,i) = ip.z; }
qweight(i) = ip.weight;
fe->CalcShape(ip, shape_i);
fe->CalcDShape(ip, grad_i);
for (int j = 0; j < P; j++)
{
shape(j, i) = shape_i(dof_map[j]);
for (int d = 0; d < dim; ++d)
{
grad(j+i*P+d*Q*P) = grad_i(dof_map[j], d);
}
}
}
}
else // Native ordering
{
for (int i = 0; i < Q; i++)
{
const IntegrationPoint &ip = ir.IntPoint(i);
qref(0,i) = ip.x;
if (dim>1) { qref(1,i) = ip.y; }
if (dim>2) { qref(2,i) = ip.z; }
qweight(i) = ip.weight;
fe->CalcShape(ip, shape_i);
fe->CalcDShape(ip, grad_i);
for (int j = 0; j < P; j++)
{
shape(j, i) = shape_i(j);
for (int d = 0; d < dim; ++d)
{
grad(j+i*P+d*Q*P) = grad_i(j, d);
}
}
}
}
CeedBasisCreateH1(ceed, GetCeedTopology(fe->GetGeomType()), fes.GetVDim(),
fe->GetDof(), ir.GetNPoints(), shape.GetData(),
grad.GetData(), qref.GetData(), qweight.GetData(), basis);
}
static void InitCeedNonTensorRestriction(const FiniteElementSpace &fes,
const IntegrationRule &ir,
Ceed ceed, CeedElemRestriction *restr)
{
Mesh *mesh = fes.GetMesh();
const FiniteElement *fe = fes.GetFE(0);
const int dim = mesh->Dimension();
const int P = fe->GetDof();
const int Q = ir.GetNPoints();
DenseMatrix shape(P, Q);
Vector grad(P*dim*Q);
DenseMatrix qref(dim, Q);
Vector qweight(Q);
Vector shape_i(P);
DenseMatrix grad_i(P, dim);
CeedInt compstride = fes.GetOrdering()==Ordering::byVDIM ? 1 : fes.GetNDofs();
const Table &el_dof = fes.GetElementToDofTable();
Array<int> tp_el_dof(el_dof.Size_of_connections());
@@ -124,7 +192,6 @@ static void InitCeedNonTensorBasisAndRestriction(const FiniteElementSpace &fes,
}
}
}
for (int i = 0; i < mesh->GetNE(); i++)
{
const int el_offset = fe->GetDof() * i;
@@ -162,7 +229,6 @@ static void InitCeedNonTensorBasisAndRestriction(const FiniteElementSpace &fes,
}
}
}
for (int e = 0; e < mesh->GetNE(); e++)
{
for (int i = 0; i < P; i++)
@@ -178,19 +244,15 @@ static void InitCeedNonTensorBasisAndRestriction(const FiniteElementSpace &fes,
}
}
}
CeedBasisCreateH1(ceed, GetCeedTopology(fe->GetGeomType()), fes.GetVDim(),
fe->GetDof(), ir.GetNPoints(), shape.GetData(),
grad.GetData(), qref.GetData(), qweight.GetData(), basis);
CeedElemRestrictionCreate(ceed, mesh->GetNE(), fe->GetDof(), fes.GetVDim(),
compstride, (fes.GetVDim())*(fes.GetNDofs()),
CEED_MEM_HOST, CEED_COPY_VALUES,
tp_el_dof.GetData(), restr);
}
static void InitCeedTensorBasisAndRestriction(const FiniteElementSpace &fes,
const IntegrationRule &ir,
Ceed ceed, CeedBasis *basis,
CeedElemRestriction *restr)
static void InitCeedTensorBasis(const FiniteElementSpace &fes,
const IntegrationRule &ir,
Ceed ceed, CeedBasis *basis)
{
Mesh *mesh = fes.GetMesh();
const FiniteElement *fe = fes.GetFE(0);
@@ -198,7 +260,6 @@ static void InitCeedTensorBasisAndRestriction(const FiniteElementSpace &fes,
const TensorBasisElement * tfe =
dynamic_cast<const TensorBasisElement *>(fe);
MFEM_VERIFY(tfe, "invalid FE");
const Array<int>& dof_map = tfe->GetDofMap();
const FiniteElement *fe1d =
fes.FEColl()->FiniteElementForGeometry(Geometry::SEGMENT);
DenseMatrix shape1d(fe1d->GetDof(), ir.GetNPoints());
@@ -227,6 +288,28 @@ static void InitCeedTensorBasisAndRestriction(const FiniteElementSpace &fes,
ir.GetNPoints(), shape1d.GetData(),
grad1d.GetData(), qref1d.GetData(),
qweight1d.GetData(), basis);
}
static void InitCeedTensorRestriction(const FiniteElementSpace &fes,
const IntegrationRule &ir,
Ceed ceed, CeedElemRestriction *restr)
{
Mesh *mesh = fes.GetMesh();
const FiniteElement *fe = fes.GetFE(0);
const TensorBasisElement * tfe =
dynamic_cast<const TensorBasisElement *>(fe);
MFEM_VERIFY(tfe, "invalid FE");
const Array<int>& dof_map = tfe->GetDofMap();
const FiniteElement *fe1d =
fes.FEColl()->FiniteElementForGeometry(Geometry::SEGMENT);
DenseMatrix shape1d(fe1d->GetDof(), ir.GetNPoints());
DenseMatrix grad1d(fe1d->GetDof(), ir.GetNPoints());
Vector qref1d(ir.GetNPoints()), qweight1d(ir.GetNPoints());
Vector shape_i(shape1d.Height());
DenseMatrix grad_i(grad1d.Height(), 1);
const H1_SegmentElement *h1_fe1d =
dynamic_cast<const H1_SegmentElement *>(fe1d);
MFEM_VERIFY(h1_fe1d, "invalid FE");
CeedInt compstride = fes.GetOrdering()==Ordering::byVDIM ? 1 : fes.GetNDofs();
const Table &el_dof = fes.GetElementToDofTable();
@@ -258,14 +341,52 @@ void InitCeedBasisAndRestriction(const FiniteElementSpace &fes,
Ceed ceed, CeedBasis *basis,
CeedElemRestriction *restr)
{
if (UsesTensorBasis(fes))
// Check for FES -> basis, restriction in hash tables
const Mesh *mesh = fes.GetMesh();
const FiniteElement *fe = fes.GetFE(0);
const int P = fe->GetDof();
const int Q = irm.GetNPoints();
const int nelem = mesh->GetNE();
const int ncomp = fes.GetVDim();
CeedBasisKey basis_key(&fes, &irm, ncomp, P, Q);
auto basis_itr = internal::ceed_basis_map.find(basis_key);
CeedRestrKey restr_key(&fes, nelem, P, ncomp);
auto restr_itr = internal::ceed_restr_map.find(restr_key);
// Init or retreive key values
if (basis_itr == internal::ceed_basis_map.end())
{
const IntegrationRule &ir = IntRules.Get(Geometry::SEGMENT, irm.GetOrder());
InitCeedTensorBasisAndRestriction(fes, ir, ceed, basis, restr);
if (UsesTensorBasis(fes))
{
const IntegrationRule &ir = IntRules.Get(Geometry::SEGMENT, irm.GetOrder());
InitCeedTensorBasis(fes, ir, ceed, basis);
}
else
{
InitCeedNonTensorBasis(fes, irm, ceed, basis);
}
internal::ceed_basis_map[basis_key] = *basis;
}
else
{
InitCeedNonTensorBasisAndRestriction(fes, irm, ceed, basis, restr);
*basis = basis_itr->second;
}
if (restr_itr == internal::ceed_restr_map.end())
{
if (UsesTensorBasis(fes))
{
const IntegrationRule &ir = IntRules.Get(Geometry::SEGMENT, irm.GetOrder());
InitCeedTensorRestriction(fes, ir, ceed, restr);
}
else
{
InitCeedNonTensorRestriction(fes, irm, ceed, restr);
}
internal::ceed_restr_map[restr_key] = *restr;
}
else
{
*restr = restr_itr->second;
}
}
@@ -327,8 +448,8 @@ void CeedPAAssemble(const CeedPAOperator& op,
CeedVectorCreate(ceed, nelem * nqpts * qdatasize, &ceedData.rho);
// Context data to be passed to the 'f_build_diff' Q-function.
ceedData.build_ctx.dim = mesh->Dimension();
ceedData.build_ctx.space_dim = mesh->SpaceDimension();
ceedData.build_ctx_data.dim = mesh->Dimension();
ceedData.build_ctx_data.space_dim = mesh->SpaceDimension();
std::string qf_file = GetCeedPath() + op.header;
std::string qf;
@@ -342,7 +463,7 @@ void CeedPAAssemble(const CeedPAOperator& op,
CeedQFunctionCreateInterior(ceed, 1, op.const_qf,
qf.c_str(),
&ceedData.build_qfunc);
ceedData.build_ctx.coeff = ((CeedConstCoeff*)ceedData.coeff)->val;
ceedData.build_ctx_data.coeff = ((CeedConstCoeff*)ceedData.coeff)->val;
break;
case CeedCoeff::Grid:
qf = qf_file + op.grid_func;
@@ -358,8 +479,12 @@ void CeedPAAssemble(const CeedPAOperator& op,
CeedQFunctionAddInput(ceedData.build_qfunc, "weights", 1, CEED_EVAL_WEIGHT);
CeedQFunctionAddOutput(ceedData.build_qfunc, "qdata", qdatasize,
CEED_EVAL_NONE);
CeedQFunctionSetContext(ceedData.build_qfunc, &ceedData.build_ctx,
sizeof(ceedData.build_ctx));
CeedQFunctionContextCreate(ceed, &ceedData.build_ctx);
CeedQFunctionContextSetData(ceedData.build_ctx, CEED_MEM_HOST, CEED_USE_POINTER,
sizeof(ceedData.build_ctx_data),
&ceedData.build_ctx_data);
CeedQFunctionSetContext(ceedData.build_qfunc, ceedData.build_ctx);
// Create the operator that builds the quadrature data for the operator.
CeedOperatorCreate(ceed, ceedData.build_qfunc, NULL, NULL,
@@ -399,8 +524,7 @@ void CeedPAAssemble(const CeedPAOperator& op,
CeedQFunctionAddInput(ceedData.apply_qfunc, "qdata", qdatasize,
CEED_EVAL_NONE);
CeedQFunctionAddOutput(ceedData.apply_qfunc, "v", dimV, op.test_op);
CeedQFunctionSetContext(ceedData.apply_qfunc, &ceedData.build_ctx,
sizeof(ceedData.build_ctx));
CeedQFunctionSetContext(ceedData.apply_qfunc, ceedData.build_ctx);
// Create the diff operator.
CeedOperatorCreate(ceed, ceedData.apply_qfunc, NULL, NULL, &ceedData.oper);
+46 -8
View File
@@ -18,6 +18,9 @@
#include "../../general/device.hpp"
#include "../../linalg/vector.hpp"
#include <ceed.h>
#include <ceed-hash.h>
#include <tuple>
#include <unordered_map>
namespace mfem
{
@@ -27,7 +30,47 @@ class GridFunction;
class IntegrationRule;
class Coefficient;
namespace internal { extern Ceed ceed; } // defined in device.cpp
// Hash table for CeedBasis
using CeedBasisKey =
std::tuple<const FiniteElementSpace*, const IntegrationRule*, int, int, int>;
struct CeedBasisHash
{
std::size_t operator()(const CeedBasisKey& k) const
{
return CeedHashCombine(CeedHashCombine(CeedHashInt(
reinterpret_cast<CeedHash64_t>(std::get<0>(k))),
CeedHashInt(
reinterpret_cast<CeedHash64_t>(std::get<1>(k)))),
CeedHashCombine(CeedHashCombine(CeedHashInt(std::get<2>(k)),
CeedHashInt(std::get<3>(k))),
CeedHashInt(std::get<4>(k))));
}
};
using CeedBasisMap =
std::unordered_map<const CeedBasisKey, CeedBasis, CeedBasisHash>;
// Hash table for CeedElemRestriction
using CeedRestrKey = std::tuple<const FiniteElementSpace*, int, int, int>;
struct CeedRestrHash
{
std::size_t operator()(const CeedRestrKey& k) const
{
return CeedHashCombine(CeedHashCombine(CeedHashInt(
reinterpret_cast<CeedHash64_t>(std::get<0>(k))),
CeedHashInt(std::get<1>(k))),
CeedHashCombine(CeedHashInt(std::get<2>(k)),
CeedHashInt(std::get<3>(k))));
}
};
using CeedRestrMap =
std::unordered_map<const CeedRestrKey, CeedElemRestriction, CeedRestrHash>;
namespace internal
{
extern Ceed ceed; // defined in device.cpp
extern CeedBasisMap basis_map;
extern CeedRestrMap restr_map;
}
/// A structure used to pass additional data to f_build_diff and f_apply_diff
struct BuildContext { CeedInt dim, space_dim; CeedScalar coeff; };
@@ -56,7 +99,8 @@ struct CeedData
CeedVector node_coords, rho;
CeedCoeff coeff_type;
void* coeff;
BuildContext build_ctx;
CeedQFunctionContext build_ctx;
BuildContext build_ctx_data;
CeedVector u, v;
@@ -64,10 +108,6 @@ struct CeedData
{
CeedOperatorDestroy(&build_oper);
CeedOperatorDestroy(&oper);
CeedBasisDestroy(&basis);
CeedBasisDestroy(&mesh_basis);
CeedElemRestrictionDestroy(&restr);
CeedElemRestrictionDestroy(&mesh_restr);
CeedElemRestrictionDestroy(&restr_i);
CeedElemRestrictionDestroy(&mesh_restr_i);
CeedQFunctionDestroy(&apply_qfunc);
@@ -77,8 +117,6 @@ struct CeedData
if (coeff_type==CeedCoeff::Grid)
{
CeedGridCoeff* c = (CeedGridCoeff*)coeff;
CeedBasisDestroy(&c->basis);
CeedElemRestrictionDestroy(&c->restr);
CeedVectorDestroy(&c->coeffVector);
delete c;
}
+8
View File
@@ -204,6 +204,14 @@ void LinearForm::Update(FiniteElementSpace *f, Vector &v, int v_offset)
ResetDeltaLocations();
}
void LinearForm::MakeRef(FiniteElementSpace *f, Vector &v, int v_offset)
{
MFEM_ASSERT(v.Size() >= v_offset + f->GetVSize(), "");
fes = f;
v.UseDevice(true);
this->Vector::MakeRef(v, v_offset, fes->GetVSize());
}
void LinearForm::AssembleDelta()
{
if (dlfi_delta.Size() == 0) { return; }
+11 -1
View File
@@ -26,7 +26,7 @@ protected:
/// FE space on which the LinearForm lives. Not owned.
FiniteElementSpace *fes;
/** @brief Indicates the LinerFormIntegrator%s stored in #dlfi, #dlfi_delta,
/** @brief Indicates the LinearFormIntegrator%s stored in #dlfi, #dlfi_delta,
#blfi, and #flfi are owned by another LinearForm. */
int extern_lfs;
@@ -175,6 +175,16 @@ public:
@note This method does not perform assembly. */
void Update(FiniteElementSpace *f, Vector &v, int v_offset);
/** @brief Make the LinearForm reference external data on a new
FiniteElementSpace. */
/** This method changes the FiniteElementSpace associated with the LinearForm
@a *f and sets the data of the Vector @a v (plus the @a v_offset) as
external data in the LinearForm.
@note This version of the method will also perform bounds checks when the
build option MFEM_DEBUG is enabled. */
virtual void MakeRef(FiniteElementSpace *f, Vector &v, int v_offset);
/// Return the action of the LinearForm as a linear mapping.
/** Linear forms are linear functionals which map GridFunctions to
the real numbers. This method performs this mapping which in
+6 -39
View File
@@ -457,20 +457,8 @@ void VectorFEDomainLFCurlIntegrator::AssembleRHSElementVect(
Tr.SetIntPoint (&ip);
el.CalcPhysCurlShape(Tr, curlshape);
QF->Eval(vec, Tr, ip);
switch (spaceDim)
{
case 3:
MFEM_VERIFY(QF, "VectorFunctionCoefficient not provided");
QF->Eval(vec, Tr, ip);
break;
case 2:
MFEM_VERIFY(Q, "FunctionCoefficient (Scalar) not provided");
vec[0] = Q->Eval(Tr, ip);
break;
default:
break; // This should be unreachable
}
vec *= ip.weight * Tr.Weight();
curlshape.AddMult (vec, elvect);
}
@@ -480,38 +468,17 @@ void VectorFEDomainLFCurlIntegrator::AssembleDeltaElementVect(
const FiniteElement &fe, ElementTransformation &Trans, Vector &elvect)
{
int spaceDim = Trans.GetSpaceDim();
switch (spaceDim)
{
case 3:
MFEM_ASSERT(vec_delta != NULL,
"coefficient must be VectorDeltaCoefficient");
break;
case 2:
MFEM_ASSERT(delta != NULL,
"coefficient must be DeltaCoefficient");
break;
default:
break; // This should be unreachable
}
MFEM_ASSERT(vec_delta != NULL,
"coefficient must be VectorDeltaCoefficient");
int dof = fe.GetDof();
int n=(spaceDim == 3)? spaceDim : 1;
vec.SetSize(n);
curlshape.SetSize(dof, n);
elvect.SetSize(dof);
fe.CalcPhysCurlShape(Trans, curlshape);
switch (spaceDim)
{
case 3:
vec_delta->EvalDelta(vec, Trans, Trans.GetIntPoint());
curlshape.Mult(vec, elvect);
break;
case 2:
curlshape.GetColumn(0,elvect);
elvect *= delta->EvalDelta(Trans, Trans.GetIntPoint());
break;
default:
break; // This should be unreachable
}
vec_delta->EvalDelta(vec, Trans, Trans.GetIntPoint());
curlshape.Mult(vec, elvect);
}
void VectorFEDomainLFDivIntegrator::AssembleRHSElementVect(
-3
View File
@@ -284,7 +284,6 @@ class VectorFEDomainLFCurlIntegrator : public DeltaLFIntegrator
{
private:
VectorCoefficient *QF=nullptr;
Coefficient *Q=nullptr;
DenseMatrix curlshape;
Vector vec;
@@ -292,8 +291,6 @@ public:
/// Constructs the domain integrator (Q, curl v)
VectorFEDomainLFCurlIntegrator(VectorCoefficient &F)
: DeltaLFIntegrator(F), QF(&F) { }
VectorFEDomainLFCurlIntegrator(Coefficient &F)
: DeltaLFIntegrator(F), Q(&F) { }
virtual void AssembleRHSElementVect(const FiniteElement &el,
ElementTransformation &Tr,
+3 -52
View File
@@ -10,7 +10,6 @@
// CONTRIBUTING.md for details.
#include "fem.hpp"
#include "../general/forall.hpp"
namespace mfem
{
@@ -28,7 +27,7 @@ void NonlinearForm::SetAssemblyLevel(AssemblyLevel assembly_level)
// This is the default behavior.
break;
case AssemblyLevel::PARTIAL:
ext = new PANonlinearForm(this);
ext = new PANonlinearFormExtension(this);
break;
default:
mfem_error("Unknown assembly level for this form.");
@@ -81,13 +80,6 @@ void NonlinearForm::SetEssentialVDofs(const Array<int> &ess_vdofs_list)
double NonlinearForm::GetGridFunctionEnergy(const Vector &x) const
{
if (ext)
{
MFEM_VERIFY(!fnfi.Size(), "Interior faces terms not yet implemented!");
MFEM_VERIFY(!bfnfi.Size(), "Boundary face terms not yet implemented!");
return ext->GetGridFunctionEnergy(x);
}
Array<int> vdofs;
Vector el_x;
const FiniteElement *fe;
@@ -146,14 +138,6 @@ void NonlinearForm::Mult(const Vector &x, Vector &y) const
if (ext)
{
ext->Mult(px, py);
if (Serial())
{
if (cP) { cP->MultTranspose(py, y); }
const int N = ess_tdof_list.Size();
const auto tdof = ess_tdof_list.Read();
auto Y = y.ReadWrite();
MFEM_FORALL(i, N, Y[tdof[i]] = 0.0; );
}
return;
}
@@ -280,16 +264,7 @@ Operator &NonlinearForm::GetGradient(const Vector &x) const
{
if (ext)
{
Operator &grad = ext->GetGradient(Prolongate(x));
hGrad.Reset(&grad, false);
if (Serial())
{
Operator *Gop;
if (cP) { hGrad.Reset(new RAPOperator(*cP, grad, *cP)); }
hGrad.Ptr()->Operator::FormSystemOperator(ess_tdof_list, Gop);
hGrad.Reset(Gop);
}
return *hGrad.Ptr();
MFEM_ABORT("Not yet implemented!");
}
const int skip_zeros = 0;
@@ -451,31 +426,7 @@ void NonlinearForm::Update()
void NonlinearForm::Setup()
{
if (ext) { return ext->Setup(); }
}
void NonlinearForm::AssembleGradientDiagonal(Vector &diag) const
{
if (ext)
{
MFEM_ASSERT(diag.Size() == fes->GetTrueVSize(),
"Vector for holding diagonal has wrong size!");
const Operator *P = fes->GetProlongationMatrix();
if (!IsIdentityProlongation(P))
{
Vector local_diag(P->Height());
ext->AssembleGradientDiagonal(local_diag);
P->MultTranspose(local_diag, diag);
}
else
{
ext->AssembleGradientDiagonal(diag);
}
}
else
{
MFEM_ABORT("Not implemented. Can be obtained through GetGradient().");
}
if (ext) { return ext->AssemblePA(); }
}
NonlinearForm::~NonlinearForm()
-10
View File
@@ -45,7 +45,6 @@ protected:
Array<Array<int>*> bfnfi_marker; // not owned
mutable SparseMatrix *Grad, *cGrad; // owned
mutable OperatorHandle hGrad;
/// A list of all essential true dofs
Array<int> ess_tdof_list;
@@ -166,15 +165,6 @@ public:
/// Setup the NonlinearForm
virtual void Setup();
/** @brief Assemble the diagonal of the gradient into diag
For adaptively refined meshes, this returns P^T d_e, where d_e is the
locally assembled diagonal on each element and P^T is the transpose of
the conforming prolongation. In general this is not the correct diagonal
for an AMR mesh. */
void AssembleGradientDiagonal(Vector &diag) const;
/// Get the finite element space prolongation matrix
virtual const Operator *GetProlongation() const { return P; }
/// Get the finite element space restriction matrix
+38 -77
View File
@@ -13,101 +13,62 @@
// PABilinearFormExtension and MFBilinearFormExtension.
#include "nonlinearform.hpp"
#include "../general/forall.hpp"
namespace mfem
{
NonlinearFormExtension::NonlinearFormExtension(const NonlinearForm *nlf)
: Operator(nlf->FESpace()->GetTrueVSize()), nlf(nlf) { }
PANonlinearForm::PANonlinearForm(NonlinearForm *nlf):
NonlinearFormExtension(nlf),
x_grad(NULL),
fes(*nlf->FESpace()),
dnfi(*nlf->GetDNFI()),
R(fes.GetElementRestriction(ElementDofOrdering::LEXICOGRAPHIC))
NonlinearFormExtension::NonlinearFormExtension(NonlinearForm *form)
: Operator(form->FESpace()->GetTrueVSize()), n(form)
{
MFEM_VERIFY(R, "Not yet implemented!");
xe.SetSize(R->Height(), Device::GetMemoryType());
ye.SetSize(R->Height(), Device::GetMemoryType());
ye.UseDevice(true);
// empty
}
double PANonlinearForm::GetGridFunctionEnergy(const Vector &x) const
PANonlinearFormExtension::PANonlinearFormExtension(NonlinearForm *form):
NonlinearFormExtension(form), fes(*form->FESpace())
{
double energy = 0.0;
R->Mult(x, xe);
for (int i = 0; i < dnfi.Size(); i++)
const ElementDofOrdering ordering = ElementDofOrdering::LEXICOGRAPHIC;
elem_restrict_lex = fes.GetElementRestriction(ordering);
if (elem_restrict_lex)
{
energy += dnfi[i]->GetGridFunctionEnergyPA(xe);
localX.SetSize(elem_restrict_lex->Height(), Device::GetMemoryType());
localY.SetSize(elem_restrict_lex->Height(), Device::GetMemoryType());
localY.UseDevice(true); // ensure 'localY = 0.0' is done on device
}
return energy;
}
void PANonlinearForm::Setup()
void PANonlinearFormExtension::AssemblePA()
{
for (int i = 0; i < dnfi.Size(); ++i) { dnfi[i]->AssemblePA(fes); }
}
void PANonlinearForm::Mult(const Vector &x, Vector &y) const
{
ye = 0.0;
R->Mult(x, xe);
for (int i = 0; i < dnfi.Size(); ++i) { dnfi[i]->AddMultPA(xe, ye); }
R->MultTranspose(ye, y);
}
void PANonlinearForm::AssembleGradientDiagonal(Vector &diag) const
{
MFEM_VERIFY(x_grad, "GetGradient() has not been called");
R->Mult(*x_grad, xe);
ye = 0.0;
for (int i = 0; i < dnfi.Size(); ++i)
Array<NonlinearFormIntegrator*> &integrators = *n->GetDNFI();
const int Ni = integrators.Size();
for (int i = 0; i < Ni; ++i)
{
dnfi[i]->AssembleGradientDiagonalPA(xe, ye);
integrators[i]->AssemblePA(*n->FESpace());
}
R->MultTranspose(ye, diag);
}
Operator &PANonlinearForm::GetGradient(const Vector &x) const
void PANonlinearFormExtension::Mult(const Vector &x, Vector &y) const
{
// Store the last x that was used to compute the gradient.
x_grad = &x;
Grad.Reset(new PANonlinearForm::Gradient(x, *this));
return *Grad.Ptr();
Array<NonlinearFormIntegrator*> &integrators = *n->GetDNFI();
const int iSz = integrators.Size();
if (elem_restrict_lex)
{
elem_restrict_lex->Mult(x, localX);
localY = 0.0;
for (int i = 0; i < iSz; ++i)
{
integrators[i]->AddMultPA(localX, localY);
}
elem_restrict_lex->MultTranspose(localY, y);
}
else
{
y.UseDevice(true); // typically this is a large vector, so store on device
y = 0.0;
for (int i = 0; i < iSz; ++i)
{
integrators[i]->AddMultPA(x, y);
}
}
}
PANonlinearForm::Gradient::Gradient(const Vector &x, const PANonlinearForm &e):
Operator(e.fes.GetVSize()), R(e.R), dnfi(e.dnfi)
{
ge.UseDevice(true);
ge.SetSize(R->Height(), Device::GetMemoryType());
R->Mult(x, ge);
xe.UseDevice(true);
xe.SetSize(R->Height(), Device::GetMemoryType());
ye.UseDevice(true);
ye.SetSize(R->Height(), Device::GetMemoryType());
ze.UseDevice(true);
ze.SetSize(R->Height(), Device::GetMemoryType());
// Do we still need to do this?
for (int i = 0; i < dnfi.Size(); ++i) { dnfi[i]->AssemblePA(e.fes); }
}
void PANonlinearForm::Gradient::Mult(const Vector &x, Vector &y) const
{
ze = x;
ye = 0.0;
R->Mult(ze, xe);
for (int i = 0; i < dnfi.Size(); ++i) { dnfi[i]->AddMultGradPA(ge, xe, ye); }
R->MultTranspose(ye, y);
}
} // namespace mfem
+9 -41
View File
@@ -17,60 +17,28 @@
namespace mfem
{
class NonlinearForm;
class NonlinearFormIntegrator;
/** @brief Class extending the NonlinearForm class to support the different
AssemblyLevel%s. */
class NonlinearFormExtension : public Operator
{
protected:
const NonlinearForm *nlf;
NonlinearForm *n; ///< Not owned
public:
NonlinearFormExtension(const NonlinearForm*);
virtual void Setup() = 0;
virtual Operator &GetGradient(const Vector&) const = 0;
virtual double GetGridFunctionEnergy(const Vector &x) const = 0;
virtual void AssembleGradientDiagonal(Vector &diag) const
{
MFEM_ABORT("Not implemented for this assembly level!");
}
NonlinearFormExtension(NonlinearForm *form);
virtual void AssemblePA() = 0;
};
class PANonlinearForm;
/// Data and methods for partially-assembled nonlinear forms
class PANonlinearForm : public NonlinearFormExtension
class PANonlinearFormExtension : public NonlinearFormExtension
{
private:
class Gradient : public Operator
{
protected:
const Operator *R;
mutable Vector ge, xe, ye, ze;
const Array<NonlinearFormIntegrator*> &dnfi;
public:
Gradient(const Vector &x, const PANonlinearForm &ext);
virtual void Mult(const Vector &x, Vector &y) const;
};
protected:
mutable Vector xe, ye;
mutable const Vector *x_grad;
mutable OperatorHandle Grad;
const FiniteElementSpace &fes;
const Array<NonlinearFormIntegrator*> &dnfi;
const Operator *R;
const FiniteElementSpace &fes; // Not owned
mutable Vector localX, localY;
const Operator *elem_restrict_lex; // Not owned
public:
PANonlinearForm(NonlinearForm *nlf);
void Setup();
PANonlinearFormExtension(NonlinearForm*);
void AssemblePA();
void Mult(const Vector &x, Vector &y) const;
Operator &GetGradient(const Vector &x) const;
double GetGridFunctionEnergy(const Vector &x) const;
void AssembleGradientDiagonal(Vector &diag) const;
};
}
#endif // NONLINEARFORM_EXT_HPP
-21
View File
@@ -15,13 +15,6 @@
namespace mfem
{
double NonlinearFormIntegrator::GetGridFunctionEnergyPA(const Vector &x) const
{
mfem_error ("NonlinearFormIntegrator::GetGridFunctionEnergyPA(...)\n"
" is not implemented for this class.");
return 0.0;
}
void NonlinearFormIntegrator::AssemblePA(const FiniteElementSpace&)
{
mfem_error ("NonlinearFormIntegrator::AssemblePA(...)\n"
@@ -41,20 +34,6 @@ void NonlinearFormIntegrator::AddMultPA(const Vector &, Vector &) const
" is not implemented for this class.");
}
void NonlinearFormIntegrator::AddMultGradPA(const Vector&,
const Vector&, Vector&) const
{
mfem_error ("NonlinearFormIntegrator::AddMultGradPA(...)\n"
" is not implemented for this class.");
}
void NonlinearFormIntegrator::AssembleGradientDiagonalPA(const mfem::Vector &x,
mfem::Vector &diag) const
{
mfem_error ("NonlinearFormIntegrator::AssembleDiagonalPA(...)\n"
" is not implemented for this class.");
}
void NonlinearFormIntegrator::AssembleElementVector(
const FiniteElement &el, ElementTransformation &Tr,
const Vector &elfun, Vector &elvect)
-9
View File
@@ -68,9 +68,6 @@ public:
ElementTransformation &Tr,
const Vector &elfun);
/// Compute the local energy with partial assembly.
virtual double GetGridFunctionEnergyPA(const Vector &x) const;
/// Method defining partial assembly.
/** The result of the partial assembly is stored internally so that it can be
used later in the methods AddMultPA(). */
@@ -91,12 +88,6 @@ public:
called. */
virtual void AddMultPA(const Vector &x, Vector &y) const;
/// Method for partially assembled gradient action.
virtual void AddMultGradPA(const Vector &g,
const Vector &x, Vector &y) const;
virtual void AssembleGradientDiagonalPA(const Vector &x, Vector &diag) const;
virtual ~NonlinearFormIntegrator() { }
};
+2 -2
View File
@@ -3147,7 +3147,7 @@ static void SetSubVector(const int N,
const Array<int> &indices,
const Vector &in, Vector &out)
{
auto y = out.ReadWrite();
auto y = out.Write();
const auto x = in.Read();
const auto I = indices.Read();
MFEM_FORALL(i, N, y[I[i]] = x[i];);
@@ -3234,7 +3234,7 @@ static void AddSubVector(const int num_unique_dst_indices,
const Vector &src,
Vector &dst)
{
auto y = dst.ReadWrite();
auto y = dst.Write();
const auto x = src.Read();
const auto DST_I = unique_dst_indices.Read();
const auto SRC_O = unique_to_src_offsets.Read();
+165 -5
View File
@@ -655,6 +655,167 @@ void ParGridFunction::ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
#endif
}
double ParGridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
double Nu,
const IntegrationRule *irs[]) const
{
const_cast<ParGridFunction *>(this)->ExchangeFaceNbrData();
int fdof, dim, intorder, k;
ElementTransformation *transf;
Vector shape, el_dofs, err_val, ell_coeff_val;
Array<int> vdofs;
IntegrationPoint eip;
double error = 0.0;
ParMesh *mesh = pfes->GetParMesh();
dim = mesh->Dimension();
std::map<int,int> local_to_shared;
for (int i = 0; i < mesh->GetNSharedFaces(); ++i)
{
int i_local = mesh->GetSharedFace(i);
local_to_shared[i_local] = i;
}
for (int i = 0; i < mesh->GetNumFaces(); i++)
{
double shared_face_factor = 1.0;
bool shared_face = false;
int iel1, iel2, info1, info2;
mesh->GetFaceElements(i, &iel1, &iel2);
mesh->GetFaceInfos(i, &info1, &info2);
intorder = fes->GetFE(iel1)->GetOrder();
FaceElementTransformations *face_elem_transf;
const FiniteElement *fe1, *fe2;
if (info2 >= 0 && iel2 < 0)
{
int ishared = local_to_shared[i];
face_elem_transf = mesh->GetSharedFaceTransformations(ishared);
iel2 = face_elem_transf->Elem2No - mesh->GetNE();
fe2 = pfes->GetFaceNbrFE(iel2);
if ( (k = fe2->GetOrder()) > intorder )
{
intorder = k;
}
shared_face = true;
shared_face_factor = 0.5;
}
else
{
face_elem_transf = mesh->GetFaceElementTransformations(i);
if (iel2 >= 0)
{
fe2 = pfes->GetFE(iel2);
if ( (k = fe2->GetOrder()) > intorder )
{
intorder = k;
}
}
else
{
fe2 = NULL;
}
}
intorder = 2 * intorder; // <-------------
const IntegrationRule *ir;
if (irs)
{
ir = irs[face_elem_transf->GetGeometryType()];
}
else
{
ir = &(IntRules.Get(face_elem_transf->GetGeometryType(), intorder));
}
err_val.SetSize(ir->GetNPoints());
ell_coeff_val.SetSize(ir->GetNPoints());
// side 1
transf = face_elem_transf->Elem1;
fe1 = fes->GetFE(iel1);
fdof = fe1->GetDof();
fes->GetElementVDofs(iel1, vdofs);
shape.SetSize(fdof);
el_dofs.SetSize(fdof);
for (k = 0; k < fdof; k++)
if (vdofs[k] >= 0)
{
el_dofs(k) = (*this)(vdofs[k]);
}
else
{
el_dofs(k) = - (*this)(-1-vdofs[k]);
}
for (int j = 0; j < ir->GetNPoints(); j++)
{
face_elem_transf->Loc1.Transform(ir->IntPoint(j), eip);
fe1->CalcShape(eip, shape);
transf->SetIntPoint(&eip);
ell_coeff_val(j) = ell_coeff->Eval(*transf, eip);
err_val(j) = exsol->Eval(*transf, eip) - (shape * el_dofs);
}
if (fe2 != NULL)
{
// side 2
transf = face_elem_transf->Elem2;
fdof = fe2->GetDof();
shape.SetSize(fdof);
el_dofs.SetSize(fdof);
if (shared_face)
{
pfes->GetFaceNbrElementVDofs(iel2, vdofs);
for (k = 0; k < fdof; k++)
if (vdofs[k] >= 0)
{
el_dofs(k) = face_nbr_data[vdofs[k]];
}
else
{
el_dofs(k) = - face_nbr_data[-1-vdofs[k]];
}
}
else
{
pfes->GetElementVDofs(iel2, vdofs);
for (k = 0; k < fdof; k++)
if (vdofs[k] >= 0)
{
el_dofs(k) = (*this)(vdofs[k]);
}
else
{
el_dofs(k) = - (*this)(-1 - vdofs[k]);
}
}
for (int j = 0; j < ir->GetNPoints(); j++)
{
face_elem_transf->Loc2.Transform(ir->IntPoint(j), eip);
fe2->CalcShape(eip, shape);
transf->SetIntPoint(&eip);
ell_coeff_val(j) += ell_coeff->Eval(*transf, eip);
ell_coeff_val(j) *= 0.5;
err_val(j) -= (exsol->Eval(*transf, eip) - (shape * el_dofs));
}
}
transf = face_elem_transf;
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
transf->SetIntPoint(&ip);
error += shared_face_factor*(ip.weight * Nu * ell_coeff_val(j) *
pow(transf->Weight(), 1.0-1.0/(dim-1)) *
err_val(j) * err_val(j));
}
}
error = (error < 0.0) ? -sqrt(-error) : sqrt(error);
return GlobalLpNorm(2.0, error, pfes->GetComm());
}
void ParGridFunction::Save(std::ostream &out) const
{
double *data_ = const_cast<double*>(HostRead());
@@ -711,9 +872,9 @@ void ParGridFunction::SaveAsOne(std::ostream &out)
int *nfdofs = new int[NRanks];
int *nrdofs = new int[NRanks];
HostReadWrite();
values[0] = data;
double * h_data = const_cast<double *>(this->HostRead());
values[0] = h_data;
nv[0] = pfes -> GetVSize();
nvdofs[0] = pfes -> GetNVDofs();
nedofs[0] = pfes -> GetNEDofs();
@@ -814,7 +975,7 @@ void ParGridFunction::SaveAsOne(std::ostream &out)
MPI_Send(&nvdofs[0], 1, MPI_INT, 0, 456, MyComm);
MPI_Send(&nedofs[0], 1, MPI_INT, 0, 457, MyComm);
MPI_Send(&nfdofs[0], 1, MPI_INT, 0, 458, MyComm);
MPI_Send(data, nv[0], MPI_DOUBLE, 0, 460, MyComm);
MPI_Send(h_data, nv[0], MPI_DOUBLE, 0, 460, MyComm);
}
delete [] values;
@@ -860,7 +1021,6 @@ double GlobalLpNorm(const double p, double loc_norm, MPI_Comm comm)
return glob_norm;
}
void ParGridFunction::ComputeFlux(
BilinearFormIntegrator &blfi,
GridFunction &flux, bool wcoef, int subdomain)
@@ -1001,6 +1161,6 @@ double L2ZZErrorEstimator(BilinearFormIntegrator &flux_integrator,
return pow(glob_error, 1.0/norm_p);
}
}
} // namespace mfem
#endif // MFEM_USE_MPI
+71
View File
@@ -283,6 +283,77 @@ public:
pfes->GetComm());
}
/// Returns ||grad u_ex - grad u_h||_L2 for H1 or L2 elements
virtual double ComputeGradError(VectorCoefficient *exgrad,
const IntegrationRule *irs[] = NULL) const
{
return GlobalLpNorm(2.0, GridFunction::ComputeGradError(exgrad,irs),
pfes->GetComm());
}
/// Returns ||curl u_ex - curl u_h||_L2 for ND elements
virtual double ComputeCurlError(VectorCoefficient *excurl,
const IntegrationRule *irs[] = NULL) const
{
return GlobalLpNorm(2.0, GridFunction::ComputeCurlError(excurl,irs),
pfes->GetComm());
}
/// Returns ||div u_ex - div u_h||_L2 for RT elements
virtual double ComputeDivError(Coefficient *exdiv,
const IntegrationRule *irs[] = NULL) const
{
return GlobalLpNorm(2.0, GridFunction::ComputeDivError(exdiv,irs),
pfes->GetComm());
}
/// Returns the Face Jumps error for L2 elements
virtual double ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
double Nu,
const IntegrationRule *irs[]=NULL)
const;
/// Returns either the H1-seminorm or the DG Face Jumps error or both
/// depending on norm_type = 1, 2, 3
virtual double ComputeH1Error(Coefficient *exsol, VectorCoefficient *exgrad,
Coefficient *ell_coef, double Nu,
int norm_type) const
{
return GlobalLpNorm(2.0,
GridFunction::ComputeH1Error(exsol,exgrad,ell_coef,
Nu, norm_type),
pfes->GetComm());
}
/// Returns the error measured in H1-norm for H1 elements or in "broken"
/// H1-norm for L2 elements
virtual double ComputeH1Error(Coefficient *exsol, VectorCoefficient *exgrad,
const IntegrationRule *irs[] = NULL) const
{
return GlobalLpNorm(2.0, GridFunction::ComputeH1Error(exsol,exgrad,irs),
pfes->GetComm());
}
/// Returns the error measured H(div)-norm for RT elements
virtual double ComputeHDivError(VectorCoefficient *exsol,
Coefficient *exdiv,
const IntegrationRule *irs[] = NULL) const
{
return GlobalLpNorm(2.0, GridFunction::ComputeHDivError(exsol,exdiv,irs),
pfes->GetComm());
}
/// Returns the error measured H(curl)-norm for ND elements
virtual double ComputeHCurlError(VectorCoefficient *exsol,
VectorCoefficient *excurl,
const IntegrationRule *irs[] = NULL) const
{
return GlobalLpNorm(2.0,
GridFunction::ComputeHCurlError(exsol,excurl,irs),
pfes->GetComm());
}
virtual double ComputeMaxError(Coefficient *exsol[],
const IntegrationRule *irs[] = NULL) const
{
+13 -1
View File
@@ -21,7 +21,6 @@ namespace mfem
void ParLinearForm::Update(ParFiniteElementSpace *pf)
{
if (pf) { pfes = pf; }
LinearForm::Update(pfes);
}
@@ -31,6 +30,19 @@ void ParLinearForm::Update(ParFiniteElementSpace *pf, Vector &v, int v_offset)
LinearForm::Update(pf,v,v_offset);
}
void ParLinearForm::MakeRef(FiniteElementSpace *f, Vector &v, int v_offset)
{
LinearForm::MakeRef(f, v, v_offset);
pfes = dynamic_cast<ParFiniteElementSpace*>(f);
MFEM_ASSERT(pfes != NULL, "not a ParFiniteElementSpace");
}
void ParLinearForm::MakeRef(ParFiniteElementSpace *pf, Vector &v, int v_offset)
{
LinearForm::MakeRef(pf, v, v_offset);
pfes = pf;
}
void ParLinearForm::ParallelAssemble(Vector &tv)
{
const Operator* prolong = pfes->GetProlongationMatrix();
+25 -4
View File
@@ -92,6 +92,27 @@ public:
@note This method does not perform assembly. */
void Update(ParFiniteElementSpace *pf, Vector &v, int v_offset);
/** @brief Make the ParLinearForm reference external data on a new
FiniteElementSpace. */
/** This method changes the FiniteElementSpace associated with the
ParLinearForm to @a *f and sets the data of the Vector @a v (plus the @a
v_offset) as external data in the ParLinearForm.
@note This version of the method will also perform bounds checks when the
build option MFEM_DEBUG is enabled. */
virtual void MakeRef(FiniteElementSpace *f, Vector &v, int v_offset);
/** @brief Make the ParLinearForm reference external data on a new
ParFiniteElementSpace. */
/** This method changes the ParFiniteElementSpace associated with the
ParLinearForm to @a *pf and sets the data of the Vector @a v (plus the @a
v_offset) as external data in the ParLinearForm.
@note This version of the method will also perform bounds checks when the
build option MFEM_DEBUG is enabled. */
void MakeRef(ParFiniteElementSpace *pf, Vector &v, int v_offset);
/// Assemble the vector on the true dofs, i.e. P^t v.
void ParallelAssemble(Vector &tv);
@@ -99,10 +120,10 @@ public:
HypreParVector *ParallelAssemble();
/// Return the action of the ParLinearForm as a linear mapping.
/** Linear forms are linear functionals which map ParGridFunction%s to
the real numbers. This method performs this mapping which in
this case is equivalent as an inner product of the ParLinearForm
and ParGridFunction. */
/** Linear forms are linear functionals which map ParGridFunction%s to the
real numbers. This method performs this mapping which in this case is
equivalent as an inner product of the ParLinearForm and
ParGridFunction. */
double operator()(const ParGridFunction &gf) const
{
return InnerProduct(pfes->GetComm(), *this, gf);
+9 -16
View File
@@ -14,7 +14,6 @@
#ifdef MFEM_USE_MPI
#include "fem.hpp"
#include "../general/forall.hpp"
namespace mfem
{
@@ -50,7 +49,6 @@ void ParNonlinearForm::Mult(const Vector &x, Vector &y) const
if (fnfi.Size())
{
MFEM_VERIFY(!NonlinearForm::ext,"");
// Terms over shared interior faces in parallel.
ParFiniteElementSpace *pfes = ParFESpace();
ParMesh *pmesh = pfes->GetParMesh();
@@ -88,16 +86,15 @@ void ParNonlinearForm::Mult(const Vector &x, Vector &y) const
P->MultTranspose(aux2, y);
const int N = ess_tdof_list.Size();
const auto idx = ess_tdof_list.Read();
auto Y = y.ReadWrite();
MFEM_FORALL(i, N, Y[idx[i]] = 0.0; );
y.HostReadWrite();
for (int i = 0; i < ess_tdof_list.Size(); i++)
{
y(ess_tdof_list[i]) = 0.0;
}
}
const SparseMatrix &ParNonlinearForm::GetLocalGradient(const Vector &x) const
{
if (NonlinearForm::ext) { MFEM_ABORT("Not yet implemented!"); }
NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.
return *Grad;
@@ -107,20 +104,16 @@ Operator &ParNonlinearForm::GetGradient(const Vector &x) const
{
ParFiniteElementSpace *pfes = ParFESpace();
Operator &grad = NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.
pGrad.Clear();
NonlinearForm::GetGradient(x); // (re)assemble Grad, no b.c.
OperatorHandle dA(pGrad.Type()), Ph(pGrad.Type());
if (fnfi.Size() == 0)
{
if (NonlinearForm::ext) { dA.Reset(&grad, false); }
else
{
dA.MakeSquareBlockDiag(pfes->GetComm(), pfes->GlobalVSize(),
pfes->GetDofOffsets(), Grad);
}
dA.MakeSquareBlockDiag(pfes->GetComm(), pfes->GlobalVSize(),
pfes->GetDofOffsets(), Grad);
}
else
{
+1135 -404
View File
File diff suppressed because it is too large Load Diff
+15 -33
View File
@@ -41,11 +41,10 @@ protected:
const FiniteElementSpace *fespace; ///< Not owned
const QuadratureSpace *qspace; ///< Not owned
const IntegrationRule *IntRule; ///< Not owned
mutable QVectorLayout q_layout; ///< Output Q-vector layout
mutable bool use_tensor_products; ///< Tensor product evaluation mmode
public:
mutable bool use_tensor_products;
static const int MAX_NQ2D = 100;
static const int MAX_ND2D = 100;
static const int MAX_VDIM2D = 3;
@@ -54,6 +53,7 @@ public:
static const int MAX_ND3D = 1000;
static const int MAX_VDIM3D = 3;
public:
enum EvalFlags
{
VALUES = 1 << 0, ///< Evaluate the values at quadrature points
@@ -61,28 +61,21 @@ public:
/** @brief Assuming the derivative at quadrature points form a matrix,
this flag can be used to compute and store their determinants. This
flag can only be used in Mult(). */
DETERMINANTS = 1 << 2,
PHYSICAL_DERIVATIVES = 1 << 3 ///< Evaluate the physical derivatives
DETERMINANTS = 1 << 2
};
QuadratureInterpolator(const FiniteElementSpace &fes,
const IntegrationRule &ir,
const bool use_tensor_products = false);
const IntegrationRule &ir);
QuadratureInterpolator(const FiniteElementSpace &fes,
const QuadratureSpace &qs,
const bool use_tensor_products = false);
const QuadratureSpace &qs);
/** @brief Disable the use of tensor product evaluations, for tensor-product
elements, e.g. quads and hexes. */
void DisableTensorProducts() const { use_tensor_products = false; }
/** @brief Enable the use of tensor product evaluations, for tensor-product
elements, e.g. quads and hexes. */
void EnableTensorProducts() const { use_tensor_products = true; }
/** @brief Query the current evaluation mode. */
bool UseTensorProducts() const { return use_tensor_products; }
/** Currently, tensor product evaluations are not implemented and this method
has no effect. */
void DisableTensorProducts(bool disable = true) const
{ use_tensor_products = !disable; }
/** @brief Query the current output Q-vector layout. The default value is
QVectorLayout::byNODES. */
@@ -90,7 +83,8 @@ public:
/** @brief Set the desired output Q-vector layout. The default value is
QVectorLayout::byNODES. */
void SetOutputLayout(QVectorLayout layout) const { q_layout = layout; }
void SetOutputLayout(QVectorLayout out_layout) const
{ q_layout = out_layout; }
/// Interpolate the E-vector @a e_vec to quadrature points.
/** The @a eval_flags are a bitwise mask of constants from the EvalFlags
@@ -105,36 +99,26 @@ public:
Vector &q_val, Vector &q_der, Vector &q_det) const;
/// Interpolate the values of the E-vector @a e_vec at quadrature points.
template <QVectorLayout>
void Values(const Vector &e_vec, Vector &q_val) const;
void Values(const Vector &e_vec, Vector &q_val) const;
/** @brief Interpolate the derivatives of the E-vector @a e_vec at quadrature
points. */
template <QVectorLayout>
void Derivatives(const Vector &e_vec, Vector &q_der) const;
void Derivatives(const Vector &e_vec, Vector &q_der) const;
/** @brief Interpolate the derivatives in physical space of the E-vector
@a e_vec at quadrature points. */
template <QVectorLayout>
void PhysDerivatives(const Vector &e_vec, Vector &q_der) const;
void PhysDerivatives(const Vector &e_vec, Vector &q_der) const;
/// Compute the determinant of the E-vector @a e_vec at quadrature points.
void Determinants(const Vector &e_vec, Vector &q_det) const;
/// Perform the transpose operation of Mult(). (TODO)
void MultTranspose(unsigned eval_flags, const Vector &q_val,
const Vector &q_der, Vector &e_vec) const;
// Compute kernels follow (cannot be private or protected with nvcc)
/// Template compute kernel for 2D.
template<const int T_VDIM = 0, const int T_ND = 0, const int T_NQ = 0>
static void Mult2D(const int NE,
static void Eval2D(const int NE,
const int vdim,
const QVectorLayout q_layout,
const GeometricFactors *geom,
const DofToQuad &maps,
const Vector &e_vec,
Vector &q_val,
@@ -144,10 +128,8 @@ public:
/// Template compute kernel for 3D.
template<const int T_VDIM = 0, const int T_ND = 0, const int T_NQ = 0>
static void Mult3D(const int NE,
static void Eval3D(const int NE,
const int vdim,
const QVectorLayout q_layout,
const GeometricFactors *geom,
const DofToQuad &maps,
const Vector &e_vec,
Vector &q_val,
-208
View File
@@ -1,208 +0,0 @@
// Copyright (c) 2010-2020, 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 "tmop_pa.hpp"
#include "quadinterpolator.hpp"
#include "../general/forall.hpp"
#include "../linalg/dtensor.hpp"
#include "../fem/kernels.hpp"
#include "../linalg/kernels.hpp"
using namespace mfem;
namespace mfem
{
template<int T_D1D = 0, int T_Q1D = 0, int MAX_D1D = 0, int MAX_Q1D = 0>
static void Det2D(const int NE,
const double *b,
const double *g,
const double *x,
double *y,
const int vdim = 1,
const int d1d = 0,
const int q1d = 0)
{
constexpr int DIM = 2;
constexpr int NBZ = 1;
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const auto B = Reshape(b, Q1D, D1D);
const auto G = Reshape(g, Q1D, D1D);
const auto X = Reshape(x, D1D, D1D, DIM, NE);
auto Y = Reshape(y, Q1D, Q1D, NE);
MFEM_FORALL_2D(e, NE, Q1D, Q1D, NBZ,
{
constexpr int NBZ = 1;
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
MFEM_SHARED double BG[2][MQ1*MD1];
MFEM_SHARED double XY[2][NBZ][MD1*MD1];
MFEM_SHARED double DQ[4][NBZ][MD1*MQ1];
MFEM_SHARED double QQ[4][NBZ][MQ1*MQ1];
kernels::LoadX<MD1,NBZ>(e,D1D,X,XY);
kernels::LoadBG<MD1,MQ1>(D1D,Q1D,B,G,BG);
kernels::GradX<MD1,MQ1,NBZ>(D1D,Q1D,BG,XY,DQ);
kernels::GradY<MD1,MQ1,NBZ>(D1D,Q1D,BG,DQ,QQ);
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double J[4];
kernels::PullGrad<MQ1,NBZ>(qx,qy,QQ,J);
Y(qx,qy,e) = kernels::Det<2>(J);
}
}
});
}
template<int T_D1D = 0, int T_Q1D = 0, int MAX_D1D = 0, int MAX_Q1D = 0>
static void Det3D(const int NE,
const double *b,
const double *g,
const double *x,
double *y,
const int vdim = 1,
const int d1d = 0,
const int q1d = 0)
{
constexpr int DIM = 3;
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const auto B = Reshape(b, Q1D, D1D);
const auto G = Reshape(g, Q1D, D1D);
const auto X = Reshape(x, D1D, D1D, D1D, DIM, NE);
auto Y = Reshape(y, Q1D, Q1D, Q1D, NE);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
constexpr int MDQ = MQ1 > MD1 ? MQ1 : MD1;
MFEM_SHARED double BG[2][MQ1*MD1];
MFEM_SHARED double sm0[9][MDQ*MDQ*MDQ];
MFEM_SHARED double sm1[9][MDQ*MDQ*MDQ];
double (*DDD)[MD1*MD1*MD1] = (double (*)[MD1*MD1*MD1]) (sm0);
double (*DDQ)[MD1*MD1*MQ1] = (double (*)[MD1*MD1*MQ1]) (sm1);
double (*DQQ)[MD1*MQ1*MQ1] = (double (*)[MD1*MQ1*MQ1]) (sm0);
double (*QQQ)[MQ1*MQ1*MQ1] = (double (*)[MQ1*MQ1*MQ1]) (sm1);
kernels::LoadX<MD1>(e,D1D,X,DDD);
kernels::LoadBG<MD1,MQ1>(D1D,Q1D,B,G,BG);
kernels::GradX<MD1,MQ1>(D1D,Q1D,BG,DDD,DDQ);
kernels::GradY<MD1,MQ1>(D1D,Q1D,BG,DDQ,DQQ);
kernels::GradZ<MD1,MQ1>(D1D,Q1D,BG,DQQ,QQQ);
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double J[9];
kernels::PullGrad<MQ1>(qx,qy,qz, QQQ, J);
Y(qx,qy,qz,e) = kernels::Det<3>(J);
}
}
}
});
}
void QuadratureInterpolator::Determinants(const Vector &e_vec,
Vector &q_det) const
{
if (use_tensor_products)
{
const int NE = fespace->GetNE();
if (NE == 0) { return; }
const int vdim = fespace->GetVDim();
const int dim = fespace->GetMesh()->Dimension();
const FiniteElement *fe = fespace->GetFE(0);
const IntegrationRule *ir =
IntRule ? IntRule : &qspace->GetElementIntRule(0);
const DofToQuad &maps = fe->GetDofToQuad(*ir, DofToQuad::TENSOR);
const int D1D = maps.ndof;
const int Q1D = maps.nqpt;
const double *B = maps.B.Read();
const double *G = maps.G.Read();
const double *X = e_vec.Read();
double *Y = q_det.Write();
const int id = (dim<<12) | (vdim<<8) | (D1D<<4) | Q1D;
switch (id)
{
case 0x2222: return Det2D<2,2>(NE,B,G,X,Y);
case 0x2223: return Det2D<2,3>(NE,B,G,X,Y);
case 0x2224: return Det2D<2,4>(NE,B,G,X,Y);
case 0x2226: return Det2D<2,6>(NE,B,G,X,Y);
case 0x2234: return Det2D<3,4>(NE,B,G,X,Y);
case 0x2236: return Det2D<3,6>(NE,B,G,X,Y);
case 0x2244: return Det2D<4,4>(NE,B,G,X,Y);
case 0x2246: return Det2D<4,6>(NE,B,G,X,Y);
case 0x2256: return Det2D<5,6>(NE,B,G,X,Y);
case 0x3324: return Det3D<2,4>(NE,B,G,X,Y);
case 0x3333: return Det3D<3,3>(NE,B,G,X,Y);
case 0x3335: return Det3D<3,5>(NE,B,G,X,Y);
case 0x3336: return Det3D<3,6>(NE,B,G,X,Y);
//case 0x3348: return Det3D<4,8>(NE,B,G,X,Y);
default:
{
if (dim == 2)
{
constexpr int MD1 = 8;
constexpr int MQ1 = 8;
MFEM_VERIFY(D1D <= MD1, "Orders higher than " << MD1-1
<< " are not supported!");
MFEM_VERIFY(Q1D <= MQ1, "Quadrature rules with more than "
<< MQ1 << " 1D points are not supported!");
return Det2D<0,0,MD1,MQ1>(NE,B,G,X,Y,vdim,D1D,Q1D);
}
if (dim == 3)
{
constexpr int MD1 = 6;
constexpr int MQ1 = 6;
MFEM_VERIFY(D1D <= MD1, "Orders higher than " << MD1-1
<< " are not supported!");
MFEM_VERIFY(Q1D <= MQ1, "Quadrature rules with more than "
<< MQ1 << " 1D points are not supported!");
return Det3D<0,0,MD1,MQ1>(NE,B,G,X,Y,vdim,D1D,Q1D);
}
}
}
MFEM_ABORT("Kernel " << std::hex << id << std::dec << " not supported yet");
}
else
{
Vector empty;
Mult(e_vec, DETERMINANTS, empty, empty, q_det);
}
}
} // namespace mfem
-233
View File
@@ -1,233 +0,0 @@
// Copyright (c) 2010-2020, 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 "quadinterpolator.hpp"
#include "../general/forall.hpp"
#include "../linalg/dtensor.hpp"
#include "../linalg/kernels.hpp"
namespace mfem
{
template<QVectorLayout Q_LAYOUT,
int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
int T_NBZ = 1, int MAX_D1D = 0, int MAX_Q1D = 0>
static void Eval2D(const int NE,
const double *b_,
const double *x_,
double *y_,
const int vdim = 0,
const int d1d = 0,
const int q1d = 0)
{
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
const auto b = Reshape(b_, Q1D, D1D);
const auto x = Reshape(x_, D1D, D1D, VDIM, NE);
auto y = Q_LAYOUT == QVectorLayout:: byNODES ?
Reshape(y_, Q1D, Q1D, VDIM, NE):
Reshape(y_, VDIM, Q1D, Q1D, NE);
MFEM_FORALL_2D(e, NE, Q1D, Q1D, NBZ,
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
const int tidz = MFEM_THREAD_ID(z);
MFEM_SHARED double s_B[MQ1*MD1];
DeviceTensor<2,double> B(s_B, Q1D, D1D);
MFEM_SHARED double s_DD[NBZ][MD1*MD1];
DeviceTensor<2,double> DD((double*)(s_DD+tidz), MD1, MD1);
MFEM_SHARED double s_DQ[NBZ][MD1*MQ1];
DeviceTensor<2,double> DQ((double*)(s_DQ+tidz), MD1, MQ1);
if (tidz == 0)
{
MFEM_FOREACH_THREAD(d,y,D1D)
{
MFEM_FOREACH_THREAD(q,x,Q1D)
{
B(q,d) = b(q,d);
}
}
}
MFEM_SYNC_THREAD;
for (int c = 0; c < VDIM; c++)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
{
DD(dx,dy) = x(dx,dy,c,e);
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
for (int dx = 0; dx < D1D; ++dx)
{
u += B(qx,dx) * DD(dx,dy);
}
DQ(dy,qx) = u;
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
for (int dy = 0; dy < D1D; ++dy)
{
u += DQ(dy,qx) * B(qy,dy);
}
if (Q_LAYOUT == QVectorLayout::byVDIM) { y(c,qx,qy,e) = u; }
if (Q_LAYOUT == QVectorLayout::byNODES) { y(qx,qy,c,e) = u; }
}
}
MFEM_SYNC_THREAD;
}
});
}
template<QVectorLayout Q_LAYOUT,
int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
int MAX_D1D = 0, int MAX_Q1D = 0>
static void Eval3D(const int NE,
const double *b_,
const double *x_,
double *y_,
const int vdim = 0,
const int d1d = 0,
const int q1d = 0)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
const auto b = Reshape(b_, Q1D, D1D);
const auto x = Reshape(x_, D1D, D1D, D1D, VDIM, NE);
auto y = Q_LAYOUT == QVectorLayout:: byNODES ?
Reshape(y_, Q1D, Q1D, Q1D, VDIM, NE):
Reshape(y_, VDIM, Q1D, Q1D, Q1D, NE);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
const int tidz = MFEM_THREAD_ID(z);
MFEM_SHARED double s_B[MQ1*MD1];
DeviceTensor<2,double> B(s_B, Q1D, D1D);
MFEM_SHARED double sm0[MDQ*MDQ*MDQ];
MFEM_SHARED double sm1[MDQ*MDQ*MDQ];
DeviceTensor<3,double> DDD(sm0, MD1, MD1, MD1);
DeviceTensor<3,double> DDQ(sm1, MD1, MD1, MQ1);
DeviceTensor<3,double> DQQ(sm0, MD1, MQ1, MQ1);
if (tidz == 0)
{
MFEM_FOREACH_THREAD(d,y,D1D)
{
MFEM_FOREACH_THREAD(q,x,Q1D)
{
B(q,d) = b(q,d);
}
}
}
MFEM_SYNC_THREAD;
for (int c = 0; c < VDIM; c++)
{
MFEM_FOREACH_THREAD(dz,z,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
{
DDD(dx,dy,dz) = x(dx,dy,dz,c,e);
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dz,z,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
for (int dx = 0; dx < D1D; ++dx)
{
u += B(qx,dx) * DDD(dx,dy,dz);
}
DDQ(dz,dy,qx) = u;
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dz,z,D1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
for (int dy = 0; dy < D1D; ++dy)
{
u += DDQ(dz,dy,qx) * B(qy,dy);
}
DQQ(dz,qy,qx) = u;
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
for (int dz = 0; dz < D1D; ++dz)
{
u += DQQ(dz,qy,qx) * B(qz,dz);
}
if (Q_LAYOUT == QVectorLayout::byVDIM) { y(c,qx,qy,qz,e) = u; }
if (Q_LAYOUT == QVectorLayout::byNODES) { y(qx,qy,qz,c,e) = u; }
}
}
}
MFEM_SYNC_THREAD;
}
});
}
} // namespace mfem
-110
View File
@@ -1,110 +0,0 @@
// Copyright (c) 2010-2020, 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 "quadinterpolator.hpp"
#include "quadinterpolator_eval.hpp"
#include "../general/forall.hpp"
#include "../linalg/dtensor.hpp"
#include "../linalg/kernels.hpp"
namespace mfem
{
template<>
void QuadratureInterpolator::Values<QVectorLayout::byNODES>(
const Vector &e_vec, Vector &q_val) const
{
const int NE = fespace->GetNE();
if (NE == 0) { return; }
const int vdim = fespace->GetVDim();
const int dim = fespace->GetMesh()->Dimension();
const FiniteElement *fe = fespace->GetFE(0);
const IntegrationRule *ir =
IntRule ? IntRule : &qspace->GetElementIntRule(0);
const DofToQuad &maps = fe->GetDofToQuad(*ir, DofToQuad::TENSOR);
const int D1D = maps.ndof;
const int Q1D = maps.nqpt;
const double *B = maps.B.Read();
const double *X = e_vec.Read();
double *Y = q_val.Write();
constexpr QVectorLayout L = QVectorLayout::byNODES;
const int id = (dim<<12) | (vdim<<8) | (D1D<<4) | Q1D;
switch (id)
{
case 0x2133: return Eval2D<L,1,3,3>(NE,B,X,Y);
case 0x2124: return Eval2D<L,1,2,4>(NE,B,X,Y);
case 0x2132: return Eval2D<L,1,3,2>(NE,B,X,Y);
case 0x2134: return Eval2D<L,1,3,4>(NE,B,X,Y);
case 0x2143: return Eval2D<L,1,4,3>(NE,B,X,Y);
case 0x2144: return Eval2D<L,1,4,4>(NE,B,X,Y);
case 0x2222: return Eval2D<L,2,2,2>(NE,B,X,Y);
case 0x2223: return Eval2D<L,2,2,3>(NE,B,X,Y);
case 0x2224: return Eval2D<L,2,2,4>(NE,B,X,Y);
case 0x2225: return Eval2D<L,2,2,5>(NE,B,X,Y);
case 0x2226: return Eval2D<L,2,2,6>(NE,B,X,Y);
case 0x2233: return Eval2D<L,2,3,3>(NE,B,X,Y);
case 0x2234: return Eval2D<L,2,3,4>(NE,B,X,Y);
case 0x2236: return Eval2D<L,2,3,6>(NE,B,X,Y);
case 0x2243: return Eval2D<L,2,4,3>(NE,B,X,Y);
case 0x2244: return Eval2D<L,2,4,4>(NE,B,X,Y);
case 0x2245: return Eval2D<L,2,4,5>(NE,B,X,Y);
case 0x2246: return Eval2D<L,2,4,6>(NE,B,X,Y);
case 0x2247: return Eval2D<L,2,4,7>(NE,B,X,Y);
case 0x2256: return Eval2D<L,2,5,6>(NE,B,X,Y);
case 0x3124: return Eval3D<L,1,2,4>(NE,B,X,Y);
case 0x3133: return Eval3D<L,1,3,3>(NE,B,X,Y);
case 0x3134: return Eval3D<L,1,3,4>(NE,B,X,Y);
case 0x3136: return Eval3D<L,1,3,6>(NE,B,X,Y);
case 0x3143: return Eval3D<L,1,4,3>(NE,B,X,Y);
case 0x3144: return Eval3D<L,1,4,4>(NE,B,X,Y);
case 0x3148: return Eval3D<L,1,4,8>(NE,B,X,Y);
case 0x3222: return Eval3D<L,2,2,2>(NE,B,X,Y);
case 0x3223: return Eval3D<L,2,2,3>(NE,B,X,Y);
case 0x3234: return Eval3D<L,2,3,4>(NE,B,X,Y);
case 0x3323: return Eval3D<L,3,2,3>(NE,B,X,Y);
case 0x3324: return Eval3D<L,3,2,4>(NE,B,X,Y);
case 0x3325: return Eval3D<L,3,2,5>(NE,B,X,Y);
case 0x3326: return Eval3D<L,3,2,6>(NE,B,X,Y);
case 0x3333: return Eval3D<L,3,3,3>(NE,B,X,Y);
case 0x3334: return Eval3D<L,3,3,4>(NE,B,X,Y);
case 0x3335: return Eval3D<L,3,3,5>(NE,B,X,Y);
case 0x3336: return Eval3D<L,3,3,6>(NE,B,X,Y);
case 0x3343: return Eval3D<L,3,4,3>(NE,B,X,Y);
case 0x3344: return Eval3D<L,3,4,4>(NE,B,X,Y);
case 0x3346: return Eval3D<L,3,4,6>(NE,B,X,Y);
case 0x3347: return Eval3D<L,3,4,7>(NE,B,X,Y);
case 0x3348: return Eval3D<L,3,4,8>(NE,B,X,Y);
default:
{
constexpr int MD1 = 8;
constexpr int MQ1 = 8;
MFEM_VERIFY(D1D <= MD1, "Orders higher than " << MD1-1
<< " are not supported!");
MFEM_VERIFY(Q1D <= MQ1, "Quadrature rules with more than "
<< MQ1 << " 1D points are not supported!");
if (dim == 2) { Eval2D<L,0,0,0,0,MD1,MQ1>(NE,B,X,Y,vdim,D1D,Q1D); }
if (dim == 3) { Eval3D<L,0,0,0,MD1,MQ1>(NE,B,X,Y,vdim,D1D,Q1D); }
return;
}
}
mfem::out << "Unknown kernel 0x" << std::hex << id << std::endl;
MFEM_ABORT("Kernel not supported yet");
}
} // namespace mfem
-79
View File
@@ -1,79 +0,0 @@
// Copyright (c) 2010-2020, 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 "quadinterpolator.hpp"
#include "quadinterpolator_eval.hpp"
#include "../general/forall.hpp"
#include "../linalg/dtensor.hpp"
#include "../linalg/kernels.hpp"
namespace mfem
{
template<>
void QuadratureInterpolator::Values<QVectorLayout::byVDIM>(
const Vector &e_vec, Vector &q_val) const
{
const int NE = fespace->GetNE();
if (NE == 0) { return; }
const int vdim = fespace->GetVDim();
const int dim = fespace->GetMesh()->Dimension();
const FiniteElement *fe = fespace->GetFE(0);
const IntegrationRule *ir =
IntRule ? IntRule : &qspace->GetElementIntRule(0);
const DofToQuad &maps = fe->GetDofToQuad(*ir, DofToQuad::TENSOR);
const int D1D = maps.ndof;
const int Q1D = maps.nqpt;
const double *B = maps.B.Read();
const double *X = e_vec.Read();
double *Y = q_val.Write();
constexpr QVectorLayout L = QVectorLayout::byVDIM;
const int id = (dim<<12) | (vdim<<8) | (D1D<<4) | Q1D;
switch (id)
{
case 0x2124: return Eval2D<L,1,2,4,8>(NE,B,X,Y);
case 0x2136: return Eval2D<L,1,3,6,4>(NE,B,X,Y);
case 0x2148: return Eval2D<L,1,4,8,2>(NE,B,X,Y);
case 0x2224: return Eval2D<L,2,2,4,8>(NE,B,X,Y);
case 0x2234: return Eval2D<L,2,3,4,8>(NE,B,X,Y);
case 0x2236: return Eval2D<L,2,3,6,4>(NE,B,X,Y);
case 0x2248: return Eval2D<L,2,4,8,2>(NE,B,X,Y);
case 0x3124: return Eval3D<L,1,2,4>(NE,B,X,Y);
case 0x3136: return Eval3D<L,1,3,6>(NE,B,X,Y);
case 0x3148: return Eval3D<L,1,4,8>(NE,B,X,Y);
case 0x3324: return Eval3D<L,3,2,4>(NE,B,X,Y);
case 0x3336: return Eval3D<L,3,3,6>(NE,B,X,Y);
case 0x3348: return Eval3D<L,3,4,8>(NE,B,X,Y);
default:
{
constexpr int MD1 = 8;
constexpr int MQ1 = 8;
MFEM_VERIFY(D1D <= MD1, "Orders higher than " << MD1-1
<< " are not supported!");
MFEM_VERIFY(Q1D <= MQ1, "Quadrature rules with more than "
<< MQ1 << " 1D points are not supported!");
if (dim == 2) { Eval2D<L,0,0,0,0,MD1,MQ1>(NE,B,X,Y,vdim,D1D,Q1D); }
if (dim == 3) { Eval3D<L,0,0,0,MD1,MQ1>(NE,B,X,Y,vdim,D1D,Q1D); }
return;
}
}
mfem::out << "Unknown kernel 0x" << std::hex << id << std::endl;
MFEM_ABORT("Kernel not supported yet");
}
} // namespace mfem
+2 -3
View File
@@ -495,9 +495,8 @@ void FaceQuadratureInterpolator::Mult(
}
}
void FaceQuadratureInterpolator::Values(const Vector &e_vec,
Vector &q_val) const
void FaceQuadratureInterpolator::Values(
const Vector &e_vec, Vector &q_val) const
{
Vector q_der, q_det, q_nor;
Mult(e_vec, VALUES, q_val, q_der, q_det, q_nor);
-282
View File
@@ -1,282 +0,0 @@
// Copyright (c) 2010-2020, 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 "quadinterpolator.hpp"
#include "../general/forall.hpp"
#include "../linalg/dtensor.hpp"
#include "../linalg/kernels.hpp"
namespace mfem
{
template<QVectorLayout Q_LAYOUT,
int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
int T_NBZ = 1, int MAX_D1D = 0, int MAX_Q1D = 0>
static void Grad2D(const int NE,
const double *b_,
const double *g_,
const double *x_,
double *y_,
const int vdim = 0,
const int d1d = 0,
const int q1d = 0)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
const int VDIM = T_VDIM ? T_VDIM : vdim;
const auto b = Reshape(b_, Q1D, D1D);
const auto g = Reshape(g_, Q1D, D1D);
const auto x = Reshape(x_, D1D, D1D, VDIM, NE);
auto y = Q_LAYOUT ==QVectorLayout:: byNODES ?
Reshape(y_, Q1D, Q1D, VDIM, 2, NE):
Reshape(y_, VDIM, 2, Q1D, Q1D, NE);
MFEM_FORALL_2D(e, NE, Q1D, Q1D, NBZ,
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
const int tidz = MFEM_THREAD_ID(z);
MFEM_SHARED double s_B[MQ1*MD1];
MFEM_SHARED double s_G[MQ1*MD1];
DeviceTensor<2,double> B(s_B, Q1D, D1D);
DeviceTensor<2,double> G(s_G, Q1D, D1D);
MFEM_SHARED double s_X[NBZ][MD1*MD1];
DeviceTensor<2,double> X((double*)(s_X+tidz), MD1, MD1);
MFEM_SHARED double s_DQ[2][NBZ][MD1*MQ1];
DeviceTensor<2,double> DQ0((double*)(s_DQ[0]+tidz), MD1, MQ1);
DeviceTensor<2,double> DQ1((double*)(s_DQ[1]+tidz), MD1, MQ1);
if (tidz == 0)
{
MFEM_FOREACH_THREAD(d,y,D1D)
{
MFEM_FOREACH_THREAD(q,x,Q1D)
{
B(q,d) = b(q,d);
G(q,d) = g(q,d);
}
}
}
MFEM_SYNC_THREAD;
for (int c = 0; c < VDIM; ++c)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
{
X(dx,dy) = x(dx,dy,c,e);
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
double v = 0.0;
for (int dx = 0; dx < D1D; ++dx)
{
const double input = X(dx,dy);
u += input * B(qx,dx);
v += input * G(qx,dx);
}
DQ0(dy,qx) = u;
DQ1(dy,qx) = v;
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
double v = 0.0;
for (int dy = 0; dy < D1D; ++dy)
{
u += DQ1(dy,qx) * B(qy,dy);
v += DQ0(dy,qx) * G(qy,dy);
}
if (Q_LAYOUT == QVectorLayout::byNODES)
{
y(qx,qy,c,0,e) = u;
y(qx,qy,c,1,e) = v;
}
if (Q_LAYOUT == QVectorLayout::byVDIM)
{
y(c,0,qx,qy,e) = u;
y(c,1,qx,qy,e) = v;
}
}
}
MFEM_SYNC_THREAD;
}
});
}
template<QVectorLayout Q_LAYOUT,
int T_VDIM = 0, int T_D1D = 0, int T_Q1D = 0,
int MAX_D1D = 0, int MAX_Q1D = 0>
static void Grad3D(const int NE,
const double *b_,
const double *g_,
const double *x_,
double *y_,
const int vdim = 0,
const int d1d = 0,
const int q1d = 0)
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
const auto b = Reshape(b_, Q1D, D1D);
const auto g = Reshape(g_, Q1D, D1D);
const auto x = Reshape(x_, D1D, D1D, D1D, VDIM, NE);
auto y = Q_LAYOUT ==QVectorLayout:: byNODES ?
Reshape(y_, Q1D, Q1D, Q1D, VDIM, 3, NE):
Reshape(y_, VDIM, 3, Q1D, Q1D, Q1D, NE);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
const int VDIM = T_VDIM ? T_VDIM : vdim;
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
const int tidz = MFEM_THREAD_ID(z);
MFEM_SHARED double s_B[MQ1*MD1];
MFEM_SHARED double s_G[MQ1*MD1];
DeviceTensor<2,double> B(s_B, Q1D, D1D);
DeviceTensor<2,double> G(s_G, Q1D, D1D);
MFEM_SHARED double sm0[3][MQ1*MQ1*MQ1];
MFEM_SHARED double sm1[3][MQ1*MQ1*MQ1];
DeviceTensor<3,double> X((double*)(sm0+2), MD1, MD1, MD1);
DeviceTensor<3,double> DDQ0((double*)(sm0+0), MD1, MD1, MQ1);
DeviceTensor<3,double> DDQ1((double*)(sm0+1), MD1, MD1, MQ1);
DeviceTensor<3,double> DQQ0((double*)(sm1+0), MD1, MQ1, MQ1);
DeviceTensor<3,double> DQQ1((double*)(sm1+1), MD1, MQ1, MQ1);
DeviceTensor<3,double> DQQ2((double*)(sm1+2), MD1, MQ1, MQ1);
if (tidz == 0)
{
MFEM_FOREACH_THREAD(d,y,D1D)
{
MFEM_FOREACH_THREAD(q,x,Q1D)
{
B(q,d) = b(q,d);
G(q,d) = g(q,d);
}
}
}
MFEM_SYNC_THREAD;
for (int c = 0; c < VDIM; ++c)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(dz,z,D1D)
{
X(dx,dy,dz) = x(dx,dy,dz,c,e);
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dz,z,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
double v = 0.0;
for (int dx = 0; dx < D1D; ++dx)
{
const double input = X(dx,dy,dz);
u += input * B(qx,dx);
v += input * G(qx,dx);
}
DDQ0(dz,dy,qx) = u;
DDQ1(dz,dy,qx) = v;
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dz,z,D1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
double v = 0.0;
double w = 0.0;
for (int dy = 0; dy < D1D; ++dy)
{
u += DDQ1(dz,dy,qx) * B(qy,dy);
v += DDQ0(dz,dy,qx) * G(qy,dy);
w += DDQ0(dz,dy,qx) * B(qy,dy);
}
DQQ0(dz,qy,qx) = u;
DQQ1(dz,qy,qx) = v;
DQQ2(dz,qy,qx) = w;
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u = 0.0;
double v = 0.0;
double w = 0.0;
for (int dz = 0; dz < D1D; ++dz)
{
u += DQQ0(dz,qy,qx) * B(qz,dz);
v += DQQ1(dz,qy,qx) * B(qz,dz);
w += DQQ2(dz,qy,qx) * G(qz,dz);
}
if (Q_LAYOUT == QVectorLayout::byNODES)
{
y(qx,qy,qz,c,0,e) = u;
y(qx,qy,qz,c,1,e) = v;
y(qx,qy,qz,c,2,e) = w;
}
if (Q_LAYOUT == QVectorLayout::byVDIM)
{
y(c,0,qx,qy,qz,e) = u;
y(c,1,qx,qy,qz,e) = v;
y(c,2,qx,qy,qz,e) = w;
}
}
}
}
MFEM_SYNC_THREAD;
}
});
}
} // namespace mfem
-109
View File
@@ -1,109 +0,0 @@
// Copyright (c) 2010-2020, 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 "quadinterpolator.hpp"
#include "quadinterpolator_grad.hpp"
namespace mfem
{
template<>
void QuadratureInterpolator::Derivatives<QVectorLayout::byNODES>(
const Vector &e_vec, Vector &q_der) const
{
const int NE = fespace->GetNE();
if (NE == 0) { return; }
const int vdim = fespace->GetVDim();
const int dim = fespace->GetMesh()->Dimension();
const FiniteElement *fe = fespace->GetFE(0);
const IntegrationRule *ir =
IntRule ? IntRule : &qspace->GetElementIntRule(0);
const DofToQuad &maps = fe->GetDofToQuad(*ir, DofToQuad::TENSOR);
const int D1D = maps.ndof;
const int Q1D = maps.nqpt;
const double *B = maps.B.Read();
const double *G = maps.G.Read();
const double *X = e_vec.Read();
double *Y = q_der.Write();
constexpr QVectorLayout L = QVectorLayout::byNODES;
const int id = (dim<<12) | (vdim<<8) | (D1D<<4) | Q1D;
switch (id)
{
case 0x2133: return Grad2D<L,1,3,3,16>(NE,B,G,X,Y);
case 0x2134: return Grad2D<L,1,3,4,16>(NE,B,G,X,Y);
case 0x2143: return Grad2D<L,1,4,3,16>(NE,B,G,X,Y);
case 0x2144: return Grad2D<L,1,4,4,16>(NE,B,G,X,Y);
case 0x2222: return Grad2D<L,2,2,2,16>(NE,B,G,X,Y);
case 0x2223: return Grad2D<L,2,2,3,8>(NE,B,G,X,Y);
case 0x2224: return Grad2D<L,2,2,4,4>(NE,B,G,X,Y);
case 0x2225: return Grad2D<L,2,2,5,4>(NE,B,G,X,Y);
case 0x2226: return Grad2D<L,2,2,6,2>(NE,B,G,X,Y);
case 0x2233: return Grad2D<L,2,3,3,2>(NE,B,G,X,Y);
case 0x2234: return Grad2D<L,2,3,4,4>(NE,B,G,X,Y);
case 0x2243: return Grad2D<L,2,4,3,4>(NE,B,G,X,Y);
case 0x2236: return Grad2D<L,2,3,6,2>(NE,B,G,X,Y);
case 0x2244: return Grad2D<L,2,4,4,2>(NE,B,G,X,Y);
case 0x2245: return Grad2D<L,2,4,5,2>(NE,B,G,X,Y);
case 0x2246: return Grad2D<L,2,4,6,2>(NE,B,G,X,Y);
case 0x2247: return Grad2D<L,2,4,7,2>(NE,B,G,X,Y);
case 0x2256: return Grad2D<L,2,5,6,2>(NE,B,G,X,Y);
case 0x3124: return Grad3D<L,1,2,4>(NE,B,G,X,Y);
case 0x3133: return Grad3D<L,1,3,3>(NE,B,G,X,Y);
case 0x3134: return Grad3D<L,1,3,4>(NE,B,G,X,Y);
case 0x3136: return Grad3D<L,1,3,6>(NE,B,G,X,Y);
case 0x3144: return Grad3D<L,1,4,4>(NE,B,G,X,Y);
case 0x3148: return Grad3D<L,1,4,8>(NE,B,G,X,Y);
case 0x3323: return Grad3D<L,3,2,3>(NE,B,G,X,Y);
case 0x3324: return Grad3D<L,3,2,4>(NE,B,G,X,Y);
case 0x3325: return Grad3D<L,3,2,5>(NE,B,G,X,Y);
case 0x3326: return Grad3D<L,3,2,6>(NE,B,G,X,Y);
case 0x3333: return Grad3D<L,3,3,3>(NE,B,G,X,Y);
case 0x3334: return Grad3D<L,3,3,4>(NE,B,G,X,Y);
case 0x3335: return Grad3D<L,3,3,5>(NE,B,G,X,Y);
case 0x3336: return Grad3D<L,3,3,6>(NE,B,G,X,Y);
case 0x3344: return Grad3D<L,3,4,4>(NE,B,G,X,Y);
case 0x3346: return Grad3D<L,3,4,6>(NE,B,G,X,Y);
case 0x3347: return Grad3D<L,3,4,7>(NE,B,G,X,Y);
case 0x3348: return Grad3D<L,3,4,8>(NE,B,G,X,Y);
default:
{
constexpr int MD1 = 8;
constexpr int MQ1 = 8;
MFEM_VERIFY(D1D <= MD1, "Orders higher than " << MD1-1
<< " are not supported!");
MFEM_VERIFY(Q1D <= MQ1, "Quadrature rules with more than "
<< MQ1 << " 1D points are not supported!");
if (dim == 2)
{
return Grad2D<L,0,0,0,0,MD1,MQ1>(NE,B,G,X,Y,vdim,D1D,Q1D);
}
if (dim == 3)
{
return Grad3D<L,0,0,0,MD1,MQ1>(NE,B,G,X,Y,vdim,D1D,Q1D);
}
}
}
mfem::out << "Unknown kernel 0x" << std::hex << id << std::endl;
MFEM_ABORT("Kernel not supported yet");
}
} // namespace mfem
-76
View File
@@ -1,76 +0,0 @@
// Copyright (c) 2010-2020, 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 "quadinterpolator.hpp"
#include "quadinterpolator_grad.hpp"
namespace mfem
{
template<>
void QuadratureInterpolator::Derivatives<QVectorLayout::byVDIM>(
const Vector &e_vec, Vector &q_der) const
{
const int NE = fespace->GetNE();
if (NE == 0) { return; }
const int vdim = fespace->GetVDim();
const int dim = fespace->GetMesh()->Dimension();
const FiniteElement *fe = fespace->GetFE(0);
const IntegrationRule *ir =
IntRule ? IntRule : &qspace->GetElementIntRule(0);
const DofToQuad &maps = fe->GetDofToQuad(*ir, DofToQuad::TENSOR);
const int D1D = maps.ndof;
const int Q1D = maps.nqpt;
const double *B = maps.B.Read();
const double *G = maps.G.Read();
const double *X = e_vec.Read();
double *Y = q_der.Write();
constexpr QVectorLayout L = QVectorLayout::byVDIM;
const int id = (dim<<12) | (vdim<<8) | (D1D<<4) | Q1D;
switch (id)
{
case 0x2134: return Grad2D<L,1,3,4,8>(NE,B,G,X,Y);
case 0x2146: return Grad2D<L,1,4,6,4>(NE,B,G,X,Y);
case 0x2158: return Grad2D<L,1,5,8,2>(NE,B,G,X,Y);
case 0x2234: return Grad2D<L,2,3,4,8>(NE,B,G,X,Y);
case 0x2246: return Grad2D<L,2,4,6,4>(NE,B,G,X,Y);
case 0x2258: return Grad2D<L,2,5,8,2>(NE,B,G,X,Y);
case 0x3134: return Grad3D<L,1,3,4>(NE,B,G,X,Y);
case 0x3146: return Grad3D<L,1,4,6>(NE,B,G,X,Y);
case 0x3158: return Grad3D<L,1,5,8>(NE,B,G,X,Y);
case 0x3334: return Grad3D<L,3,3,4>(NE,B,G,X,Y);
case 0x3346: return Grad3D<L,3,4,6>(NE,B,G,X,Y);
case 0x3358: return Grad3D<L,3,5,8>(NE,B,G,X,Y);
default:
{
constexpr int MD1 = 8;
constexpr int MQ1 = 8;
MFEM_VERIFY(D1D <= MD1, "Orders higher than " << MD1-1
<< " are not supported!");
MFEM_VERIFY(Q1D <= MQ1, "Quadrature rules with more than "
<< MQ1 << " 1D points are not supported!");
if (dim == 2) { Grad2D<L,0,0,0,0,MD1,MQ1>(NE,B,G,X,Y,vdim,D1D,Q1D); }
if (dim == 3) { Grad3D<L,0,0,0,MD1,MQ1>(NE,B,G,X,Y,vdim,D1D,Q1D); }
return;
}
}
mfem::out << "Unknown kernel 0x" << std::hex << id << std::endl;
MFEM_ABORT("Kernel not supported yet");
}
} // namespace mfem

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