Compare commits

...
814 Commits
Author SHA1 Message Date
Dylan Copeland 432df01647 Adding cusparse ILU and incomplete Cholesky solvers on GPU. 2020-08-20 18:55:01 -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
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
camierjs 3f2c2acf23 Merge master in feature/stitt4/more-work-units 2020-08-19 08:12:42 -07: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
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
camierjs a72fa476c5 Merge master in feature/stitt4/more-work-units 2020-08-14 11:23:42 -07:00
Tzanio Kolev 3a06bc39df Merge pull request #1618 from mfem/abs-mult-dev
AbsMult and AbsMultTranspose
2020-08-14 10:48:53 -07:00
Tzanio a3e9ac8e8d minor 2020-08-14 10:48:17 -07:00
stefanhenneking 353fd60e42 Adding comment to explain usage of AbsMult. 2020-08-14 11:40:09 -05:00
camierjs da8624fd45 Merge branch 'master' into feature/stitt4/more-work-units 2020-08-14 08:28:52 -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
camierjs 69bfdbe248 Merge branch 'master' into feature/stitt4/more-work-units 2020-08-13 14:54:59 -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
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
Veselin Dobrev bfdfec0a2c Minor formatting edits. 2020-08-07 16:58:35 -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
jeremylt 0d1f3028f4 Update libCEED install git hash 2020-08-05 08:47:08 -06:00
Tzanio Kolev b9a40daf5b Merge pull request #1672 from mfem/tmop-bug-fix
Fix a minor bug in TMOP
2020-08-04 20:33:22 -07:00
Tzanio Kolev 78eb1edcaf Merge pull request #1658 from mfem/unittest-minor-fix
Minor fix in unit test
2020-08-04 19:43:12 -07:00
Tzanio Kolev 66b57d1591 Merge pull request #1600 from mfem/testing/pedantic_flags
CI: add pedantic flags
2020-08-04 19:39:56 -07:00
camierjs 7afce5a62c Use inner threads for mass and diffusion setup 2020-08-04 14:19:43 -07:00
camierjs 1e6cd92ad7 Merge branch 'master' into feature/stitt4/more-work-units 2020-08-04 11:57:58 -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
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
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
Tzanio Kolev ba51fe2c53 Merge pull request #1627 from mfem/yohann/remove-simd
Set MFEM_USE_SIMD=NO by default
2020-08-01 23:28:47 -07:00
Tzanio Kolev f5e82a777f Merge pull request #1596 from mfem/jeremy/ceed-diag-dev
Ceed Native Diagonal Assembly [jeremy/ceed-diag-dev]
2020-08-01 23:26:48 -07: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 725534735c add element type for isoparametrictransformation 2020-07-31 12:45:22 -07:00
Ketan Mittal a73a473055 fix for Tpr->ElementType due to another PR 2020-07-31 12:01:54 -07: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 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
Stowell, Mark L 2e2d42a8a9 Cleanup compiler warnings 2020-07-29 10:45:08 -07:00
Tomov 0080f2898d Changelog. 2020-07-28 16:09:36 -07:00
Tzanio fd0d5927f6 Final updates 2020-07-28 14:30:42 -07: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 167cda84c9 minor 2020-07-28 09:00:58 -07:00
Jeremy L Thompson 39280b7acd switch back to using pointer to ceed data 2020-07-28 09:47:36 -06:00
Jeremy L Thompson aef0d14090 fix typo 2020-07-27 21:10:58 -06:00
Yohann Dudouit 5a3f58bdf7 Fix a bug in Diffusion EA 3D. 2020-07-27 16:57:27 -07:00
Jeremy L Thompson 8bdbf38318 swap function order in ceed.cpp 2020-07-27 16:18:02 -06:00
Dylan Copeland 2d464874e1 Merge branch 'master' of https://github.com/mfem/mfem into matcoefpa 2020-07-27 14:39:40 -07:00
Tzanio f7ca315106 minor 2020-07-27 12:19:45 -07:00
Tzanio Kolev bba973db73 Merge pull request #1468 from mfem/blockop_cuda
BlockOperator on device
2020-07-27 12:11:58 -07:00
Tzanio Kolev c3394d330e Merge pull request #1587 from flomnes/master
Simplify memory management in example 1
2020-07-27 12:06:30 -07: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
Jeremy L Thompson 8ecd5eb54b fix local build difficulties 2020-07-27 10:59:34 -06:00
Dylan Copeland 534d74a281 Improving readability with some boolean variables. 2020-07-27 09:50:10 -07:00
Jeremy L Thompson 402b8bf3d3 make style 2020-07-27 08:07:39 -06:00
Jeremy L Thompson 7372f4902a switch backwards function contents 2020-07-27 07:44:29 -06:00
stefanhenneking da77e1abc9 Minor fix in unit test. 2020-07-25 18:33:16 -05: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
Tomov 857ddd0c24 Merge branch 'master' into tmop-el-type 2020-07-24 16:06:58 -07:00
Tomov 30acc283d6 Reverted the change in the limiting; make style. 2020-07-24 15:36:52 -07:00
Veselin Dobrev 57557ec53b Merge pull request #1141 from mfem/feature/artv3/quad-data
Add QuadratueFunctionCoefficient support in PA assembly [feature/artv3/quad-data]
2020-07-24 14:29:20 -07: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
Arturo Vargas ad208cadfa update changelog 2020-07-23 09:28:44 -07:00
Dylan CopelandandTzanio Kolev 2fa920a88b Update CHANGELOG
Co-authored-by: Tzanio Kolev <tzanio@llnl.gov>
2020-07-22 17:34:14 -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
Jeremy L Thompson 5a3923e842 fix style issue 2020-07-22 16:12:39 -06:00
Jeremy L Thompson 67eda2ba05 fix merge issue 2020-07-22 15:00:33 -06:00
Jeremy L Thompson 1f3480ada1 Merge branch 'master' into jeremy/ceed-diag-dev 2020-07-22 14:56:29 -06: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
Jeremy L Thompson 1066cda295 Refactor CeedOperatorApplyAdd and CeedOperatorLinearAssembleAddDiagonal use to reduce repeated code 2020-07-22 14:31:49 -06:00
stefanhenneking 585f9149d1 Merge branch 'master' of github.com:mfem/mfem into blockop_cuda 2020-07-22 14:19:34 -05:00
stefanhenneking b6a3a119a1 Minor change in comments. 2020-07-22 14:18:59 -05: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
Arturo Vargas a59817b8a7 Merge branch 'feature/artv3/cusparse-Spmv' of https://github.com/mfem/mfem into feature/artv3/cusparse-Spmv 2020-07-21 16:24:23 -07:00
Arturo Vargas 4e8a531bb1 add guards for cpu with cuda codes 2020-07-21 16:23:43 -07:00
Yohann Dudouit 40c0412c63 Edit CHANGELOG 2020-07-21 16:13:03 -07:00
Tzanio Kolev 5457d033d4 Merge pull request #1380 from mfem/CVODESSolver-dev
CVODES Adjoint-Sensitivity Support
2020-07-21 16:05:35 -07:00
Tzanio 1deb071ada Update documentation 2020-07-21 16:03:53 -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 64ac989d07 Merge pull request #1582 from mfem/multigrid-nonsymmetric-smoother
[multigrid-nonsymmetric-smoother] Allow nonsymmetric smoothers in Multigrid object.
2020-07-21 15:25:30 -07:00
Veselin Dobrev 51397513f1 Merge branch 'master' into residual-bc-monitor 2020-07-21 15:23:14 -07:00
Arturo Vargas 11964610e1 move cuda header to guards 2020-07-21 15:10:21 -07:00
Tzanio bfff83d9de Fixed README 2020-07-21 15:00:30 -07:00
Tzanio 0efa0dcb21 Merge branch 'master' into CVODESSolver-dev
Conflicts:
	CHANGELOG
2020-07-21 14:19:48 -07:00
Tzanio Kolev 944cd2f09f Merge pull request #1567 from mfem/tmop-derivatives-dev
Complete action for the TMOP Integrator
2020-07-21 14:18:02 -07:00
Tzanio 01bf5db292 remove whitespace 2020-07-21 14:13:21 -07:00
Ketan Mittal 0b76f8d984 update changelog 2020-07-21 14:10:20 -07:00
Tzanio b52671541e minor styling 2020-07-21 13:57:48 -07:00
Tzanio e09103966e Merge branch 'master' into tmop-derivatives-dev 2020-07-21 12:54:43 -07: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
Arturo Vargas 9937009eab clean up pass, guard for resizing 2020-07-21 11:59:42 -07:00
Arturo Vargas 9bd06e360e temp_buffer->new_buffer 2020-07-21 11:13:33 -07:00
Arturo Vargas 2bea6d11f1 Merge branch 'feature/artv3/cusparse-Spmv' of github.com:mfem/mfem into feature/artv3/cusparse-Spmv 2020-07-21 11:11:49 -07:00
Arturo Vargas 264886c511 PR comments 2020-07-21 11:11:38 -07:00
Tzanio Kolev 697cb9bb95 Merge pull request #1563 from mfem/complex-operator-pa
Partial assembly for complex operators
2020-07-21 10:52:24 -07:00
Tzanio 7ec3c5a30c Merge branch 'master' into feature/artv3/cusparse-Spmv 2020-07-21 10:42:19 -07: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
Adrien M. Bernede 4fbd599058 Removing pedantic flags from Gitlab CI 2020-07-20 19:07:51 -07:00
Arturo Vargas c1071bf82e compare integration rule addr 2020-07-20 19:06:54 -07:00
Veselin Dobrev fe0211557b Minor: better formatting for multi-line string constants. 2020-07-20 18:34:06 -07: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
Veselin Dobrev 684ae6f21f In .travis.yml, update the hypre cache directory for the
"gitignore" job.
2020-07-20 17:17:42 -07:00
Veselin Dobrev 2543863092 Merge branch 'master' into testing/pedantic_flags
Resolved conflicts:
   .appveyor.yml
   .travis.yml
2020-07-20 17:14:09 -07:00
Tomov 85d171e7cb Sample runs for mixed meshes in pmesh-optimizer. 2020-07-20 17:10:29 -07:00
Tzanio Kolev 4d3db426c6 Merge pull request #1635 from mfem/fix/tpls_urls
Using MFEM hosted dependencies in CI context
2020-07-20 16:37:04 -07:00
Adrien M. Bernede 24fd1e1fc0 Revert "Suggesting hypre 2.18.2 instead of brand new 2.19"
This reverts commit 5a8cebeea7.
2020-07-20 16:25:59 -07:00
Tomov 8e631732e1 Merge branch 'master' into tmop-el-type 2020-07-20 16:13:27 -07:00
Adrien M. Bernede 5a8cebeea7 Suggesting hypre 2.18.2 instead of brand new 2.19 2020-07-20 15:25:29 -07:00
Veselin Dobrev 4cd4e21bc6 In .appveyor.yml, fix the hypre path given to mfem. 2020-07-20 13:34:52 -07:00
Veselin Dobrev 6489ecb59e In travis and appveyor, update to hypre v2.19.0. 2020-07-20 13:28:20 -07:00
Adrien M. Bernede 4e8aaf7f11 Fix hypre tar name in travis 2020-07-20 11:19:07 -07:00
Adrien M. Bernede ccce5c8217 Fix file name 2020-07-20 10:53:39 -07:00
Adrien M. Bernede ad9adab6dc Fix extension 2020-07-20 10:44:55 -07:00
Adrien M. Bernede b2cdfbf8bc Reverting changes for Hypre 2020-07-20 10:30:23 -07:00
Adrien BernedeandTzanio Kolev fb9c3fa30a Update .travis.yml
Co-authored-by: Tzanio Kolev <tzanio@llnl.gov>
2020-07-20 10:23:31 -07:00
Adrien BernedeandTzanio Kolev 8b1ecbc3af Update .travis.yml
Co-authored-by: Tzanio Kolev <tzanio@llnl.gov>
2020-07-20 10:22:53 -07:00
Adrien BernedeandTzanio Kolev 66cbd5450e Update .appveyor.yml
Co-authored-by: Tzanio Kolev <tzanio@llnl.gov>
2020-07-20 10:22:38 -07:00
Tzanio Kolev a965c079fb Merge pull request #1604 from mfem/Complex-umfpacksolver
ComplexUMFPackSolver
2020-07-19 21:51:51 -07:00
Tzanio Kolev 31d2ff15e2 Merge pull request #1588 from mfem/hip-defs
[HIP/AMD] #define fix & Diffusion kernel optimization
2020-07-19 21:49:40 -07:00
Arturo Vargas 15b50a277e move InitCuSparse to protected 2020-07-18 22:10:47 -07:00
Arturo Vargas 2a85ec5f97 Merge branch 'master' into feature/artv3/cusparse-Spmv 2020-07-18 22:05:07 -07:00
Veselin Dobrev 268c3cb461 In .travis.yml, fix a shell command. 2020-07-18 13:23:59 -07:00
Veselin Dobrev 401249f1ac In .travis.yml, disable ccache while building cached dependencies. 2020-07-18 13:19:23 -07:00
Veselin Dobrev 6bea0b205d In travis and appveyor, use a mirror to download metis.
In travis, on mac, update to OpenMPI 2.1.6.
2020-07-18 12:19:14 -07:00
Veselin Dobrev e9be0b2074 In .travis.yml, enable ccache for all mac os builds. 2020-07-18 11:23:22 -07:00
Veselin Dobrev c78cf79474 Travis test. 2020-07-18 10:56:33 -07:00
Jonathan Wong 72d7f7ccb7 Added to miniapps to code documentation 2020-07-17 21:39:42 -07:00
Jonathan Wong 44e8364877 modified CHANGELOG to accommodate column limit 2020-07-17 21:09:57 -07:00
Jonathan Wong b4b6c7e106 updated CHANGELOG 2020-07-17 21:05:58 -07:00
Veselin Dobrev e6e3c27cc9 In .travis.yml, try using newer osx image since homebrew does not
seem to work with the default osx image version.
2020-07-17 20:54:17 -07:00
Adrien M. Bernede d64ce893ad Using MFEM hosted dependencies in CI context 2020-07-17 18:09:25 -07:00
Veselin Dobrev d66695fb30 In .travis.yml, enable ccache for the "Mac: Serial + Debug" job. 2020-07-17 17:08:11 -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
Veselin Dobrev a652d89a2d In .travis.yml, use ccache for all linux builds. 2020-07-16 18:51:24 -07:00
Stowell, Mark L bfad6c9903 Removing unneeded Gmsh files 2020-07-16 15:19:41 -07:00
Veselin Dobrev c6e1bdf28d In .travis.yml, enable ccache for the "gitignore" job. 2020-07-16 14:30:41 -07:00
Yohann Dudouit 7a2084a438 Same with cmake. 2020-07-16 14:03:29 -07:00
Yohann Dudouit 48c8173ebd Set MFEM_USE_SIMD=NO by default 2020-07-16 13:50:47 -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
Veselin Dobrev 2622e50d40 In .travis.yml, use the warning flags '-pedantic -Wall -Werror'
selectively to avoid problems when building with gcc with optimization.
2020-07-16 11:29:55 -07:00
stefanhenneking 5c1f9b64af Removing faulty initialization of the solution vector. 2020-07-16 13:24:55 -05:00
Dylan Copeland 77b6729309 Updating description of input parameters omitted from a previous PR. 2020-07-16 10:11:18 -07:00
Veselin Dobrev a6a2351e06 In .travis.yml, in the "gitignore" job, remove the '-Werror'
flag to see which other builds fail due to some warnings.
2020-07-15 23:20:32 -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
Veselin Dobrev de80deeb0b Merge branch 'master' into testing/pedantic_flags 2020-07-15 22:56:20 -07:00
Veselin Dobrev 2f28691de3 In .travis.yml, in the "gitignore" job, move commands from the
"script" step to the "before_script" step, so that failures will
cause the job to stop immediately.
2020-07-15 22:41:48 -07:00
Veselin Dobrev 9238db6d2b In .travis.yml:
* For the "code-style" job, use the "xenial" distro because "bionic"
  does not have the required version of astyle.
* For the "documentation" job, do not use mpi.
* Run the "branch-history" job only if branch != next.

In tests/scripts/documentation, do not run 'make config' and
'make status'.
2020-07-15 21:25:37 -07:00
Veselin Dobrev 8d5364482b In .travis.yml:
* Use caching for the "gitignore" job.
* Try using the "bionic" linux distro instead of the default.
2020-07-15 18:46:20 -07:00
Veselin Dobrev 0effa7abff Merge pull request #1430 from mfem/ode-state-io-dev
Add access mechanism for state vectors in ODE solvers [ode-state-io-dev]
2020-07-15 18:18:58 -07:00
Veselin Dobrev 127fa2645c Merge pull request #1569 from mfem/coefficient-use-cases-doc-dev
Add comment about coefficient use cases [coefficient-use-cases-doc-dev]
2020-07-15 18:16:24 -07:00
Veselin Dobrev f4959fc875 Merge pull request #1503 from najlkin/pr13
Fixed GeometryRefiner::RefineInterior() to not cause invalid deallocations
2020-07-15 18:14:17 -07:00
Veselin Dobrev dd3c075b1b Merge pull request #1550 from mfem/block-nlf-bc-fix
Performance fix with essential dofs in BlockNonlinearForm
2020-07-15 18:11:19 -07:00
Tomov 27ef7812f8 Minor. 2020-07-15 17:00:57 -07:00
Tomov e29ee5f5fc Changed the exact derivative test (to cover more geometric parameters). 2020-07-15 16:59:14 -07:00
stefanhenneking a9f3f42289 Updating changelog. 2020-07-15 17:24:04 -05:00
Tzanio Kolev 0da14b3875 Merge branch 'master' into ho-gmsh-dev 2020-07-15 14:52:44 -07:00
Veselin Dobrev c1a15aa858 Merge branch 'master' into h1-hessian-dev 2020-07-15 14:33:29 -07:00
Veselin Dobrev f3771a22a5 Merge branch 'master' into ode-state-io-dev 2020-07-15 14:29:50 -07:00
Veselin Dobrev 31e4a9d8ee Merge branch 'master' into multigrid-nonsymmetric-smoother 2020-07-15 14:27:20 -07:00
Tzanio Kolev 75ef30918c Merge branch 'master' into complex-operator-pa 2020-07-15 14:25:25 -07:00
Tzanio Kolev 6871b1c6dc Merge branch 'master' into blockop_cuda 2020-07-15 14:23:17 -07:00
Tzanio 92ef9d0629 minor 2020-07-15 14:21:39 -07:00
Tzanio Kolev 1e15e6b57f Merge pull request #1615 from mfem/array-doc-pod-dev
Document that Array<T> operates correctly only with POD types
2020-07-15 14:06:07 -07:00
Tzanio Kolev d1beabdd0d Merge branch 'master' into Complex-umfpacksolver 2020-07-15 14:05:02 -07: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
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
Stefan HennekingandWill Pazner fc1d4fffaf Apply suggestions from code review
A few simplifications.

Co-authored-by: Will Pazner <11493037+pazner@users.noreply.github.com>
2020-07-15 12:17:54 -05:00
stefanhenneking d79f834750 Use dynamic_cast to check operator type. 2020-07-15 12:02:47 -05:00
stefanhenneking b765ebad81 Minor correction. 2020-07-15 11:54:38 -05:00
Stefan HennekingandWill Pazner 61be39191a Apply suggestions from code review
minor

Co-authored-by: Will Pazner <11493037+pazner@users.noreply.github.com>
2020-07-15 11:50:13 -05:00
stefanhenneking 8fc24ace79 Adding AssembleDiagonal for NCMesh using AbsMultTranspose. 2020-07-15 11:39:35 -05:00
camierjs cfe7834b95 minor 2020-07-15 08:51:17 -07:00
Stefan Henneking 79aa92e217 Merge branch 'master' into abs-mult-dev 2020-07-15 10:51:00 -05:00
camierjs 1a8d88440e Remove dead code, add comments and move AtomicAdd function for visibility 2020-07-15 08:22:43 -07:00
camierjs 99c4becfae Merge branch 'master' into hip-defs 2020-07-15 07:24:28 -07: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
psocratis 5ef9a11e9f unit test for rectangular HyprePar and Sparse Matrices 2020-07-14 18:25:10 -07:00
Tzanio 40e633b36f minor styling 2020-07-14 18:04:38 -07:00
Tzanio Kolev 94a5e625be Merge branch 'master' into CVODESSolver-dev 2020-07-14 17:22:46 -07:00
Tzanio Kolev 840ff99288 Merge pull request #1506 from mfem/yohann/fa
Full Assembly built on top of Element Assembly
2020-07-14 17:21:46 -07:00
Tzanio fbe242a2e2 Updated CHANGELOG. Minor styling 2020-07-14 17:18:59 -07: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
Tzanio Kolev ae880b4ee8 Merge branch 'master' into yohann/fa 2020-07-14 16:42:03 -07:00
stefanhenneking 33b413042a Destroying aliased block vectors to avoid issues with dangling references in memory manager. 2020-07-14 18:32:26 -05:00
Tzanio Kolev 9cff5875c7 Merge pull request #1463 from mfem/mixedcurl
PA for mixed curl integrators
2020-07-14 16:22:54 -07:00
Tzanio 80c787a79f minor 2020-07-14 16:15:33 -07:00
Tzanio 9e76838fe4 minor 2020-07-14 16:08:33 -07:00
Tzanio Kolev 75f5a89d2c Merge branch 'master' into array-doc-pod-dev 2020-07-14 15:56:09 -07:00
psocratis 6fc3b74033 Added unit tests for HypreParMatrix::AbsMult and SparseMatrix::AbsMult 2020-07-14 15:34:59 -07:00
Tzanio Kolev c4d8bd4744 Merge branch 'master' into yohann/fa 2020-07-14 15:27:10 -07:00
Tzanio Kolev 0fb7f04d6c Merge branch 'master' into mixedcurl 2020-07-14 15:26:40 -07:00
Tzanio Kolev 01476b98cb Merge branch 'master' into CVODESSolver-dev 2020-07-14 15:26:30 -07:00
psocratis b20b819e0e Added implementation for hypre_ParCSRMatrixAbsMatvec 2020-07-14 14:55:23 -07:00
Tzanio d2ae506e8e minor 2020-07-14 12:20:11 -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
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
Ketan Mittal 65dfcd5e0a minor 2020-07-12 13:11:24 -07:00
Ketan Mittal c3d869cd6c flag to enable exact action 2020-07-10 17:00:59 -07:00
Ketan Mittal 6b256c7cbb Merge branch 'master' of https://github.com/mfem/mfem into tmop-derivatives-dev 2020-07-10 12:03:05 -07:00
Ketan Mittal b73225de21 reviewer comments 2020-07-10 12:02:39 -07:00
Stefan Henneking c3dd82b5ba Merge branch 'master' into complex-operator-pa 2020-07-10 11:36:55 -05:00
Bob Anderson 291875509d document that Array operates correctly only with POD types 2020-07-09 15:32:00 -07:00
Veselin Dobrev d81b3fa05a Merge pull request #1573 from mfem/vector-add-dev
Add a simple missing member function [vector-add-dev]
2020-07-09 15:17:58 -07:00
Arturo Vargas 07f7b0a943 PR comments 2020-07-09 13:28:43 -07:00
Veselin Dobrev b4b72a95ee Merge branch 'master' into vector-add-dev 2020-07-09 12:31:06 -07:00
Veselin Dobrev 57981bc329 Merge pull request #1576 from mfem/gpufix/artv3/SaveAsOne
Missing HostReadWrite: pgridfunc.cpp::SaveAsOne
2020-07-09 12:30:06 -07:00
Arturo Vargas 43ceae8f46 Merge branch 'master' into feature/artv3/quad-data 2020-07-09 11:19:45 -07:00
psocratis f329c3b760 fixed ifdef for superlu 2020-07-08 20:16:24 -07:00
Socratis ceb49b322c removed space in comment 2020-07-08 18:04:51 -07:00
psocratis 6e145a4ccf Added print_level for UMFPackSolver in ex25. Moved contruction of monolithic HypreParMatrix to the case where SuperLU is used 2020-07-08 16:57:13 -07:00
psocratis 79e9a3d320 fixed typos in complex_operator 2020-07-08 13:54:45 -07:00
Arturo Vargas ce2b02624d Merge branch 'master' into feature/artv3/cusparse-Spmv 2020-07-08 13:09:30 -07:00
stefanhenneking 80681fa56a A few small changes to simplify ex22p. Note: Hypre prec. always uses DIAG_ONE policy (no need to set it separately as in ex22). 2020-07-08 14:09:28 -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
stefanhenneking 8e8868e4a0 Simplifying ex22 and correcting preconditioner diag policy. 2020-07-08 12:35:39 -05:00
Tzanio Kolev b671a7a679 Merge branch 'master' into Complex-umfpacksolver 2020-07-08 10:26:35 -07:00
stefanhenneking 6d7b38c02f Fixed a typo. 2020-07-08 11:57:35 -05:00
Tzanio Kolev c8990d45db Merge branch 'master' into h1-hessian-dev 2020-07-08 09:24:49 -07:00
stefanhenneking 3e6889145e Adding assembly level member function to par-/sesquilinear form. 2020-07-08 10:13:46 -05:00
stefanhenneking 60378b79af Fixed a typo. 2020-07-08 09:43:37 -05:00
Veselin Dobrev 5a30e94472 Merge branch 'master' into pr13 2020-07-07 22:07:35 -07:00
Veselin Dobrev cdfe1db094 Merge branch 'master' into ode-state-io-dev 2020-07-07 21:26:29 -07:00
Veselin Dobrev 99a98596ae Merge branch 'master' into gpufix/artv3/SaveAsOne 2020-07-07 21:25:28 -07:00
Tzanio Kolev 7947109731 Merge branch 'master' into master 2020-07-07 21:19:05 -07:00
Veselin Dobrev ab13556e8c Merge branch 'master' into block-nlf-bc-fix 2020-07-07 21:16:24 -07:00
Tzanio Kolev df7aec2506 Merge pull request #1513 from mfem/quadspace-visit-dev
Add quadraturefunctions to visit datacollection [quadspace-visit-dev]
2020-07-07 21:13:53 -07:00
Veselin Dobrev f07cb7379d Merge branch 'master' into block-nlf-bc-fix 2020-07-07 21:13:31 -07:00
psocratis cbb167f231 minor comment fix 2020-07-07 19:46:17 -07:00
psocratis 49e6225b7d minor fixes 2020-07-07 19:41:36 -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
Jan Nikl 5f0630a550 Replaced the refined IntegrationRule existence check by an assert. 2020-07-07 21:52:44 +02:00
Florian Omnes 525f6d2a44 Apply code-style 2020-07-07 21:48:03 +02: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
Veselin Dobrev 6e113683af Additions and changes:
* Added makefile in miniapps/adjoint.
* Fixed interface inconsistency with the ToNVector() methods.
* Fix various warnings.
* In the CMake build system distinguish the SUNDIALS components
  CVODE and CVODES.
* Fix a file name in .gitignore.
2020-07-07 00:09:27 -07:00
Jonathan Wong 99e69b93e5 Merge branch 'CVODESSolver-dev' of github.com:mfem/mfem into CVODESSolver-dev 2020-07-06 21:39:20 -07:00
Jonathan Wong 53e952f1fd Address makefile issues 2020-07-06 21:38:36 -07:00
Jeremy L Thompson 1b265e22e0 drop unnessicary guard 2020-07-06 15:34:08 -06:00
Florian Omnes 3dd0f5c328 Tqke v-dobrev's remarks into account in ex1p.cpp 2020-07-06 23:30:20 +02:00
Jeremy L Thompson 7160b68bce use libCEED restriction for diagonal assembly
thanks-to: dudouit1@llnl.gov for finding & explaining the issue
2020-07-06 15:27:09 -06:00
Florian Omnes 827fbfb14a Take v-dobrev's remark into account in ex1.cpp 2020-07-06 23:25:51 +02:00
Jeremy L Thompson e678e66acd drop unused forced setup call 2020-07-06 14:33:24 -06:00
Jeremy L Thompson f2d7b0c75a Ceed - add mass/diffusion diagonal assembly via libCEED 2020-07-06 13:15:30 -06:00
camierjs 7c3912b2e3 Merge branch 'master' into hip-defs 2020-07-06 10:39:25 -07:00
Andreas Schafelner 5e436c109e make style 2020-07-06 09:23:23 +02:00
Tzanio 39a6c88595 Various styling edits 2020-07-05 18:41:58 -07:00
Tzanio Kolev 9145d4b1de Merge branch 'master' into Complex-umfpacksolver 2020-07-05 17:33:27 -07:00
psocratis 9fb9c4937a Merge branch 'Complex-umfpacksolver' of https://github.com/mfem/mfem into Complex-umfpacksolver 2020-07-04 21:00:45 -07:00
psocratis 9d3e3dd017 make style 2020-07-04 21:00:12 -07:00
Tzanio Kolev e8458444c6 Merge branch 'master' into CVODESSolver-dev 2020-07-04 18:57:24 -07:00
Tzanio Kolev 882a12204e Merge pull request #1487 from mfem/slepc-dev
Support for SLEPc eigensolver [slepc-dev]
2020-07-04 18:54:53 -07:00
Tzanio 703eae8d2c minor 2020-07-04 18:52:45 -07:00
Tzanio d3eccdb1e7 Merge branch 'master' into slepc-dev
Conflicts:
	CHANGELOG
2020-07-04 18:25:44 -07:00
Tzanio Kolev 2d065de342 Merge branch 'master' into mixedcurl 2020-07-04 14:25:04 -07:00
Tzanio Kolev 7c3a368562 Merge branch 'master' into Complex-umfpacksolver 2020-07-04 13:51:10 -07:00
Tzanio Kolev e4da47ee10 Merge pull request #1436 from jeremylt/master
libCEED - intermediate update prior to v0.7 release
2020-07-04 13:47:20 -07:00
Tzanio Kolev a96c057950 Merge pull request #1521 from mfem/hypreblocks-bigj
Fixing big integer issue in HypreParMatrixFromBlocks.
2020-07-04 13:43:45 -07:00
Tzanio Kolev 4ff102bfdd Merge pull request #1580 from mfem/yohann/fix-autotest
Use cuda-shared in ex1p to avoid differences in autotest.
2020-07-04 13:33:25 -07:00
Tzanio Kolev cb276c033a Merge pull request #1589 from mfem/bugfix/get-vector-value-dev
Expanding and unit testing element index GetValue/GetVectorValue methods  [bugfix/get-vector-value-dev]
2020-07-04 13:24:28 -07:00
Tzanio Kolev 83d34459e8 Merge pull request #1558 from mfem/bugfix/mesh-trimmer
Fixing boundary attributes and 1D mesh support [bugfix/mesh-trimmer]
2020-07-04 13:20:39 -07:00
psocratis e2ff03e4ba fixed numbering of comments 2020-07-03 16:31:06 -07:00
psocratis a510328015 Remove Constuction of monolithic SparseMatrix from a ComplexSparseMatrix. Not needed anymore 2020-07-03 15:56:24 -07:00
psocratis 97440f9500 Added ComplexUMFPackSolver to ex25.cpp. Removed unused variable u_gf from ex25[p].cpp 2020-07-03 15:33:57 -07:00
psocratis 781fddddc6 Added ComplexUMFPackSolver to ComplexOperator 2020-07-03 15:10:23 -07:00
Stowell, Mark L 346af0560f Gmsh pyramid mappings 2020-07-03 14:56:33 -07:00
psocratis 7fcc651020 Added GetConvention to ComplexOperator 2020-07-03 14:54:04 -07:00
Tzanio 4c719ad706 minor: 2020-07-02 21:40:45 -07:00
Adrien M. Bernede 7ab523f5a2 Initialize variable to avoid warning 2020-07-02 17:33:04 -07:00
Yohann Dudouit 2de28abb19 Revert changes in ex9 and ex9p. 2020-07-02 15:51:05 -07:00
Adrien M. Bernede a26f7e6b51 Add pedantic flags to MFEM build in Travis CI 2020-07-02 15:42:40 -07:00
Adrien M. Bernede d728e4f9a4 Add pedantic flags to MFEM build in Gitlab CI 2020-07-02 15:42:40 -07:00
Veselin Dobrev 79dd7c14b2 Merge branch 'master' into ode-state-io-dev 2020-07-02 14:47:31 -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
Dylan Copeland c1320238ae Minor changes to MFEM_ABORT_KERNEL. 2020-07-02 10:51:12 -07:00
Stowell, Mark L 89ae6ad31c Adding new gmsh.[ch]pp files to cmake 2020-07-02 10:33:17 -07:00
Veselin Dobrev 4b10b7c44b Merge branch 'master' into block-nlf-bc-fix 2020-07-01 23:01:59 -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
Stowell, Mark L ce12d60a57 Adding Gmsh specific high-order vertex mapping functions 2020-07-01 11:54:53 -07:00
Stefan Henneking 91eacf5af7 Removing typo. 2020-07-01 09:37:46 -07:00
Stefan Henneking 6543ffb790 Update method should support vectors allocated on device. 2020-07-01 09:14:04 -07:00
Stefan Henneking e4290e6d33 Make memory allocation precise to avoid futures issues. 2020-07-01 09:13:08 -07:00
Stefan Henneking de34bf094c Setting block vector memory type to support device computation. 2020-07-01 09:12:14 -07:00
Stefan Henneking a52a59b524 Removing obsolete comments. 2020-07-01 07:24:42 -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
Ido Akkerman 30b2b43814 Correct typo 2020-07-01 09:39:35 +02: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 1f4024879c Adding -d cuda support to ex5p. 2020-06-30 17:51:38 -07:00
Stefan Henneking d949f69a4b Modifying BlockOperator and BlockDiagonalPreconditioner MultTranspose for device support. 2020-06-30 15:53:41 -07:00
stefanhenneking 6cdad9b4ee Minor style change. 2020-06-30 17:25:40 -05:00
Stefan Henneking d727b1a14b Minor change. 2020-06-30 15:23:41 -07:00
Stefan Henneking a6c6fb18cf Using alias to compute BlockOperator and BlockDiagonalPreconditioner Mult on device. 2020-06-30 15:20:28 -07:00
Stefan Henneking 069e57b3a4 Removing HostRead (should not be necessary here). 2020-06-30 15:17:36 -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
Florian Omnes df59effa09 Revert config 2020-06-30 23:04:52 +02:00
Florian Omnes 09c9c94916 Simplify memory management in ex1p.cpp 2020-06-30 23:00:53 +02:00
stefanhenneking 30ad68af20 Merge branch 'master' of github.com:mfem/mfem into blockop_cuda
Merging master into feature branch.
2020-06-30 14:59:44 -05:00
Yohann Dudouit dc29574cfb Add fix to ex1 too. 2020-06-30 11:37:36 -07:00
Dylan Copeland 237905c956 Addressing Veselin's comments about MFEM_ABORT_KERNEL. 2020-06-30 11:15:14 -07:00
Jeremy L ThompsonandYohann 7fc4ab47eb Update compstride calculation
Co-authored-by: Yohann <yohann.dudouit@gmail.com>
2020-06-30 12:09:47 -06:00
Jeremy L ThompsonandYohann 607b15741b Update compstride calculation
Co-authored-by: Yohann <yohann.dudouit@gmail.com>
2020-06-30 12:09:34 -06:00
Jeremy L Thompson 346f92e4e4 Install - use libCEED in between releases until new OCCA backend is finished 2020-06-30 11:07:16 -06:00
Veselin Dobrev b4d870c3be Merge branch 'master' into gpufix/artv3/SaveAsOne 2020-06-29 21:47:12 -07:00
Stowell, Mark L b0f7299444 Adding serial and parallel unit tests for the GetValue and GetVectorValue methods with element index arguments 2020-06-29 20:55:05 -07:00
Stowell, Mark L 052f04a645 Adding support for INTEGRAL map type in GetValue and GetVectorValue with element index arguments 2020-06-29 20:53:54 -07:00
Stowell, Mark L 86af594baa Adding ParGridFunction::GetVectorValue override with element index argument 2020-06-29 20:53:08 -07:00
Stowell, Mark L 7247b1fdc1 Adding access to the face neighbor ElementTransformation object through ParFiniteElementSpace and ParMesh. 2020-06-29 20:51:36 -07:00
Stowell, Mark L e6beb268e7 Supporting INTEGRAL map type in GridFunction::GetVectorValue 2020-06-29 20:02:40 -07:00
Stowell, Mark L 011b035540 Supporting INTEGRAL map type in GridFunction::GetValue 2020-06-29 20:02:07 -07:00
Arturo Vargas 213a290511 use host read only 2020-06-29 16:28:16 -07:00
Andrew T. Barker 2fa65d4846 Add unit test for symmetry of OperatorChebyshevSmoother 2020-06-29 15:08:37 -07:00
camierjs 661a7f6f38 Update CHANGELOG 2020-06-29 15:08:10 -07:00
camierjs 14e663d663 Update general/CMakeLists.txt 2020-06-29 15:06:59 -07:00
Florian Omnes b8270effa2 Simplify memory management in example 1 2020-06-29 22:24:16 +02:00
camierjs 99bc161b86 Cleanup & Meld toward master 2020-06-29 10:52:16 -07:00
camierjs 85b642bd77 Merge branch 'master' into hip-defs 2020-06-29 10:32:59 -07:00
Dylan Copeland b732ae829f Replacing comments. 2020-06-29 10:05:50 -07:00
Tzanio Kolev 551f507709 Merge pull request #1529 from mfem/bugfix/gf-getvalue-dev
Fixing GetValue methods in parallel [bugfix/gf-getvalue-dev]
2020-06-28 08:16:27 -07:00
Tzanio 87e11ed0b9 minor 2020-06-28 08:15:27 -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
Tzanio 4a2449d87f Small adjustment in ceed-cuda skipped sample runs 2020-06-27 18:15:43 -07:00
Tzanio cafa782a79 Merge branch 'master' into bugfix/gf-getvalue-dev
Conflicts:
	tests/unit/fem/test_get_value.cpp
2020-06-27 18:10:05 -07:00
Tzanio Kolev 8518e8899e Merge pull request #1520 from mfem/small-bugfixes
Two small bugfixes
2020-06-27 18:04:40 -07:00
Tzanio ea7495b5a6 Small adjustment in CHANGELOG 2020-06-27 18:03:41 -07:00
Tzanio Kolev f235473206 Merge pull request #1491 from mfem/face-nbr-numbering
Change face neighbor numbering in `GetSharedFaceTransformations`
2020-06-27 18:00:14 -07:00
Veselin Dobrev ab019493f2 Fix integration issue with the concurrent PR #1429. 2020-06-26 17:53:00 -07:00
Veselin Dobrev a514baf88b Merge branch 'face-nbr-numbering' into bugfix/gf-getvalue-dev 2020-06-26 17:42:20 -07:00
Andrew T. Barker 03533d095c Allow nonsymmetric smoothers in Multigrid object. 2020-06-26 13:22:25 -07:00
Stowell, Mark L 9a6954b957 Tweaks after double-checking high order hexahedron support 2020-06-26 09:42:56 -07:00
Ido Akkerman bd695bc74c Make style 2020-06-26 11:02:08 +02:00
Ido Akkerman e165101b27 Revert gitignore and make clean back to old version as unit test output has disappeared 2020-06-26 10:40:43 +02:00
Ido Akkerman 096e5ffb93 Adding quadfunctions to visit unit test 2020-06-26 10:36:42 +02:00
Ido Akkerman fb8e595da3 Reverting back unit test and cmake file 2020-06-26 10:24:21 +02:00
Ido Akkerman 868d8aa057 Add comment regarding VisIt's inability to visualize quadfun as of yet 2020-06-26 09:59:50 +02:00
Ido Akkerman dd09413e47 Convert comment to correct doxygen format 2020-06-26 09:53:49 +02:00
Veselin Dobrev 9b73c3c47b In HypreParMatrixFromBlocks, use O(log(P)) binary search instead
of O(P) linear search, where P is the number of processors.
2020-06-25 20:32:44 -07:00
Yohann Dudouit c6a5a75d35 Fix strange Valgrind uninitialized value. 2020-06-25 19:59:41 -07:00
Yohann Dudouit 63abc65aa0 Use cuda-shared in ex1p to avoid differences in autotest. 2020-06-25 15:19:36 -07:00
Arturo Vargas 1d35d74e85 fix logic for using cusparse 2020-06-25 11:40:28 -07:00
Arturo Vargas dceaf60897 Merge branch 'master' into feature/artv3/cusparse-Spmv 2020-06-25 11:37:20 -07:00
Arturo Vargas f761e4d033 add runtime option to use cusparse - on by default 2020-06-25 10:41:19 -07:00
Veselin Dobrev c0e8b29d07 Add test runs with SuperLU_DIST when it is enabled. 2020-06-25 02:15:16 -07:00
Veselin Dobrev 6dd2d81def Merge branch 'master' into hypreblocks-bigj
Resolved conflict:
   linalg/superlu.cpp
2020-06-25 01:41:00 -07:00
Veselin Dobrev 8798a933f3 Add support for 64bit HYPRE_Int in HypreParMatrixFromBlocks() and
GatherBlockOffsetData().

Add overflow check in GatherBlockOffsetData().

In the SuperLURowLocMatrix constructor from HypreParMatrix,
remove the check for the number of columns and add a note why it is
not necessary at the moment.

Add a compile-time check when building with SuperLU_DIST support
that HYPRE_Int is int which is required by the current implementation.
2020-06-25 01:17:30 -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
Arturo Vargas 66c6b9aa0d forgot to add file 2020-06-24 12:03:45 -07:00
Ketan Mittal c27db29466 minor 2020-06-24 11:39:59 -07:00
Tomov cfdd39a066 Merge branch 'master' into tmop-el-type 2020-06-24 10:40:02 -07:00
stefanhenneking b027c1c6cc Minor style changes. 2020-06-24 12:20:55 -05:00
Tzanio Kolev f3c822a4d3 Merge branch 'master' into face-nbr-numbering 2020-06-24 10:08:27 -07:00
Tzanio Kolev b5d35f9870 Merge branch 'master' into slepc-dev 2020-06-24 10:08:13 -07:00
Tzanio Kolev 1b74301fa7 Merge branch 'master' into bugfix/gf-getvalue-dev 2020-06-24 10:07:57 -07:00
stefanhenneking 29136050db Minor change in initializing member variable. 2020-06-24 12:07:09 -05:00
stefanhenneking 89aade4b2d Fixing minor bug. 2020-06-24 11:56:53 -05:00
Stowell, Mark L a0e9c74b9d Generalizing 2D .geo script for different orders and element types 2020-06-24 09:36:19 -07:00
stefanhenneking 0770a21d2a Fixing minor bug. 2020-06-24 11:10:34 -05: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
stefanhenneking 92cb4a02a7 Merge branch 'master' of github.com:mfem/mfem into complex-operator-pa
Merging changes from master into feature branch.
2020-06-24 10:57:44 -05:00
stefanhenneking 335d810155 Fixing typo. 2020-06-24 10:40:14 -05:00
stefanhenneking 18bb5a5ac0 Remove DIAG_KEEP option for now. 2020-06-24 10:39:07 -05:00
Ido Akkerman f29e1b82f7 Add vector unit test 2020-06-24 17:20:38 +02:00
Ido Akkerman 0b5ee4ea04 Add missing add vector member function 2020-06-24 17:20:20 +02:00
Ido Akkerman 6201d7c5bb Adding to clean 2020-06-24 10:40:15 +02:00
Ido Akkerman a5e0c3f856 Ignore output dir of unit test 2020-06-24 10:17:30 +02: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
Veselin Dobrev e267de2e26 Merge branch 'master' into small-bugfixes 2020-06-23 20:55:01 -07:00
Veselin Dobrev d533b98501 Revert "In tests/unit/fem/test_get_value.cpp, add constexpr to some"
This reverts commit 23078ff76c.
2020-06-23 20:53:02 -07:00
Stowell, Mark L f8f928028c Merge remote-tracking branch 'origin/gf-getgradient-dev' into bugfix/gf-getvalue-dev
# Conflicts:
#	mesh/pmesh.cpp
#	tests/unit/fem/test_get_value.cpp
2020-06-23 19:05:29 -07:00
Stowell, Mark L 67c70dc827 Adding support for 10 node tetrahedra 2020-06-23 18:58:21 -07:00
Ketan Mittal e170d20edc minor 2020-06-23 17:35:23 -07:00
Ketan Mittal beedb1e931 Merge branch 'master' of https://github.com/mfem/mfem into tmop-derivatives-dev 2020-06-23 17:35:01 -07:00
Stowell, Mark L 93a7b6ae86 High order Gmsh support in 1D and 2D 2020-06-23 16:50:17 -07:00
Arturo Vargas 684785eb64 clean up pass 2020-06-23 15:55:46 -07:00
Arturo Vargas bddf1110b4 PR review updates 2020-06-23 15:48:25 -07:00
Dylan Copeland 83ec745644 Revert "Implemented matrix coefficients in H(curl) mass integrator, for symmetric and asymmetric cases. Added symmetry property to MatrixCoefficient. Unit tests cover the new features."
This reverts commit 7929766814.

Conflicts:
	fem/coefficient.hpp
2020-06-23 14:22:07 -07:00
Tzanio Kolev 12590207fa Merge branch 'master' into CVODESSolver-dev 2020-06-23 13:25:01 -07:00
Jonathan Wong cc64d1fd9c changed cmake name from advection_diffusion to adjoint_advection_diffusion to highlight that the adjoint calculation is being performed 2020-06-23 13:21:57 -07:00
Tzanio Kolev 36c7d5f973 Merge pull request #1476 from mfem/tmop-solvers-dev
General action-based non-linear solver (L-BFGS) with example of application to TMOP
2020-06-23 13:15:47 -07:00
Bob Anderson ab4c17ab7d Add note about coefficient use cases 2020-06-23 11:37:00 -07:00
Ido Akkerman 18007107d8 make style 2020-06-23 10:34:21 +02:00
Veselin Dobrev 37b90f6dad Merge pull request #1545 from mfem/opt/artv3/exchFaceNbdry
ExchangeFaceNbrData memory optimization - avoid cuda mallocs
2020-06-22 23:35:54 -07:00
Jonathan Wong 85349d3a95 Properly intialize quad integration vectors.
Fixed memory errors in ToNVector and initialize in CVODESSolver::RHSB
2020-06-22 23:34:43 -07:00
Jean-Étienne Tremblay 68ecd01b9a cmake: Simplify FindSLEPc.cmake
make: Source slepcvariables for external libraries (tested with e.g. ARPACK)
Both cmake and make: Add test targets for ex11p
ex11p: Fix unitialized
rc_ex11p_*: add LOBPCG example
2020-06-22 20:13:10 -07:00
Veselin Dobrev 0966625cd2 Merge branch 'master' into opt/artv3/exchFaceNbdry 2020-06-22 20:02:08 -07:00
Veselin Dobrev 0a8028efbd Merge branch 'master' into face-nbr-numbering 2020-06-22 18:46:10 -07:00
Veselin Dobrev 427f3026ee Merge branch 'master' into small-bugfixes 2020-06-22 16:36:02 -07:00
Ketan Mittal 2e610493c6 Merge branch 'tmop-solvers-dev' of https://github.com/mfem/mfem into tmop-derivatives-dev 2020-06-22 16:35:46 -07:00
Ketan Mittal 79aa383c63 resolve conflicts 2020-06-22 15:38:53 -07:00
Veselin Dobrev f104e78310 Make class ParMesh a friend of class FaceElementTransformations. 2020-06-22 15:26:39 -07:00
Veselin Dobrev 126e75048c Merge branch 'master' into gf-getgradient-dev 2020-06-22 14:15:58 -07:00
Veselin Dobrev 5f34f7f9a9 In class FaceElementTransformations, rename the parameter 'ip'
in the methods SetIntPoint and SetAllIntPoints to 'face_ip'.

In ex18.hpp, use FaceElementTransformations::SetAllIntPoints
instead of FaceElementTransformations::SetIntPoint.

In class DGDirichletLFIntegrator, evaluate the diffusivity
coefficient (Q or MQ) through the volume transformation to
support use cases where it is defined based on the volume
attributes.
2020-06-22 14:08:47 -07:00
Tzanio Kolev 62e95fe7bc Merge pull request #1564 from mfem/nc-amr-hybridization-fix
Fix a bug with hybridization on 2D NC meshes
2020-06-22 12:47:31 -07:00
stefanhenneking 64bbbc3d8c Minor style changes. 2020-06-21 23:32:47 -05:00
Dylan Copeland 7e88d111f9 Merge branch 'master' of https://github.com/mfem/mfem into mixedcurl
Conflicts:
	fem/coefficient.hpp
2020-06-19 23:15:18 -07:00
Dylan Copeland 7929766814 Implemented matrix coefficients in H(curl) mass integrator, for symmetric and asymmetric cases. Added symmetry property to MatrixCoefficient. Unit tests cover the new features. 2020-06-19 22:58:08 -07:00
Veselin Dobrev c62681aaf8 Merge branch 'master' into nc-amr-hybridization-fix 2020-06-19 21:07:07 -07:00
Veselin Dobrev a25138e611 Add an optional output stream parameter to the new method
FaceElementTransformations::CheckConsistency and improved its
documentation.

Extended Mesh::GetFaceGeometryType to support ghost child faces
and use this to generalize ParFiniteElementSpace::GetFaceNbrFaceFE
to support all face types.

Cleanup some old and debug code.
2020-06-19 20:43:47 -07:00
Stowell, Mark L 7eee66e015 Switching to FaceElementTransformations::SetAllIntPoints in applicable integrators 2020-06-19 17:26:04 -07:00
Jean-Étienne Tremblay 7e3766eb02 Remove ex28p mention from CHANGELOG
Update sample runs for SLEPc ex11p
Add rc_ex11p to test slepcopts parameter
2020-06-19 15:58:52 -07:00
Stowell, Mark L a9fd6daf3c Merge remote-tracking branch 'origin/master' into bugfix/gf-getvalue-dev 2020-06-19 15:35:52 -07:00
Stowell, Mark L 88ac2efaad Setting FaceElementTransformations config mask based on configured pieces rather than input argument 2020-06-19 15:33:37 -07:00
Stowell, Mark L f7aa1d9972 Adding FaceElementTransformations::SetAllIntPoints method 2020-06-19 15:32:50 -07:00
stefanhenneking bc795fc99a Adding PA option to example ex22. 2020-06-19 16:18:49 -05:00
Veselin Dobrev 7f575e3e83 Merge branch 'master' into small-bugfixes 2020-06-19 14:08:17 -07:00
Veselin Dobrev f225d35ef6 Added a brief CHANGELOG entry for the navier miniapp. 2020-06-19 14:06:45 -07:00
stefanhenneking 5d80f8e195 Using OperatorHandle for SesquilinearForm to enable PA. 2020-06-19 15:58:54 -05:00
Stowell, Mark L 0acdc5dcd5 Adding Doxygen comments for the new ConfigMasks enumeration 2020-06-19 13:15:48 -07:00
Veselin Dobrev a00bcade5f Merge branch 'master' into pr13 2020-06-19 12:47:06 -07:00
stefanhenneking 8491ec4183 Adding PA option to ex22p. 2020-06-19 13:45:21 -05:00
stefanhenneking dbba71bc7c Adding diagonal policy to ParSesquilinearForm for PA. 2020-06-19 11:59:56 -05:00
stefanhenneking aea81c2920 Adding diagonal policy to constrained operator. 2020-06-19 11:54:48 -05:00
Jean-Étienne Tremblay 1399fe2d7c Remove SLEPc ex28p for now, will add later as a miniapp 2020-06-19 09:53:09 -07:00
stefanhenneking 4e7821c809 Remove operator ownership before calling destructor. 2020-06-19 09:58:08 -05:00
Tzanio Kolev cc3a4475d2 Merge pull request #1460 from mfem/LF-grad-curl-div
Additional LF-integrators
2020-06-18 18:52:17 -07:00
Tzanio 8e00ae03e4 Removed convergence/bae.cpp, this will be handled in another PR. 2020-06-18 18:49:12 -07:00
Stowell, Mark L d72ff9948b Adding an enumeration for the FaceElementTransformations mask values 2020-06-18 16:34:59 -07:00
Stowell, Mark L 8f3bafa318 Supporting 1D meshes. 2020-06-18 15:16:10 -07:00
Stowell, Mark L bed918ad77 Fixing preservation of pre-existing boundary attributes 2020-06-18 15:15:54 -07:00
Veselin Dobrev 47886b13d8 Merge branch 'master' into opt/artv3/exchFaceNbdry 2020-06-18 13:22:48 -07:00
Tzanio Kolev bf3423dcba Merge pull request #1497 from mfem/coef-dev
Adding accessor methods to compound coefficient classes [coef-dev]
2020-06-18 10:55:33 -07:00
Stowell, Mark L 56066f9cac Modifying mask variable as a mask (with |=) rather than an integer (with +=) 2020-06-18 10:44:35 -07:00
Veselin Dobrev dd23ccddb3 In ex4p, added a sample run that tests hybridization in 2D when
there are ghost shared faces using amr-quad.mesh on 3 processors.

In ex9p, added a sample run on amr-hex.mesh on 3 processors so
have a test case with ghost shared faces in 3D.
2020-06-17 22:39:16 -07:00
Veselin Dobrev ab41b4f02c Merge branch 'master' into opt/artv3/exchFaceNbdry 2020-06-17 20:41:16 -07:00
Jonathan Wong c85d34c34a corrected typo and added documentation that @jandrej suggested 2020-06-17 17:05:30 -07:00
Tzanio Kolev 3c5dc275a4 Merge pull request #1539 from mfem/navier-bookkeeping-fix
Navier miniapp bookkeeping fix
2020-06-17 16:37:23 -07:00
Veselin Dobrev 7e7e2064f2 Merge branch 'master' into opt/artv3/exchFaceNbdry 2020-06-17 14:45:23 -07:00
Yohann Dudouit fd5fe341b1 Refine face_mat condition. 2020-06-17 11:51:13 -07:00
Jean-Étienne Tremblay 2a72bfcd5c Check for vector size in SlepcEigenSolver::GetEigenVector, and distribute eigenvector correctly in SLEPc ex11p 2020-06-17 08:32:51 -07:00
Veselin Dobrev 6604ba702c WIP: debugging and bugfix for the issue with hybridization on 2D
nonconforming meshes, see issue #1105 on github.
2020-06-16 21:09:48 -07:00
Tomov a7cc1e74c3 wip on tmop with mixed meshes. 2020-06-16 16:41:59 -07:00
Jean-Étienne Tremblay ec634749cf Work around zero pivot in serial LU for ex28p 2020-06-16 13:07:32 -07:00
Veselin Dobrev bf62d2923c Small code simplification. 2020-06-15 20:54:17 -07:00
Veselin Dobrev 8e76ad9cd8 Merge branch 'master' into small-bugfixes 2020-06-15 19:16:52 -07:00
Julian Andrej b95407f6ea finalize jacobian blocks in BlockNonlinearForm before essential dof eliminiation 2020-06-15 15:09:04 -07:00
Jonathan Wong 02f6ca0ef2 Freed the nvector to prevent a memory leak 2020-06-15 15:05:20 -07:00
Arturo Vargas 88b98c8fb4 small fixes for applications 2020-06-13 22:01:12 -07:00
Arturo Vargas ec9f1a6224 update docs 2020-06-13 21:58:14 -07:00
Arturo Vargas 664216ca9b memory optimization - avoid cuda mallocs 2020-06-13 21:51:11 -07:00
Stowell, Mark L 2fda14b373 Adding a missing contribution to the FaceElementTransformations creation mask 2020-06-13 09:58:03 -07:00
Veselin Dobrev 7b18a4b932 Bugfixes in ParMesh::GetGhostFaceTransformation and
GridFunction::GetFaceVectorValues.
2020-06-12 18:14:26 -07:00
Julian Andrej 395e75f69a Merge branch 'master' into navier-bookkeeping-fix 2020-06-12 11:21:38 -07:00
Julian Andrej 1875c34055 Add move constructor to custom types 2020-06-12 11:20:07 -07:00
Arturo Vargas 6c1ee0c854 skip computation if matrix is zero 2020-06-11 20:33:43 -07:00
Jean-Étienne Tremblay a6db609f67 make style 2020-06-11 12:47:39 -07:00
Yohann Dudouit fc57c1be85 Fix a bug. 2020-06-11 12:35:02 -07:00
Arturo Vargas e7674ba0e7 free data if init 2020-06-11 09:44:28 -07:00
Ido Akkerman 21e6e7f669 Adding quadfun read write unit_test 2020-06-11 18:21:30 +02:00
Ido Akkerman c9c2cd825e Merge branch 'master' into quadspace-visit-dev 2020-06-11 17:21:29 +02:00
Stowell, Mark L defc3378c6 Expanding GetVectorValue tests in parallel 2020-06-10 16:36:04 -07:00
Stowell, Mark L 371a5cc714 Changing function calls to coefficient evaluations 2020-06-10 16:18:53 -07:00
Stowell, Mark L 8ad33458e1 Setting configuration mask for FaceElementTransformations in GetSharedFaceTransformations 2020-06-10 16:02:58 -07:00
Dylan Copeland 5aa36b19de Adding hypre version checks. 2020-06-10 15:30:26 -07:00
Dylan Copeland 86178916e7 Adding checks for whether big_j is used. 2020-06-10 15:05:38 -07:00
Yohann Dudouit 6c52bec12d Try less verbose constant lambda capture. 2020-06-10 14:34:36 -07:00
Yohann Dudouit 01c8643d1d make style. 2020-06-10 14:10:59 -07:00
Yohann Dudouit 3b35126fbc Remove some of the #ifdef MFEM_USE_MPI (thanks Will Pazner) 2020-06-10 13:29:16 -07:00
Yohann Dudouit 3ec12f0866 Add device sample runs to ex9 and ex9p. 2020-06-10 12:45:10 -07:00
Yohann Dudouit 1c8a8dbcb1 Minor 2020-06-09 20:28:21 -07:00
Yohann Dudouit 55b26db935 make style. 2020-06-09 20:26:18 -07:00
Veselin Dobrev 4e235c421a Fix a bug/typo in tests/unit/fem/test_get_value.cpp 2020-06-09 20:14:16 -07:00
Yohann Dudouit 5ebc924b20 Add parallel support for DG face terms. 2020-06-09 19:56:33 -07:00
Stowell, Mark L 39f26a201f Bugfix in unit test 2020-06-09 15:18:50 -07:00
Stowell, Mark L cebce14371 Further reducing the mesh size in 2D and 3D. 2020-06-09 15:18:36 -07:00
Stowell, Mark L 27f720ac20 Removing unneeded calls to ExchangeFaceNbrData and decreasing parallel mesh sizes 2020-06-09 15:07:45 -07:00
Stowell, Mark L d1ceb124c5 Merge remote-tracking branch 'origin/master' into bugfix/gf-getvalue-dev 2020-06-09 14:59:05 -07:00
Yohann Dudouit e975ad2950 Revert iteration count in ex1 to be different. 2020-06-09 14:37:19 -07:00
Veselin Dobrev 23078ff76c In tests/unit/fem/test_get_value.cpp, add constexpr to some
'dim' variables to avoid the use VLAs -- this generated warnings
when building with -pedantic flag.
2020-06-09 14:32:42 -07:00
Jonathan Wong 58997c32bd initialized N_Vector pointer to struct type to NULL 2020-06-09 14:07:26 -07:00
Stowell, Mark L f58decb421 Adding Doxygen comments for the new accessor methods 2020-06-09 13:51:46 -07:00
Jonathan Wong c0395c6371 tidy up parallel output for advection_diffusion problem 2020-06-09 13:21:25 -07:00
Tomov f34493eb0d Cleanup. 2020-06-09 10:35:15 -07:00
Stowell, Mark L 635ac55e77 Creating Doxygen group for compound coefficient 2020-06-09 09:41:44 -07:00
Stowell, Mark L 6beb0decd7 Merge remote-tracking branch 'origin/master' into coef-dev
# Conflicts:
#	fem/coefficient.hpp
2020-06-09 09:41:13 -07:00
Stowell, Mark L 99bcdec9ed Using the new GetVectorValue interface in Joule miniapp 2020-06-09 09:16:22 -07:00
Tzanio Kolev c8118c532a Merge branch 'master' into gf-getgradient-dev 2020-06-09 07:28:36 -07:00
Tzanio Kolev 253aebb734 Merge branch 'master' into LF-grad-curl-div 2020-06-09 07:28:20 -07:00
Dylan Copeland 68fd30d2f9 Adding MFEM_ABORT_KERNEL, currently used only in SparseMatrix::DiagScale. 2020-06-08 22:42:48 -07:00
Dylan Copeland e4a6e1c724 Added MFEM_FORALL to SparseMatrix::DiagScale. Made some minor style improvements. 2020-06-08 21:40:11 -07:00
Arturo Vargas 802e20160c clean up pass 2020-06-08 19:53:03 -07:00
Arturo Vargas 0055894917 added support for user coefficient scaling for conv,trace,diff,mass 2020-06-08 19:29:14 -07:00
Yohann Dudouit f1ac4b1eff Rename mfemAtomicAdd ro AtomicAdd. 2020-06-08 18:40:24 -07:00
Yohann Dudouit c2de4ee220 Move synchronization inside Print(). 2020-06-08 18:37:11 -07:00
Yohann Dudouit c53fe3ffda Remove dead code. 2020-06-08 18:21:18 -07:00
Yohann Dudouit 105a991779 Remove MFEM_ABORT... 2020-06-08 18:17:52 -07:00
Yohann Dudouit e831e8007b Use OperatorJacobiSmoother in ex9.
- implement GetDiag() for SparseMatrix on device.
2020-06-08 18:10:13 -07:00
Arturo Vargas 01d53b32fa added user quadrature support to mass/diffusion integrators 2020-06-08 17:42:51 -07:00
Tomov 6fc9562ae4 Minor. 2020-06-08 17:21:15 -07:00
Yohann Dudouit dee42c559a AppVeyor... 2020-06-08 17:19:56 -07:00
Tomov 4c183aaebc Merge branch 'tmop-solvers-dev' of github.com:mfem/mfem into tmop-solvers-dev 2020-06-08 17:13:17 -07:00
Tomov 46f80874dc Renamed a metric. 2020-06-08 17:12:49 -07:00
Tomov f941857625 Added a sample run and minor edits. 2020-06-08 17:02:10 -07:00
Yohann Dudouit 33c28f7591 Try to make AppVeyor happy... 2020-06-08 17:00:20 -07:00
Ketan Mittal 5802774a28 removed copy of past history to reduce ops 2020-06-08 16:32:43 -07:00
Stowell, Mark L 60db6756cb Adding parallel unit tests to test_get_value 2020-06-08 16:32:26 -07:00
Stowell, Mark L e026fa6c26 Setting ElementType member data in GetFaceNbrElementTransformation 2020-06-08 16:31:56 -07:00
Stowell, Mark L 039adec0fc Mimicking the serial GetValue in parallel 2020-06-08 16:31:07 -07:00
Yohann Dudouit 03c0009414 Rename simplify into factorize_face_terms. 2020-06-08 15:52:56 -07:00
Yohann Dudouit 6f4c373d58 update AssemblyLevel documentation. 2020-06-08 15:33:14 -07:00
Yohann Dudouit 5a27cb9e54 update documentation. 2020-06-08 15:30:39 -07:00
Yohann Dudouit 48a018e7a3 Remove commented optimization ideas. 2020-06-08 15:25:05 -07:00
Yohann Dudouit 39fc24685f Attempt to make AppVeyor happy. 2020-06-08 15:08:53 -07:00
Ketan Mittal dce355c41b reviewer comments 2020-06-08 14:14:20 -07:00
Yohann Dudouit db626777be make style 2020-06-08 13:31:42 -07:00
Ketan Mittal 2eb8667642 Merge branch 'master' of https://github.com/mfem/mfem into tmop-solvers-dev 2020-06-08 13:17:34 -07:00
Stowell, Mark L 5ab8dfc15c Creating overrides to GetValue and GetVectorValue for face neighbor elements 2020-06-08 13:16:27 -07:00
Yohann Dudouit b3f4e5bb0b Remove magic number. 2020-06-08 12:59:00 -07:00
Stowell, Mark L b542fcd25b Clarifying comment in GetDivergence 2020-06-08 12:44:15 -07:00
Stowell, Mark L ac1bc5f2ab Clarifying comment 2020-06-08 12:40:31 -07:00
Yohann Dudouit 04f1d562b7 Revert ex1 and ex1p. 2020-06-08 12:38:59 -07:00
Stowell, Mark L ac426c336b Adding check for valid dimension 2020-06-08 12:35:49 -07:00
Stowell, Mark L 7de36b40bb Wrapping math formulae in \f$ 2020-06-08 12:27:59 -07:00
Yohann c610cabe53 Merge branch 'master' into yohann/fa 2020-06-08 12:22:54 -07:00
Yohann Dudouit 14ac6afcd8 Rename GetNnzInd to GetAndIncrementNnzIndex. 2020-06-08 12:19:24 -07:00
Yohann Dudouit eea03f48bb Rename FactorizeBlocks to AddFaceMatricesToElementMatrices. 2020-06-08 12:04:39 -07:00
Yohann Dudouit bd10bef5d1 Rename FillSpMat to FillSparseMatrix. 2020-06-08 11:33:02 -07:00
Yohann Dudouit cb3202f9f9 Rename GetNnzInd to GetNnzIndex and add doc. 2020-06-08 11:11:42 -07:00
Yohann Dudouit 3fb736981e Rename FillJandData to FillJAndData. 2020-06-08 11:06:09 -07:00
Yohann Dudouit 802a4afce0 make style 2020-06-08 11:00:55 -07:00
Tomov 8d33bbde0e Minor. 2020-06-07 17:25:32 -07:00
Tomov e7799b3576 Merge branch 'master' into tmop-solvers-dev 2020-06-07 16:30:08 -07:00
Stowell, Mark L bf54fc6b3f Expanding name of MatVecCoefficient to conform to standard set by other product coefficients 2020-06-07 13:59:16 -07:00
Stowell, Mark L fb3b943cf0 Adding/improving comments 2020-06-07 13:53:24 -07:00
Arturo Vargas 10bed2997c use quadraturefunction coefficient to supply user qpt scaling 2020-06-05 10:24:35 -07:00
Ido Akkerman ec8796ebde make style 2020-06-05 17:43:36 +02:00
Ido Akkerman e985684812 Improved get refinement routines 2020-06-05 17:12:26 +02:00
Dylan Copeland b8811828aa Fixing big integer issue with recent versions of hypre, in HypreParMatrixFromBlocks. 2020-06-04 15:37:28 -07:00
Veselin Dobrev 88261ed314 Two small bugfixes. 2020-06-04 13:43:13 -07:00
Arturo Vargas 55d27cbd91 Merge branch 'master' into feature/artv3/quad-data 2020-06-03 16:29:18 -07:00
Ido Akkerman 51faf60eab Corrections for double int conversion 2020-06-03 22:09:26 +02:00
Ido Akkerman 23cec0568b Corrections for double int conversion 2020-06-03 22:09:09 +02:00
Ido Akkerman d83112c174 Add individual LOD param to visit fields 2020-06-03 16:36:25 +02:00
Ido Akkerman cab24d6f3d Add GetRefinementLevel routine 2020-06-03 16:24:52 +02:00
Ido Akkerman 572470939a Adding ClosedGL pointset for ViSit vis of quadrature data 2020-06-03 16:22:11 +02:00
psocratis df3d0b51c2 renamed example name 2020-06-02 15:54:36 -07:00
psocratis 4c4aeaeec3 renamed example 2020-06-02 15:51:28 -07:00
Yohann Dudouit ff57240475 Update unit tests. 2020-06-02 15:23:11 -07:00
Yohann Dudouit 650941acc9 Update CHANGELOG 2020-06-02 15:10:44 -07:00
Jonathan Wong 4540775fdd deleted extra blank lines 2020-06-02 12:17:29 -07:00
jeremylt 97b785caf0 Install - update requirement to OCCA v1.0.10, required for libCEED compatibility 2020-06-02 10:14:05 -06:00
Jeremy L Thompson 614b409d24 Install - update libCEED requirement to v0.7 2020-06-02 10:14:05 -06:00
cd81e6c51a libCEED - update restrictions for offsets change in API
adjust size of L-vector for identity restriction

update tensor offset array creation

update nontensor offset array creation

style

Co-authored-by: Natalie Beams <nbeams@icl.utk.edu>

Update restriction API again (#1)

* libCEED - update restrictions for offsets change in API

* Install - update libCEED requirement to v0.7

* Install - update requirement to OCCA v1.0.10, required for libCEED compatibility

* adjust size of L-vector for identity restriction

* update tensor offset array creation

* update nontensor offset array creation

Co-authored-by: jeremylt <jeremy.thompson@colorado.edu>
Co-authored-by: Jeremy L Thompson <thompson.jeremy.luke@gmail.com>
2020-06-02 10:14:01 -06:00
Jonathan Wong e18858ab09 adjusted comment in SUNIMplicitSolveB 2020-06-01 23:01:16 -07:00
Jonathan Wong 5878be5cb8 delete eliminated matrix that results from calls to EliminateRowsCols() 2020-06-01 22:58:10 -07:00
Jonathan Wong 17d4cba0c9 fixed memory leak issues 2020-06-01 22:51:44 -07:00
Jonathan Wong e30182268d fixed linewidths, removed numbering, removed unused objects 2020-06-01 22:17:40 -07:00
Jonathan Wong e6163eb49c fixed merge with master and changes in hyper ToNvector() 2020-06-01 16:14:00 -07:00
Vargas 9b83346ed3 make style 2020-06-01 10:42:45 -07:00
Arturo Vargas 26d3646c1b add guards for non cuda 2020-06-01 10:42:04 -07:00
Jean-Étienne Tremblay d27f3d683e Add second attribute to ex28p mesh to define a dielectric waveguide core 2020-06-01 10:35:10 -07:00
Vargas f7724b30d9 make style 2020-06-01 10:15:09 -07:00
Arturo Vargas c28cfb92ac clean up pass, add diffusion benchmark 2020-06-01 10:13:55 -07:00
Jean-Étienne Tremblay c7fe398bd7 Build SLEPc examples only when MFEM_USE_SLEPC is defined.
Make SLEPc detection more robust
Fix typos in ex28p.cpp
2020-06-01 10:00:27 -07:00
Arturo Vargas 2a5a1fc73b Merge branch 'master' into feature/artv3/cusparse-Spmv 2020-06-01 08:55:03 -07:00
Arturo Vargas c61af0cce9 comment out debugging code 2020-05-29 10:28:24 -07:00
Arturo Vargas e1bd6275d1 Merge branch 'master' into feature/artv3/cusparse-Spmv 2020-05-29 09:19:58 -07:00
Jonathan Wong edee386ec8 fixed numbering issue in advection_diffusion.cpp 2020-05-28 20:51:48 -07:00
Dylan Copeland f5aa751bba Fixed SparseMatrix::DiagScale to work on GPU. 2020-05-28 16:46:41 -07:00
Jean-Étienne Tremblay 1855ec2993 Add conversion from EPS to PetscObject.
Another typo in the boundary conditions of ex28p.
2020-05-28 16:04:55 -07:00
psocratis cadb9778a4 Added the legal statement at the top. Corrected the mesh path 2020-05-28 15:14:43 -07:00
Dylan Copeland 81b1848021 Fixing some compiler warnings. 2020-05-28 12:57:24 -07:00
Tzanio Kolev caedc3be67 Merge branch 'master' into mixedcurl 2020-05-28 10:44:51 -07:00
Socratis 32bdcb6ef2 make style 2020-05-27 19:01:16 -07:00
Socratis e74d501ac3 fixed comments in example 2020-05-27 19:00:11 -07:00
Socratis fcd2f0ceb2 Merge branch 'master' into LF-grad-curl-div 2020-05-27 18:44:36 -07:00
Socratis c0879aaf76 fixed valgrind leaks 2020-05-27 18:44:06 -07:00
Jean-Étienne Tremblay abfc34d652 Fix boundary condition typo in ex28p 2020-05-27 17:00:35 -07:00
Jean-Étienne Tremblay 15e01b2021 Add option to ex28p to use block matrices or not. Some SLEPc options (e.g. shift-and-invert with direct solvers) don't support block matrices. 2020-05-27 16:45:55 -07:00
Jean-Étienne Tremblay a21130a958 Merge remote-tracking branch 'origin/master' into slepc-dev 2020-05-27 15:22:24 -07:00
Ketan Mittal 19f484ec72 Merge branch 'tmop-solvers-dev' of https://github.com/mfem/mfem into tmop-derivatives-dev 2020-05-27 11:26:16 -07:00
Ketan Mittal e29ae919ad minor 2020-05-27 11:24:06 -07:00
Ido Akkerman d87f4e347c add qspace to visit 2020-05-27 17:53:10 +02:00
Yohann Dudouit a502f38360 Simplify FillI() for face DG. 2020-05-27 01:15:26 -07:00
Yohann Dudouit fa5ccb3e9f Remove MultTranspose in ParL2FaceRestriction. 2020-05-27 00:54:04 -07:00
Yohann Dudouit fc24fad31c Revert the constructor of ParL2FaceRestriction. 2020-05-26 19:11:11 -07:00
Yohann Dudouit 96a5ef5392 Reorganize L2FaceRestriction constructors (thanks Will Pazner). 2020-05-26 17:17:19 -07:00
Yohann Dudouit 5fe2e5e573 Authorize SetAssemblyLevel(LEGACYFULL). 2020-05-26 17:05:15 -07:00
Yohann Dudouit bac87d5bdf Move constexpr inside MFEM_FORALL. 2020-05-26 16:07:20 -07:00
Yohann Dudouit 1441fca816 Another attempt for AppVeyor. 2020-05-26 16:01:56 -07:00
Yohann Dudouit 272d529aee Another attempt to make AppVeyor happy. 2020-05-26 15:40:39 -07:00
Yohann Dudouit 5e3d92693f Use contexpr to try to make AppVeyor happy. 2020-05-26 15:13:21 -07:00
Yohann Dudouit b0abbc3a24 Set LEGACYFULL to 0. 2020-05-26 14:20:11 -07:00
Yohann Dudouit 22afa40eb0 Update Documentation. 2020-05-26 14:12:51 -07:00
Yohann Dudouit 6e8001e206 Add a LEGACYFULL assembly mode. 2020-05-26 14:08:05 -07:00
Yohann Dudouit 27b6172257 Modify test_matrix_square to use the legacy full assembly. 2020-05-26 13:35:26 -07:00
Yohann Dudouit 00a431e5b3 Remove white space. 2020-05-26 13:19:59 -07:00
Yohann Dudouit cc9dd4e34e Modify parallel exemples for testing purpose. 2020-05-26 13:03:49 -07:00
Yohann Dudouit ca8e3e73a9 Rewrite a bit FactorizeBlocks. 2020-05-26 12:56:56 -07:00
Yohann Dudouit c4a1a23756 Use MFEM_FOR_ALL 2020-05-26 12:51:51 -07:00
Yohann Dudouit 6571977c97 Modify constructor of L2FaceRestriction. 2020-05-26 12:44:54 -07:00
Yohann Dudouit e0b19c5520 make style. 2020-05-26 11:44:04 -07:00
Yohann Dudouit 1ea27f2805 Make ParL2FaceRestriction inherit from L2FaceRestriction. 2020-05-26 11:19:29 -07:00
Ketan Mittal 5d10bdb339 LBFGS removed from mesh-optimizer.hpp 2020-05-26 06:50:46 -07:00
Ketan Mittal f7c3eb92d2 Merge branch 'master' of https://github.com/mfem/mfem into tmop-solvers-dev 2020-05-25 18:44:50 -07:00
Yohann Dudouit 957aa9aeef Remove ex9pa. 2020-05-22 21:14:16 -07:00
Yohann Dudouit ae5da8e9ac Fix MultTranspose in Element Assembly. 2020-05-22 21:04:37 -07:00
Yohann Dudouit c45ed09112 Typos. 2020-05-22 21:00:18 -07:00
Yohann Dudouit 42522ddd43 Remove more dead code. 2020-05-22 20:57:12 -07:00
Yohann Dudouit 1ecf80a2f7 Remove dead code. 2020-05-22 20:49:46 -07:00
Tomov deceb79c31 LBFGSSolver inherits NewtonSolver.
TMOPSolver inherits LBFGSSolver and switches its Mult().
2020-05-22 20:43:30 -07:00
Yohann Dudouit 93c3684eb1 Use atomicAdd instead of ++... 2020-05-22 20:40:30 -07:00
Yohann Dudouit 84cc5c7f4b Minor 2020-05-22 20:22:06 -07:00
Yohann Dudouit 8a0724498c Change a bit the logic in FillI. 2020-05-22 20:12:41 -07:00
Yohann Dudouit f9976955cf Fix a bug in CG full assembly. 2020-05-22 19:16:52 -07:00
Yohann Dudouit 8ecb802662 More code cleaning. 2020-05-22 19:01:00 -07:00
Yohann Dudouit 568dff92bb Update ex9pa. 2020-05-22 18:15:35 -07:00
Yohann Dudouit bbc186136d Clean the code. 2020-05-22 18:05:52 -07:00
Yohann Dudouit c2253a9532 Replace size_t with int. 2020-05-22 17:46:12 -07:00
Yohann Dudouit 3309b8d49b Rewrite Full Assembly for DG. 2020-05-22 17:36:58 -07:00
Jan Nikl 9fb292898e Fixed GeometryRefiner::RefineInterior to not append existing integration rules. 2020-05-22 14:58:38 +02:00
Ketan Mittal 15c1ff069c minor 2020-05-21 14:29:06 -07:00
Ketan Mittal 061b70f461 adding missing terms in gradient 2020-05-21 14:21:25 -07:00
Jean-Étienne Tremblay aa354598ca Add proper includes to petsinternals.hpp
Remove operatorset logic
Use EPSGetTolerances instead of storing internal state
2020-05-21 13:47:41 -07:00
Yohann Dudouit a250b07a34 Fix a bug due to unsynchronized host/device array. 2020-05-20 19:48:46 -07:00
Yohann Dudouit b3a06ecbc0 Add host synchronization in the Print of SpMat. 2020-05-20 18:07:44 -07:00
Yohann Dudouit 12a8465047 Uncomment the actual SpMat print. 2020-05-20 17:32:48 -07:00
Yohann Dudouit 15f6269ad4 Add some debugging prints. 2020-05-20 17:30:42 -07:00
Jean-Étienne Tremblay 45881cbdd5 Only allow PetscParMatrix for SLEPc operators 2020-05-20 17:13:18 -07:00
Yohann Dudouit e6ed2fafa0 Help the smart class to be less... 2020-05-20 16:59:46 -07:00
Yohann Dudouit 9c37a19c7f Same weird bug somewhere else. 2020-05-20 16:56:42 -07:00
Yohann Dudouit 27a3f4bfce Forgot one line in previous commit... 2020-05-20 16:50:04 -07:00
Yohann Dudouit 5def286b2a Fix strange bug. 2020-05-20 16:49:07 -07:00
Yohann Dudouit b5aa280711 Use MFEM_FORALL... 2020-05-20 16:28:55 -07:00
Yohann Dudouit ec8bcb8c16 More of the same. 2020-05-20 16:15:13 -07:00
Yohann Dudouit 8d5249c9ba Add MFEM_HOST_DEVICE qualifiers. 2020-05-20 16:13:44 -07:00
Yohann Dudouit 6cc9989653 Remove 'private' qualifier due to nvcc. 2020-05-20 16:11:57 -07:00
Yohann Dudouit fe59dc5f29 Remove commented old code. 2020-05-20 16:08:43 -07:00
Yohann Dudouit fd7b8c84e0 Comment unused code. 2020-05-20 16:06:03 -07:00
Yohann Dudouit 5bea192dd7 Minor for GPU. 2020-05-20 16:04:36 -07:00
Jean-Étienne Tremblay bc40981ffe Move PETSc error handling to shared header 2020-05-20 15:51:05 -07:00
Yohann Dudouit 596306b12d Add MFEM_FORALL. 2020-05-20 15:45:04 -07:00
Stowell, Mark L e024ac0f9c Adding accessor methods to compound coefficient classes (and adding a couple new ones) 2020-05-20 15:43:17 -07:00
Jean-Étienne Tremblay d4416684e8 Improve comments and fix formatting. 2020-05-20 15:33:46 -07:00
Yohann Dudouit c5dea1ee17 Add temporarly modified ex1, ex9, and add ex9pa for testing purpose. 2020-05-20 15:26:27 -07:00
Yohann Dudouit 9c09fea06b Remove dead code. 2020-05-20 14:39:50 -07:00
Yohann Dudouit bc28f6f06e Replace += with mfemAtomicAdd. 2020-05-20 14:39:37 -07:00
Stowell, Mark L 552971d35f make style 2020-05-20 14:24:38 -07:00
Stowell, Mark L 5d5f35af69 Removing unnecessary local variable 2020-05-20 14:24:16 -07:00
Stowell, Mark L 8e7c37ace6 Fixing typo in unit test 2020-05-20 14:23:46 -07:00
Stowell, Mark L 73f9540674 Merge remote-tracking branch 'origin/master' into gf-getgradient-dev
# Conflicts:
#	tests/unit/fem/test_get_value.cpp
2020-05-20 14:06:28 -07:00
Yohann Dudouit 76b044ae99 Fix bugs in the full assembly for DG. 2020-05-20 11:40:25 -07:00
Yohann Dudouit 27b4be77a9 Use Array<int> instead of Vector. 2020-05-20 11:39:22 -07:00
Dylan Copeland 039a04b3e2 New BlockOperator implementation based on using MakeRef in BlockVector. 2020-05-19 16:52:13 -07:00
Jean-Étienne Tremblay 8d983963dd Update CHANGELOG and INSTALL for SLEPc
Fix compiling SLEPc with regular make
Don't store number of converged eigenvalues for SLEPc
2020-05-19 16:12:43 -07:00
Jonathan Wong ceba505e4e merged with master 2020-05-19 15:12:10 -07:00
Jonathan Wong ed556b5c63 tried to fix all line formatting to 80 cols. Added some more documentation and used QuadratureSensitivity in the advection_diffusion example 2020-05-19 15:08:24 -07:00
Yohann Dudouit 6f34ccec75 Change algorithms to assemble CG sparse matrices. 2020-05-19 15:00:59 -07:00
Dylan Copeland feb79f3d56 Merge branch 'master' of github.com:mfem/mfem into blockop_cuda 2020-05-19 14:34:54 -07:00
Yohann Dudouit 35704d508d Fix a bug in Element Assembly.
Integrators were not adding values.
2020-05-19 13:26:25 -07:00
Jonathan Wong 721ea4323b fixed documenation from SUNImplicitSetupB and moved ex9p to advection_diffusion.cpp 2020-05-19 12:30:03 -07:00
Jonathan Wong 8e36f5ebdc made sure linalg/operator.hpp is under 80 col 2020-05-19 12:25:25 -07:00
Will Pazner b4daabfc10 Change Elem2No in GetSharedFaceTransformations
Instead of returning the element neighbor index (i.e. starting from 0)
in `Elem2No`, now return the "shifted element index" (i.e. starting
from `NumOfElements`), so that callers of method (e.g. integrators)
can distinguish between local elements (`index < NumOfElements`) and
face neighbor element (`index >= NumOfElements`). The element neighbor
index can be recovered simply by subtracting `NumOfElements`.
2020-05-19 12:01:16 -07:00
Tzanio Kolev 0f54e013aa Merge branch 'master' into h1-hessian-dev 2020-05-19 09:31:42 -07:00
Ido Akkerman df650aab6b Switching from Array to std::vector for non-POD 2020-05-19 14:15:51 +02:00
Arturo Vargas 8b9b0f7a0d uncomment inportant code 2020-05-18 17:58:43 -07:00
Arturo Vargas fd0ac87506 added driver for testing performance 2020-05-18 17:46:39 -07:00
Jean-Étienne Tremblay 8e22e2b2e9 Don't build SLEPc when not asked 2020-05-18 16:48:53 -07:00
Arturo Vargas 83d753c036 proof of concept 2020-05-18 15:53:26 -07:00
Arturo Vargas fb249c5775 fixed configuration for sparse matvec 2020-05-18 14:32:32 -07:00
Yohann Dudouit 4415622c99 Change the algorithm to initialize I for CG. 2020-05-18 14:04:07 -07:00
Yohann Dudouit 479a70c65f Fix some bugs 2020-05-18 14:03:32 -07:00
Arturo Vargas a3e73ee1a3 init commit of cuSparse Spmv 2020-05-18 13:32:15 -07:00
Jean-Étienne Tremblay 5f8dab5dd3 Improve ex28p (2D Maxwell waveguide) documentation 2020-05-18 12:52:12 -07:00
Ketan Mittal 83c48a33a3 Merge branch 'tmop-solvers-dev' of https://github.com/mfem/mfem 2020-05-18 07:30:50 -07:00
Jean-Étienne Tremblay a34395c540 SLEPc: Add options to wrap or not matrix, and to specify options file
Fix SLEPc ex11p
2020-05-17 19:02:30 -07:00
Jean-Étienne Tremblay 35519303a9 Small fixes to SLEPc. 2020-05-16 17:44:35 -07:00
Jean-Étienne Tremblay 6ef4c66236 Rename 2D Maxwell eigenproblem example (ex28p) 2020-05-16 17:44:35 -07:00
Jean-Étienne Tremblay c7d65ff383 Create SLEPc class
Add SLEPc to build system
Add example 11 to PETSc folder using SLEPc eigensolver
2020-05-16 17:44:35 -07:00
Jean-Étienne Tremblay f487715dca PETSc example with 2D Maxwell eigenproblem 2020-05-16 17:44:35 -07:00
Ido Akkerman 21d77c738d Adding NULL vector as return value to make compilers happy 2020-05-14 11:34:41 +02:00
Ketan Mittal 5d204627ea merge with master and resolve conflicts 2020-05-12 15:28:30 -07:00
Ido Akkerman 10ec2a1818 Small typo 2020-05-12 15:35:35 +02:00
Ido Akkerman 49469131c2 Merge branch 'master' into ode-state-io-dev 2020-05-12 15:19:01 +02:00
Ido Akkerman 2dbb377f91 Adding alternative GetVector mechanism 2020-05-12 14:20:56 +02:00
Ido Akkerman 539176a2e1 Add override keyword 2020-05-12 13:11:22 +02:00
Tzanio Kolev e987383708 Merge branch 'master' into blockop_cuda 2020-05-11 17:15:35 -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
Jonathan Wong 0db220c79d started cleaning up the ex9p_adjoint example 2020-05-08 16:14:21 -07:00
Jonathan Wong 73d1d2a1f2 fixed quoting issue over multiple lines in operator.hpp 2020-05-08 16:04:34 -07:00
Jonathan Wong 185fc97786 Merge branch 'master' of github.com:mfem/mfem into CVODESSolver-dev 2020-05-08 15:48:09 -07:00
Jonathan Wong 146205eba6 under 80 char width 2020-05-08 15:26:45 -07:00
Yohann Dudouit d76811ac9a Skeleton for SpMat assembly. 2020-05-08 15:20:11 -07:00
Jonathan Wong 343f9e02a6 changed formating to 80 char width 2020-05-08 15:19:36 -07:00
Jonathan Wong 56d6efd7c6 updated .gitignore for miniapps/adjoint 2020-05-08 15:16:36 -07:00
Jonathan Wong 211738b616 formated CHANGELOG to 80 char width 2020-05-08 15:13:36 -07:00
Jonathan Wong 9e16d2c109 Moved files over to a miniapps directory and renamed ex26 to cvsRobers_ASAi_dns for the time being 2020-05-08 15:11:20 -07:00
Jonathan Wong 62f0f65d05 @gardner48 suggested removing the parhyp calls from hypre as they are not used anymore in the MFEM interfaces 2020-05-08 14:58:04 -07:00
Ketan Mittal 808ce8a771 LBFGS solver 2020-05-08 14:16:38 -07:00
Dylan Copeland 1ec02f0b23 Changed BlockOperator and BlockDiagonalPreconditioner to copy data to and from separate vectors for each block multiplication, in order to work on device. Updated MINRES for device runs. Now ex5 works on device. 2020-05-08 13:20:37 -07:00
Jonathan Wong c25845e724 Changed RobertsSUNDIALS to RobertsTDAOperator to highlight that it is a TimeDependentAdjointOperator which implements adjoint related rate equations as well as the time dependent operator rate equation 2020-05-07 21:31:06 -07:00
Jonathan Wong b0a7fd45e6 Made suggested documentation changes to test/ex26.cpp 2020-05-07 21:25:02 -07:00
Jonathan Wong 213b6e51d3 Added documentation for building with cvodes to default files. Changed name from objective sensitivity to quadrature sensitivity for consistency. Added documentation to sundials files. 2020-05-07 21:24:30 -07:00
Jonathan Wong e1f47f0079 corrected sundials makefile to use new test naming scheme 2020-05-07 15:55:41 -07:00
Jonathan Wong 91ed44e45a changed names of test.cpp and test_advDiff.cpp to ex26.cpp and ex27p.cpp. Replaced cvode with cvodes for SUNDIALS throughout. 2020-05-07 15:49:24 -07:00
Jonathan Wong 9a0f991da6 added NumSteps calls which might be useful for controlling aspects of stepsizes 2020-05-07 13:26:35 -07:00
Dylan Copeland 7cc35b68c2 Fixed a bug in a unit test. Defined MAX_D1D and MAX_Q1D in some functions that were using definitions from forall.hpp. 2020-05-07 09:38:27 -07:00
Dylan Copeland 525fb59dd2 Adding PA for mixed curl integrator with RT test functions, with sample runs in ex24. 2020-05-06 10:32:43 -07:00
Socratis 20089dd62b valgrind checks passed 2020-05-05 15:36:16 -07:00
psocratis a8ebdf16bd Added convergence tests 2020-05-05 15:19:27 -07:00
Ketan Mittal c3c05bba4e Merge branch 'tmop-multidiscrete-dev' of https://github.com/mfem/mfem 2020-05-05 13:54:56 -07:00
Dylan Copeland ab74459790 Adding curl interpolation example to ex24/ex24p. 2020-05-05 11:18:55 -07:00
Dylan Copeland ec745ebb25 Adding PA implementations for mixed H(curl)-vector L2 forms, along with unit tests. Also extending PA for some vector mass and curl integrators to handle diagonal matrix coefficients. 2020-05-04 21:26:01 -07:00
psocratis 99372de933 Added parallel test 2020-05-04 20:35:27 -07:00
psocratis 70d84e441d make style 2020-05-04 19:56:38 -07:00
psocratis f6bc0f8988 Added test for the newly added LF integrators 2020-05-04 19:55:00 -07:00
psocratis ef54519a29 Added LF integrators (Q, grard V), (Q, curl V) and (Q, div V) 2020-05-04 19:54:24 -07:00
Stowell, Mark L beed127764 Adding unit tests for GetCurl and GetDivergence in 2D and 3D 2020-04-30 21:01:00 -07:00
Stowell, Mark L 4b76903cf1 Correcting dimension of 2D CurlGridFunctionCoefficient 2020-04-30 21:00:24 -07:00
Arturo Vargas b686dbb897 Update bilininteg_mass.cpp 2020-04-30 18:10:29 -07:00
Stowell, Mark L 1e8cf0ff3f Replacing explicit integers with dim where appropriate in GetValue unit tests 2020-04-30 15:06:46 -07:00
Stowell, Mark L 8b183d8f1b Adding GetGradient unit tests 2020-04-30 15:05:58 -07:00
Stowell, Mark L 751a1bfdbb Merge remote-tracking branch 'origin/gf-getvalue-dev' into gf-getgradient-dev 2020-04-30 11:27:15 -07:00
Stowell, Mark L 341023cc34 Initial draft of GetGradient unit test 2020-04-30 11:22:35 -07:00
Stowell, Mark L e3665d6cd1 Removing ActiveSide concept and simplifying the logic in GetGrad, GetVecGrad, GetDiv, and GetCurl 2020-04-30 10:45:57 -07:00
Stowell, Mark L 3a4c82c960 Merge remote-tracking branch 'origin/gf-getvalue-dev' into gf-getgradient-dev
# Conflicts:
#	fem/eltrans.hpp
2020-04-30 10:04:37 -07:00
Yohann Dudouit bfc4484715 Initial commit for Full Assembly 2020-04-28 15:54:11 -07:00
Vargas dfbb139273 make style 2020-04-27 22:25:00 -07:00
Arturo Vargas e18ae9cbfc user quadrature data 2020-04-27 22:16:37 -07:00
Arturo Vargas 8782faff18 quadrature coefficient 2020-04-27 21:11:16 -07:00
Arturo Vargas bcde578a5d Merge branch 'master' into feature/artv3/quad-data 2020-04-27 21:07:11 -07:00
Arturo Vargas 12609ea7dd dismiss changes 2020-04-27 21:06:50 -07:00
Stowell, Mark L 7c857883ad Generalizing GetVectorGradient 2020-04-27 14:26:36 -07:00
Stowell, Mark L 4b99e0096f Generalizing GetDivergence and GetCurl to work on boundary elements 2020-04-27 14:23:11 -07:00
Stowell, Mark L 07344159a4 Implementing GridFunction::GetGradient which works on boundary elements 2020-04-27 13:41:32 -07:00
Stowell, Mark L 1c9bdb456b Adding FaceElementTransformation::SetIntPoint method 2020-04-27 13:40:47 -07:00
camierjs abc671eb04 Merge branch 'master' into hip-defs 2020-04-21 13:41:24 -07:00
Ido Akkerman 288cef9ccf Fine tunning the number of states available 2020-04-21 10:59:48 +02:00
camierjs c6f122e392 Qualifiers for device inline functions 2020-04-20 12:08:24 -07:00
camierjs 73de0369a1 Half & half B & G to save enough smem for order 8 2020-04-20 11:29:24 -07:00
camierjs 2d7c1c6756 SmemPADiffusion2Apply3D order 8 2020-04-20 11:06:04 -07:00
camierjs 64b51e3e2b SmemPADiffusion2Apply3D orders tries 2020-04-20 10:57:54 -07:00
camierjs b5e1a0732c Diffusion with shared mem & unroll 2020-04-20 10:39:19 -07:00
Ido Akkerman 27879297e4 Make style 2020-04-20 16:40:40 +02:00
Ido Akkerman b3babbef60 Adding state vector access mechanism for 2nd order to unit tests 2020-04-20 16:38:47 +02:00
Ido Akkerman 7909fab83f Adding state vector access mechanism for 1st order to unit tests 2020-04-20 16:28:19 +02:00
Ido Akkerman 9d0015949a Adding state vector access mechanism for first order ODE solvers 2020-04-20 16:27:28 +02:00
camierjs bfabd546fd Introduce MFEM_LAMBDA for the diffs CUDA vs HIP 2020-04-19 17:59:30 -07:00
camierjs c2796cd1c7 Lambda scope to getaround tile_static used in a non-amp error 2020-04-19 14:34:50 -07:00
camierjs 72ffdecfa6 Create backends.hpp to centralize defines 2020-04-19 13:01:37 -07:00
camierjs d765407dbe Revert logic try 2020-04-18 18:06:58 -07:00
camierjs f6c8898506 Not Cuda or Hip logic 2020-04-18 17:39:07 -07:00
camierjs 8f0817c621 Cuda header sync 2020-04-18 14:55:39 -07:00
camierjs 2ffb058e61 Use __HIP_DEVICE_COMPILE__ 2020-04-18 14:52:35 -07:00
Jonathan Wong 023e63dfb1 Reran astyle with astyle 2.05.1 2020-03-30 12:51:23 -07:00
Jonathan Wong e63ac279c1 Merge branch 'master' of github.com:mfem/mfem into CVODESSolver-dev
Fixed merge conflict in linalg/operator.hpp.
Cleaned up linalg/sundials.cpp a little bit.
Reverted defaults.mk change.
2020-03-30 12:49:40 -07:00
Jonathan Wong 8b7f15cdca revert astyle changes 2020-03-30 12:45:43 -07:00
Jonathan Wong a263658bdb Started working on CONTRIBUTING.md list 2020-03-27 12:09:53 -07:00
Jonathan Wong 3f4a6ce0d2 ran astyle 2020-03-25 12:58:46 -07:00
Jonathan Wong 4ee2b18d97 Changed from SetN_Vector to .ToNVector. Fixed implementation as suggested by gardner
Added an extra argument to Vector::ToNVector() to better handle parallel vectors
2020-03-25 12:58:33 -07:00
Jonathan Wong 5f3f056703 Initial commits of changes suggested by the SUNDIALS team 2020-01-14 13:53:05 -08:00
Jonathan Wong c933973249 Initial CVODESSolver implementation. Simple serial and parallel problem solved. Added Rootfunction finding and error control support 2020-01-06 15:40:05 -08:00
Vargas 7ee2335810 first pass at block diagonal mass matrix 2019-11-23 10:52:27 -08:00
Vargas 3c064fb4af Merge branch 'master' into feature/artv3/quad-data 2019-11-22 13:29:07 -08:00
artv3 6629cb4adb proof of concept for scaling 2019-11-01 17:48:56 -07:00
198 changed files with 21555 additions and 4480 deletions
+10 -8
View File
@@ -15,8 +15,10 @@ install:
- msmpisdk.msi /passive
- set PATH=C:\Program Files\Microsoft MPI\Bin;%PATH%
# Install METIS
- ps: Start-FileDownload 'http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/metis-5.1.0.tar.gz'
# Install METIS, use a mirror because the original source server is not always
# up. Original url:
# http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/metis-5.1.0.tar.gz
- ps: Start-FileDownload 'https://mfem.github.io/tpls/metis-5.1.0.tar.gz'
- 7z x metis-5.1.0.tar.gz -so | 7z x -si -ttar > nul
- cd metis-5.1.0
- ps: ( get-content "GKlib\gk_arch.h") | % { If ($_.ReadCount -ge 52) {$_ -replace "#ifdef __MSC__","#ifdef DISABLE_THIS_ANCIENT_MSC_CHECK"} Else {$_} } | set-content "GKlib\gk_arch.h"
@@ -26,17 +28,17 @@ install:
- cd ..
# Install hypre
- ps: Start-FileDownload 'https://github.com/hypre-space/hypre/archive/V2-10-0b.tar.gz'
- 7z x V2-10-0b.tar.gz -so | 7z x -si -ttar > nul
- cd hypre-2-10-0b
- cmake -H. -Bbuild -DHYPRE_USING_FEI=OFF -DMPI_C_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include" -DMPI_C_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include"
- ps: Start-FileDownload 'https://github.com/hypre-space/hypre/archive/v2.19.0.tar.gz'
- 7z x v2.19.0.tar.gz -so | 7z x -si -ttar > nul
- cd hypre-2.19.0/src
- cmake -H. -Bbuild -DMPI_C_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include" -DMPI_C_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include"
- cmake --build build
- cmake --build build --target install
- cd ..
- cd ../..
# MFEM
before_build:
- cmake -H. -DCMAKE_INSTALL_PREFIX=install -Bbuild_parallel -DMFEM_USE_MPI=TRUE -DMFEM_USE_METIS_5=TRUE -DMPI_CXX_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include" -DHYPRE_LIBRARIES=%cd%\hypre-2-10-0b\hypre\lib\HYPRE.lib -DHYPRE_INCLUDE_DIRS=%cd%\hypre-2-10-0b\hypre\include -DHYPRE_VERSION=21000 -DMETIS_LIBRARIES=%cd%\metis-5.1.0\build\libmetis\Debug\metis.lib -DMETIS_INCLUDE_DIRS=%cd%\metis-5.1.0\include
- cmake -H. -DCMAKE_INSTALL_PREFIX=install -Bbuild_parallel -DMFEM_USE_MPI=TRUE -DMFEM_USE_METIS_5=TRUE -DMPI_CXX_LIBRARIES="C:\Program Files (x86)\Microsoft SDKs\MPI\Lib\x86\msmpi.lib" -DMPI_CXX_INCLUDE_PATH="C:\Program Files (x86)\Microsoft SDKs\MPI\Include" -DHYPRE_DIR=%cd%\hypre-2.19.0\src\hypre -DMETIS_LIBRARIES=%cd%\metis-5.1.0\build\libmetis\Debug\metis.lib -DMETIS_INCLUDE_DIRS=%cd%\metis-5.1.0\include
- cmake -H. -DCMAKE_INSTALL_PREFIX=install -Bbuild_serial -DMFEM_USE_MPI=FALSE
build_script:
+5 -1
View File
@@ -122,7 +122,7 @@ examples/sundials/ex16-final.*
examples/sundials/Example16*
examples/petsc/ex[1-69]p
examples/petsc/ex10p
examples/petsc/ex1[0-1]p
examples/petsc/mesh.*
examples/petsc/sol.*
@@ -137,6 +137,7 @@ examples/petsc/Example9*
examples/petsc/deformed.*
examples/petsc/velocity.*
examples/petsc/elastic_energy.*
examples/petsc/mode_*
examples/pumi/ex1
examples/pumi/ex[126]p
@@ -243,6 +244,9 @@ miniapps/navier/navier_3dfoc
miniapps/navier/tgv_out*.txt
miniapps/navier/*_output
miniapps/adjoint/cvsRoberts_ASAi_dns
miniapps/adjoint/adjoint_advection_diffusion
# Unit test binary and outputs
tests/unit/output_meshes
tests/unit/unit_tests
+98 -33
View File
@@ -11,11 +11,20 @@
language: cpp
os: linux
dist: bionic
stages:
- checks
- tests
- optional
env:
global:
- HYPRE_ARCHIVE=v2.19.0.tar.gz
HYPRE_URL=https://github.com/hypre-space/hypre/archive/$HYPRE_ARCHIVE
HYPRE_TOP_DIR=hypre-2.19.0
jobs:
include:
@@ -28,6 +37,7 @@ jobs:
- stage: checks
os: linux
dist: xenial
name: "code-style"
addons:
apt:
@@ -46,9 +56,6 @@ jobs:
packages:
- doxygen
- graphviz
- mpich
- libmpich-dev
env: MPI=YES
script:
- cd ${TRAVIS_BUILD_DIR}
- cd tests/scripts
@@ -63,13 +70,24 @@ jobs:
- mpich
- libmpich-dev
env: MPI=YES
script:
before_script:
- cd ${TRAVIS_BUILD_DIR}
- mpicxx -v
- make config MFEM_USE_MPI=YES MFEM_MPI_NP=2
- make all -j3
- make test-noclean
script:
- cd tests/scripts
- ./runtest gitignore
cache:
ccache: true
directories:
- $TRAVIS_BUILD_DIR/../$HYPRE_TOP_DIR/src/hypre
- $TRAVIS_BUILD_DIR/../metis-4.0
before_cache:
- cd $TRAVIS_BUILD_DIR/../metis-4.0;
mv libmetis.a Lib ..; rm -rf * ; mv ../libmetis.a ../Lib .;
rm -f Lib/*.{c,o}
# ========================
# Optional Checks/Tests
@@ -78,6 +96,7 @@ jobs:
- stage: optional
name: "branch-history"
if: branch != next
# need full git history for the binary/big files check
git:
depth: false
@@ -106,6 +125,8 @@ jobs:
MPI=NO
CODECOV=NO
MFEM_TEST_TARGET=check
cache:
ccache: true
- os: linux
compiler: gcc
@@ -114,6 +135,8 @@ jobs:
MPI=NO
CODECOV=NO
MFEM_TEST_TARGET=test
cache:
ccache: true
- os: linux
compiler: gcc
@@ -137,9 +160,9 @@ jobs:
MFEM_TEST_TARGET=check
NPROCS=2
cache:
ccache: true
directories:
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
- $TRAVIS_BUILD_DIR/../$HYPRE_TOP_DIR/src/hypre
- $TRAVIS_BUILD_DIR/../metis-4.0
before_cache:
- cd $TRAVIS_BUILD_DIR/../metis-4.0;
@@ -168,9 +191,9 @@ jobs:
MFEM_TEST_TARGET=test
NPROCS=2
cache:
ccache: true
directories:
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
- $TRAVIS_BUILD_DIR/../$HYPRE_TOP_DIR/src/hypre
- $TRAVIS_BUILD_DIR/../metis-4.0
before_cache:
- cd $TRAVIS_BUILD_DIR/../metis-4.0;
@@ -193,16 +216,16 @@ jobs:
- cd ${TRAVIS_BUILD_DIR}/build
- cmake ..
-DMFEM_USE_MPI=ON
-DHYPRE_DIR=${TRAVIS_BUILD_DIR}/../hypre-2.10.0b/src/hypre
-DHYPRE_DIR=${TRAVIS_BUILD_DIR}/../$HYPRE_TOP_DIR/src/hypre
-DMFEM_MPI_NP=$NPROCS
- make -j3 mfem examples
- cd ${TRAVIS_BUILD_DIR}/build/tests/unit
- make -j3
- ctest --output-on-failure
cache:
ccache: true
directories:
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
- $TRAVIS_BUILD_DIR/../$HYPRE_TOP_DIR/src/hypre
- $TRAVIS_BUILD_DIR/../metis-4.0
before_cache:
- cd $TRAVIS_BUILD_DIR/../metis-4.0;
@@ -218,27 +241,43 @@ jobs:
# - parallel
- os: osx
# osx_image: xcode7.3
osx_image: xcode11.2
compiler: clang
name: "Mac: Serial + Debug"
addons:
homebrew:
packages:
- ccache
env: DEBUG=YES
MPI=NO
CODECOV=NO
MFEM_TEST_TARGET=check
cache:
ccache: true
- os: osx
# osx_image: xcode7.3
osx_image: xcode11.2
compiler: clang
name: "Mac: Serial"
addons:
homebrew:
packages:
- ccache
env: DEBUG=NO
MPI=NO
CODECOV=NO
MFEM_TEST_TARGET=test
cache:
ccache: true
- os: osx
# osx_image: xcode7.3
osx_image: xcode11.2
compiler: clang
name: "Mac: Parallel + Debug"
addons:
homebrew:
packages:
- ccache
env: DEBUG=YES
MPI=YES
CODECOV=NO
@@ -246,9 +285,9 @@ jobs:
NPROCS=4
TMPDIR=/tmp
cache:
ccache: true
directories:
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
- $TRAVIS_BUILD_DIR/../$HYPRE_TOP_DIR/src/hypre
- $TRAVIS_BUILD_DIR/../metis-4.0
- $HOME/local-cached
before_cache:
@@ -257,9 +296,13 @@ jobs:
rm -f Lib/*.{c,o}
- os: osx
# osx_image: xcode7.3
osx_image: xcode11.2
compiler: clang
name: "Mac: Parallel"
addons:
homebrew:
packages:
- ccache
env: DEBUG=NO
MPI=YES
CODECOV=YES
@@ -267,9 +310,9 @@ jobs:
NPROCS=4
TMPDIR=/tmp
cache:
ccache: true
directories:
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/lib
- $TRAVIS_BUILD_DIR/../hypre-2.10.0b/src/hypre/include
- $TRAVIS_BUILD_DIR/../$HYPRE_TOP_DIR/src/hypre
- $TRAVIS_BUILD_DIR/../metis-4.0
- $HOME/local-cached
before_cache:
@@ -283,14 +326,19 @@ before_install:
# brew install open-mpi;
# fi
# On Mac OS X, build and cache OpenMPI 2.1.1:
# Disable ccache while building dependencies that are cached:
- echo "before \$PATH = $PATH";
export PATH=${PATH//\/usr\/lib\/ccache:/};
echo "after \$PATH = $PATH"
# On Mac OS X, build and cache OpenMPI 2.1.6:
- if [ $TRAVIS_OS_NAME == "osx" ] && [ $MPI == "YES" ]; then
if [ ! -e $HOME/local-cached/bin/mpicc ]; then
mkdir -p $HOME/builds && cd $HOME/builds &&
wget https://www.open-mpi.org/software/ompi/v2.1/downloads/openmpi-2.1.1.tar.bz2 &&
tar jxf openmpi-2.1.1.tar.bz2 &&
wget https://download.open-mpi.org/release/open-mpi/v2.1/openmpi-2.1.6.tar.bz2 &&
tar jxf openmpi-2.1.6.tar.bz2 &&
mkdir openmpi-build && cd openmpi-build &&
../openmpi-2.1.1/configure --prefix=$HOME/local-cached &&
../openmpi-2.1.6/configure --prefix=$HOME/local-cached &&
make -j3 all && make install;
fi;
PATH=$HOME/local-cached/bin:$PATH;
@@ -335,26 +383,28 @@ install:
# hypre
- if [ $MPI == "YES" ]; then
if [ ! -e hypre-2.10.0b/src/hypre/lib/libHYPRE.a ]; then
wget https://computation.llnl.gov/project/linear_solvers/download/hypre-2.10.0b.tar.gz --no-check-certificate;
rm -rf hypre-2.10.0b;
tar xvzf hypre-2.10.0b.tar.gz;
cd hypre-2.10.0b/src;
./configure --disable-fortran --without-fei CC=mpicc CXX=mpic++;
if [ ! -e $HYPRE_TOP_DIR/src/hypre/lib/libHYPRE.a ]; then
wget $HYPRE_URL;
rm -rf $HYPRE_TOP_DIR;
tar xvzf $HYPRE_ARCHIVE;
cd $HYPRE_TOP_DIR/src;
./configure --disable-fortran CC=mpicc CXX=mpic++;
make -j3;
cd ../..;
else
echo "Reusing cached hypre-2.10.0b/";
echo "Reusing cached $HYPRE_TOP_DIR/";
fi;
ln -s hypre-2.10.0b hypre;
ln -s $HYPRE_TOP_DIR hypre;
else
echo "Serial build, not using hypre";
fi
# METIS
# METIS, use a mirror because the original source server is not always up.
# Original url:
# http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD/metis-4.0.3.tar.gz
- if [ $MPI == "YES" ]; then
if [ ! -e metis-4.0/libmetis.a ]; then
wget http://glaros.dtc.umn.edu/gkhome/fetch/sw/metis/OLD/metis-4.0.3.tar.gz;
wget https://mfem.github.io/tpls/metis-4.0.3.tar.gz;
tar xvzf metis-4.0.3.tar.gz;
make -j3 -C metis-4.0.3/Lib CC="$CC" OPTFLAGS="-O2";
rm -rf metis-4.0;
@@ -364,6 +414,18 @@ install:
fi;
fi
# Re-enable ccache on linux; enable ccache on mac os:
- if [ $TRAVIS_OS_NAME == "linux" ]; then
export PATH="/usr/lib/ccache:$PATH";
else
if [ $TRAVIS_OS_NAME == "osx" ]; then
export PATH="/usr/local/opt/ccache/libexec:$PATH";
fi;
fi
- printf "which \$CC = "; which $CC;
printf "which \$CXX = "; which $CXX
script:
# Compiler
- if [ $MPI == "YES" ]; then
@@ -384,6 +446,9 @@ script:
if [ "$CODECOV" == "YES" ]; then
CPPFLAGS="--coverage -g";
fi;
if [ "$TRAVIS_OS_NAME" != "linux" ] || [ "$DEBUG" == "YES" ]; then
CPPFLAGS+=" -pedantic -Wall -Werror";
fi
# Configure the library
- make config MFEM_USE_MPI=$MPI MFEM_DEBUG=$DEBUG $MAKE_CXX_FLAG
+53 -10
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,11 +32,11 @@ 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 TMOP capability for approximate tangential mesh relaxation. Added
support and examples for using TMOP on mixed meshes.
- 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 complete action of the TMOP Integrator to account for the spatial
derivatives of discrete and analytic targets.
Performance improvements
------------------------
@@ -41,13 +46,24 @@ Performance improvements
- x86 (SSE/AVX/AVX2/AVX512),
- Power8 & Power9 (VSX),
- BG/Q (QPX).
These are now enabled by default, and can be disabled with MFEM_USE_SIMD=NO.
These are disabled by default, and can be enabled with MFEM_USE_SIMD=YES.
See the new file linalg/simd.hpp and the new directory linalg/simd.
Improved GPU capabilities
-------------------------
- Added support for Chebyshev accelerated polynomial smoother on GPU.
- Optimized AMD/HIP kernel support.
- Added a Full Assembly mode compatible with Device kernel execution. This
assembly level builds on top of the current Element Assembly kernels to
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.
Discretization improvements
---------------------------
- Added support for matrix-free interpolation and restriction operators between
@@ -71,7 +87,7 @@ Discretization improvements
and, in the continuous field case, arbitrary mesh edges and faces.
- Added new coefficient and vector coefficient classes for QuadratureFunctions.
Additionaly, new LinearForm integrators were also added which make use of
Additionally, new LinearForm integrators were also added which make use of
these new QuadratureFunction coefficient classes.
- Added support face integrals on the boundaries of NURBS meshes.
@@ -88,6 +104,10 @@ Linear and nonlinear solvers
and solution during the solving process of an IterativeSolver after every
iteration.
- Added support for the CVODES package in SUNDIALS which provides ODE
solvers with sensitivity analysis capabilities. See the CVODESSolver
class and the new adjoint miniapps below.
- Block arrays of parallel matrices can now be merged into a single parallel
matrix with the function HypreParMatrixFromBlocks. This could be useful for
solving block systems with parallel direct solvers such as STRUMPACK.
@@ -95,6 +115,8 @@ Linear and nonlinear solvers
- In SLISolver, changed the residual inner product from (Br,r) to (Br,Br) so the
solver can work with non-SPD preconditioner B.
- Added support for the SLEPc eigensolver package.
New and updated examples and miniapps
-------------------------------------
- Added a new example, Example 25/25p, to demonstrate the use of a Perfectly
@@ -109,6 +131,21 @@ New and updated examples and miniapps
for applying Dirichlet, Neumann (both homogeneous and inhomogeneous), Robin,
and periodic boundary conditions with either H1 or DG discretizations.
- Added a new miniapp, Navier, that solves the time-dependent Navier-Stokes
equations of incompressible fluid dynamics. See the miniapps/navier directory
for more details.
- Added a new miniapps/adjoint directory with two miniapps demonstrating how to
solve adjoint problems in MFEM using the CVODES package in SUNDIALS. Both of
these miniapps require the MFEM_USE_SUNDIALS configuration option.
* The cvsRoberts_ASAi_dns miniapp solves a backward adjoint problem for a
system of ODEs, evaluating both forward and adjoint quadratures in serial.
* The adjoint_advection_diffusion miniapp solves a backward adjoint problem
for an advection diffusion PDE, evaluating adjoint quadratures in parallel.
- Ported Example 11p to SLEPc, to demonstrate solving the Laplace eigenvalue
equation with the shift-and-invert spectral transformation method.
- Added a simple meshing miniapp, Twist, which demonstrates MFEM's strategy of
stitching together opposite surfaces of a mesh to create a topologically
periodic mesh.
@@ -116,11 +153,13 @@ 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 partial assembly support to examples 4/4p and 5/5p, with diagonal
- Added partial assembly support to Example 4/4p and Example 5/5p, with diagonal
preconditioning.
- Added a new test problem in example 24/24p, demonstrating a mixed bilinear
form for H(div) and L_2, with partial assembly support.
- Added full assembly support in Example 9/9p.
- Added a new test problem in Example 24/24p, demonstrating a mixed bilinear
form for H1, H(curl), H(div) and L_2, with partial assembly support.
- Added weak Dirichlet boundary conditions (Nitsche) to the NURBS miniapp.
@@ -128,6 +167,10 @@ 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 device support in Example 5/5p.
- Added the option to plot a function in Mesh Explorer.
Improved testing
----------------
- Added a GitLab pipeline that automates PR testing on supercomputing systems
+40 -21
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)
@@ -149,9 +179,13 @@ if (MFEM_USE_MPI)
message(FATAL_ERROR "PETSc version >= 3.8.0 is required")
endif()
set(PETSC_INCLUDE_DIRS ${PETSC_INCLUDES})
if (MFEM_USE_SLEPC)
find_package(SLEPc REQUIRED config)
message(STATUS "Found SLEPc version ${SLEPC_VERSION}")
endif()
endif()
else()
set(PKGS_NEED_MPI SUPERLU PETSC STRUMPACK PUMI)
set(PKGS_NEED_MPI SUPERLU PETSC SLEPC STRUMPACK PUMI)
foreach(PKG IN LISTS PKGS_NEED_MPI)
if (MFEM_USE_${PKG})
message(STATUS "Disabling package ${PKG} - requires MPI")
@@ -207,10 +241,10 @@ endif()
# SUNDIALS
if (MFEM_USE_SUNDIALS)
if (NOT MFEM_USE_MPI)
find_package(SUNDIALS REQUIRED NVector_Serial CVODE ARKODE KINSOL)
find_package(SUNDIALS REQUIRED NVector_Serial CVODES ARKODE KINSOL)
else()
find_package(SUNDIALS REQUIRED
NVector_Serial NVector_Parallel NVector_ParHyp CVODE ARKODE KINSOL)
NVector_Serial NVector_Parallel NVector_ParHyp CVODES ARKODE KINSOL)
endif()
endif()
@@ -292,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)
@@ -352,8 +370,9 @@ endif()
# integers, the METIS header (with 32-bit indices, as used by mfem) needs to
# be before SuiteSparse.
set(MFEM_TPLS MPI_CXX OPENMP BLAS LAPACK METIS HYPRE SuiteSparse SUNDIALS PETSC
MESQUITE SuperLUDist STRUMPACK AXOM CONDUIT Ginkgo GNUTLS GSLIB NETCDF
MPFR PUMI HIOP POSIXCLOCKS MFEMBacktrace ZLIB OCCA CEED RAJA UMPIRE ADIOS2)
SLEPC MESQUITE SuperLUDist STRUMPACK AXOM CONDUIT Ginkgo GNUTLS GSLIB NETCDF
MPFR PUMI HIOP POSIXCLOCKS MFEMBacktrace ZLIB OCCA CEED RAJA UMPIRE ADIOS2
CUSPARSE)
# Add all *_FOUND libraries in the variable TPL_LIBRARIES.
set(TPL_LIBRARIES "")
set(TPL_INCLUDE_DIRS "")
+1
View File
@@ -109,6 +109,7 @@ The MFEM source code has the following structure:
├── linalg
├── mesh
├── miniapps
│ ├── adjoint
│ ├── common
│ ├── electromagnetics
│ ├── gslib
+12 -3
View File
@@ -383,6 +383,10 @@ MFEM_USE_PETSC = YES/NO
and other features based on the PETSc package. When enabled, this option uses
the PETSC_* library options, see below.
MFEM_USE_SLEPC = YES/NO
Enable MFEM eigensolvers based on the SLEPc package. When enabled, this
option uses the SLEPC_* library options, see below.
MFEM_USE_MPFR = YES/NO
MPFR is a library for multiple-precision floating-point computations. This
option enables the use of MPFR in MFEM, e.g. for precise computation of 1D
@@ -597,6 +601,12 @@ The specific libraries and their options are:
Options: PETSC_OPT, PETSC_LIB.
Versions: PETSc >= 3.8.0.
- SLEPc (optional), used when MFEM_USE_SLEPC = YES. SLEPc depends on PETSc and
uses some of the PETSc options when compiled.
URL: https://slepc.upv.es/
Options: SLEPC_OPT, SLEPC_LIB.
Versions: SLEPc >= 3.8.0.
- Sidre (optional), part of LLNL's axom project, used when MFEM_USE_SIDRE = YES.
Starting with MFEM v4.1, Axom version 0.3.1 or later is required.
URL: https://github.com/LLNL/axom
@@ -649,12 +659,11 @@ The specific libraries and their options are:
Options: OCCA_DIR, OCCA_OPT, OCCA_LIB.
Versions: OCCA >= 1.0.9.
- libCEED (optional), used when MFEM_USE_CEED = YES. Requires libCEED v0.6
or later version, specifically, git-hash 3d05795 or later.
- libCEED (optional), used when MFEM_USE_CEED = YES.
URL: https://github.com/CEED/libCEED
https://ceed.exascaleproject.org/libceed
Options: CEED_DIR, CEED_OPT, CEED_LIB.
Versions: libCEED >= 0.6.
Versions: libCEED > 0.6, git-hash fe5822c.
- RAJA (optional), used when MFEM_USE_RAJA = YES.
Beginning with MFEM v4.1, only RAJA v0.10.0+ is supported.
+4
View File
@@ -244,6 +244,10 @@ IF (DEFINED TPL_ENABLE_PETSC)
SET(MFEM_USE_PETSC ${TPL_ENABLE_PETSC} CACHE BOOL "Enable PETSc support." FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_SLEPC)
SET(MFEM_USE_SLEPC ${TPL_ENABLE_SLEPC} CACHE BOOL "Enable SLEPc support." FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_MPFR)
SET(MFEM_USE_MPFR ${TPL_ENABLE_MPFR} CACHE BOOL "Enable MPFR usage." FORCE)
ENDIF()
+1
View File
@@ -38,6 +38,7 @@ set(MFEM_USE_GNUTLS @MFEM_USE_GNUTLS@)
set(MFEM_USE_GSLIB @MFEM_USE_GSLIB@)
set(MFEM_USE_NETCDF @MFEM_USE_NETCDF@)
set(MFEM_USE_PETSC @MFEM_USE_PETSC@)
set(MFEM_USE_SLEPC @MFEM_USE_SLEPC@)
set(MFEM_USE_MPFR @MFEM_USE_MPFR@)
set(MFEM_USE_SIDRE @MFEM_USE_SIDRE@)
set(MFEM_USE_CONDUIT @MFEM_USE_CONDUIT@)
+3
View File
@@ -104,6 +104,9 @@
// Enable MFEM functionality based on the PETSc library
#cmakedefine MFEM_USE_PETSC
// Enable MFEM functionality based on the SLEPc library
#cmakedefine MFEM_USE_SLEPC
// Enable MFEM functionality based on the Sidre library
#cmakedefine MFEM_USE_SIDRE
+44
View File
@@ -0,0 +1,44 @@
# 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.
# Sets the following variables:
# - SLEPC_FOUND
# - SLEPC_INCLUDE_DIRS
# - SLEPC_LIBRARIES
set(SLEPc_REQUIRED_PACKAGES "PETSC" CACHE STRING
"Additional packages required by SLEPc")
include(MfemCmakeUtilities)
mfem_find_package(SLEPc SLEPC SLEPC_DIR
"include" "slepceps.h"
"${PETSC_ARCH}/lib" "slepc" # add NAMES_PER_DIR?
"Paths to headers required by SLEPc."
"Libraries required by SLEPc."
ADD_COMPONENT "config" "${PETSC_ARCH}/include" "slepcconf.h" "" ""
CHECK_BUILD SLEPC_VERSION_OK TRUE
"
#include \"petsc.h\"
#include \"slepceps.h\"
int main()
{
PetscErrorCode ierr;
int argc = 0;
char** argv = NULL;
ierr = SlepcInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL);
EPS eps;
ierr = EPSCreate(PETSC_COMM_SELF, &eps); CHKERRQ(ierr);
ierr = EPSDestroy(&eps); CHKERRQ(ierr);
ierr = SlepcFinalize(); CHKERRQ(ierr);
return 0;
}
"
)
+1
View File
@@ -25,5 +25,6 @@ mfem_find_package(SUNDIALS SUNDIALS SUNDIALS_DIR
ADD_COMPONENT NVector_ParHyp
"include" nvector/nvector_parhyp.h "lib" sundials_nvecparhyp
ADD_COMPONENT CVODE "include" cvode/cvode.h "lib" sundials_cvode
ADD_COMPONENT CVODES "include" cvodes/cvodes.h "lib" sundials_cvodes
ADD_COMPONENT ARKODE "include" arkode/arkode.h "lib" sundials_arkode
ADD_COMPONENT KINSOL "include" kinsol/kinsol.h "lib" sundials_kinsol)
+10 -2
View File
@@ -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
@@ -731,7 +739,7 @@ function(mfem_export_mk_files)
MFEM_USE_LAPACK MFEM_THREAD_SAFE MFEM_USE_OPENMP MFEM_USE_LEGACY_OPENMP
MFEM_USE_MEMALLOC MFEM_USE_SUNDIALS MFEM_USE_MESQUITE MFEM_USE_SUITESPARSE
MFEM_USE_SUPERLU MFEM_USE_STRUMPACK MFEM_USE_GNUTLS
MFEM_USE_GSLIB MFEM_USE_NETCDF MFEM_USE_PETSC MFEM_USE_MPFR MFEM_USE_SIDRE
MFEM_USE_GSLIB MFEM_USE_NETCDF MFEM_USE_PETSC MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_SIDRE
MFEM_USE_CONDUIT MFEM_USE_PUMI MFEM_USE_CUDA MFEM_USE_OCCA MFEM_USE_RAJA
MFEM_USE_UMPIRE MFEM_USE_SIMD MFEM_USE_ADIOS2)
foreach(var ${CONFIG_MK_BOOL_VARS})
+3
View File
@@ -48,6 +48,9 @@
#ifdef MFEM_USE_PETSC
#error Building with PETSc (MFEM_USE_PETSC=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#ifdef MFEM_USE_SLEPC
#error Building with SLEPc (MFEM_USE_SLEPC=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
#ifdef MFEM_USE_PUMI
#error Building with PUMI (MFEM_USE_PUMI=YES) requires MPI (MFEM_USE_MPI=YES)
#endif
+3
View File
@@ -118,6 +118,9 @@
// Enable functionality based on the PETSc library
// #define MFEM_USE_PETSC
// Enable functionality based on the SLEPc library
// #define MFEM_USE_SLEPC
// Enable functionality based on the MPFR library.
// #define MFEM_USE_MPFR
+1
View File
@@ -37,6 +37,7 @@ MFEM_USE_GINKGO = @MFEM_USE_GINKGO@
MFEM_USE_GNUTLS = @MFEM_USE_GNUTLS@
MFEM_USE_NETCDF = @MFEM_USE_NETCDF@
MFEM_USE_PETSC = @MFEM_USE_PETSC@
MFEM_USE_SLEPC = @MFEM_USE_SLEPC@
MFEM_USE_MPFR = @MFEM_USE_MPFR@
MFEM_USE_SIDRE = @MFEM_USE_SIDRE@
MFEM_USE_CONDUIT = @MFEM_USE_CONDUIT@
+8 -1
View File
@@ -39,6 +39,7 @@ option(MFEM_USE_GNUTLS "Enable GNUTLS usage" OFF)
option(MFEM_USE_GSLIB "Enable GSLIB usage" OFF)
option(MFEM_USE_NETCDF "Enable NETCDF usage" OFF)
option(MFEM_USE_PETSC "Enable PETSc support." OFF)
option(MFEM_USE_SLEPC "Enable SLEPc support." OFF)
option(MFEM_USE_MPFR "Enable MPFR usage." OFF)
option(MFEM_USE_SIDRE "Enable Axom/Sidre usage" OFF)
option(MFEM_USE_CONDUIT "Enable Conduit usage" OFF)
@@ -49,7 +50,7 @@ option(MFEM_USE_OCCA "Enable OCCA" OFF)
option(MFEM_USE_RAJA "Enable RAJA" OFF)
option(MFEM_USE_CEED "Enable CEED" OFF)
option(MFEM_USE_UMPIRE "Enable Umpire" OFF)
option(MFEM_USE_SIMD "Enable use of SIMD intrinsics" ON)
option(MFEM_USE_SIMD "Enable use of SIMD intrinsics" OFF)
option(MFEM_USE_ADIOS2 "Enable ADIOS2" OFF)
set(MFEM_MPI_NP 4 CACHE STRING "Number of processes used for MPI tests")
@@ -87,6 +88,8 @@ set(METIS_DIR "${MFEM_DIR}/../metis-4.0" CACHE PATH "Path to the METIS library."
set(LIBUNWIND_DIR "" CACHE PATH "Path to Libunwind.")
# For sundials_nvecparhyp and nvecparallel remember to build with MPI_ENABLED=ON
# and modify cmake variables for hypre for sundials
set(SUNDIALS_DIR "${MFEM_DIR}/../sundials-5.0.0/instdir" CACHE PATH
"Path to the SUNDIALS library.")
# The following may be necessary, if SUNDIALS was built with KLU:
@@ -155,6 +158,10 @@ set(PETSC_DIR "${MFEM_DIR}/../petsc" CACHE PATH
"Path to the PETSc main directory.")
set(PETSC_ARCH "arch-linux2-c-debug" CACHE STRING "PETSc build architecture.")
set(SLEPC_DIR "${MFEM_DIR}/../slepc" CACHE PATH
"Path to the SLEPc main directory.")
set(SLEPC_ARCH "arch-linux2-c-debug" CACHE STRING "SLEPC build architecture.")
set(MPFR_DIR "" CACHE PATH "Path to the MPFR library.")
set(CONDUIT_DIR "${MFEM_DIR}/../conduit" CACHE PATH
+21 -4
View File
@@ -125,6 +125,7 @@ MFEM_USE_GINKGO = NO
MFEM_USE_GNUTLS = NO
MFEM_USE_NETCDF = NO
MFEM_USE_PETSC = NO
MFEM_USE_SLEPC = NO
MFEM_USE_MPFR = NO
MFEM_USE_SIDRE = NO
MFEM_USE_CONDUIT = NO
@@ -137,7 +138,7 @@ MFEM_USE_RAJA = NO
MFEM_USE_OCCA = NO
MFEM_USE_CEED = NO
MFEM_USE_UMPIRE = NO
MFEM_USE_SIMD = YES
MFEM_USE_SIMD = NO
MFEM_USE_ADIOS2 = NO
# Compile and link options for zlib.
@@ -188,10 +189,12 @@ OPENMP_LIB =
POSIX_CLOCKS_LIB = -lrt
# SUNDIALS library configuration
# For sundials_nvecparhyp and nvecparallel remember to build with MPI_ENABLED=ON
# and modify cmake variables for hypre for sundials
SUNDIALS_DIR = @MFEM_DIR@/../sundials-5.0.0/instdir
SUNDIALS_OPT = -I$(SUNDIALS_DIR)/include
SUNDIALS_LIB = -Wl,-rpath,$(SUNDIALS_DIR)/lib64 -L$(SUNDIALS_DIR)/lib64\
-lsundials_arkode -lsundials_cvode -lsundials_nvecserial -lsundials_kinsol
-lsundials_arkode -lsundials_cvodes -lsundials_nvecserial -lsundials_kinsol
ifeq ($(MFEM_USE_MPI),YES)
SUNDIALS_LIB += -lsundials_nvecparhyp -lsundials_nvecparallel
@@ -276,6 +279,20 @@ ifeq ($(PETSC_FOUND),YES)
-L$(abspath $(PETSC_DIR))/lib -lpetsc $(PETSC_LIB)
endif
SLEPC_DIR := $(MFEM_DIR)/../slepc
SLEPC_VARS := $(SLEPC_DIR)/lib/slepc/conf/slepc_variables
SLEPC_FOUND := $(if $(wildcard $(SLEPC_VARS)),YES,)
SLEPC_INC_VAR = SLEPC_INCLUDE
SLEPC_LIB_VAR = SLEPC_EXTERNAL_LIB
ifeq ($(SLEPC_FOUND),YES)
SLEPC_OPT := $(shell sed -n "s/$(SLEPC_INC_VAR) *= *//p" $(SLEPC_VARS))
# Some additional external libraries might be defined in this file
-include ${SLEPC_DIR}/${PETSC_ARCH}/lib/slepc/conf/slepcvariables
SLEPC_LIB := $(shell sed -n "s/$(SLEPC_LIB_VAR) *= *//p" $(SLEPC_VARS))
SLEPC_LIB := -Wl,-rpath,$(abspath $(SLEPC_DIR))/$(PETSC_ARCH)/lib\
-L$(abspath $(SLEPC_DIR))/$(PETSC_ARCH)/lib -lslepc $(SLEPC_LIB)
endif
# MPFR library configuration
MPFR_OPT =
MPFR_LIB = -lmpfr
@@ -324,9 +341,9 @@ GSLIB_DIR = @MFEM_DIR@/../gslib/build
GSLIB_OPT = -I$(GSLIB_DIR)/include
GSLIB_LIB = -L$(GSLIB_DIR)/lib -lgs
# CUDA library configuration (currently not needed)
# CUDA library configuration
CUDA_OPT =
CUDA_LIB =
CUDA_LIB = -lcusparse
# HIP library configuration (currently not needed)
HIP_OPT =
+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
+1
View File
@@ -770,6 +770,7 @@ INPUT = @MFEM_SOURCE_DIR@/doc/CodeDocumentation.dox \
@MFEM_SOURCE_DIR@/examples/pumi \
@MFEM_SOURCE_DIR@/examples/hiop \
@MFEM_SOURCE_DIR@/examples/sundials \
@MFEM_SOURCE_DIR@/miniapps/adjoint \
@MFEM_SOURCE_DIR@/miniapps/common \
@MFEM_SOURCE_DIR@/miniapps/electromagnetics \
@MFEM_SOURCE_DIR@/miniapps/gslib \
+6 -3
View File
@@ -88,8 +88,8 @@ namespace mfem {
* - <a class="el" href="ex24p_8cpp_source.html">Example 24p</a>: parallel mixed finite element spaces and interpolators
* - <a class="el" href="ex25_8cpp_source.html">Example 25</a>: simulation of electromagnetic wave propagation using a Perfectly Matched Layer (PML)
* - <a class="el" href="ex25p_8cpp_source.html">Example 25p</a>: parallel simulation of electromagnetic wave propagation using a Perfectly Matched Layer (PML)
* - <a class="el" href="ex26_8cpp_source.html">Example 26</a>: multigrid preconditioner for the Laplace problem using nodal H1 FEM
* - <a class="el" href="ex26p_8cpp_source.html">Example 26p</a>: parallel multigrid preconditioner for the Laplace problem using nodal H1 FEM
* - <a class="el" href="ex26_8cpp_source.html">Example 26</a>: multigrid preconditioner for the Laplace problem using nodal H1 FEM
* - <a class="el" href="ex26p_8cpp_source.html">Example 26p</a>: parallel multigrid preconditioner for the Laplace problem using nodal H1 FEM
*
* <H4>SUNDIALS Examples</H4>
* - Variants of Examples
@@ -101,6 +101,9 @@ namespace mfem {
* and
* <a class="el" href="sundials_2ex16p_8cpp_source.html">16p</a>
* demonstrating the use of MFEM's \link sundials.hpp SUNDIALS classes\endlink
* - CVODES adjoint examples:
* <a class="el" href="cvsRoberts__ASAi__dns_8cpp_source.html">serial ODE system</a>,
* <a class="el" href="adjoint__advection__diffusion_8cpp_source.html">parallel advection-diffusion</a>
*
* <H4>PETSc Examples</H4>
* - Variants of Examples
@@ -140,6 +143,7 @@ namespace mfem {
* - <a class="el" href="tesla_8cpp_source.html">Tesla</a>: simple magnetostatics simulation code
* - <a class="el" href="maxwell_8cpp_source.html">Maxwell</a>: simple transient full-wave electromagnetics simulation code
* - <a class="el" href="joule_8cpp_source.html">Joule</a>: transient magnetics and Joule heating miniapp
* - <a class="el" href="classmfem_1_1navier_1_1NavierSolver.html">Navier</a>: solve the transient incompressible Navier-Stokes equations
* - <a class="el" href="mobius-strip_8cpp_source.html">Mobius Strip</a>: generate various Mobius strip-like meshes
* - <a class="el" href="klein-bottle_8cpp_source.html">Klein Bottle</a>: generate three types of Klein bottle surfaces
* - <a class="el" href="toroid_8cpp_source.html">Toroid</a>: generate simple toroidal meshes
@@ -157,7 +161,6 @@ 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="classmfem_1_1navier_1_1NavierSolver.html">Navier</a>: solve the transient incompressible Navier-Stokes equations
* - <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
+11 -2
View File
@@ -91,7 +91,7 @@ foreach(SRC_FILE ${ALL_EXE_SRCS})
add_test(NAME ${TEST_NAME}_ser
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
else()
add_test(NAME ${TEST_NAME}_np=4
add_test(NAME ${TEST_NAME}_np=${MFEM_MPI_NP}
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
${MPIEXEC_PREFLAGS}
$<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS}
@@ -101,13 +101,22 @@ endforeach()
# If STRUMPACK is enabled, add a test run that uses it.
if (MFEM_USE_STRUMPACK)
add_test(NAME ex11p_strumpack_np=4
add_test(NAME ex11p_strumpack_np=${MFEM_MPI_NP}
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
${MPIEXEC_PREFLAGS}
$<TARGET_FILE:ex11p> "-no-vis" "--strumpack"
${MPIEXEC_POSTFLAGS})
endif()
# If SuperLU_DIST is enabled, add a test run that uses it.
if (MFEM_USE_SUPERLU)
add_test(NAME ex11p_superlu_np=${MFEM_MPI_NP}
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
${MPIEXEC_PREFLAGS}
$<TARGET_FILE:ex11p> "-no-vis" "--superlu"
${MPIEXEC_POSTFLAGS})
endif()
# Include the examples/sundials directory if SUNDIALS is enabled.
if (MFEM_USE_SUNDIALS)
add_subdirectory(sundials)
+62 -36
View File
@@ -34,7 +34,8 @@
// ex1 -pa -d raja-omp
// ex1 -pa -d occa-omp
// ex1 -pa -d ceed-cpu
// ex1 -pa -d ceed-cuda
// * ex1 -pa -d ceed-cuda
// ex1 -pa -d ceed-cuda:/gpu/cuda/shared
// ex1 -m ../data/beam-hex.mesh -pa -d cuda
// ex1 -m ../data/beam-tet.mesh -pa -d ceed-cpu
// ex1 -m ../data/beam-tet.mesh -pa -d ceed-cuda:/gpu/cuda/ref
@@ -102,8 +103,8 @@ int main(int argc, char *argv[])
// 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();
Mesh mesh(mesh_file, 1, 1);
int dim = mesh.Dimension();
// 4. Refine the mesh to increase the resolution. In this example we do
// 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
@@ -111,10 +112,10 @@ int main(int argc, char *argv[])
// elements.
{
int ref_levels =
(int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
(int)floor(log(50000./mesh.GetNE())/log(2.)/dim);
for (int l = 0; l < ref_levels; l++)
{
mesh->UniformRefinement();
mesh.UniformRefinement();
}
}
@@ -122,76 +123,102 @@ int main(int argc, char *argv[])
// Lagrange finite elements of the specified order. If order < 1, we
// instead use an isoparametric/isogeometric space.
FiniteElementCollection *fec;
bool delete_fec;
if (order > 0)
{
fec = new H1_FECollection(order, dim);
delete_fec = true;
}
else if (mesh->GetNodes())
else if (mesh.GetNodes())
{
fec = mesh->GetNodes()->OwnFEC();
fec = mesh.GetNodes()->OwnFEC();
delete_fec = false;
cout << "Using isoparametric FEs: " << fec->Name() << endl;
}
else
{
fec = new H1_FECollection(order = 1, dim);
delete_fec = true;
}
FiniteElementSpace *fespace = new FiniteElementSpace(mesh, fec);
FiniteElementSpace fespace(&mesh, fec);
cout << "Number of finite element unknowns: "
<< fespace->GetTrueVSize() << endl;
<< fespace.GetTrueVSize() << endl;
// 6. Determine the list of true (i.e. 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 (mesh->bdr_attributes.Size())
if (mesh.bdr_attributes.Size())
{
Array<int> ess_bdr(mesh->bdr_attributes.Max());
Array<int> ess_bdr(mesh.bdr_attributes.Max());
ess_bdr = 1;
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
// 7. Set up the 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 the finite element fespace.
LinearForm *b = new LinearForm(fespace);
LinearForm b(&fespace);
ConstantCoefficient one(1.0);
b->AddDomainIntegrator(new DomainLFIntegrator(one));
b->Assemble();
b.AddDomainIntegrator(new DomainLFIntegrator(one));
b.Assemble();
// 8. Define the solution vector x as a finite element grid function
// corresponding to fespace. Initialize x with initial guess of zero,
// which satisfies the boundary conditions.
GridFunction x(fespace);
GridFunction x(&fespace);
x = 0.0;
// 9. Set up the bilinear form a(.,.) on the finite element space
// corresponding to the Laplacian operator -Delta, by adding the Diffusion
// domain integrator.
BilinearForm *a = new BilinearForm(fespace);
if (pa) { a->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
a->AddDomainIntegrator(new DiffusionIntegrator(one));
BilinearForm a(&fespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
//a.AddDomainIntegrator(new DiffusionIntegrator(one));
a.AddDomainIntegrator(new MassIntegrator(one));
// 10. Assemble the bilinear form and the corresponding linear system,
// applying any necessary transformations such as: eliminating boundary
// conditions, applying conforming constraints for non-conforming AMR,
// static condensation, etc.
if (static_cond) { a->EnableStaticCondensation(); }
a->Assemble();
if (static_cond) { a.EnableStaticCondensation(); }
a.Assemble();
OperatorPtr A;
OperatorPtr A, As;
Vector B, X;
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
Array<int> empty_list;
a.FormSystemMatrix(empty_list, As);
//a.FormLinearSystem(empty_list, x, b, A, X, B);
//a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
cout << "Size of linear system: " << A->Height() << endl;
//cout << "Size of linear system: " << A->Height() << endl;
// 11. Solve the linear system A X = B.
if (!pa)
{
#ifndef MFEM_USE_SUITESPARSE
// Use a simple symmetric Gauss-Seidel preconditioner with PCG.
GSSmoother M((SparseMatrix&)(*A));
PCG(*A, M, B, X, 1, 200, 1e-12, 0.0);
//GSSmoother M((SparseMatrix&)(*A));
//SparseMatrix &Asp = *As.As<SparseMatrix>();
SparseMatrix &Asp = a.SpMat();
Asp.Finalize();
Asp.SortColumnIndices();
Vector tmpx(B.Size());
Vector tmpy(B.Size());
tmpx = 1.0;
tmpy = 0.0;
//As.As<SparseMatrix>()->Mult(tmpx, tmpy);
Asp.Mult(tmpx, tmpy);
//IncompleteCholesky M(*As.As<SparseMatrix>());
IncompleteCholesky M(Asp);
//ILUcusparse M(*A.As<SparseMatrix>());
PCG(*As, M, B, X, 1, 200, 1e-12, 0.0);
#else
// If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
UMFPackSolver umf_solver;
@@ -202,9 +229,9 @@ int main(int argc, char *argv[])
}
else // Jacobi preconditioning in partial assembly mode
{
if (UsesTensorBasis(*fespace))
if (UsesTensorBasis(fespace))
{
OperatorJacobiSmoother M(*a, ess_tdof_list);
OperatorJacobiSmoother M(a, ess_tdof_list);
PCG(*A, M, B, X, 1, 400, 1e-12, 0.0);
}
else
@@ -214,13 +241,13 @@ int main(int argc, char *argv[])
}
// 12. Recover the solution as a finite element grid function.
a->RecoverFEMSolution(X, *b, x);
a.RecoverFEMSolution(X, b, x);
// 13. Save the refined mesh and the solution. This output can be viewed later
// using GLVis: "glvis -m refined.mesh -g sol.gf".
ofstream mesh_ofs("refined.mesh");
mesh_ofs.precision(8);
mesh->Print(mesh_ofs);
mesh.Print(mesh_ofs);
ofstream sol_ofs("sol.gf");
sol_ofs.precision(8);
x.Save(sol_ofs);
@@ -232,15 +259,14 @@ int main(int argc, char *argv[])
int visport = 19916;
socketstream sol_sock(vishost, visport);
sol_sock.precision(8);
sol_sock << "solution\n" << *mesh << x << flush;
sol_sock << "solution\n" << mesh << x << flush;
}
// 15. Free the used memory.
delete a;
delete b;
delete fespace;
if (order > 0) { delete fec; }
delete mesh;
if (delete_fec)
{
delete fec;
}
return 0;
}
+3 -8
View File
@@ -88,8 +88,6 @@ private:
Vector funval2;
Vector nor;
Vector fluxN;
IntegrationPoint eip1;
IntegrationPoint eip2;
public:
FaceIntegrator(RiemannSolver &rsolver_, const int dim);
@@ -424,19 +422,16 @@ void FaceIntegrator::AssembleFaceVector(const FiniteElement &el1,
{
const IntegrationPoint &ip = ir->IntPoint(i);
Tr.Loc1.Transform(ip, eip1);
Tr.Loc2.Transform(ip, eip2);
Tr.SetAllIntPoints(&ip); // set face and element int. points
// Calculate basis functions on both elements at the face
el1.CalcShape(eip1, shape1);
el2.CalcShape(eip2, shape2);
el1.CalcShape(Tr.GetElement1IntPoint(), shape1);
el2.CalcShape(Tr.GetElement2IntPoint(), shape2);
// Interpolate elfun at the point
elfun1_mat.MultTranspose(shape1, funval1);
elfun2_mat.MultTranspose(shape2, funval2);
Tr.SetIntPoint(&ip);
// Get the normal vector and the flux on the face
CalcOrtho(Tr.Jacobian(), nor);
const double mcs = rsolver.Eval(funval1, funval2, nor, fluxN);
+59 -39
View File
@@ -32,7 +32,8 @@
// mpirun -np 4 ex1p -pa -d occa-cuda
// mpirun -np 4 ex1p -pa -d raja-omp
// mpirun -np 4 ex1p -pa -d ceed-cpu
// mpirun -np 4 ex1p -pa -d ceed-cuda
// * mpirun -np 4 ex1p -pa -d ceed-cuda
// mpirun -np 4 ex1p -pa -d ceed-cuda:/gpu/cuda/shared
// mpirun -np 4 ex1p -m ../data/beam-tet.mesh -pa -d ceed-cpu
//
// Description: This example code demonstrates the use of MFEM to define a
@@ -111,8 +112,8 @@ int main(int argc, char *argv[])
// 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();
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
@@ -120,23 +121,23 @@ int main(int argc, char *argv[])
// more than 10,000 elements.
{
int ref_levels =
(int)floor(log(10000./mesh->GetNE())/log(2.)/dim);
for (int l = 0; l < ref_levels; l++)
(int)floor(log(10000./mesh.GetNE())/log(2.)/dim);
for (int l = 0; l < ref_levels-1; l++)
{
mesh->UniformRefinement();
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 = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
ParMesh pmesh(MPI_COMM_WORLD, mesh);
mesh.Clear();
{
int par_ref_levels = 2;
int par_ref_levels = 1;
for (int l = 0; l < par_ref_levels; l++)
{
pmesh->UniformRefinement();
pmesh.UniformRefinement();
}
}
@@ -144,13 +145,16 @@ int main(int argc, char *argv[])
// use continuous Lagrange finite elements of the specified order. If
// order < 1, we instead use an isoparametric/isogeometric space.
FiniteElementCollection *fec;
bool delete_fec;
if (order > 0)
{
fec = new H1_FECollection(order, dim);
delete_fec = true;
}
else if (pmesh->GetNodes())
else if (pmesh.GetNodes())
{
fec = pmesh->GetNodes()->OwnFEC();
fec = pmesh.GetNodes()->OwnFEC();
delete_fec = false;
if (myid == 0)
{
cout << "Using isoparametric FEs: " << fec->Name() << endl;
@@ -159,9 +163,10 @@ int main(int argc, char *argv[])
else
{
fec = new H1_FECollection(order = 1, dim);
delete_fec = true;
}
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
HYPRE_Int size = fespace->GlobalTrueVSize();
ParFiniteElementSpace fespace(&pmesh, fec);
HYPRE_Int size = fespace.GlobalTrueVSize();
if (myid == 0)
{
cout << "Number of finite element unknowns: " << size << endl;
@@ -172,44 +177,51 @@ int main(int argc, char *argv[])
// 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())
if (pmesh.bdr_attributes.Size())
{
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
Array<int> ess_bdr(pmesh.bdr_attributes.Max());
ess_bdr = 1;
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
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 = new ParLinearForm(fespace);
ParLinearForm b(&fespace);
ConstantCoefficient one(1.0);
b->AddDomainIntegrator(new DomainLFIntegrator(one));
b->Assemble();
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);
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 = new ParBilinearForm(fespace);
if (pa) { a->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
a->AddDomainIntegrator(new DiffusionIntegrator(one));
ParBilinearForm a(&fespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
a.AddDomainIntegrator(new DiffusionIntegrator(one));
// 12. Assemble the parallel bilinear form and the corresponding linear
// system, applying any necessary transformations such as: parallel
// assembly, eliminating boundary conditions, applying conforming
// constraints for non-conforming AMR, static condensation, etc.
if (static_cond) { a->EnableStaticCondensation(); }
a->Assemble();
if (static_cond) { a.EnableStaticCondensation(); }
a.Assemble();
OperatorPtr A;
Vector B, X;
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
SparseMatrix Asp;
A.As<HypreParMatrix>()->GetDiag(Asp);
Vector diag;
StopWatch sw;
sw.Start();
// 13. Solve the linear system A X = B.
// * With full assembly, use the BoomerAMG preconditioner from hypre.
@@ -217,14 +229,21 @@ int main(int argc, char *argv[])
Solver *prec = NULL;
if (pa)
{
if (UsesTensorBasis(*fespace))
if (UsesTensorBasis(fespace))
{
prec = new OperatorJacobiSmoother(*a, ess_tdof_list);
prec = new OperatorJacobiSmoother(a, ess_tdof_list);
}
}
else
{
prec = new HypreBoomerAMG;
//prec = new HypreBoomerAMG;
Asp.Finalize();
Asp.SortColumnIndices();
Asp.GetDiag(diag);
prec = new OperatorJacobiSmoother(diag, ess_tdof_list);
//prec = new IncompleteCholesky(Asp);
//prec = new ILUcusparse(Asp);
}
CGSolver cg(MPI_COMM_WORLD);
cg.SetRelTol(1e-12);
@@ -235,9 +254,12 @@ int main(int argc, char *argv[])
cg.Mult(B, X);
delete prec;
sw.Stop();
cout << "Step 13 solve time " << sw.RealTime() << endl;
// 14. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
a->RecoverFEMSolution(X, *b, x);
a.RecoverFEMSolution(X, b, x);
// 15. Save the refined mesh and the solution in parallel. This output can
// be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
@@ -248,7 +270,7 @@ int main(int argc, char *argv[])
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(8);
pmesh->Print(mesh_ofs);
pmesh.Print(mesh_ofs);
ofstream sol_ofs(sol_name.str().c_str());
sol_ofs.precision(8);
@@ -263,16 +285,14 @@ int main(int argc, char *argv[])
socketstream sol_sock(vishost, visport);
sol_sock << "parallel " << num_procs << " " << myid << "\n";
sol_sock.precision(8);
sol_sock << "solution\n" << *pmesh << x << flush;
sol_sock << "solution\n" << pmesh << x << flush;
}
// 17. Free the used memory.
delete a;
delete b;
delete fespace;
if (order > 0) { delete fec; }
delete pmesh;
if (delete_fec)
{
delete fec;
}
MPI_Finalize();
return 0;
+37 -28
View File
@@ -13,6 +13,11 @@
// ex22 -m ../data/inline-hex.mesh -o 2 -p 2
// 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
//
// Description: This example code demonstrates the use of MFEM to define and
// solve simple complex-valued linear systems. It implements three
// variants of a damped harmonic oscillator:
@@ -76,6 +81,7 @@ int main(int argc, char *argv[])
bool visualization = 1;
bool herm_conv = true;
bool exact_sol = true;
bool pa = false;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
@@ -106,6 +112,8 @@ int main(int argc, char *argv[])
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
"--no-partial-assembly", "Enable Partial Assembly.");
args.Parse();
if (!args.Good())
{
@@ -282,6 +290,7 @@ int main(int argc, char *argv[])
ConstantCoefficient negMassCoef(omega_ * omega_ * epsilon_);
SesquilinearForm *a = new SesquilinearForm(fespace, conv);
if (pa) { a->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
switch (prob)
{
case 0:
@@ -318,6 +327,8 @@ int main(int argc, char *argv[])
// -Grad(a Div) - omega^2 b + omega c
//
BilinearForm *pcOp = new BilinearForm(fespace);
if (pa) { pcOp->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
switch (prob)
{
case 0:
@@ -348,19 +359,8 @@ int main(int argc, char *argv[])
Vector B, U;
a->FormLinearSystem(ess_tdof_list, u, b, A, U, B);
u = 0.0;
U = 0.0;
OperatorHandle PCOp;
pcOp->FormSystemMatrix(ess_tdof_list, PCOp);
{
ComplexSparseMatrix * Asp =
dynamic_cast<ComplexSparseMatrix*>(A.Ptr());
cout << "Size of linear system: "
<< 2 * Asp->real().Width() << endl << endl;
}
cout << "Size of linear system: " << A->Width() << endl << endl;
// 10. Define and apply a GMRES solver for AU=B with a block diagonal
// preconditioner based on the appropriate sparse smoother.
@@ -368,8 +368,8 @@ int main(int argc, char *argv[])
Array<int> blockOffsets;
blockOffsets.SetSize(3);
blockOffsets[0] = 0;
blockOffsets[1] = PCOp.Ptr()->Height();
blockOffsets[2] = PCOp.Ptr()->Height();
blockOffsets[1] = A->Height() / 2;
blockOffsets[2] = A->Height() / 2;
blockOffsets.PartialSum();
BlockDiagonalPreconditioner BDP(blockOffsets);
@@ -377,22 +377,31 @@ int main(int argc, char *argv[])
Operator * pc_r = NULL;
Operator * pc_i = NULL;
double s = 1.0;
switch (prob)
if (pa)
{
case 0:
pc_r = new DSmoother(*PCOp.As<SparseMatrix>());
break;
case 1:
pc_r = new GSSmoother(*PCOp.As<SparseMatrix>());
s = -1.0;
break;
case 2:
pc_r = new DSmoother(*PCOp.As<SparseMatrix>());
break;
default: break; // This should be unreachable
pc_r = new OperatorJacobiSmoother(*pcOp, ess_tdof_list);
}
else
{
OperatorHandle PCOp;
pcOp->SetDiagonalPolicy(mfem::Operator::DIAG_ONE);
pcOp->FormSystemMatrix(ess_tdof_list, PCOp);
switch (prob)
{
case 0:
pc_r = new DSmoother(*PCOp.As<SparseMatrix>());
break;
case 1:
pc_r = new GSSmoother(*PCOp.As<SparseMatrix>());
break;
case 2:
pc_r = new DSmoother(*PCOp.As<SparseMatrix>());
break;
default:
break; // This should be unreachable
}
}
double s = (prob != 1) ? 1.0 : -1.0;
pc_i = new ScaledOperator(pc_r,
(conv == ComplexOperator::HERMITIAN) ?
s:-s);
+39 -28
View File
@@ -13,6 +13,11 @@
// mpirun -np 4 ex22p -m ../data/inline-hex.mesh -o 2 -p 2
// 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
//
// Description: This example code demonstrates the use of MFEM to define and
// solve simple complex-valued linear systems. It implements three
// variants of a damped harmonic oscillator:
@@ -84,6 +89,7 @@ int main(int argc, char *argv[])
bool visualization = 1;
bool herm_conv = true;
bool exact_sol = true;
bool pa = false;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
@@ -116,6 +122,8 @@ int main(int argc, char *argv[])
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
"--no-partial-assembly", "Enable Partial Assembly.");
args.Parse();
if (!args.Good())
{
@@ -315,6 +323,7 @@ int main(int argc, char *argv[])
ConstantCoefficient negMassCoef(omega_ * omega_ * epsilon_);
ParSesquilinearForm *a = new ParSesquilinearForm(fespace, conv);
if (pa) { a->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
switch (prob)
{
case 0:
@@ -351,6 +360,7 @@ int main(int argc, char *argv[])
// -Grad(a Div) - omega^2 b + omega c
//
ParBilinearForm *pcOp = new ParBilinearForm(fespace);
if (pa) { pcOp->SetAssemblyLevel(AssemblyLevel::PARTIAL); }
switch (prob)
{
case 0:
@@ -382,19 +392,11 @@ int main(int argc, char *argv[])
Vector B, U;
a->FormLinearSystem(ess_tdof_list, u, b, A, U, B);
u = 0.0;
U = 0.0;
OperatorHandle PCOp;
pcOp->FormSystemMatrix(ess_tdof_list, PCOp);
if (myid == 0)
{
ComplexHypreParMatrix * Ahyp =
dynamic_cast<ComplexHypreParMatrix*>(A.Ptr());
cout << "Size of linear system: "
<< 2 * Ahyp->real().GetGlobalNumRows() << endl << endl;
<< 2 * fespace->GlobalTrueVSize() << endl << endl;
}
// 12. Define and apply a parallel FGMRES solver for AU=B with a block
@@ -404,8 +406,8 @@ int main(int argc, char *argv[])
Array<int> blockTrueOffsets;
blockTrueOffsets.SetSize(3);
blockTrueOffsets[0] = 0;
blockTrueOffsets[1] = PCOp.Ptr()->Height();
blockTrueOffsets[2] = PCOp.Ptr()->Height();
blockTrueOffsets[1] = A->Height() / 2;
blockTrueOffsets[2] = A->Height() / 2;
blockTrueOffsets.PartialSum();
BlockDiagonalPreconditioner BDP(blockTrueOffsets);
@@ -413,25 +415,34 @@ int main(int argc, char *argv[])
Operator * pc_r = NULL;
Operator * pc_i = NULL;
switch (prob)
if (pa)
{
case 0:
pc_r = new HypreBoomerAMG(*PCOp.As<HypreParMatrix>());
break;
case 1:
pc_r = new HypreAMS(*PCOp.As<HypreParMatrix>(), fespace);
break;
case 2:
if (dim == 2 )
{
pc_r = new OperatorJacobiSmoother(*pcOp, ess_tdof_list);
}
else
{
OperatorHandle PCOp;
pcOp->FormSystemMatrix(ess_tdof_list, PCOp);
switch (prob)
{
case 0:
pc_r = new HypreBoomerAMG(*PCOp.As<HypreParMatrix>());
break;
case 1:
pc_r = new HypreAMS(*PCOp.As<HypreParMatrix>(), fespace);
}
else
{
pc_r = new HypreADS(*PCOp.As<HypreParMatrix>(), fespace);
}
break;
default: break; // This should be unreachable
break;
case 2:
if (dim == 2 )
{
pc_r = new HypreAMS(*PCOp.As<HypreParMatrix>(), fespace);
}
else
{
pc_r = new HypreADS(*PCOp.As<HypreParMatrix>(), fespace);
}
break;
default: break; // This should be unreachable
}
}
pc_i = new ScaledOperator(pc_r,
(conv == ComplexOperator::HERMITIAN) ?
+87 -8
View File
@@ -7,6 +7,7 @@
// ex24 -m ../data/beam-tet.mesh
// ex24 -m ../data/beam-hex.mesh -o 2 -pa
// ex24 -m ../data/beam-hex.mesh -o 2 -pa -p 1
// ex24 -m ../data/beam-hex.mesh -o 2 -pa -p 2
// ex24 -m ../data/escher.mesh
// ex24 -m ../data/escher.mesh -o 2
// ex24 -m ../data/fichera.mesh
@@ -24,12 +25,13 @@
// ex24 -m ../data/beam-hex.mesh -pa -d cuda
//
// Description: This example code illustrates usage of mixed finite element
// spaces, with two variants:
// spaces, with three variants:
//
// 1) (grad p, u) for p in H^1 tested against u in H(curl)
// 2) (div v, q) for v in H(div) tested against q in L_2
// 2) (curl v, u) for v in H(curl) tested against u in H(div), 3D
// 3) (div v, q) for v in H(div) tested against q in L_2
//
// Using different approaches, we project the gradient or
// Using different approaches, we project the gradient, curl, or
// divergence to the appropriate space.
//
// We recommend viewing examples 1, 3, and 5 before viewing this
@@ -45,8 +47,11 @@ using namespace mfem;
double p_exact(const Vector &x);
void gradp_exact(const Vector &, Vector &);
double div_gradp_exact(const Vector &x);
void v_exact(const Vector &x, Vector &v);
void curlv_exact(const Vector &x, Vector &cv);
int dim;
double freq = 1.0, kappa;
int main(int argc, char *argv[])
{
@@ -65,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",
@@ -83,6 +88,7 @@ int main(int argc, char *argv[])
return 1;
}
args.PrintOptions(cout);
kappa = freq * M_PI;
// 2. Enable hardware devices such as GPUs, and programming models such as
// CUDA, OCCA, RAJA and OpenMP based on command line options.
@@ -119,10 +125,15 @@ int main(int argc, char *argv[])
trial_fec = new H1_FECollection(order, dim);
test_fec = new ND_FECollection(order, dim);
}
else if (prob == 1)
{
trial_fec = new ND_FECollection(order, dim);
test_fec = new RT_FECollection(order-1, dim);
}
else
{
trial_fec = new RT_FECollection(order - 1, dim);
test_fec = new L2_FECollection(order - 1, dim);
trial_fec = new RT_FECollection(order-1, dim);
test_fec = new L2_FECollection(order-1, dim);
}
FiniteElementSpace trial_fes(mesh, trial_fec);
@@ -136,6 +147,12 @@ int main(int argc, char *argv[])
cout << "Number of Nedelec finite element unknowns: " << test_size << endl;
cout << "Number of H1 finite element unknowns: " << trial_size << endl;
}
else if (prob == 1)
{
cout << "Number of Nedelec finite element unknowns: " << trial_size << endl;
cout << "Number of Raviart-Thomas finite element unknowns: " << test_size <<
endl;
}
else
{
cout << "Number of Raviart-Thomas finite element unknowns: "
@@ -150,12 +167,18 @@ int main(int argc, char *argv[])
GridFunction x(&test_fes);
FunctionCoefficient p_coef(p_exact);
VectorFunctionCoefficient gradp_coef(sdim, gradp_exact);
VectorFunctionCoefficient v_coef(sdim, v_exact);
VectorFunctionCoefficient curlv_coef(sdim, curlv_exact);
FunctionCoefficient divgradp_coef(div_gradp_exact);
if (prob == 0)
{
gftrial.ProjectCoefficient(p_coef);
}
else if (prob == 1)
{
gftrial.ProjectCoefficient(v_coef);
}
else
{
gftrial.ProjectCoefficient(gradp_coef);
@@ -179,6 +202,11 @@ int main(int argc, char *argv[])
a.AddDomainIntegrator(new VectorFEMassIntegrator(one));
a_mixed.AddDomainIntegrator(new MixedVectorGradientIntegrator(one));
}
else if (prob == 1)
{
a.AddDomainIntegrator(new VectorFEMassIntegrator(one));
a_mixed.AddDomainIntegrator(new MixedVectorCurlIntegrator(one));
}
else
{
a.AddDomainIntegrator(new MassIntegrator(one));
@@ -244,6 +272,10 @@ int main(int argc, char *argv[])
{
dlo.AddDomainInterpolator(new GradientInterpolator());
}
else if (prob == 1)
{
dlo.AddDomainInterpolator(new CurlInterpolator());
}
else
{
dlo.AddDomainInterpolator(new DivergenceInterpolator());
@@ -258,6 +290,10 @@ int main(int argc, char *argv[])
{
exact_proj.ProjectCoefficient(gradp_coef);
}
else if (prob == 1)
{
exact_proj.ProjectCoefficient(curlv_coef);
}
else
{
exact_proj.ProjectCoefficient(divgradp_coef);
@@ -276,10 +312,23 @@ int main(int argc, char *argv[])
cout << "\n Solution of (E_h,v) = (grad p_h,v) for E_h and v in H(curl): "
"|| E_h - grad p ||_{L_2} = " << errSol << '\n' << endl;
cout << " Gradient interpolant E_h = grad p_h in H(curl): || E_h - grad p"
"||_{L_2} = " << errInterp << '\n' << endl;
" ||_{L_2} = " << errInterp << '\n' << endl;
cout << " Projection E_h of exact grad p in H(curl): || E_h - grad p "
"||_{L_2} = " << errProj << '\n' << endl;
}
else if (prob == 1)
{
double errSol = x.ComputeL2Error(curlv_coef);
double errInterp = discreteInterpolant.ComputeL2Error(curlv_coef);
double errProj = exact_proj.ComputeL2Error(curlv_coef);
cout << "\n Solution of (E_h,w) = (curl v_h,w) for E_h and w in H(div): "
"|| E_h - curl v ||_{L_2} = " << errSol << '\n' << endl;
cout << " Curl interpolant E_h = curl v_h in H(div): || E_h - curl v "
"||_{L_2} = " << errInterp << '\n' << endl;
cout << " Projection E_h of exact curl v in H(div): || E_h - curl v "
"||_{L_2} = " << errProj << '\n' << endl;
}
else
{
int order_quad = max(2, 2*order+1);
@@ -295,7 +344,7 @@ int main(int argc, char *argv[])
cout << "\n Solution of (f_h,q) = (div v_h,q) for f_h and q in L_2: "
"|| f_h - div v ||_{L_2} = " << errSol << '\n' << endl;
cout << " Divergence interpolant f_h = div v_h in L_2: || f_h - div v"
cout << " Divergence interpolant f_h = div v_h in L_2: || f_h - div v "
"||_{L_2} = " << errInterp << '\n' << endl;
cout << " Projection f_h of exact div v in L_2: || f_h - div v "
"||_{L_2} = " << errProj << '\n' << endl;
@@ -371,3 +420,33 @@ double div_gradp_exact(const Vector &x)
return 0.0;
}
void v_exact(const Vector &x, Vector &v)
{
if (dim == 3)
{
v(0) = sin(kappa * x(1));
v(1) = sin(kappa * x(2));
v(2) = sin(kappa * x(0));
}
else
{
v(0) = sin(kappa * x(1));
v(1) = sin(kappa * x(0));
if (x.Size() == 3) { v(2) = 0.0; }
}
}
void curlv_exact(const Vector &x, Vector &cv)
{
if (dim == 3)
{
cv(0) = -kappa * cos(kappa * x(2));
cv(1) = -kappa * cos(kappa * x(0));
cv(2) = -kappa * cos(kappa * x(1));
}
else
{
cv = 0.0;
}
}
+94 -12
View File
@@ -6,7 +6,8 @@
// mpirun -np 4 ex24p -m ../data/square-disc.mesh -o 2
// mpirun -np 4 ex24p -m ../data/beam-tet.mesh
// mpirun -np 4 ex24p -m ../data/beam-hex.mesh -o 2 -pa
// mpirun -np 4 ex24p -m ../data/beam-hex.mesh -o 2 -p 1 -pa
// mpirun -np 4 ex24p -m ../data/beam-hex.mesh -o 2 -pa -p 1
// mpirun -np 4 ex24p -m ../data/beam-hex.mesh -o 2 -pa -p 2
// mpirun -np 4 ex24p -m ../data/escher.mesh
// mpirun -np 4 ex24p -m ../data/escher.mesh -o 2
// mpirun -np 4 ex24p -m ../data/fichera.mesh
@@ -24,12 +25,13 @@
// mpirun -np 4 ex24p -m ../data/beam-hex.mesh -pa -d cuda
//
// Description: This example code illustrates usage of mixed finite element
// spaces, with two variants:
// spaces, with three variants:
//
// 1) (grad p, u) for p in H^1 tested against u in H(curl)
// 2) (div v, q) for v in H(div) tested against q in L_2
// 2) (curl v, u) for v in H(curl) tested against u in H(div), 3D
// 3) (div v, q) for v in H(div) tested against q in L_2
//
// Using different approaches, we project the gradient or
// Using different approaches, we project the gradient, curl, or
// divergence to the appropriate space.
//
// We recommend viewing examples 1, 3, and 5 before viewing this
@@ -45,8 +47,11 @@ using namespace mfem;
double p_exact(const Vector &x);
void gradp_exact(const Vector &, Vector &);
double div_gradp_exact(const Vector &x);
void v_exact(const Vector &x, Vector &v);
void curlv_exact(const Vector &x, Vector &cv);
int dim;
double freq = 1.0, kappa;
int main(int argc, char *argv[])
{
@@ -71,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",
@@ -96,6 +101,7 @@ int main(int argc, char *argv[])
{
args.PrintOptions(cout);
}
kappa = freq * M_PI;
// 3. Enable hardware devices such as GPUs, and programming models such as
// CUDA, OCCA, RAJA and OpenMP based on command line options.
@@ -147,10 +153,15 @@ int main(int argc, char *argv[])
trial_fec = new H1_FECollection(order, dim);
test_fec = new ND_FECollection(order, dim);
}
else if (prob == 1)
{
trial_fec = new ND_FECollection(order, dim);
test_fec = new RT_FECollection(order-1, dim);
}
else
{
trial_fec = new RT_FECollection(order - 1, dim);
test_fec = new L2_FECollection(order - 1, dim);
trial_fec = new RT_FECollection(order-1, dim);
test_fec = new L2_FECollection(order-1, dim);
}
ParFiniteElementSpace trial_fes(pmesh, trial_fec);
@@ -166,6 +177,12 @@ int main(int argc, char *argv[])
cout << "Number of Nedelec finite element unknowns: " << test_size << endl;
cout << "Number of H1 finite element unknowns: " << trial_size << endl;
}
else if (prob == 1)
{
cout << "Number of Nedelec finite element unknowns: " << trial_size << endl;
cout << "Number of Raviart-Thomas finite element unknowns: " << test_size <<
endl;
}
else
{
cout << "Number of Raviart-Thomas finite element unknowns: "
@@ -181,12 +198,18 @@ int main(int argc, char *argv[])
ParGridFunction x(&test_fes);
FunctionCoefficient p_coef(p_exact);
VectorFunctionCoefficient gradp_coef(sdim, gradp_exact);
VectorFunctionCoefficient v_coef(sdim, v_exact);
VectorFunctionCoefficient curlv_coef(sdim, curlv_exact);
FunctionCoefficient divgradp_coef(div_gradp_exact);
if (prob == 0)
{
gftrial.ProjectCoefficient(p_coef);
}
else if (prob == 1)
{
gftrial.ProjectCoefficient(v_coef);
}
else
{
gftrial.ProjectCoefficient(gradp_coef);
@@ -210,6 +233,11 @@ int main(int argc, char *argv[])
a.AddDomainIntegrator(new VectorFEMassIntegrator(one));
a_mixed.AddDomainIntegrator(new MixedVectorGradientIntegrator(one));
}
else if (prob == 1)
{
a.AddDomainIntegrator(new VectorFEMassIntegrator(one));
a_mixed.AddDomainIntegrator(new MixedVectorCurlIntegrator(one));
}
else
{
a.AddDomainIntegrator(new MassIntegrator(one));
@@ -293,6 +321,10 @@ int main(int argc, char *argv[])
{
dlo.AddDomainInterpolator(new GradientInterpolator());
}
else if (prob == 1)
{
dlo.AddDomainInterpolator(new CurlInterpolator());
}
else
{
dlo.AddDomainInterpolator(new DivergenceInterpolator());
@@ -307,6 +339,10 @@ int main(int argc, char *argv[])
{
exact_proj.ProjectCoefficient(gradp_coef);
}
else if (prob == 1)
{
exact_proj.ProjectCoefficient(curlv_coef);
}
else
{
exact_proj.ProjectCoefficient(divgradp_coef);
@@ -324,14 +360,30 @@ int main(int argc, char *argv[])
if (myid == 0)
{
cout << "\n Solution of (E_h,v) = (grad p_h,v) for E_h and v in H(curl): "
"|| E_h - grad p ||_{L_2} = " << errSol << '\n' << endl;
cout << " Gradient interpolant E_h = grad p_h in H(curl): || E_h - grad p"
"||_{L_2} = " << errInterp << '\n' << endl;
cout << "\n Solution of (E_h,v) = (grad p_h,v) for E_h and v in H(curl)"
": || E_h - grad p ||_{L_2} = " << errSol << '\n' << endl;
cout << " Gradient interpolant E_h = grad p_h in H(curl): || E_h - grad"
" p ||_{L_2} = " << errInterp << '\n' << endl;
cout << " Projection E_h of exact grad p in H(curl): || E_h - grad p "
"||_{L_2} = " << errProj << '\n' << endl;
}
}
else if (prob == 1)
{
double errSol = x.ComputeL2Error(curlv_coef);
double errInterp = discreteInterpolant.ComputeL2Error(curlv_coef);
double errProj = exact_proj.ComputeL2Error(curlv_coef);
if (myid == 0)
{
cout << "\n Solution of (E_h,w) = (curl v_h,w) for E_h and w in "
"H(div): || E_h - curl v ||_{L_2} = " << errSol << '\n' << endl;
cout << " Curl interpolant E_h = curl v_h in H(div): || E_h - curl v "
"||_{L_2} = " << errInterp << '\n' << endl;
cout << " Projection E_h of exact curl v in H(div): || E_h - curl v "
"||_{L_2} = " << errProj << '\n' << endl;
}
}
else
{
int order_quad = max(2, 2*order+1);
@@ -350,7 +402,7 @@ int main(int argc, char *argv[])
cout << "\n Solution of (f_h,q) = (div v_h,q) for f_h and q in L_2: "
"|| f_h - div v ||_{L_2} = " << errSol << '\n' << endl;
cout << " Divergence interpolant f_h = div v_h in L_2: || f_h - div v"
"||_{L_2} = " << errInterp << '\n' << endl;
" ||_{L_2} = " << errInterp << '\n' << endl;
cout << " Projection f_h of exact div v in L_2: || f_h - div v "
"||_{L_2} = " << errProj << '\n' << endl;
}
@@ -436,3 +488,33 @@ double div_gradp_exact(const Vector &x)
return 0.0;
}
void v_exact(const Vector &x, Vector &v)
{
if (dim == 3)
{
v(0) = sin(kappa * x(1));
v(1) = sin(kappa * x(2));
v(2) = sin(kappa * x(0));
}
else
{
v(0) = sin(kappa * x(1));
v(1) = sin(kappa * x(0));
if (x.Size() == 3) { v(2) = 0.0; }
}
}
void curlv_exact(const Vector &x, Vector &cv)
{
if (dim == 3)
{
cv(0) = -kappa * cos(kappa * x(2));
cv(1) = -kappa * cos(kappa * x(0));
cv(2) = -kappa * cos(kappa * x(1));
}
else
{
cv = 0.0;
}
}
+15 -23
View File
@@ -389,27 +389,22 @@ int main(int argc, char *argv[])
// applying any necessary transformations such as: assembly, eliminating
// boundary conditions, applying conforming constraints for
// non-conforming AMR, etc.
a.Assemble();
a.Assemble(0);
OperatorHandle Ah;
OperatorPtr A;
Vector B, X;
a.FormLinearSystem(ess_tdof_list, x, b, Ah, X, B);
a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);
// 13. Transform to monolithic SparseMatrix
SparseMatrix *A = Ah.As<ComplexSparseMatrix>()->GetSystemMatrix();
cout << "Size of linear system: " << A->Height() << endl;
// 14. Solve using a direct or an iterative solver
// 13. Solve using a direct or an iterative solver
#ifdef MFEM_USE_SUITESPARSE
{
UMFPackSolver solver(*A);
solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
solver.Mult(B, X);
ComplexUMFPackSolver csolver(*A.As<ComplexSparseMatrix>());
csolver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
csolver.SetPrintLevel(1);
csolver.Mult(B, X);
}
#else
// 14a. Set up the Bilinear form a(.,.) for the preconditioner
// 13a. Set up the Bilinear form a(.,.) for the preconditioner
//
// In Comp
// Domain: 1/mu (Curl E, Curl F) + omega^2 * epsilon (E,F)
@@ -437,10 +432,10 @@ int main(int argc, char *argv[])
prec.Assemble();
OperatorHandle PCOpAh;
OperatorPtr PCOpAh;
prec.FormSystemMatrix(ess_tdof_list, PCOpAh);
// 14b. Define and apply a GMRES solver for AU=B with a block diagonal
// 13b. Define and apply a GMRES solver for AU=B with a block diagonal
// preconditioner based on the Gauss-Seidel sparse smoother.
Array<int> offsets(3);
offsets[0] = 0;
@@ -467,17 +462,15 @@ int main(int argc, char *argv[])
}
#endif
// 15. Recover the solution as a finite element grid function and compute the
// 14. Recover the solution as a finite element grid function and compute the
// errors if the exact solution is known.
a.RecoverFEMSolution(X, b, x);
// If exact is known compute the error
if (exact_known)
{
ComplexGridFunction x_gf(fespace);
VectorFunctionCoefficient E_ex_Re(dim, E_exact_Re);
VectorFunctionCoefficient E_ex_Im(dim, E_exact_Im);
x_gf.ProjectCoefficient(E_ex_Re, E_ex_Im);
int order_quad = max(2, 2 * order + 1);
const IntegrationRule *irs[Geometry::NumGeom];
for (int i = 0; i < Geometry::NumGeom; ++i)
@@ -506,7 +499,7 @@ int main(int argc, char *argv[])
<< sqrt(L2Error_Re*L2Error_Re + L2Error_Im*L2Error_Im) << "\n\n";
}
// 16. Save the refined mesh and the solution. This output can be viewed
// 15. Save the refined mesh and the solution. This output can be viewed
// later using GLVis: "glvis -m mesh -g sol".
{
ofstream mesh_ofs("ex25.mesh");
@@ -521,7 +514,7 @@ int main(int argc, char *argv[])
x.imag().Save(sol_i_ofs);
}
// 17. Send the solution by socket to a GLVis server.
// 16. Send the solution by socket to a GLVis server.
if (visualization)
{
// Define visualization keys for GLVis (see GLVis documentation)
@@ -572,8 +565,7 @@ int main(int argc, char *argv[])
}
}
// 18. Free the used memory.
delete A;
// 17. Free the used memory.
delete pml;
delete fespace;
delete fec;
+7 -16
View File
@@ -419,21 +419,15 @@ int main(int argc, char *argv[])
// constraints for non-conforming AMR, etc.
a.Assemble();
OperatorHandle Ah;
OperatorPtr Ah;
Vector B, X;
a.FormLinearSystem(ess_tdof_list, x, b, Ah, X, B);
// 15. Transform to monolithic HypreParMatrix
HypreParMatrix *A = Ah.As<ComplexHypreParMatrix>()->GetSystemMatrix();
if (myid == 0)
{
cout << "Size of linear system: " << A->GetGlobalNumRows() << endl;
}
// 16. Solve using a direct or an iterative solver
// 15. Solve using a direct or an iterative solver
#ifdef MFEM_USE_SUPERLU
{
// Transform to monolithic HypreParMatrix
HypreParMatrix *A = Ah.As<ComplexHypreParMatrix>()->GetSystemMatrix();
SuperLURowLocMatrix SA(*A);
SuperLUSolver superlu(MPI_COMM_WORLD);
superlu.SetPrintStatistics(false);
@@ -441,9 +435,9 @@ int main(int argc, char *argv[])
superlu.SetColumnPermutation(superlu::PARMETIS);
superlu.SetOperator(SA);
superlu.Mult(B, X);
delete A;
}
#else
// 16a. Set up the parallel Bilinear form a(.,.) for the preconditioner
//
// In Comp
@@ -472,7 +466,7 @@ int main(int argc, char *argv[])
prec.Assemble();
OperatorHandle PCOpAh;
OperatorPtr PCOpAh;
prec.FormSystemMatrix(ess_tdof_list, PCOpAh);
// 16b. Define and apply a parallel GMRES solver for AU=B with a block
@@ -496,7 +490,7 @@ int main(int argc, char *argv[])
gmres.SetMaxIter(2000);
gmres.SetRelTol(1e-5);
gmres.SetAbsTol(0.0);
gmres.SetOperator(*A);
gmres.SetOperator(*Ah);
gmres.SetPreconditioner(BlockAMS);
gmres.Mult(B, X);
}
@@ -509,10 +503,8 @@ int main(int argc, char *argv[])
// If exact is known compute the error
if (exact_known)
{
ParComplexGridFunction x_gf(fespace);
VectorFunctionCoefficient E_ex_Re(dim, E_exact_Re);
VectorFunctionCoefficient E_ex_Im(dim, E_exact_Im);
x_gf.ProjectCoefficient(E_ex_Re, E_ex_Im);
int order_quad = max(2, 2 * order + 1);
const IntegrationRule *irs[Geometry::NumGeom];
for (int i = 0; i < Geometry::NumGeom; ++i)
@@ -629,7 +621,6 @@ int main(int argc, char *argv[])
}
// 20. Free the used memory.
delete A;
delete pml;
delete fespace;
delete fec;
+1
View File
@@ -16,6 +16,7 @@
// mpirun -np 4 ex4p -m ../data/periodic-square.mesh -no-bc
// mpirun -np 4 ex4p -m ../data/periodic-cube.mesh -no-bc
// mpirun -np 4 ex4p -m ../data/amr-quad.mesh
// mpirun -np 3 ex4p -m ../data/amr-quad.mesh -o 2 -hb
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -sc
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -hb
// mpirun -np 4 ex4p -m ../data/star-surf.mesh -o 3 -hb
+36 -17
View File
@@ -11,6 +11,12 @@
// ex5 -m ../data/escher.mesh
// ex5 -m ../data/fichera.mesh
//
// Device sample runs:
// ex5 -m ../data/star.mesh -pa -d cuda
// ex5 -m ../data/star.mesh -pa -d raja-cuda
// ex5 -m ../data/star.mesh -pa -d raja-omp
// ex5 -m ../data/beam-hex.mesh -pa -d cuda
//
// Description: This example code solves a simple 2D/3D mixed Darcy problem
// corresponding to the saddle point system
// k*u + grad p = f
@@ -50,6 +56,7 @@ int main(int argc, char *argv[])
const char *mesh_file = "../data/star.mesh";
int order = 1;
bool pa = false;
const char *device_config = "cpu";
bool visualization = 1;
OptionsParser args(argc, argv);
@@ -59,6 +66,8 @@ int main(int argc, char *argv[])
"Finite element order (polynomial degree).");
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.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
@@ -70,13 +79,18 @@ int main(int argc, char *argv[])
}
args.PrintOptions(cout);
// 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 the resolution. In this example we do
// 4. Refine the mesh to increase the resolution. In this example we do
// 'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
// largest number that gives a final mesh with no more than 10,000
// elements.
@@ -89,7 +103,7 @@ int main(int argc, char *argv[])
}
}
// 4. Define a finite element space on the mesh. Here we use the
// 5. Define a finite element space on the mesh. Here we use the
// Raviart-Thomas finite elements of the specified order.
FiniteElementCollection *hdiv_coll(new RT_FECollection(order, dim));
FiniteElementCollection *l2_coll(new L2_FECollection(order, dim));
@@ -97,7 +111,7 @@ int main(int argc, char *argv[])
FiniteElementSpace *R_space = new FiniteElementSpace(mesh, hdiv_coll);
FiniteElementSpace *W_space = new FiniteElementSpace(mesh, l2_coll);
// 5. Define the BlockStructure of the problem, i.e. define the array of
// 6. Define the BlockStructure of the problem, i.e. define the array of
// offsets for each variable. The last component of the Array is the sum
// of the dimensions of each block.
Array<int> block_offsets(3); // number of variables + 1
@@ -112,7 +126,7 @@ int main(int argc, char *argv[])
std::cout << "dim(R+W) = " << block_offsets.Last() << "\n";
std::cout << "***********************************************************\n";
// 6. Define the coefficients, analytical solution, and rhs of the PDE.
// 7. Define the coefficients, analytical solution, and rhs of the PDE.
ConstantCoefficient k(1.0);
VectorFunctionCoefficient fcoeff(dim, fFun);
@@ -122,25 +136,28 @@ int main(int argc, char *argv[])
VectorFunctionCoefficient ucoeff(dim, uFun_ex);
FunctionCoefficient pcoeff(pFun_ex);
// 7. Allocate memory (x, rhs) for the analytical solution and the right hand
// 8. Allocate memory (x, rhs) for the analytical solution and the right hand
// side. Define the GridFunction u,p for the finite element solution and
// linear forms fform and gform for the right hand side. The data
// allocated by x and rhs are passed as a reference to the grid functions
// (u,p) and the linear forms (fform, gform).
BlockVector x(block_offsets), rhs(block_offsets);
MemoryType mt = device.GetMemoryType();
BlockVector x(block_offsets, mt), rhs(block_offsets, mt);
LinearForm *fform(new LinearForm);
fform->Update(R_space, rhs.GetBlock(0), 0);
fform->AddDomainIntegrator(new VectorFEDomainLFIntegrator(fcoeff));
fform->AddBoundaryIntegrator(new VectorFEBoundaryFluxLFIntegrator(fnatcoeff));
fform->Assemble();
fform->SyncAliasMemory(rhs);
LinearForm *gform(new LinearForm);
gform->Update(W_space, rhs.GetBlock(1), 0);
gform->AddDomainIntegrator(new DomainLFIntegrator(gcoeff));
gform->Assemble();
gform->SyncAliasMemory(rhs);
// 8. Assemble the finite element matrices for the Darcy operator
// 9. Assemble the finite element matrices for the Darcy operator
//
// D = [ M B^T ]
// [ B 0 ]
@@ -185,7 +202,7 @@ int main(int argc, char *argv[])
darcyOp.SetBlock(1,0, &B);
}
// 9. Construct the operators for preconditioner
// 10. Construct the operators for preconditioner
//
// P = [ diag(M) 0 ]
// [ 0 B diag(M)^-1 B^T ]
@@ -202,10 +219,11 @@ int main(int argc, char *argv[])
if (pa)
{
mVarf->AssembleDiagonal(Md);
auto Md_host = Md.HostRead();
Vector invMd(mVarf->Height());
for (int i=0; i<mVarf->Height(); ++i)
{
invMd(i) = 1.0 / Md(i);
invMd(i) = 1.0 / Md_host[i];
}
Vector BMBt_diag(bVarf->Height());
@@ -246,7 +264,7 @@ int main(int argc, char *argv[])
darcyPrec.SetDiagonalBlock(0, invM);
darcyPrec.SetDiagonalBlock(1, invS);
// 10. Solve the linear system with MINRES.
// 11. Solve the linear system with MINRES.
// Check the norm of the unpreconditioned residual.
int maxIter(1000);
double rtol(1.e-6);
@@ -263,6 +281,7 @@ int main(int argc, char *argv[])
solver.SetPrintLevel(1);
x = 0.0;
solver.Mult(rhs, x);
if (device.IsEnabled()) { x.HostRead(); }
chrono.Stop();
if (solver.GetConverged())
@@ -273,7 +292,7 @@ int main(int argc, char *argv[])
<< " iterations. Residual norm is " << solver.GetFinalNorm() << ".\n";
std::cout << "MINRES solver took " << chrono.RealTime() << "s. \n";
// 11. Create the grid functions u and p. Compute the L2 error norms.
// 12. Create the grid functions u and p. Compute the L2 error norms.
GridFunction u, p;
u.MakeRef(R_space, x.GetBlock(0), 0);
p.MakeRef(W_space, x.GetBlock(1), 0);
@@ -293,7 +312,7 @@ int main(int argc, char *argv[])
std::cout << "|| u_h - u_ex || / || u_ex || = " << err_u / norm_u << "\n";
std::cout << "|| p_h - p_ex || / || p_ex || = " << err_p / norm_p << "\n";
// 12. Save the mesh and the solution. This output can be viewed later using
// 13. Save the mesh and the solution. This output can be viewed later using
// GLVis: "glvis -m ex5.mesh -g sol_u.gf" or "glvis -m ex5.mesh -g
// sol_p.gf".
{
@@ -310,13 +329,13 @@ int main(int argc, char *argv[])
p.Save(p_ofs);
}
// 13. Save data in the VisIt format
// 14. Save data in the VisIt format
VisItDataCollection visit_dc("Example5", mesh);
visit_dc.RegisterField("velocity", &u);
visit_dc.RegisterField("pressure", &p);
visit_dc.Save();
// 14. Save data in the ParaView format
// 15. Save data in the ParaView format
ParaViewDataCollection paraview_dc("Example5", mesh);
paraview_dc.SetPrefixPath("ParaView");
paraview_dc.SetLevelsOfDetail(order);
@@ -328,7 +347,7 @@ int main(int argc, char *argv[])
paraview_dc.RegisterField("pressure",&p);
paraview_dc.Save();
// 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";
@@ -341,7 +360,7 @@ int main(int argc, char *argv[])
p_sock << "solution\n" << *mesh << p << "window_title 'Pressure'" << endl;
}
// 16. Free the used memory.
// 17. Free the used memory.
delete fform;
delete gform;
delete invM;
+42 -21
View File
@@ -11,6 +11,12 @@
// mpirun -np 4 ex5p -m ../data/escher.mesh
// mpirun -np 4 ex5p -m ../data/fichera.mesh
//
// Device sample runs:
// mpirun -np 4 ex5p -m ../data/star.mesh -r 2 -pa -d cuda
// mpirun -np 4 ex5p -m ../data/star.mesh -r 2 -pa -d raja-cuda
// mpirun -np 4 ex5p -m ../data/star.mesh -r 2 -pa -d raja-omp
// mpirun -np 4 ex5p -m ../data/beam-hex.mesh -pa -d cuda
//
// Description: This example code solves a simple 2D/3D mixed Darcy problem
// corresponding to the saddle point system
// k*u + grad p = f
@@ -60,6 +66,7 @@ int main(int argc, char *argv[])
int order = 1;
bool par_format = false;
bool pa = false;
const char *device_config = "cpu";
bool visualization = 1;
bool adios2 = false;
@@ -75,6 +82,8 @@ int main(int argc, char *argv[])
"Format to use when saving the results for VisIt.");
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.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
@@ -96,13 +105,18 @@ int main(int argc, char *argv[])
args.PrintOptions(cout);
}
// 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. In
// 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, unless the user specifies it as input.
@@ -118,7 +132,7 @@ int main(int argc, char *argv[])
}
}
// 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);
@@ -131,7 +145,7 @@ int main(int argc, char *argv[])
}
}
// 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 the Raviart-Thomas finite elements of the specified order.
FiniteElementCollection *hdiv_coll(new RT_FECollection(order, dim));
FiniteElementCollection *l2_coll(new L2_FECollection(order, dim));
@@ -151,7 +165,7 @@ int main(int argc, char *argv[])
std::cout << "***********************************************************\n";
}
// 7. Define the two BlockStructure of the problem. block_offsets is used
// 8. Define the two BlockStructure of the problem. block_offsets is used
// for Vector based on dof (like ParGridFunction or ParLinearForm),
// block_trueOffstes is used for Vector based on trueDof (HypreParVector
// for the rhs and solution of the linear system). The offsets computed
@@ -168,7 +182,7 @@ int main(int argc, char *argv[])
block_trueOffsets[2] = W_space->TrueVSize();
block_trueOffsets.PartialSum();
// 8. Define the coefficients, analytical solution, and rhs of the PDE.
// 9. Define the coefficients, analytical solution, and rhs of the PDE.
ConstantCoefficient k(1.0);
VectorFunctionCoefficient fcoeff(dim, fFun);
@@ -178,25 +192,30 @@ int main(int argc, char *argv[])
VectorFunctionCoefficient ucoeff(dim, uFun_ex);
FunctionCoefficient pcoeff(pFun_ex);
// 9. Define the parallel grid function and parallel linear forms, solution
// vector and rhs.
BlockVector x(block_offsets), rhs(block_offsets);
BlockVector trueX(block_trueOffsets), trueRhs(block_trueOffsets);
// 10. Define the parallel grid function and parallel linear forms, solution
// vector and rhs.
MemoryType mt = device.GetMemoryType();
BlockVector x(block_offsets, mt), rhs(block_offsets, mt);
BlockVector trueX(block_trueOffsets, mt), trueRhs(block_trueOffsets, mt);
ParLinearForm *fform(new ParLinearForm);
fform->Update(R_space, rhs.GetBlock(0), 0);
fform->AddDomainIntegrator(new VectorFEDomainLFIntegrator(fcoeff));
fform->AddBoundaryIntegrator(new VectorFEBoundaryFluxLFIntegrator(fnatcoeff));
fform->Assemble();
fform->SyncAliasMemory(rhs);
fform->ParallelAssemble(trueRhs.GetBlock(0));
trueRhs.GetBlock(0).SyncAliasMemory(trueRhs);
ParLinearForm *gform(new ParLinearForm);
gform->Update(W_space, rhs.GetBlock(1), 0);
gform->AddDomainIntegrator(new DomainLFIntegrator(gcoeff));
gform->Assemble();
gform->SyncAliasMemory(rhs);
gform->ParallelAssemble(trueRhs.GetBlock(1));
trueRhs.GetBlock(1).SyncAliasMemory(trueRhs);
// 10. Assemble the finite element matrices for the Darcy operator
// 11. Assemble the finite element matrices for the Darcy operator
//
// D = [ M B^T ]
// [ B 0 ]
@@ -249,7 +268,7 @@ int main(int argc, char *argv[])
darcyOp->SetBlock(1,0, B);
}
// 11. Construct the operators for preconditioner
// 12. Construct the operators for preconditioner
//
// P = [ diag(M) 0 ]
// [ 0 B diag(M)^-1 B^T ]
@@ -266,10 +285,11 @@ int main(int argc, char *argv[])
{
Md_PA.SetSize(R_space->GetTrueVSize());
mVarf->AssembleDiagonal(Md_PA);
auto Md_host = Md_PA.HostRead();
Vector invMd(Md_PA.Size());
for (int i=0; i<Md_PA.Size(); ++i)
{
invMd(i) = 1.0 / Md_PA(i);
invMd(i) = 1.0 / Md_host[i];
}
Vector BMBt_diag(W_space->GetTrueVSize());
@@ -302,7 +322,7 @@ int main(int argc, char *argv[])
darcyPr->SetDiagonalBlock(0, invM);
darcyPr->SetDiagonalBlock(1, invS);
// 12. Solve the linear system with MINRES.
// 13. Solve the linear system with MINRES.
// Check the norm of the unpreconditioned residual.
int maxIter(pa ? 1000 : 500);
double rtol(1.e-6);
@@ -319,6 +339,7 @@ int main(int argc, char *argv[])
solver.SetPrintLevel(verbose);
trueX = 0.0;
solver.Mult(trueRhs, trueX);
if (device.IsEnabled()) { trueX.HostRead(); }
chrono.Stop();
if (verbose)
@@ -332,7 +353,7 @@ int main(int argc, char *argv[])
std::cout << "MINRES solver took " << chrono.RealTime() << "s. \n";
}
// 13. Extract the parallel grid function corresponding to the finite element
// 14. Extract the parallel grid function corresponding to the finite element
// approximation X. This is the local solution on each processor. Compute
// L2 error norms.
ParGridFunction *u(new ParGridFunction);
@@ -360,7 +381,7 @@ int main(int argc, char *argv[])
std::cout << "|| p_h - p_ex || / || p_ex || = " << err_p / norm_p << "\n";
}
// 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, u_name, p_name;
@@ -381,7 +402,7 @@ int main(int argc, char *argv[])
p->Save(p_ofs);
}
// 15. Save data in the VisIt format
// 16. Save data in the VisIt format
VisItDataCollection visit_dc("Example5-Parallel", pmesh);
visit_dc.RegisterField("velocity", u);
visit_dc.RegisterField("pressure", p);
@@ -390,7 +411,7 @@ int main(int argc, char *argv[])
DataCollection::PARALLEL_FORMAT);
visit_dc.Save();
// 16. Save data in the ParaView format
// 17. Save data in the ParaView format
ParaViewDataCollection paraview_dc("Example5P", pmesh);
paraview_dc.SetPrefixPath("ParaView");
paraview_dc.SetLevelsOfDetail(order);
@@ -402,7 +423,7 @@ int main(int argc, char *argv[])
paraview_dc.RegisterField("pressure",p);
paraview_dc.Save();
// 17. Optionally output a BP (binary pack) file using ADIOS2. This can be
// 18. Optionally output a BP (binary pack) file using ADIOS2. This can be
// visualized with the ParaView VTX reader.
#ifdef MFEM_USE_ADIOS2
if (adios2)
@@ -422,7 +443,7 @@ int main(int argc, char *argv[])
}
#endif
// 18. Send the solution by socket to a GLVis server.
// 19. Send the solution by socket to a GLVis server.
if (visualization)
{
char vishost[] = "localhost";
@@ -442,7 +463,7 @@ int main(int argc, char *argv[])
<< endl;
}
// 19. Free the used memory.
// 20. Free the used memory.
delete fform;
delete gform;
delete u;
+1 -1
View File
@@ -20,7 +20,7 @@
// ex6 -pa -d occa-cuda
// ex6 -pa -d raja-omp
// ex6 -pa -d ceed-cpu
// * ex6 -pa -d ceed-cuda
// * ex6 -pa -d ceed-cuda
// ex6 -pa -d ceed-cuda:/gpu/cuda/shared
//
// Description: This is a version of Example 1 with a simple adaptive mesh
+1 -1
View File
@@ -20,7 +20,7 @@
// mpirun -np 4 ex6p -pa -d occa-cuda
// mpirun -np 4 ex6p -pa -d raja-omp
// mpirun -np 4 ex6p -pa -d ceed-cpu
// * mpirun -np 4 ex6p -pa -d ceed-cuda
// * mpirun -np 4 ex6p -pa -d ceed-cuda
// mpirun -np 4 ex6p -pa -d ceed-cuda:/gpu/cuda/shared
//
// Description: This is a version of Example 1 with a simple adaptive mesh
+18 -9
View File
@@ -20,8 +20,11 @@
// Device sample runs:
// ex9 -pa
// ex9 -ea
// ex9 -fa
// ex9 -pa -m ../data/periodic-cube.mesh
// ex9 -pa -m ../data/periodic-cube.mesh -d cuda
// ex9 -ea -m ../data/periodic-cube.mesh -d cuda
// ex9 -fa -m ../data/periodic-cube.mesh -d cuda
//
// Description: This example code solves the time-dependent advection equation
// du/dt + v.grad(u) = 0, where v is a given fluid velocity, and
@@ -144,6 +147,7 @@ int main(int argc, char *argv[])
int order = 3;
bool pa = false;
bool ea = false;
bool fa = false;
const char *device_config = "cpu";
int ode_solver_type = 4;
double t_final = 10.0;
@@ -170,6 +174,8 @@ int main(int argc, char *argv[])
"--no-partial-assembly", "Enable Partial Assembly.");
args.AddOption(&ea, "-ea", "--element-assembly", "-no-ea",
"--no-element-assembly", "Enable Element Assembly.");
args.AddOption(&fa, "-fa", "--full-assembly", "-no-fa",
"--no-full-assembly", "Enable Full Assembly.");
args.AddOption(&device_config, "-d", "--device",
"Device configuration string, see Device::Configure().");
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
@@ -278,6 +284,11 @@ int main(int argc, char *argv[])
m.SetAssemblyLevel(AssemblyLevel::ELEMENT);
k.SetAssemblyLevel(AssemblyLevel::ELEMENT);
}
else if (fa)
{
m.SetAssemblyLevel(AssemblyLevel::FULL);
k.SetAssemblyLevel(AssemblyLevel::FULL);
}
m.AddDomainIntegrator(new MassIntegrator);
k.AddDomainIntegrator(new ConvectionIntegrator(velocity, -1.0));
k.AddInteriorFaceIntegrator(
@@ -437,21 +448,19 @@ int main(int argc, char *argv[])
FE_Evolution::FE_Evolution(BilinearForm &_M, BilinearForm &_K, const Vector &_b)
: TimeDependentOperator(_M.Height()), M(_M), K(_K), b(_b), z(_M.Height())
{
bool pa = M.GetAssemblyLevel() == AssemblyLevel::PARTIAL;
bool ea = M.GetAssemblyLevel() == AssemblyLevel::ELEMENT;
Array<int> ess_tdof_list;
if (pa || ea)
if (M.GetAssemblyLevel() == AssemblyLevel::LEGACYFULL)
{
M_prec = new DSmoother(M.SpMat());
M_solver.SetOperator(M.SpMat());
dg_solver = new DG_Solver(M.SpMat(), K.SpMat(), *M.FESpace());
}
else
{
M_prec = new OperatorJacobiSmoother(M, ess_tdof_list);
M_solver.SetOperator(M);
dg_solver = NULL;
}
else
{
M_prec = new DSmoother(M.SpMat());
dg_solver = new DG_Solver(M.SpMat(), K.SpMat(), *M.FESpace());
M_solver.SetOperator(M.SpMat());
}
M_solver.SetPreconditioner(*M_prec);
M_solver.iterative_mode = false;
M_solver.SetRelTol(1e-9);
+25 -15
View File
@@ -16,12 +16,16 @@
// mpirun -np 4 ex9p -m ../data/disc-nurbs.mesh -p 2 -rp 1 -dt 0.005 -tf 9
// mpirun -np 4 ex9p -m ../data/periodic-square.mesh -p 3 -rp 2 -dt 0.0025 -tf 9 -vs 20
// mpirun -np 4 ex9p -m ../data/periodic-cube.mesh -p 0 -o 2 -rp 1 -dt 0.01 -tf 8
// mpirun -np 3 ex9p -m ../data/amr-hex.mesh -p 1 -rs 1 -rp 0 -dt 0.005 -tf 0.5
//
// Device sample runs:
// mpirun -np 4 ex9p -pa
// mpirun -np 4 ex9p -ea
// mpirun -np 4 ex9p -fa
// mpirun -np 4 ex9p -pa -m ../data/periodic-cube.mesh
// mpirun -np 4 ex9p -pa -m ../data/periodic-cube.mesh -d cuda
// mpirun -np 4 ex9p -ea -m ../data/periodic-cube.mesh -d cuda
// mpirun -np 4 ex9p -fa -m ../data/periodic-cube.mesh -d cuda
//
// Description: This example code solves the time-dependent advection equation
// du/dt + v.grad(u) = 0, where v is a given fluid velocity, and
@@ -163,6 +167,7 @@ int main(int argc, char *argv[])
int order = 3;
bool pa = false;
bool ea = false;
bool fa = false;
const char *device_config = "cpu";
int ode_solver_type = 4;
double t_final = 10.0;
@@ -192,6 +197,8 @@ int main(int argc, char *argv[])
"--no-partial-assembly", "Enable Partial Assembly.");
args.AddOption(&ea, "-ea", "--element-assembly", "-no-ea",
"--no-element-assembly", "Enable Element Assembly.");
args.AddOption(&fa, "-fa", "--full-assembly", "-no-fa",
"--no-full-assembly", "Enable Full Assembly.");
args.AddOption(&device_config, "-d", "--device",
"Device configuration string, see Device::Configure().");
args.AddOption(&ode_solver_type, "-s", "--ode-solver",
@@ -328,6 +335,12 @@ int main(int argc, char *argv[])
m->SetAssemblyLevel(AssemblyLevel::ELEMENT);
k->SetAssemblyLevel(AssemblyLevel::ELEMENT);
}
else if (fa)
{
m->SetAssemblyLevel(AssemblyLevel::FULL);
k->SetAssemblyLevel(AssemblyLevel::FULL);
}
m->AddDomainIntegrator(new MassIntegrator);
k->AddDomainIntegrator(new ConvectionIntegrator(velocity, -1.0));
k->AddInteriorFaceIntegrator(
@@ -564,29 +577,21 @@ FE_Evolution::FE_Evolution(ParBilinearForm &_M, ParBilinearForm &_K,
M_solver(_M.ParFESpace()->GetComm()),
z(_M.Height())
{
bool pa = _M.GetAssemblyLevel()==AssemblyLevel::PARTIAL;
bool ea = _M.GetAssemblyLevel()==AssemblyLevel::ELEMENT;
if (pa || ea)
{
M.Reset(&_M, false);
K.Reset(&_K, false);
}
else
if (_M.GetAssemblyLevel()==AssemblyLevel::LEGACYFULL)
{
M.Reset(_M.ParallelAssemble(), true);
K.Reset(_K.ParallelAssemble(), true);
}
else
{
M.Reset(&_M, false);
K.Reset(&_K, false);
}
M_solver.SetOperator(*M);
Array<int> ess_tdof_list;
if (pa || ea)
{
M_prec = new OperatorJacobiSmoother(_M, ess_tdof_list);
dg_solver = NULL;
}
else
if (_M.GetAssemblyLevel()==AssemblyLevel::LEGACYFULL)
{
HypreParMatrix &M_mat = *M.As<HypreParMatrix>();
HypreParMatrix &K_mat = *K.As<HypreParMatrix>();
@@ -595,6 +600,11 @@ FE_Evolution::FE_Evolution(ParBilinearForm &_M, ParBilinearForm &_K,
dg_solver = new DG_Solver(M_mat, K_mat, *_M.FESpace());
}
else
{
M_prec = new OperatorJacobiSmoother(_M, ess_tdof_list);
dg_solver = NULL;
}
M_solver.SetPreconditioner(*M_prec);
M_solver.iterative_mode = false;
+5
View File
@@ -114,6 +114,11 @@ ex11p-test-strumpack: ex11p
@$(call mfem-test,$<, $(RUN_MPI), STRUMPACK example,--strumpack)
test-par-YES: ex11p-test-strumpack
endif
ifeq ($(MFEM_USE_SUPERLU),YES)
ex11p-test-superlu: ex11p
@$(call mfem-test,$<, $(RUN_MPI), SuperLU_DIST example,--superlu)
test-par-YES: ex11p-test-superlu
endif
# Testing: "test" target and mfem-test* variables are defined in config/test.mk
+23 -4
View File
@@ -34,6 +34,15 @@ if (MFEM_USE_MPI)
)
endif()
if (MFEM_USE_SLEPC)
list(APPEND PETSC_EXAMPLES_SRCS
ex11p.cpp
)
list(APPEND PETSC_RC_FILES
rc_ex11p_lobpcg rc_ex11p_gd
)
endif()
# Include the source directory where mfem.hpp and mfem-performance.hpp are.
include_directories(BEFORE ${PROJECT_BINARY_DIR})
@@ -78,12 +87,22 @@ set(EX9_E_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts
set(EX9_ES_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_expl --no-step)
set(EX9_IS_ARGS -m ../../data/periodic-hexagon.mesh --usepetsc --petscopts rc_ex9p_impl --implicit -tf 0.5)
set(EX10_ARGS -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p -tf 30 -s 3 -rs 2 -dt 3)
if (MFEM_USE_SLEPC)
set(EX11_ARGS_SINV -m ../../data/star.mesh --useslepc)
set(EX11_ARGS_LOBPCG -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg)
set(EX11_ARGS_GD -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_gd)
endif()
# Add the tests: one test per command-line-variable.
foreach(TEST_OPTIONS_VAR
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX3_ARGS EX4_ARGS EX4_HYB_ARGS
EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS EX5_FSPL_ARGS EX6_ARGS EX6_NONOVL_ARGS
EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS EX10_ARGS)
set(TEST_OPTIONS_VARS
EX1_ARGS_W EX1_ARGS_P EX2_ARGS EX3_ARGS EX4_ARGS EX4_HYB_ARGS
EX5_BDDC_LB_ARGS EX5_BDDC_GB_ARGS EX5_FSPL_ARGS EX6_ARGS EX6_NONOVL_ARGS
EX9_E_ARGS EX9_ES_ARGS EX9_IS_ARGS EX10_ARGS)
if (MFEM_USE_SLEPC)
list(APPEND TEST_OPTIONS_VARS EX11_ARGS_SINV EX11_ARGS_LOBPCG EX11_ARGS_GD)
endif()
foreach(TEST_OPTIONS_VAR ${TEST_OPTIONS_VARS})
string(REGEX REPLACE "^(.+)_ARGS" "\\1" TEST_NAME_UC ${TEST_OPTIONS_VAR})
string(REGEX REPLACE "^([^_]+)" "\\1P" TEST_NAME_UC ${TEST_NAME_UC})
string(TOLOWER ${TEST_NAME_UC} TEST_NAME_FULL)
+440
View File
@@ -0,0 +1,440 @@
// MFEM Example 11 - Parallel Version
// PETSc Modification
//
// Compile with: make ex11p
//
// Sample runs: mpirun -np 4 ex11p -m ../../data/star.mesh
// mpirun -np 4 ex11p -m ../../data/star.mesh --slepcopts rc_ex11p_lobpcg
// mpirun -np 4 ex11p -m ../../data/star.mesh --slepcopts rc_ex11p_gd
//
// Description: This example code demonstrates the use of MFEM to solve the
// eigenvalue problem -Delta u = lambda u with homogeneous
// Dirichlet boundary conditions.
//
// We compute a number of the lowest eigenmodes by discretizing
// the Laplacian and Mass operators using a FE space of the
// specified order, or an isoparametric/isogeometric space if
// order < 1 (quadratic for quadratic curvilinear mesh, NURBS for
// NURBS mesh, etc.)
//
// The example demonstrates the use of the SLEPc eigensolver as an
// alternative to the LOBPCG eigenvalue solver. The shift and
// invert spectral transformation is used to help the convergence
// to the smaller eigenvalues. Alternative solver parameters can
// be passed in a file with "-slepcopts".
//
// Reusing a single GLVis visualization window for multiple
// eigenfunctions is also illustrated.
//
// We recommend viewing Example 1 before viewing this example.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
#ifndef MFEM_USE_SLEPC
#error This examples requires that MFEM is build with MFEM_USE_SLEPC=YES
#endif
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/star.mesh";
int ser_ref_levels = 2;
int par_ref_levels = 1;
int order = 1;
int nev = 5;
int seed = 75;
bool slu_solver = false;
bool sp_solver = false;
bool visualization = 1;
bool use_slepc = true;
const char *slepcrc_file = "";
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
"Number of times to refine the mesh uniformly in serial.");
args.AddOption(&par_ref_levels, "-rp", "--refine-parallel",
"Number of times to refine the mesh uniformly in parallel.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree) or -1 for"
" isoparametric space.");
args.AddOption(&nev, "-n", "--num-eigs",
"Number of desired eigenmodes.");
args.AddOption(&seed, "-s", "--seed",
"Random seed used to initialize LOBPCG.");
#ifdef MFEM_USE_SUPERLU
args.AddOption(&slu_solver, "-slu", "--superlu", "-no-slu",
"--no-superlu", "Use the SuperLU Solver.");
#endif
#ifdef MFEM_USE_STRUMPACK
args.AddOption(&sp_solver, "-sp", "--strumpack", "-no-sp",
"--no-strumpack", "Use the STRUMPACK Solver.");
#endif
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&use_slepc, "-useslepc","--useslepc","-no-slepc",
"--no-slepc","Use or not SLEPc to solve the eigenvalue problem");
args.AddOption(&slepcrc_file, "-slepcopts", "--slepcopts",
"SlepcOptions file to use.");
args.Parse();
if (slu_solver && sp_solver)
{
if (myid == 0)
cout << "WARNING: Both SuperLU and STRUMPACK have been selected,"
<< " please choose either one." << endl
<< " Defaulting to SuperLU." << endl;
sp_solver = false;
}
// The command line options are also passed to the STRUMPACK
// solver. So do not exit if some options are not recognized.
if (!sp_solver)
{
if (!args.Good())
{
if (myid == 0)
{
args.PrintUsage(cout);
}
MPI_Finalize();
return 1;
}
}
if (myid == 0)
{
args.PrintOptions(cout);
}
// 2b. We initialize SLEPc. This internally initializes PETSc as well.
MFEMInitializeSlepc(NULL,NULL,slepcrc_file,NULL);
// 3. 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. In
// this example we do 'ref_levels' of uniform refinement (2 by default, or
// specified on the command line with -rs).
for (int lev = 0; lev < ser_ref_levels; lev++)
{
mesh->UniformRefinement();
}
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
// this mesh further in parallel to increase the resolution (1 time by
// default, or specified on the command line with -rp). Once the parallel
// mesh is defined, the serial mesh can be deleted.
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
for (int lev = 0; lev < par_ref_levels; lev++)
{
pmesh->UniformRefinement();
}
// 6. 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;
if (order > 0)
{
fec = new H1_FECollection(order, dim);
}
else if (pmesh->GetNodes())
{
fec = pmesh->GetNodes()->OwnFEC();
}
else
{
fec = new H1_FECollection(order = 1, dim);
}
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
HYPRE_Int size = fespace->GlobalTrueVSize();
if (myid == 0)
{
cout << "Number of unknowns: " << size << endl;
}
// 7. Set up the parallel bilinear forms a(.,.) and m(.,.) on the finite
// element space. The first corresponds to the Laplacian operator -Delta,
// while the second is a simple mass matrix needed on the right hand side
// of the generalized eigenvalue problem below. The boundary conditions
// are implemented by elimination with special values on the diagonal to
// shift the Dirichlet eigenvalues out of the computational range. After
// serial and parallel assembly we extract the corresponding parallel
// matrices A and M.
ConstantCoefficient one(1.0);
Array<int> ess_bdr;
if (pmesh->bdr_attributes.Size())
{
ess_bdr.SetSize(pmesh->bdr_attributes.Max());
ess_bdr = 1;
}
ParBilinearForm *a = new ParBilinearForm(fespace);
a->AddDomainIntegrator(new DiffusionIntegrator(one));
if (pmesh->bdr_attributes.Size() == 0)
{
// Add a mass term if the mesh has no boundary, e.g. periodic mesh or
// closed surface.
a->AddDomainIntegrator(new MassIntegrator(one));
}
a->Assemble();
a->EliminateEssentialBCDiag(ess_bdr, 1.0);
a->Finalize();
ParBilinearForm *m = new ParBilinearForm(fespace);
m->AddDomainIntegrator(new MassIntegrator(one));
m->Assemble();
// shift the eigenvalue corresponding to eliminated dofs to a large value
m->EliminateEssentialBCDiag(ess_bdr, numeric_limits<double>::min());
m->Finalize();
PetscParMatrix *pA = NULL, *pM = NULL;
HypreParMatrix *A = NULL, *M = NULL;
Operator::Type tid =
!use_slepc ? Operator::Hypre_ParCSR : Operator::PETSC_MATAIJ;
OperatorHandle Ah(tid), Mh(tid);
a->ParallelAssemble(Ah);
if (!use_slepc) { Ah.Get(A); }
else { Ah.Get(pA); }
Ah.SetOperatorOwner(false);
m->ParallelAssemble(Mh);
if (!use_slepc) {Mh.Get(M); }
else {Mh.Get(pM); }
Mh.SetOperatorOwner(false);
#if defined(MFEM_USE_SUPERLU) || defined(MFEM_USE_STRUMPACK)
Operator * Arow = NULL;
#ifdef MFEM_USE_SUPERLU
if (slu_solver)
{
Arow = new SuperLURowLocMatrix(*A);
}
#endif
#ifdef MFEM_USE_STRUMPACK
if (sp_solver)
{
Arow = new STRUMPACKRowLocMatrix(*A);
}
#endif
#endif
delete a;
delete m;
// 8. Define and configure the LOBPCG eigensolver and the BoomerAMG
// 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 (!use_slepc)
{
if (!slu_solver && !sp_solver)
{
HypreBoomerAMG * amg = new HypreBoomerAMG(*A);
amg->SetPrintLevel(0);
precond = amg;
}
else
{
#ifdef MFEM_USE_SUPERLU
if (slu_solver)
{
SuperLUSolver * superlu = new SuperLUSolver(MPI_COMM_WORLD);
superlu->SetPrintStatistics(false);
superlu->SetSymmetricPattern(true);
superlu->SetColumnPermutation(superlu::PARMETIS);
superlu->SetOperator(*Arow);
precond = superlu;
}
#endif
#ifdef MFEM_USE_STRUMPACK
if (sp_solver)
{
STRUMPACKSolver * strumpack = new STRUMPACKSolver(argc, argv, MPI_COMM_WORLD);
strumpack->SetPrintFactorStatistics(true);
strumpack->SetPrintSolveStatistics(false);
strumpack->SetKrylovSolver(strumpack::KrylovSolver::DIRECT);
strumpack->SetReorderingStrategy(strumpack::ReorderingStrategy::METIS);
strumpack->DisableMatching();
strumpack->SetOperator(*Arow);
strumpack->SetFromCommandLine();
precond = strumpack;
}
#endif
}
}
HypreLOBPCG * lobpcg = NULL;
SlepcEigenSolver * slepc = NULL;
if (!use_slepc)
{
lobpcg = new HypreLOBPCG(MPI_COMM_WORLD);
lobpcg->SetNumModes(nev);
lobpcg->SetRandomSeed(seed);
lobpcg->SetPreconditioner(*precond);
lobpcg->SetMaxIter(200);
lobpcg->SetTol(1e-8);
lobpcg->SetPrecondUsageMode(1);
lobpcg->SetPrintLevel(1);
lobpcg->SetMassMatrix(*M);
lobpcg->SetOperator(*A);
}
else
{
slepc = new SlepcEigenSolver(MPI_COMM_WORLD);
slepc->SetNumModes(nev);
slepc->SetWhichEigenpairs(SlepcEigenSolver::TARGET_REAL);
slepc->SetTarget(0.0);
slepc->SetSpectralTransformation(SlepcEigenSolver::SHIFT_INVERT);
slepc->SetOperators(*pA,*pM);
}
// 9. Compute the eigenmodes and extract the array of eigenvalues. Define a
// parallel grid function to represent each of the eigenmodes returned by
// the solver.
Array<double> eigenvalues;
if (!use_slepc)
{
lobpcg->Solve();
lobpcg->GetEigenvalues(eigenvalues);
}
else
{
slepc->Solve();
eigenvalues.SetSize(nev);
for (int i=0; i<nev; i++)
{
slepc->GetEigenvalue(i,eigenvalues[i]);
}
}
Vector temp(fespace->GetTrueVSize());
ParGridFunction x(fespace);
// 10. Save the refined mesh and the modes in parallel. This output can be
// viewed later using GLVis: "glvis -np <np> -m mesh -g mode".
{
ostringstream mesh_name, mode_name;
mesh_name << "mesh." << setfill('0') << setw(6) << myid;
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(8);
pmesh->Print(mesh_ofs);
for (int i=0; i<nev; i++)
{
// convert eigenvector from HypreParVector to ParGridFunction
if (!use_slepc)
{
x = lobpcg->GetEigenvector(i);
}
else
{
slepc->GetEigenvector(i,temp);
x.Distribute(temp);
}
mode_name << "mode_" << setfill('0') << setw(2) << i << "."
<< setfill('0') << setw(6) << myid;
ofstream mode_ofs(mode_name.str().c_str());
mode_ofs.precision(8);
x.Save(mode_ofs);
mode_name.str("");
}
}
// 11. Send the solution by socket to a GLVis server.
if (visualization)
{
char vishost[] = "localhost";
int visport = 19916;
socketstream mode_sock(vishost, visport);
mode_sock.precision(8);
for (int i=0; i<nev; i++)
{
if ( myid == 0 )
{
cout << "Eigenmode " << i+1 << '/' << nev
<< ", Lambda = " << eigenvalues[i] << endl;
}
// convert eigenvector from HypreParVector to ParGridFunction
if (!use_slepc)
{
x = lobpcg->GetEigenvector(i);
}
else
{
slepc->GetEigenvector(i,temp);
x.Distribute(temp);
}
mode_sock << "parallel " << num_procs << " " << myid << "\n"
<< "solution\n" << *pmesh << x << flush
<< "window_title 'Eigenmode " << i+1 << '/' << nev
<< ", Lambda = " << eigenvalues[i] << "'" << endl;
char c;
if (myid == 0)
{
cout << "press (q)uit or (c)ontinue --> " << flush;
cin >> c;
}
MPI_Bcast(&c, 1, MPI_CHAR, 0, MPI_COMM_WORLD);
if (c != 'c')
{
break;
}
}
mode_sock.close();
}
// 12. Free the used memory.
if (!use_slepc)
{
delete lobpcg;
}
else
{
delete slepc;
}
delete precond;
delete M;
delete A;
#if defined(MFEM_USE_SUPERLU) || defined(MFEM_USE_STRUMPACK)
delete Arow;
#endif
delete fespace;
if (order > 0)
{
delete fec;
}
delete pmesh;
// We finalize SLEPc
MFEMFinalizeSlepc();
MPI_Finalize();
return 0;
}
+12
View File
@@ -23,6 +23,9 @@ MFEM_LIB_FILE = mfem_is_not_built
SEQ_EXAMPLES =
PAR_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex9p ex10p
ifeq ($(MFEM_USE_SLEPC),YES)
PAR_EXAMPLES += ex11p
endif
ifeq ($(MFEM_USE_MPI),NO)
EXAMPLES = $(SEQ_EXAMPLES)
else
@@ -87,6 +90,9 @@ EX10_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p
EX10_MF_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_mf -tf 6 -s 3 -rs 0 -dt 3
EX10_MFOP_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_mfop -tf 6 -s 3 -rs 0 -dt 3
EX10_JFNK_ARGS := -m ../../data/beam-quad.mesh --usepetsc --petscopts rc_ex10p_jfnk --jfnk -tf 6 -s 3 -rs 0 -dt 3
EX11_ARGS_SINV := -m ../../data/star.mesh --useslepc
EX11_ARGS_LOBPCG := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_lobpcg
EX11_ARGS_GD := -m ../../data/star.mesh --useslepc --slepcopts rc_ex11p_gd
ex1p-test-par: ex1p
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX1_ARGS_W))
@@ -114,6 +120,12 @@ ex10p-test-par: ex10p
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX10_MF_ARGS))
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX10_MFOP_ARGS))
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX10_JFNK_ARGS))
ifeq ($(MFEM_USE_SLEPC),YES)
ex11p-test-par: ex11p
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_SINV))
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_LOBPCG))
@$(call mfem-test,$<, $(RUN_MPI), $(TESTNAME),$(EX11_ARGS_GD))
endif
# Testing: "test" target and mfem-test* variables are defined in config/test.mk
+6
View File
@@ -0,0 +1,6 @@
# Options for the eigenvalue solver
-eps_view
-eps_converged_reason
-eps_type gd
# Options for the spectral transform
-st_type precond
+11
View File
@@ -0,0 +1,11 @@
# Options for the eigenvalue solver
-eps_monitor
-eps_converged_reason
-eps_view_values
-eps_type lobpcg
-eps_gen_hermitian
-eps_smallest_real
-eps_lobpcg_blocksize 5
# Options for the spectral transform
-st_type precond
-st_pc_type gamg
+43 -14
View File
@@ -76,7 +76,7 @@ BilinearForm::BilinearForm(FiniteElementSpace * f)
precompute_sparsity = 0;
diag_policy = DIAG_KEEP;
assembly = AssemblyLevel::FULL;
assembly = AssemblyLevel::LEGACYFULL;
batch = 1;
ext = NULL;
}
@@ -94,7 +94,7 @@ BilinearForm::BilinearForm (FiniteElementSpace * f, BilinearForm * bf, int ps)
precompute_sparsity = ps;
diag_policy = DIAG_KEEP;
assembly = AssemblyLevel::FULL;
assembly = AssemblyLevel::LEGACYFULL;
batch = 1;
ext = NULL;
@@ -121,9 +121,10 @@ void BilinearForm::SetAssemblyLevel(AssemblyLevel assembly_level)
assembly = assembly_level;
switch (assembly)
{
case AssemblyLevel::LEGACYFULL:
break;
case AssemblyLevel::FULL:
// ext = new FABilinearFormExtension(this);
// Use the original BilinearForm implementation for now
ext = new FABilinearFormExtension(this);
break;
case AssemblyLevel::ELEMENT:
ext = new EABilinearFormExtension(this);
@@ -143,7 +144,7 @@ void BilinearForm::SetAssemblyLevel(AssemblyLevel assembly_level)
void BilinearForm::EnableStaticCondensation()
{
delete static_cond;
if (assembly != AssemblyLevel::FULL)
if (assembly != AssemblyLevel::LEGACYFULL)
{
static_cond = NULL;
MFEM_WARNING("Static condensation not supported for this assembly level");
@@ -168,7 +169,7 @@ void BilinearForm::EnableHybridization(FiniteElementSpace *constr_space,
const Array<int> &ess_tdof_list)
{
delete hybridization;
if (assembly != AssemblyLevel::FULL)
if (assembly != AssemblyLevel::LEGACYFULL)
{
delete constr_integ;
hybridization = NULL;
@@ -223,7 +224,7 @@ MatrixInverse * BilinearForm::Inverse() const
void BilinearForm::Finalize (int skip_zeros)
{
if (assembly == AssemblyLevel::FULL)
if (assembly == AssemblyLevel::LEGACYFULL)
{
if (!static_cond) { mat->Finalize(skip_zeros); }
if (mat_e) { mat_e->Finalize(skip_zeros); }
@@ -626,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());
@@ -639,8 +667,7 @@ void BilinearForm::AssembleDiagonal(Vector &diag) const
}
else
{
MFEM_ABORT("Not implemented. Maybe assemble your bilinear form into a "
"matrix and use SparseMatrix::GetDiag?");
mat->GetDiag(diag);
}
}
@@ -1083,7 +1110,7 @@ MixedBilinearForm::MixedBilinearForm (FiniteElementSpace *tr_fes,
mat = NULL;
mat_e = NULL;
extern_bfs = 0;
assembly = AssemblyLevel::FULL;
assembly = AssemblyLevel::LEGACYFULL;
ext = NULL;
}
@@ -1108,7 +1135,7 @@ MixedBilinearForm::MixedBilinearForm (FiniteElementSpace *tr_fes,
bbfi_marker = mbf->bbfi_marker;
btfbfi_marker = mbf->btfbfi_marker;
assembly = AssemblyLevel::FULL;
assembly = AssemblyLevel::LEGACYFULL;
ext = NULL;
}
@@ -1121,6 +1148,8 @@ void MixedBilinearForm::SetAssemblyLevel(AssemblyLevel assembly_level)
assembly = assembly_level;
switch (assembly)
{
case AssemblyLevel::LEGACYFULL:
break;
case AssemblyLevel::FULL:
// ext = new FAMixedBilinearFormExtension(this);
// Use the original BilinearForm implementation for now
@@ -1191,7 +1220,7 @@ void MixedBilinearForm::AddMultTranspose(const Vector & x, Vector & y,
MatrixInverse * MixedBilinearForm::Inverse() const
{
if (assembly != AssemblyLevel::FULL)
if (assembly != AssemblyLevel::LEGACYFULL)
{
MFEM_WARNING("MixedBilinearForm::Inverse not possible with this assembly level!");
return NULL;
@@ -1204,7 +1233,7 @@ MatrixInverse * MixedBilinearForm::Inverse() const
void MixedBilinearForm::Finalize (int skip_zeros)
{
if (assembly == AssemblyLevel::FULL)
if (assembly == AssemblyLevel::LEGACYFULL)
{
mat -> Finalize (skip_zeros);
}
@@ -1481,7 +1510,7 @@ void MixedBilinearForm::AssembleDiagonal_ADAt(const Vector &D,
void MixedBilinearForm::ConformingAssemble()
{
if (assembly != AssemblyLevel::FULL)
if (assembly != AssemblyLevel::LEGACYFULL)
{
MFEM_WARNING("Conforming assemble not supported for this assembly level!");
return;
+6 -3
View File
@@ -29,8 +29,11 @@ namespace mfem
form classes derived from Operator. */
enum class AssemblyLevel
{
/// Fully assembled form, i.e. a global sparse matrix in MFEM, Hypre or PETSC
/// format.
/// Legacy fully assembled form, i.e. a global sparse matrix in MFEM, Hypre
/// or PETSC format. This assembly is ALWAYS performed on the host.
LEGACYFULL = 0,
/// Fully assembled form, i.e. a global sparse matrix in MFEM format. This
/// assembly is compatible with device execution.
FULL,
/// Form assembled at element level, which computes and stores dense element
/// matrices.
@@ -119,7 +122,7 @@ protected:
static_cond = NULL; hybridization = NULL;
precompute_sparsity = 0;
diag_policy = DIAG_KEEP;
assembly = AssemblyLevel::FULL;
assembly = AssemblyLevel::LEGACYFULL;
batch = 1;
ext = NULL;
}
+200 -36
View File
@@ -15,6 +15,7 @@
#include "../general/forall.hpp"
#include "bilinearform.hpp"
#include "libceed/ceed.hpp"
#include "pgridfunc.hpp"
namespace mfem
{
@@ -95,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)
@@ -115,7 +119,7 @@ void PABilinearFormExtension::AssembleDiagonal(Vector &y) const
Array<BilinearFormIntegrator*> &integrators = *a->GetDBFI();
const int iSz = integrators.Size();
if (elem_restrict)
if (elem_restrict && !DeviceCanUseCeed())
{
localY = 0.0;
for (int i = 0; i < iSz; ++i)
@@ -292,7 +296,8 @@ void PABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
// Data and methods for element-assembled bilinear forms
EABilinearFormExtension::EABilinearFormExtension(BilinearForm *form)
: PABilinearFormExtension(form)
: PABilinearFormExtension(form),
factorize_face_terms(form->FESpace()->IsDGSpace())
{
}
@@ -318,6 +323,9 @@ void EABilinearFormExtension::Assemble()
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)
@@ -347,6 +355,17 @@ void EABilinearFormExtension::Assemble()
{
bdrFaceIntegrators[i]->AssembleEABoundaryFaces(*a->FESpace(),ea_data_bdr);
}
if (factorize_face_terms && int_face_restrict_lex)
{
auto restFint = dynamic_cast<const L2FaceRestriction&>(*int_face_restrict_lex);
restFint.AddFaceMatricesToElementMatrices(ea_data_int, ea_data);
}
if (factorize_face_terms && bdr_face_restrict_lex)
{
auto restFbdr = dynamic_cast<const L2FaceRestriction&>(*bdr_face_restrict_lex);
restFbdr.AddFaceMatricesToElementMatrices(ea_data_bdr, ea_data);
}
}
void EABilinearFormExtension::Mult(const Vector &x, Vector &y) const
@@ -399,24 +418,27 @@ void EABilinearFormExtension::Mult(const Vector &x, Vector &y) const
const int NDOFS = faceDofs;
auto X = Reshape(faceIntX.Read(), NDOFS, 2, nf_int);
auto Y = Reshape(faceIntY.ReadWrite(), NDOFS, 2, nf_int);
auto A_int = Reshape(ea_data_int.Read(), NDOFS, NDOFS, 2, nf_int);
MFEM_FORALL(glob_j, nf_int*NDOFS,
if (!factorize_face_terms)
{
const int f = glob_j/NDOFS;
const int j = glob_j%NDOFS;
double res = 0.0;
for (int i = 0; i < NDOFS; i++)
auto A_int = Reshape(ea_data_int.Read(), NDOFS, NDOFS, 2, nf_int);
MFEM_FORALL(glob_j, nf_int*NDOFS,
{
res += A_int(i, j, 0, f)*X(i, 0, f);
}
Y(j, 0, f) += res;
res = 0.0;
for (int i = 0; i < NDOFS; i++)
{
res += A_int(i, j, 1, f)*X(i, 1, f);
}
Y(j, 1, f) += res;
});
const int f = glob_j/NDOFS;
const int j = glob_j%NDOFS;
double res = 0.0;
for (int i = 0; i < NDOFS; i++)
{
res += A_int(i, j, 0, f)*X(i, 0, f);
}
Y(j, 0, f) += res;
res = 0.0;
for (int i = 0; i < NDOFS; i++)
{
res += A_int(i, j, 1, f)*X(i, 1, f);
}
Y(j, 1, f) += res;
});
}
auto A_ext = Reshape(ea_data_ext.Read(), NDOFS, NDOFS, 2, nf_int);
MFEM_FORALL(glob_j, nf_int*NDOFS,
{
@@ -443,7 +465,7 @@ void EABilinearFormExtension::Mult(const Vector &x, Vector &y) const
// Treatment of boundary faces
Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
const int bFISz = bdrFaceIntegrators.Size();
if (bdr_face_restrict_lex && bFISz>0)
if (!factorize_face_terms && bdr_face_restrict_lex && bFISz>0)
{
// Apply the Boundary Face Restriction
bdr_face_restrict_lex->Mult(x, faceBdrX);
@@ -522,24 +544,27 @@ void EABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
const int NDOFS = faceDofs;
auto X = Reshape(faceIntX.Read(), NDOFS, 2, nf_int);
auto Y = Reshape(faceIntY.ReadWrite(), NDOFS, 2, nf_int);
auto A_int = Reshape(ea_data_int.Read(), NDOFS, NDOFS, 2, nf_int);
MFEM_FORALL(glob_j, nf_int*NDOFS,
if (!factorize_face_terms)
{
const int f = glob_j/NDOFS;
const int j = glob_j%NDOFS;
double res = 0.0;
for (int i = 0; i < NDOFS; i++)
auto A_int = Reshape(ea_data_int.Read(), NDOFS, NDOFS, 2, nf_int);
MFEM_FORALL(glob_j, nf_int*NDOFS,
{
res += A_int(j, i, 0, f)*X(i, 0, f);
}
Y(j, 0, f) += res;
res = 0.0;
for (int i = 0; i < NDOFS; i++)
{
res += A_int(j, i, 1, f)*X(i, 1, f);
}
Y(j, 1, f) += res;
});
const int f = glob_j/NDOFS;
const int j = glob_j%NDOFS;
double res = 0.0;
for (int i = 0; i < NDOFS; i++)
{
res += A_int(j, i, 0, f)*X(i, 0, f);
}
Y(j, 0, f) += res;
res = 0.0;
for (int i = 0; i < NDOFS; i++)
{
res += A_int(j, i, 1, f)*X(i, 1, f);
}
Y(j, 1, f) += res;
});
}
auto A_ext = Reshape(ea_data_ext.Read(), NDOFS, NDOFS, 2, nf_int);
MFEM_FORALL(glob_j, nf_int*NDOFS,
{
@@ -566,7 +591,7 @@ void EABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
// Treatment of boundary faces
Array<BilinearFormIntegrator*> &bdrFaceIntegrators = *a->GetBFBFI();
const int bFISz = bdrFaceIntegrators.Size();
if (bdr_face_restrict_lex && bFISz>0)
if (!factorize_face_terms && bdr_face_restrict_lex && bFISz>0)
{
// Apply the Boundary Face Restriction
bdr_face_restrict_lex->Mult(x, faceBdrX);
@@ -595,6 +620,139 @@ void EABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
}
}
// Data and methods for fully-assembled bilinear forms
FABilinearFormExtension::FABilinearFormExtension(BilinearForm *form)
: EABilinearFormExtension(form),
mat(form->FESpace()->GetVSize(),form->FESpace()->GetVSize(),0),
face_mat(form->FESpace()->GetVSize(),0,0),
use_face_mat(false)
{
#ifdef MFEM_USE_MPI
if ( ParFiniteElementSpace* pfes =
dynamic_cast<ParFiniteElementSpace*>(form->FESpace()) )
{
if (pfes->IsDGSpace())
{
use_face_mat = true;
pfes->ExchangeFaceNbrData();
face_mat.SetWidth(pfes->GetFaceNbrVSize());
}
}
#endif
}
void FABilinearFormExtension::Assemble()
{
EABilinearFormExtension::Assemble();
FiniteElementSpace &fes = *a->FESpace();
if (fes.IsDGSpace())
{
const L2ElementRestriction *restE =
static_cast<const L2ElementRestriction*>(elem_restrict);
const L2FaceRestriction *restF =
static_cast<const L2FaceRestriction*>(int_face_restrict_lex);
// 1. Fill I
// 1.1 Increment with restE
restE->FillI(mat);
// 1.2 Increment with restF
if (restF) { restF->FillI(mat, face_mat); }
// 1.3 Sum the non-zeros in I
auto h_I = mat.HostReadWriteI();
int cpt = 0;
const int vd = fes.GetVDim();
const int ndofs = ne*elemDofs*vd;
for (int i = 0; i < ndofs; i++)
{
const int nnz = h_I[i];
h_I[i] = cpt;
cpt += nnz;
}
const int nnz = cpt;
h_I[ndofs] = nnz;
mat.GetMemoryJ().New(nnz, mat.GetMemoryJ().GetMemoryType());
mat.GetMemoryData().New(nnz, mat.GetMemoryData().GetMemoryType());
if (use_face_mat && restF)
{
auto h_I_face = face_mat.HostReadWriteI();
int cpt = 0;
for (int i = 0; i < ndofs; i++)
{
const int nnz = h_I_face[i];
h_I_face[i] = cpt;
cpt += nnz;
}
const int nnz_face = cpt;
h_I_face[ndofs] = nnz_face;
face_mat.GetMemoryJ().New(nnz_face,
face_mat.GetMemoryJ().GetMemoryType());
face_mat.GetMemoryData().New(nnz_face,
face_mat.GetMemoryData().GetMemoryType());
}
// 2. Fill J and Data
// 2.1 Fill J and Data with Elem ea_data
restE->FillJAndData(ea_data, mat);
// 2.2 Fill J and Data with Face ea_data_ext
if (restF) { restF->FillJAndData(ea_data_ext, mat, face_mat); }
// 2.3 Shift indirections in I back to original
auto I = mat.HostReadWriteI();
for (int i = ndofs; i > 0; i--)
{
I[i] = I[i-1];
}
I[0] = 0;
if (use_face_mat && restF)
{
auto I_face = face_mat.HostReadWriteI();
for (int i = ndofs; i > 0; i--)
{
I_face[i] = I_face[i-1];
}
I_face[0] = 0;
}
}
else // continuous Galerkin case
{
const ElementRestriction &rest =
static_cast<const ElementRestriction&>(*elem_restrict);
rest.FillSparseMatrix(ea_data, mat);
}
}
void FABilinearFormExtension::Mult(const Vector &x, Vector &y) const
{
mat.Mult(x, y);
#ifdef MFEM_USE_MPI
if (const ParFiniteElementSpace *pfes =
dynamic_cast<const ParFiniteElementSpace*>(testFes))
{
ParGridFunction x_gf;
x_gf.MakeRef(const_cast<ParFiniteElementSpace*>(pfes),
const_cast<Vector&>(x),0);
x_gf.ExchangeFaceNbrData();
Vector &shared_x = x_gf.FaceNbrData();
if (shared_x.Size()) { face_mat.AddMult(shared_x, y); }
}
#endif
}
void FABilinearFormExtension::MultTranspose(const Vector &x, Vector &y) const
{
mat.MultTranspose(x, y);
#ifdef MFEM_USE_MPI
if (const ParFiniteElementSpace *pfes =
dynamic_cast<const ParFiniteElementSpace*>(testFes))
{
ParGridFunction x_gf;
x_gf.MakeRef(const_cast<ParFiniteElementSpace*>(pfes),
const_cast<Vector&>(x),0);
x_gf.ExchangeFaceNbrData();
Vector &shared_x = x_gf.FaceNbrData();
if (shared_x.Size()) { face_mat.AddMultTranspose(shared_x, y); }
}
#endif
}
MixedBilinearFormExtension::MixedBilinearFormExtension(MixedBilinearForm *form)
: Operator(form->Height(), form->Width()), a(form)
{
@@ -642,6 +800,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()
+19 -21
View File
@@ -62,27 +62,6 @@ public:
virtual void Update() = 0;
};
/** @brief Data and methods for fully-assembled bilinear forms.
Not yet implemented! Use the BilinearForm Class instead. */
class FABilinearFormExtension : public BilinearFormExtension
{
public:
FABilinearFormExtension(BilinearForm *form)
: BilinearFormExtension(form) { }
/// TODO
void Assemble() {}
void FormSystemMatrix(const Array<int> &ess_tdof_list, OperatorHandle &A) {}
void FormLinearSystem(const Array<int> &ess_tdof_list,
Vector &x, Vector &b,
OperatorHandle &A, Vector &X, Vector &B,
int copy_interior = 0) {}
void Mult(const Vector &x, Vector &y) const {}
void MultTranspose(const Vector &x, Vector &y) const {}
void Update() {}
~FABilinearFormExtension() {}
};
/// Data and methods for partially-assembled bilinear forms
class PABilinearFormExtension : public BilinearFormExtension
{
@@ -119,10 +98,12 @@ class EABilinearFormExtension : public PABilinearFormExtension
protected:
int ne;
int elemDofs;
// The element matrices are stored row major
Vector ea_data;
int nf_int, nf_bdr;
int faceDofs;
Vector ea_data_int, ea_data_ext, ea_data_bdr;
bool factorize_face_terms;
public:
EABilinearFormExtension(BilinearForm *form);
@@ -132,6 +113,23 @@ public:
void MultTranspose(const Vector &x, Vector &y) const;
};
/// Data and methods for fully-assembled bilinear forms
class FABilinearFormExtension : public EABilinearFormExtension
{
private:
SparseMatrix mat;
/// face_mat handles parallelism for DG face terms.
SparseMatrix face_mat;
bool use_face_mat;
public:
FABilinearFormExtension(BilinearForm *form);
void Assemble();
void Mult(const Vector &x, Vector &y) const;
void MultTranspose(const Vector &x, Vector &y) const;
};
/// Data and methods for matrix-free bilinear forms NOT YET IMPLEMENTED.
class MFBilinearFormExtension : public BilinearFormExtension
{
+40 -23
View File
@@ -926,11 +926,14 @@ void BoundaryMassIntegrator::AssembleFaceMatrix(
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
IntegrationPoint eip;
Trans.Loc1.Transform(ip, eip);
// Set the integration point in the face and the neighboring element
Trans.SetAllIntPoints(&ip);
// Access the neighboring element's integration point
const IntegrationPoint &eip = Trans.GetElement1IntPoint();
el1.CalcShape(eip, shape);
Trans.SetIntPoint(&ip);
w = Trans.Weight() * ip.weight;
if (Q)
{
@@ -2571,15 +2574,16 @@ void DGTraceIntegrator::AssembleFaceMatrix(const FiniteElement &el1,
for (int p = 0; p < ir->GetNPoints(); p++)
{
const IntegrationPoint &ip = ir->IntPoint(p);
IntegrationPoint eip1, eip2;
Trans.Loc1.Transform(ip, eip1);
if (ndof2)
{
Trans.Loc2.Transform(ip, eip2);
}
el1.CalcShape(eip1, shape1);
Trans.SetIntPoint(&ip);
// Set the integration point in the face and the neighboring elements
Trans.SetAllIntPoints(&ip);
// Access the neighboring elements' integration points
// Note: eip2 will only contain valid data if Elem2 exists
const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
el1.CalcShape(eip1, shape1);
u->Eval(vu, *Trans.Elem1, eip1);
@@ -2727,10 +2731,15 @@ void DGDiffusionIntegrator::AssembleFaceMatrix(
for (int p = 0; p < ir->GetNPoints(); p++)
{
const IntegrationPoint &ip = ir->IntPoint(p);
IntegrationPoint eip1, eip2;
Trans.Loc1.Transform(ip, eip1);
Trans.SetIntPoint(&ip);
// Set the integration point in the face and the neighboring elements
Trans.SetAllIntPoints(&ip);
// Access the neighboring elements' integration points
// Note: eip2 will only contain valid data if Elem2 exists
const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
if (dim == 1)
{
nor(0) = 2*eip1.x - 1.0;
@@ -2787,7 +2796,6 @@ void DGDiffusionIntegrator::AssembleFaceMatrix(
if (ndof2)
{
Trans.Loc2.Transform(ip, eip2);
el2.CalcShape(eip2, shape2);
el2.CalcDShape(eip2, dshape2);
w = ip.weight/2/Trans.Elem2->Weight();
@@ -3005,9 +3013,14 @@ void DGElasticityIntegrator::AssembleFaceMatrix(
for (int pind = 0; pind < ir->GetNPoints(); ++pind)
{
const IntegrationPoint &ip = ir->IntPoint(pind);
IntegrationPoint eip1, eip2; // integration point in the reference space
Trans.Loc1.Transform(ip, eip1);
Trans.SetIntPoint(&ip);
// Set the integration point in the face and the neighboring elements
Trans.SetAllIntPoints(&ip);
// Access the neighboring elements' integration points
// Note: eip2 will only contain valid data if Elem2 exists
const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
el1.CalcShape(eip1, shape1);
el1.CalcDShape(eip1, dshape1);
@@ -3027,7 +3040,6 @@ void DGElasticityIntegrator::AssembleFaceMatrix(
double w, wLM;
if (ndofs2)
{
Trans.Loc2.Transform(ip, eip2);
el2.CalcShape(eip2, shape2);
el2.CalcDShape(eip2, dshape2);
CalcAdjugate(Trans.Elem2->Jacobian(), adjJ);
@@ -3165,17 +3177,22 @@ void TraceJumpIntegrator::AssembleFaceMatrix(
for (int p = 0; p < ir->GetNPoints(); p++)
{
const IntegrationPoint &ip = ir->IntPoint(p);
IntegrationPoint eip1, eip2;
// Set the integration point in the face and the neighboring elements
Trans.SetAllIntPoints(&ip);
// Access the neighboring elements' integration points
// Note: eip2 will only contain valid data if Elem2 exists
const IntegrationPoint &eip1 = Trans.GetElement1IntPoint();
const IntegrationPoint &eip2 = Trans.GetElement2IntPoint();
// Trace finite element shape function
Trans.SetIntPoint(&ip);
trial_face_fe.CalcShape(ip, face_shape);
// Side 1 finite element shape function
Trans.Loc1.Transform(ip, eip1);
test_fe1.CalcShape(eip1, shape1);
if (ndof2)
{
// Side 2 finite element shape function
Trans.Loc2.Transform(ip, eip2);
test_fe2.CalcShape(eip2, shape2);
}
w = ip.weight;
+45 -3
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
{
@@ -1685,6 +1692,22 @@ protected:
{
trial_fe.CalcPhysCurlShape(Trans, shape);
}
using BilinearFormIntegrator::AssemblePA;
virtual void AssemblePA(const FiniteElementSpace &trial_fes,
const FiniteElementSpace &test_fes);
virtual void AddMultPA(const Vector&, Vector&) const;
private:
// PA extension
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, dofs1D, dofs1Dtest,quad1D, testType, trialType, coeffDim;
};
/** Class for integrating the bilinear form a(u,v) := (Q u, curl v) in 3D and
@@ -1724,6 +1747,20 @@ protected:
{
test_fe.CalcPhysCurlShape(Trans, shape);
}
using BilinearFormIntegrator::AssemblePA;
virtual void AssemblePA(const FiniteElementSpace &trial_fes,
const FiniteElementSpace &test_fes);
virtual void AddMultPA(const Vector&, Vector&) const;
private:
// PA extension
Vector pa_data;
const DofToQuad *mapsO; ///< Not owned. DOF-to-quad map, open.
const DofToQuad *mapsC; ///< Not owned. DOF-to-quad map, closed.
const GeometricFactors *geom; ///< Not owned
int dim, ne, dofs1D, quad1D, testType, trialType, coeffDim;
};
/** Class for integrating the bilinear form a(u,v) := - (Q u, grad v) in either
@@ -1924,7 +1961,7 @@ public:
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe);
void SetupPA(const FiniteElementSpace &fes, const bool force = false);
void SetupPA(const FiniteElementSpace &fes);
};
/** Class for local mass matrix assembling a(u,v) := (Q u, v) */
@@ -2000,7 +2037,7 @@ public:
const FiniteElement &test_fe,
ElementTransformation &Trans);
void SetupPA(const FiniteElementSpace &fes, const bool force = false);
void SetupPA(const FiniteElementSpace &fes);
};
/** Mass integrator (u, v) restricted to the boundary of a domain */
@@ -2360,8 +2397,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); }
@@ -2382,6 +2422,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);
};
+6 -6
View File
@@ -32,7 +32,7 @@ static void EAConvectionAssemble1D(const int NE,
auto B = Reshape(b.Read(), Q1D, D1D);
auto G = Reshape(g.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, NE);
auto A = Reshape(eadata.Write(), D1D, D1D, NE);
auto A = Reshape(eadata.ReadWrite(), D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, 1,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -54,7 +54,7 @@ static void EAConvectionAssemble1D(const int NE,
{
val += r_Bj[k1] * D(k1, e) * r_Gi[k1];
}
A(i1, j1, e) = val;
A(i1, j1, e) += val;
}
}
});
@@ -76,7 +76,7 @@ static void EAConvectionAssemble2D(const int NE,
auto B = Reshape(b.Read(), Q1D, D1D);
auto G = Reshape(g.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, Q1D, 2, NE);
auto A = Reshape(eadata.Write(), D1D, D1D, D1D, D1D, NE);
auto A = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, 1,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -121,7 +121,7 @@ static void EAConvectionAssemble2D(const int NE,
* r_B[k1][j1]* r_B[k2][j2];
}
}
A(i1, i2, j1, j2, e) = val;
A(i1, i2, j1, j2, e) += val;
}
}
}
@@ -145,7 +145,7 @@ static void EAConvectionAssemble3D(const int NE,
auto B = Reshape(b.Read(), Q1D, D1D);
auto G = Reshape(g.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, 3, NE);
auto A = Reshape(eadata.Write(), D1D, D1D, D1D, D1D, D1D, D1D, NE);
auto A = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, D1D,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -191,7 +191,7 @@ static void EAConvectionAssemble3D(const int NE,
}
}
}
A(i1, i2, i3, j1, j2, j3, e) = val;
A(i1, i2, i3, j1, j2, j3, e) += val;
}
}
}
+14
View File
@@ -788,6 +788,20 @@ void ConvectionIntegrator::AssemblePA(const FiniteElementSpace &fes)
{
vel = cQ->GetVec();
}
else if (VectorQuadratureFunctionCoefficient* cQ =
dynamic_cast<VectorQuadratureFunctionCoefficient*>(Q))
{
const QuadratureFunction &qFun = cQ->GetQuadFunction();
MFEM_VERIFY(qFun.Size() == dim * nq * ne,
"Incompatible QuadratureFunction dimension \n");
MFEM_VERIFY(ir == &qFun.GetSpace()->GetElementIntRule(0),
"IntegrationRule used within integrator and in"
" QuadratureFunction appear to be different");
qFun.Read();
vel.MakeRef(const_cast<QuadratureFunction &>(qFun),0);
}
else
{
vel.SetSize(dim * nq * ne);
+27
View File
@@ -167,6 +167,19 @@ void DGTraceIntegrator::SetupPA(const FiniteElementSpace &fes, FaceType type)
r.SetSize(1);
r(0) = c_rho->constant;
}
else if (QuadratureFunctionCoefficient* c_rho =
dynamic_cast<QuadratureFunctionCoefficient*>(rho))
{
const QuadratureFunction &qFun = c_rho->GetQuadFunction();
MFEM_VERIFY(qFun.Size() == nq * nf,
"Incompatible QuadratureFunction dimension \n");
MFEM_VERIFY(ir == &qFun.GetSpace()->GetElementIntRule(0),
"IntegrationRule used within integrator and in"
" QuadratureFunction appear to be different");
qFun.Read();
r.MakeRef(const_cast<QuadratureFunction &>(qFun),0);
}
else
{
r.SetSize(nq * nf);
@@ -200,6 +213,20 @@ void DGTraceIntegrator::SetupPA(const FiniteElementSpace &fes, FaceType type)
{
vel = c_u->GetVec();
}
else if (VectorQuadratureFunctionCoefficient* c_u =
dynamic_cast<VectorQuadratureFunctionCoefficient*>(u))
{
// Assumed to be in lexicographical ordering
const QuadratureFunction &qFun = c_u->GetQuadFunction();
MFEM_VERIFY(qFun.Size() == dim * nq * nf,
"Incompatible QuadratureFunction dimension \n");
MFEM_VERIFY(ir == &qFun.GetSpace()->GetElementIntRule(0),
"IntegrationRule used within integrator and in"
" QuadratureFunction appear to be different");
qFun.Read();
vel.MakeRef(const_cast<QuadratureFunction &>(qFun),0);
}
else
{
vel.SetSize(dim * nq * nf);
+7 -7
View File
@@ -31,7 +31,7 @@ static void EADiffusionAssemble1D(const int NE,
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
auto G = Reshape(g.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, NE);
auto A = Reshape(eadata.Write(), D1D, D1D, NE);
auto A = Reshape(eadata.ReadWrite(), D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, 1,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -53,7 +53,7 @@ static void EADiffusionAssemble1D(const int NE,
{
val += r_Gj[k1] * D(k1, e) * r_Gi[k1];
}
A(i1, j1, e) = val;
A(i1, j1, e) += val;
}
}
});
@@ -75,7 +75,7 @@ static void EADiffusionAssemble2D(const int NE,
auto B = Reshape(b.Read(), Q1D, D1D);
auto G = Reshape(g.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, Q1D, 3, NE);
auto A = Reshape(eadata.Write(), D1D, D1D, D1D, D1D, NE);
auto A = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, 1,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -120,7 +120,7 @@ static void EADiffusionAssemble2D(const int NE,
+ gbi * D11 * gbj;
}
}
A(i1, i2, j1, j2, e) = val;
A(i1, i2, j1, j2, e) += val;
}
}
}
@@ -130,8 +130,8 @@ 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 int d1d = 0,
@@ -144,7 +144,7 @@ static void EADiffusionAssemble3D(const int NE,
auto B = Reshape(b.Read(), Q1D, D1D);
auto G = Reshape(g.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, 6, NE);
auto A = Reshape(eadata.Write(), D1D, D1D, D1D, D1D, D1D, D1D, NE);
auto A = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, D1D,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -208,7 +208,7 @@ static void EADiffusionAssemble3D(const int NE,
}
}
}
A(i1, i2, i3, j1, j2, j3, e) = val;
A(i1, i2, i3, j1, j2, j3, e) += val;
}
}
}
+354 -267
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
}
}
});
}
@@ -170,47 +174,53 @@ static void PADiffusionSetup3D(const int Q1D,
const Vector &c,
Vector &d)
{
const int NQ = Q1D*Q1D*Q1D;
const bool const_c = c.Size() == 1;
auto W = w.Read();
auto J = Reshape(j.Read(), NQ, 3, 3, NE);
auto C = const_c ? Reshape(c.Read(), 1, 1) : Reshape(c.Read(), NQ, NE);
auto D = Reshape(d.Write(), NQ, 6, NE);
MFEM_FORALL(e, NE,
const auto W = Reshape(w.Read(), Q1D,Q1D,Q1D);
const auto J = Reshape(j.Read(), Q1D,Q1D,Q1D,3,3,NE);
const auto C = const_c ? Reshape(c.Read(), 1,1,1,1) :
Reshape(c.Read(), Q1D,Q1D,Q1D,NE);
auto D = Reshape(d.Write(), Q1D,Q1D,Q1D, 6, NE);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
{
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 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 detJ = J11 * (J22 * J33 - J32 * J23) -
/* */ J21 * (J12 * J33 - J32 * J13) +
/* */ J31 * (J12 * J23 - J22 * J13);
const double coeff = const_c ? C(0,0) : C(q,e);
const double c_detJ = W[q] * coeff / detJ;
// 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);
// detJ J^{-1} J^{-T} = (1/detJ) adj(J) adj(J)^T
D(q,0,e) = c_detJ * (A11*A11 + A12*A12 + A13*A13); // 1,1
D(q,1,e) = c_detJ * (A11*A21 + A12*A22 + A13*A23); // 2,1
D(q,2,e) = c_detJ * (A11*A31 + A12*A32 + A13*A33); // 3,1
D(q,3,e) = c_detJ * (A21*A21 + A22*A22 + A23*A23); // 2,2
D(q,4,e) = c_detJ * (A21*A31 + A22*A32 + A23*A33); // 3,2
D(q,5,e) = c_detJ * (A31*A31 + A32*A32 + A33*A33); // 3,3
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
const double J11 = J(qx,qy,qz,0,0,e);
const double J21 = J(qx,qy,qz,1,0,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);
const double c_detJ = W(qx,qy,qz) * coeff / detJ;
// 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);
// detJ J^{-1} J^{-T} = (1/detJ) adj(J) adj(J)^T
D(qx,qy,qz,0,e) = c_detJ * (A11*A11 + A12*A12 + A13*A13); // 1,1
D(qx,qy,qz,1,e) = c_detJ * (A11*A21 + A12*A22 + A13*A23); // 2,1
D(qx,qy,qz,2,e) = c_detJ * (A11*A31 + A12*A32 + A13*A33); // 3,1
D(qx,qy,qz,3,e) = c_detJ * (A21*A21 + A22*A22 + A23*A23); // 2,2
D(qx,qy,qz,4,e) = c_detJ * (A21*A31 + A22*A32 + A23*A33); // 3,2
D(qx,qy,qz,5,e) = c_detJ * (A31*A31 + A32*A32 + A33*A33); // 3,3
}
}
}
});
}
@@ -253,8 +263,7 @@ static void PADiffusionSetup(const int dim,
}
}
void DiffusionIntegrator::SetupPA(const FiniteElementSpace &fes,
const bool force)
void DiffusionIntegrator::SetupPA(const FiniteElementSpace &fes)
{
// Assuming the same element type
fespace = &fes;
@@ -263,7 +272,7 @@ void DiffusionIntegrator::SetupPA(const FiniteElementSpace &fes,
const FiniteElement &el = *fes.GetFE(0);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el);
#ifdef MFEM_USE_CEED
if (DeviceCanUseCeed() && !force)
if (DeviceCanUseCeed())
{
if (ceedDataPtr) { delete ceedDataPtr; }
CeedData* ptr = new CeedData();
@@ -271,8 +280,6 @@ void DiffusionIntegrator::SetupPA(const FiniteElementSpace &fes,
InitCeedCoeff(Q, ptr);
return CeedPADiffusionAssemble(fes, *ir, *ptr);
}
#else
MFEM_CONTRACT_VAR(force);
#endif
const int dims = el.GetDim();
const int symmDims = (dims * (dims + 1)) / 2; // 1x1: 1, 2x2: 3, 3x3: 6
@@ -296,6 +303,19 @@ void DiffusionIntegrator::SetupPA(const FiniteElementSpace &fes,
coeff.SetSize(1);
coeff(0) = cQ->constant;
}
else if (QuadratureFunctionCoefficient* cQ =
dynamic_cast<QuadratureFunctionCoefficient*>(Q))
{
const QuadratureFunction &qFun = cQ->GetQuadFunction();
MFEM_VERIFY(qFun.Size() == ne*nq,
"Incompatible QuadratureFunction dimension \n");
MFEM_VERIFY(ir == &qFun.GetSpace()->GetElementIntRule(0),
"IntegrationRule used within integrator and in"
" QuadratureFunction appear to be different");
qFun.Read();
coeff.MakeRef(const_cast<QuadratureFunction &>(qFun),0);
}
else
{
coeff.SetSize(nq * ne);
@@ -736,9 +756,17 @@ static void PADiffusionAssembleDiagonal(const int dim,
void DiffusionIntegrator::AssembleDiagonalPA(Vector &diag)
{
if (pa_data.Size()==0) { SetupPA(*fespace, true); }
PADiffusionAssembleDiagonal(dim, dofs1D, quad1D, ne,
maps->B, maps->G, pa_data, diag);
#ifdef MFEM_USE_CEED
if (DeviceCanUseCeed())
{
CeedAssembleDiagonalPA(ceedDataPtr, diag);
}
else
#endif
{
PADiffusionAssembleDiagonal(dim, dofs1D, quad1D, ne,
maps->B, maps->G, pa_data, diag);
}
}
@@ -1307,7 +1335,33 @@ static void PADiffusionApply3D(const int NE,
});
}
// Shared memory PA Diffusion Apply 3D kernel
// Half of B and G are stored in shared to get B, Bt, G and Gt.
// Indices computation for SmemPADiffusionApply3D.
static MFEM_HOST_DEVICE inline int qi(const int q, const int d, const int Q)
{
return (q<=d) ? q : Q-1-q;
}
static MFEM_HOST_DEVICE inline int dj(const int q, const int d, const int D)
{
return (q<=d) ? d : D-1-d;
}
static MFEM_HOST_DEVICE inline int qk(const int q, const int d, const int Q)
{
return (q<=d) ? Q-1-q : q;
}
static MFEM_HOST_DEVICE inline int dl(const int q, const int d, const int D)
{
return (q<=d) ? D-1-d : d;
}
static MFEM_HOST_DEVICE inline double sign(const int q, const int d)
{
return (q<=d) ? -1.0 : 1.0;
}
template<int T_D1D = 0, int T_Q1D = 0>
static void SmemPADiffusionApply3D(const int NE,
const Array<double> &b_,
@@ -1320,28 +1374,27 @@ static void SmemPADiffusionApply3D(const int NE,
{
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
MFEM_VERIFY(D1D <= MD1, "");
MFEM_VERIFY(Q1D <= MQ1, "");
constexpr int M1Q = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int M1D = T_D1D ? T_D1D : MAX_D1D;
MFEM_VERIFY(D1D <= M1D, "");
MFEM_VERIFY(Q1D <= M1Q, "");
auto b = Reshape(b_.Read(), Q1D, D1D);
auto g = Reshape(g_.Read(), Q1D, D1D);
auto d = Reshape(d_.Read(), Q1D*Q1D*Q1D, 6, NE);
auto d = Reshape(d_.Read(), Q1D, Q1D, Q1D, 6, NE);
auto x = Reshape(x_.Read(), D1D, D1D, D1D, NE);
auto y = Reshape(y_.ReadWrite(), D1D, D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
MFEM_FORALL_3D(e, NE, Q1D, Q1D, 1,
{
const int tidz = MFEM_THREAD_ID(z);
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
constexpr int MQ1 = T_Q1D ? T_Q1D : MAX_Q1D;
constexpr int MD1 = T_D1D ? T_D1D : MAX_D1D;
constexpr int MDQ = MQ1 > MD1 ? MQ1 : MD1;
MFEM_SHARED double sBG[2][MQ1*MD1];
double (*B)[MD1] = (double (*)[MD1]) (sBG+0);
double (*G)[MD1] = (double (*)[MD1]) (sBG+1);
double (*Bt)[MQ1] = (double (*)[MQ1]) (sBG+0);
double (*Gt)[MQ1] = (double (*)[MQ1]) (sBG+1);
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
MFEM_SHARED double sBG[MQ1*MD1];
double (*B)[MD1] = (double (*)[MD1]) sBG;
double (*G)[MD1] = (double (*)[MD1]) sBG;
double (*Bt)[MQ1] = (double (*)[MQ1]) sBG;
double (*Gt)[MQ1] = (double (*)[MQ1]) sBG;
MFEM_SHARED double sm0[3][MDQ*MDQ*MDQ];
MFEM_SHARED double sm1[3][MDQ*MDQ*MDQ];
double (*X)[MD1][MD1] = (double (*)[MD1][MD1]) (sm0+2);
@@ -1359,108 +1412,127 @@ static void SmemPADiffusionApply3D(const int NE,
double (*QDD0)[MD1][MD1] = (double (*)[MD1][MD1]) (sm0+0);
double (*QDD1)[MD1][MD1] = (double (*)[MD1][MD1]) (sm0+1);
double (*QDD2)[MD1][MD1] = (double (*)[MD1][MD1]) (sm0+2);
MFEM_FOREACH_THREAD(dz,z,D1D)
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
MFEM_FOREACH_THREAD(dx,x,D1D)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; ++dz)
{
X[dz][dy][dx] = x(dx,dy,dz,e);
}
}
}
if (tidz == 0)
{
MFEM_FOREACH_THREAD(d,y,D1D)
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
MFEM_FOREACH_THREAD(q,x,Q1D)
{
B[q][d] = b(q,d);
G[q][d] = g(q,d);
}
const int i = qi(qx,dy,Q1D);
const int j = dj(qx,dy,D1D);
const int k = qk(qx,dy,Q1D);
const int l = dl(qx,dy,D1D);
B[i][j] = b(qx,dy);
G[k][l] = g(qx,dy) * sign(qx,dy);
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dz,z,D1D)
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
double u[D1D], v[D1D];
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; dz++) { u[dz] = v[dz] = 0.0; }
MFEM_UNROLL(MD1)
for (int dx = 0; dx < D1D; ++dx)
{
double u = 0.0;
double v = 0.0;
for (int dx = 0; dx < D1D; ++dx)
{
const double coords = X[dz][dy][dx];
u += coords * B[qx][dx];
v += coords * 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;
const int i = qi(qx,dx,Q1D);
const int j = dj(qx,dx,D1D);
const int k = qk(qx,dx,Q1D);
const int l = dl(qx,dx,D1D);
const double s = sign(qx,dx);
MFEM_UNROLL(MD1)
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];
const double coords = X[dz][dy][dx];
u[dz] += coords * B[i][j];
v[dz] += coords * G[k][l] * s;
}
QQQ0[qz][qy][qx] = u;
QQQ1[qz][qy][qx] = v;
QQQ2[qz][qy][qx] = w;
}
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; ++dz)
{
DDQ0[dz][dy][qx] = u[dz];
DDQ1[dz][dy][qx] = v[dz];
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(qz,z,Q1D)
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
double u[D1D], v[D1D], w[D1D];
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; dz++) { u[dz] = v[dz] = w[dz] = 0.0; }
MFEM_UNROLL(MD1)
for (int dy = 0; dy < D1D; ++dy)
{
const int q = qx + ((qy*Q1D) + (qz*Q1D*Q1D));
const double O11 = d(q,0,e);
const double O12 = d(q,1,e);
const double O13 = d(q,2,e);
const double O22 = d(q,3,e);
const double O23 = d(q,4,e);
const double O33 = d(q,5,e);
const double gX = QQQ0[qz][qy][qx];
const double gY = QQQ1[qz][qy][qx];
const double gZ = QQQ2[qz][qy][qx];
const int i = qi(qy,dy,Q1D);
const int j = dj(qy,dy,D1D);
const int k = qk(qy,dy,Q1D);
const int l = dl(qy,dy,D1D);
const double s = sign(qy,dy);
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; dz++)
{
u[dz] += DDQ1[dz][dy][qx] * B[i][j];
v[dz] += DDQ0[dz][dy][qx] * G[k][l] * s;
w[dz] += DDQ0[dz][dy][qx] * B[i][j];
}
}
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; dz++)
{
DQQ0[dz][qy][qx] = u[dz];
DQQ1[dz][qy][qx] = v[dz];
DQQ2[dz][qy][qx] = w[dz];
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
double u[Q1D], v[Q1D], w[Q1D];
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; qz++) { u[qz] = v[qz] = w[qz] = 0.0; }
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; ++dz)
{
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; qz++)
{
const int i = qi(qz,dz,Q1D);
const int j = dj(qz,dz,D1D);
const int k = qk(qz,dz,Q1D);
const int l = dl(qz,dz,D1D);
const double s = sign(qz,dz);
u[qz] += DQQ0[dz][qy][qx] * B[i][j];
v[qz] += DQQ1[dz][qy][qx] * B[i][j];
w[qz] += DQQ2[dz][qy][qx] * G[k][l] * s;
}
}
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; qz++)
{
const double O11 = d(qx,qy,qz,0,e);
const double O12 = d(qx,qy,qz,1,e);
const double O13 = d(qx,qy,qz,2,e);
const double O22 = d(qx,qy,qz,3,e);
const double O23 = d(qx,qy,qz,4,e);
const double O33 = d(qx,qy,qz,5,e);
const double gX = u[qz];
const double gY = v[qz];
const double gZ = w[qz];
QQQ0[qz][qy][qx] = (O11*gX) + (O12*gY) + (O13*gZ);
QQQ1[qz][qy][qx] = (O12*gX) + (O22*gY) + (O23*gZ);
QQQ2[qz][qy][qx] = (O13*gX) + (O23*gY) + (O33*gZ);
@@ -1468,78 +1540,112 @@ static void SmemPADiffusionApply3D(const int NE,
}
}
MFEM_SYNC_THREAD;
if (tidz == 0)
MFEM_FOREACH_THREAD(d,y,D1D)
{
MFEM_FOREACH_THREAD(d,y,D1D)
MFEM_FOREACH_THREAD(q,x,Q1D)
{
MFEM_FOREACH_THREAD(q,x,Q1D)
{
Bt[d][q] = b(q,d);
Gt[d][q] = g(q,d);
}
const int i = qi(q,d,Q1D);
const int j = dj(q,d,D1D);
const int k = qk(q,d,Q1D);
const int l = dl(q,d,D1D);
Bt[j][i] = b(q,d);
Gt[l][k] = g(q,d) * sign(q,d);
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(qz,z,Q1D)
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
MFEM_FOREACH_THREAD(dx,x,D1D)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
double u[Q1D], v[Q1D], w[Q1D];
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; ++qz) { u[qz] = v[qz] = w[qz] = 0.0; }
MFEM_UNROLL(MQ1)
for (int qx = 0; qx < Q1D; ++qx)
{
double u = 0.0;
double v = 0.0;
double w = 0.0;
for (int qx = 0; qx < Q1D; ++qx)
{
u += QQQ0[qz][qy][qx] * Gt[dx][qx];
v += QQQ1[qz][qy][qx] * Bt[dx][qx];
w += QQQ2[qz][qy][qx] * Bt[dx][qx];
}
QQD0[qz][qy][dx] = u;
QQD1[qz][qy][dx] = v;
QQD2[qz][qy][dx] = w;
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
{
double u = 0.0;
double v = 0.0;
double w = 0.0;
for (int qy = 0; qy < Q1D; ++qy)
{
u += QQD0[qz][qy][dx] * Bt[dy][qy];
v += QQD1[qz][qy][dx] * Gt[dy][qy];
w += QQD2[qz][qy][dx] * Bt[dy][qy];
}
QDD0[qz][dy][dx] = u;
QDD1[qz][dy][dx] = v;
QDD2[qz][dy][dx] = w;
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dz,z,D1D)
{
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
{
double u = 0.0;
double v = 0.0;
double w = 0.0;
const int i = qi(qx,dx,Q1D);
const int j = dj(qx,dx,D1D);
const int k = qk(qx,dx,Q1D);
const int l = dl(qx,dx,D1D);
const double s = sign(qx,dx);
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; ++qz)
{
u += QDD0[qz][dy][dx] * Bt[dz][qz];
v += QDD1[qz][dy][dx] * Bt[dz][qz];
w += QDD2[qz][dy][dx] * Gt[dz][qz];
u[qz] += QQQ0[qz][qy][qx] * Gt[l][k] * s;
v[qz] += QQQ1[qz][qy][qx] * Bt[j][i];
w[qz] += QQQ2[qz][qy][qx] * Bt[j][i];
}
y(dx,dy,dz,e) += (u + v + w);
}
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; ++qz)
{
QQD0[qz][qy][dx] = u[qz];
QQD1[qz][qy][dx] = v[qz];
QQD2[qz][qy][dx] = w[qz];
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
{
double u[Q1D], v[Q1D], w[Q1D];
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; ++qz) { u[qz] = v[qz] = w[qz] = 0.0; }
MFEM_UNROLL(MQ1)
for (int qy = 0; qy < Q1D; ++qy)
{
const int i = qi(qy,dy,Q1D);
const int j = dj(qy,dy,D1D);
const int k = qk(qy,dy,Q1D);
const int l = dl(qy,dy,D1D);
const double s = sign(qy,dy);
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; ++qz)
{
u[qz] += QQD0[qz][qy][dx] * Bt[j][i];
v[qz] += QQD1[qz][qy][dx] * Gt[l][k] * s;
w[qz] += QQD2[qz][qy][dx] * Bt[j][i];
}
}
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; ++qz)
{
QDD0[qz][dy][dx] = u[qz];
QDD1[qz][dy][dx] = v[qz];
QDD2[qz][dy][dx] = w[qz];
}
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(dy,y,D1D)
{
MFEM_FOREACH_THREAD(dx,x,D1D)
{
double u[D1D], v[D1D], w[D1D];
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; ++dz) { u[dz] = v[dz] = w[dz] = 0.0; }
MFEM_UNROLL(MQ1)
for (int qz = 0; qz < Q1D; ++qz)
{
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; ++dz)
{
const int i = qi(qz,dz,Q1D);
const int j = dj(qz,dz,D1D);
const int k = qk(qz,dz,Q1D);
const int l = dl(qz,dz,D1D);
const double s = sign(qz,dz);
u[dz] += QDD0[qz][dy][dx] * Bt[j][i];
v[dz] += QDD1[qz][dy][dx] * Bt[j][i];
w[dz] += QDD2[qz][dy][dx] * Gt[l][k] * s;
}
}
MFEM_UNROLL(MD1)
for (int dz = 0; dz < D1D; ++dz)
{
y(dx,dy,dz,e) += (u[dz] + v[dz] + w[dz]);
}
}
}
@@ -1574,9 +1680,11 @@ static void PADiffusionApply(const int dim,
MFEM_ABORT("OCCA PADiffusionApply unknown kernel!");
}
#endif // MFEM_USE_OCCA
const int ID = (D1D << 4 ) | Q1D;
if (dim == 2)
{
switch ((D1D << 4 ) | Q1D)
switch (ID)
{
case 0x22: return SmemPADiffusionApply2D<2,2,16>(NE,B,G,D,X,Y);
case 0x33: return SmemPADiffusionApply2D<3,3,16>(NE,B,G,D,X,Y);
@@ -1589,9 +1697,10 @@ static void PADiffusionApply(const int dim,
default: return PADiffusionApply2D(NE,B,G,Bt,Gt,D,X,Y,D1D,Q1D);
}
}
else if (dim == 3)
if (dim == 3)
{
switch ((D1D << 4 ) | Q1D)
switch (ID)
{
case 0x23: return SmemPADiffusionApply3D<2,3>(NE,B,G,D,X,Y);
case 0x34: return SmemPADiffusionApply3D<3,4>(NE,B,G,D,X,Y);
@@ -1614,29 +1723,7 @@ void DiffusionIntegrator::AddMultPA(const Vector &x, Vector &y) const
#ifdef MFEM_USE_CEED
if (DeviceCanUseCeed())
{
const CeedScalar *x_ptr;
CeedScalar *y_ptr;
CeedMemType mem;
CeedGetPreferredMemType(internal::ceed, &mem);
if ( Device::Allows(Backend::CUDA) && mem==CEED_MEM_DEVICE )
{
x_ptr = x.Read();
y_ptr = y.ReadWrite();
}
else
{
x_ptr = x.HostRead();
y_ptr = y.HostReadWrite();
mem = CEED_MEM_HOST;
}
CeedVectorSetArray(ceedDataPtr->u, mem, CEED_USE_POINTER,
const_cast<CeedScalar*>(x_ptr));
CeedVectorSetArray(ceedDataPtr->v, mem, CEED_USE_POINTER, y_ptr);
CeedOperatorApplyAdd(ceedDataPtr->oper, ceedDataPtr->u, ceedDataPtr->v,
CEED_REQUEST_IMMEDIATE);
CeedVectorSyncArray(ceedDataPtr->v, mem);
CeedAddMultPA(ceedDataPtr, x, y);
}
else
#endif
+1440 -57
View File
File diff suppressed because it is too large Load Diff
+11 -6
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,
@@ -114,6 +109,8 @@ void PAHdivMassApply2D(const int D1D,
Vector &_y)
{
constexpr static int VDIM = 2;
constexpr static int MAX_D1D = HDIV_MAX_D1D;
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
auto Bc = Reshape(_Bc.Read(), Q1D, D1D);
@@ -238,6 +235,7 @@ void PAHdivMassAssembleDiagonal2D(const int D1D,
Vector &_diag)
{
constexpr static int VDIM = 2;
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
auto Bc = Reshape(_Bc.Read(), Q1D, D1D);
@@ -614,6 +612,8 @@ static void PADivDivApply2D(const int D1D,
Vector &_y)
{
constexpr static int VDIM = 2;
constexpr static int MAX_D1D = HDIV_MAX_D1D;
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
auto Bot = Reshape(_Bot.Read(), D1D-1, Q1D);
@@ -977,6 +977,7 @@ static void PADivDivAssembleDiagonal2D(const int D1D,
Vector &_diag)
{
constexpr static int VDIM = 2;
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
auto Gc = Reshape(_Gc.Read(), Q1D, D1D);
@@ -1400,6 +1401,8 @@ static void PAHdivL2Apply2D(const int D1D,
Vector &_y)
{
constexpr static int VDIM = 2;
constexpr static int MAX_D1D = HDIV_MAX_D1D;
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
auto Gc = Reshape(_Gc.Read(), Q1D, D1D);
@@ -1666,6 +1669,8 @@ static void PAHdivL2ApplyTranspose2D(const int D1D,
Vector &_y)
{
constexpr static int VDIM = 2;
constexpr static int MAX_D1D = HDIV_MAX_D1D;
constexpr static int MAX_Q1D = HDIV_MAX_Q1D;
auto L2Bo = Reshape(_L2Bo.Read(), Q1D, L2D1D);
auto Gct = Reshape(_Gct.Read(), D1D, Q1D);
@@ -1724,7 +1729,7 @@ static void PAHdivL2ApplyTranspose2D(const int D1D,
for (int qy = 0; qy < Q1D; ++qy)
{
double aX[HDIV_MAX_D1D];
double aX[MAX_D1D];
int osc = 0;
for (int c = 0; c < VDIM; ++c) // loop over x, y components
+6 -6
View File
@@ -30,7 +30,7 @@ static void EAMassAssemble1D(const int NE,
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
auto B = Reshape(basis.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, NE);
auto M = Reshape(eadata.Write(), D1D, D1D, NE);
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, 1,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -52,7 +52,7 @@ static void EAMassAssemble1D(const int NE,
{
val += r_Bi[k1] * r_Bj[k1] * D(k1, e);
}
M(i1, j1, e) = val;
M(i1, j1, e) += val;
}
}
});
@@ -72,7 +72,7 @@ static void EAMassAssemble2D(const int NE,
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
auto B = Reshape(basis.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, Q1D, NE);
auto M = Reshape(eadata.Write(), D1D, D1D, D1D, D1D, NE);
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, 1,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -114,7 +114,7 @@ static void EAMassAssemble2D(const int NE,
* s_D[k1][k2];
}
}
M(i1, i2, j1, j2, e) = val;
M(i1, i2, j1, j2, e) += val;
}
}
}
@@ -136,7 +136,7 @@ static void EAMassAssemble3D(const int NE,
MFEM_VERIFY(Q1D <= MAX_Q1D, "");
auto B = Reshape(basis.Read(), Q1D, D1D);
auto D = Reshape(padata.Read(), Q1D, Q1D, Q1D, NE);
auto M = Reshape(eadata.Write(), D1D, D1D, D1D, D1D, D1D, D1D, NE);
auto M = Reshape(eadata.ReadWrite(), D1D, D1D, D1D, D1D, D1D, D1D, NE);
MFEM_FORALL_3D(e, NE, D1D, D1D, D1D,
{
const int D1D = T_D1D ? T_D1D : d1d;
@@ -189,7 +189,7 @@ static void EAMassAssemble3D(const int NE,
}
}
}
M(i1, i2, i3, j1, j2, j3, e) = val;
M(i1, i2, i3, j1, j2, j3, e) += val;
}
}
}
+74 -58
View File
@@ -23,7 +23,7 @@ namespace mfem
// PA Mass Assemble kernel
void MassIntegrator::SetupPA(const FiniteElementSpace &fes, const bool force)
void MassIntegrator::SetupPA(const FiniteElementSpace &fes)
{
// Assuming the same element type
fespace = &fes;
@@ -33,7 +33,7 @@ void MassIntegrator::SetupPA(const FiniteElementSpace &fes, const bool force)
ElementTransformation *T = mesh->GetElementTransformation(0);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el, *T);
#ifdef MFEM_USE_CEED
if (DeviceCanUseCeed() && !force)
if (DeviceCanUseCeed())
{
if (ceedDataPtr) { delete ceedDataPtr; }
CeedData* ptr = new CeedData();
@@ -62,6 +62,19 @@ void MassIntegrator::SetupPA(const FiniteElementSpace &fes, const bool force)
coeff.SetSize(1);
coeff(0) = cQ->constant;
}
else if (QuadratureFunctionCoefficient* cQ =
dynamic_cast<QuadratureFunctionCoefficient*>(Q))
{
const QuadratureFunction &qFun = cQ->GetQuadFunction();
MFEM_VERIFY(qFun.Size() == nq * ne,
"Incompatible QuadratureFunction dimension \n");
MFEM_VERIFY(ir == &qFun.GetSpace()->GetElementIntRule(0),
"IntegrationRule used within integrator and in"
" QuadratureFunction appear to be different");
qFun.Read();
coeff.MakeRef(const_cast<QuadratureFunction &>(qFun),0);
}
else
{
coeff.SetSize(nq * ne);
@@ -79,49 +92,64 @@ void MassIntegrator::SetupPA(const FiniteElementSpace &fes, const bool force)
if (dim==2)
{
const int NE = ne;
const int NQ = nq;
const int Q1D = quad1D;
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 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;
}
}
});
}
if (dim==3)
{
const int NE = ne;
const int NQ = nq;
const int Q1D = quad1D;
const bool const_c = coeff.Size() == 1;
auto W = ir->GetWeights().Read();
auto J = Reshape(geom->J.Read(), NQ,3,3,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 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);
MFEM_FORALL_3D(e, NE, Q1D, Q1D, Q1D,
{
for (int q = 0; q < NQ; ++q)
MFEM_FOREACH_THREAD(qx,x,Q1D)
{
const double J11 = J(q,0,0,e), J12 = J(q,0,1,e), J13 = J(q,0,2,e);
const double J21 = J(q,1,0,e), J22 = J(q,1,1,e), J23 = J(q,1,2,e);
const double J31 = J(q,2,0,e), J32 = J(q,2,1,e), J33 = J(q,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) : C(q,e);
v(q,e) = W[q] * coeff * detJ;
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
const double J11 = J(qx,qy,qz,0,0,e);
const double J21 = J(qx,qy,qz,1,0,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;
}
}
}
});
}
@@ -440,8 +468,16 @@ static void PAMassAssembleDiagonal(const int dim, const int D1D,
void MassIntegrator::AssembleDiagonalPA(Vector &diag)
{
if (pa_data.Size()==0) { SetupPA(*fespace, true); }
PAMassAssembleDiagonal(dim, dofs1D, quad1D, ne, maps->B, pa_data, diag);
#ifdef MFEM_USE_CEED
if (DeviceCanUseCeed())
{
CeedAssembleDiagonalPA(ceedDataPtr, diag);
}
else
#endif
{
PAMassAssembleDiagonal(dim, dofs1D, quad1D, ne, maps->B, pa_data, diag);
}
}
@@ -639,6 +675,7 @@ static void SmemPAMassApply2D(const int NE,
const int d1d = 0,
const int q1d = 0)
{
MFEM_CONTRACT_VAR(bt_);
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
constexpr int NBZ = T_NBZ ? T_NBZ : 1;
@@ -902,6 +939,7 @@ static void SmemPAMassApply3D(const int NE,
const int d1d = 0,
const int q1d = 0)
{
MFEM_CONTRACT_VAR(bt_);
const int D1D = T_D1D ? T_D1D : d1d;
const int Q1D = T_Q1D ? T_Q1D : q1d;
constexpr int M1Q = T_Q1D ? T_Q1D : MAX_Q1D;
@@ -1192,29 +1230,7 @@ void MassIntegrator::AddMultPA(const Vector &x, Vector &y) const
#ifdef MFEM_USE_CEED
if (DeviceCanUseCeed())
{
const CeedScalar *x_ptr;
CeedScalar *y_ptr;
CeedMemType mem;
CeedGetPreferredMemType(internal::ceed, &mem);
if ( Device::Allows(Backend::CUDA) && mem==CEED_MEM_DEVICE )
{
x_ptr = x.Read();
y_ptr = y.ReadWrite();
}
else
{
x_ptr = x.HostRead();
y_ptr = y.HostReadWrite();
mem = CEED_MEM_HOST;
}
CeedVectorSetArray(ceedDataPtr->u, mem, CEED_USE_POINTER,
const_cast<CeedScalar*>(x_ptr));
CeedVectorSetArray(ceedDataPtr->v, mem, CEED_USE_POINTER, y_ptr);
CeedOperatorApplyAdd(ceedDataPtr->oper, ceedDataPtr->u, ceedDataPtr->v,
CEED_REQUEST_IMMEDIATE);
CeedVectorSyncArray(ceedDataPtr->v, mem);
CeedAddMultPA(ceedDataPtr, x, y);
}
else
#endif
+1 -1
View File
@@ -25,7 +25,7 @@ void TransposeIntegrator::AssembleEA(const FiniteElementSpace &fes,
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.Write(), dofs, dofs, ne);
auto AT = Reshape(ea_data.ReadWrite(), dofs, dofs, ne);
MFEM_FORALL(e, ne,
{
for (int i = 0; i < dofs; i++)
+728 -39
View File
@@ -9,12 +9,14 @@
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "../general/forall.hpp"
#include "bilininteg.hpp"
namespace mfem
{
void PAHcurlSetup2D(const int Q1D,
const int coeffDim,
const int NE,
const Array<double> &w,
const Vector &j,
@@ -22,6 +24,7 @@ void PAHcurlSetup2D(const int Q1D,
Vector &op);
void PAHcurlSetup3D(const int Q1D,
const int coeffDim,
const int NE,
const Array<double> &w,
const Vector &j,
@@ -31,6 +34,7 @@ void PAHcurlSetup3D(const int Q1D,
void PAHcurlMassAssembleDiagonal2D(const int D1D,
const int Q1D,
const int NE,
const bool symmetric,
const Array<double> &_Bo,
const Array<double> &_Bc,
const Vector &_op,
@@ -39,6 +43,7 @@ void PAHcurlMassAssembleDiagonal2D(const int D1D,
void PAHcurlMassAssembleDiagonal3D(const int D1D,
const int Q1D,
const int NE,
const bool symmetric,
const Array<double> &_Bo,
const Array<double> &_Bc,
const Vector &_op,
@@ -47,6 +52,7 @@ void PAHcurlMassAssembleDiagonal3D(const int D1D,
void PAHcurlMassApply2D(const int D1D,
const int Q1D,
const int NE,
const bool symmetric,
const Array<double> &_Bo,
const Array<double> &_Bc,
const Array<double> &_Bot,
@@ -58,6 +64,7 @@ void PAHcurlMassApply2D(const int D1D,
void PAHcurlMassApply3D(const int D1D,
const int Q1D,
const int NE,
const bool symmetric,
const Array<double> &_Bo,
const Array<double> &_Bc,
const Array<double> &_Bot,
@@ -140,20 +147,573 @@ void PAHdivMassApply3D(const int D1D,
const Vector &_x,
Vector &_y);
void PAHcurlL2Setup(const int NQ,
const int coeffDim,
const int NE,
const Array<double> &w,
Vector &_coeff,
Vector &op);
// PA H(curl) x H(div) mass assemble 3D kernel, with factor
// dF^{-1} C dF for a vector or matrix coefficient C.
// If transpose, use dF^T C dF^{-T} for H(div) x H(curl).
void PAHcurlHdivSetup3D(const int Q1D,
const int coeffDim,
const int NE,
const bool transpose,
const Array<double> &_w,
const Vector &j,
Vector &_coeff,
Vector &op)
{
const int NQ = Q1D*Q1D*Q1D;
const bool symmetric = (coeffDim != 9);
auto W = _w.Read();
auto J = Reshape(j.Read(), NQ, 3, 3, NE);
auto coeff = Reshape(_coeff.Read(), coeffDim, NQ, NE);
auto y = Reshape(op.Write(), 9, NQ, NE);
const int i11 = 0;
const int i12 = transpose ? 3 : 1;
const int i13 = transpose ? 6 : 2;
const int i21 = transpose ? 1 : 3;
const int i22 = 4;
const int i23 = transpose ? 7 : 5;
const int i31 = transpose ? 2 : 6;
const int i32 = transpose ? 5 : 7;
const int i33 = 8;
MFEM_FORALL(e, NE,
{
for (int q = 0; q < NQ; ++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 J13 = J(q,0,2,e);
const double J23 = J(q,1,2,e);
const double J33 = J(q,2,2,e);
const double detJ = J11 * (J22 * J33 - J32 * J23) -
/* */ J21 * (J12 * J33 - J32 * J13) +
/* */ J31 * (J12 * J23 - J22 * J13);
const double w_detJ = W[q] / detJ;
// 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);
if (coeffDim == 6 || coeffDim == 9) // Matrix coefficient version
{
// First compute entries of R = MJ
const double M11 = (!symmetric) ? coeff(i11, q, e) : coeff(0, q, e);
const double M12 = (!symmetric) ? coeff(i12, q, e) : coeff(1, q, e);
const double M13 = (!symmetric) ? coeff(i13, q, e) : coeff(2, q, e);
const double M21 = (!symmetric) ? coeff(i21, q, e) : M12;
const double M22 = (!symmetric) ? coeff(i22, q, e) : coeff(3, q, e);
const double M23 = (!symmetric) ? coeff(i23, q, e) : coeff(4, q, e);
const double M31 = (!symmetric) ? coeff(i31, q, e) : M13;
const double M32 = (!symmetric) ? coeff(i32, q, e) : M23;
const double M33 = (!symmetric) ? coeff(i33, q, e) : coeff(5, q, e);
const double R11 = M11*J11 + M12*J12 + M13*J13;
const double R12 = M11*J21 + M12*J22 + M13*J23;
const double R13 = M11*J31 + M12*J32 + M13*J33;
const double R21 = M21*J11 + M22*J12 + M23*J13;
const double R22 = M21*J21 + M22*J22 + M23*J23;
const double R23 = M21*J31 + M22*J32 + M23*J33;
const double R31 = M31*J11 + M32*J12 + M33*J13;
const double R32 = M31*J21 + M32*J22 + M33*J23;
const double R33 = M31*J31 + M32*J32 + M33*J33;
// Now set y to detJ J^{-1} R = adj(J) R
y(i11,q,e) = w_detJ * (A11*R11 + A12*R21 + A13*R31); // 1,1
y(i12,q,e) = w_detJ * (A11*R12 + A12*R22 + A13*R32); // 1,2
y(i13,q,e) = w_detJ * (A11*R13 + A12*R23 + A13*R33); // 1,3
y(i21,q,e) = w_detJ * (A21*R11 + A22*R21 + A23*R31); // 2,1
y(i22,q,e) = w_detJ * (A21*R12 + A22*R22 + A23*R32); // 2,2
y(i23,q,e) = w_detJ * (A21*R13 + A22*R23 + A23*R33); // 2,3
y(i31,q,e) = w_detJ * (A31*R11 + A32*R21 + A33*R31); // 3,1
y(i32,q,e) = w_detJ * (A31*R12 + A32*R22 + A33*R32); // 3,2
y(i33,q,e) = w_detJ * (A31*R13 + A32*R23 + A33*R33); // 3,3
}
else if (coeffDim == 3) // Vector coefficient version
{
const double D1 = coeff(0, q, e);
const double D2 = coeff(1, q, e);
const double D3 = coeff(2, q, e);
// detJ J^{-1} DJ = adj(J) DJ
y(i11,q,e) = w_detJ * (D1*A11*J11 + D2*A12*J21 + D3*A13*J31); // 1,1
y(i12,q,e) = w_detJ * (D1*A11*J12 + D2*A12*J22 + D3*A13*J32); // 1,2
y(i13,q,e) = w_detJ * (D1*A11*J13 + D2*A12*J23 + D3*A13*J33); // 1,3
y(i21,q,e) = w_detJ * (D1*A21*J11 + D2*A22*J21 + D3*A23*J31); // 2,1
y(i22,q,e) = w_detJ * (D1*A21*J12 + D2*A22*J22 + D3*A23*J32); // 2,2
y(i23,q,e) = w_detJ * (D1*A21*J13 + D2*A22*J23 + D3*A23*J33); // 2,3
y(i31,q,e) = w_detJ * (D1*A31*J11 + D2*A32*J21 + D3*A33*J31); // 3,1
y(i32,q,e) = w_detJ * (D1*A31*J12 + D2*A32*J22 + D3*A33*J32); // 3,2
y(i33,q,e) = w_detJ * (D1*A31*J13 + D2*A32*J23 + D3*A33*J33); // 3,3
}
}
});
}
// PA H(curl) x H(div) mass assemble 2D kernel, with factor
// dF^{-1} C dF for a vector or matrix coefficient C.
// If transpose, use dF^T C dF^{-T} for H(div) x H(curl).
void PAHcurlHdivSetup2D(const int Q1D,
const int coeffDim,
const int NE,
const bool transpose,
const Array<double> &_w,
const Vector &j,
Vector &_coeff,
Vector &op)
{
const int NQ = Q1D*Q1D;
const bool symmetric = (coeffDim != 4);
auto W = _w.Read();
auto J = Reshape(j.Read(), NQ, 2, 2, NE);
auto coeff = Reshape(_coeff.Read(), coeffDim, NQ, NE);
auto y = Reshape(op.Write(), 4, NQ, NE);
const int i11 = 0;
const int i12 = transpose ? 2 : 1;
const int i21 = transpose ? 1 : 2;
const int i22 = 3;
MFEM_FORALL(e, NE,
{
for (int q = 0; q < NQ; ++q)
{
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 w_detJ = W[q] / (J11*J22) - (J21*J12);
if (coeffDim == 3 || coeffDim == 4) // Matrix coefficient version
{
// First compute entries of R = MJ
const double M11 = coeff(i11, q, e);
const double M12 = (!symmetric) ? coeff(i12, q, e) : coeff(1, q, e);
const double M21 = (!symmetric) ? coeff(i21, q, e) : M12;
const double M22 = (!symmetric) ? coeff(i22, q, e) : coeff(2, q, e);
const double R11 = M11*J11 + M12*J21;
const double R12 = M11*J12 + M12*J22;
const double R21 = M21*J11 + M22*J21;
const double R22 = M21*J12 + M22*J22;
// Now set y to J^{-1} R
y(i11,q,e) = w_detJ * ( J22*R11 - J12*R21); // 1,1
y(i12,q,e) = w_detJ * ( J22*R12 - J12*R22); // 1,2
y(i21,q,e) = w_detJ * (-J21*R11 + J11*R21); // 2,1
y(i22,q,e) = w_detJ * (-J21*R12 + J11*R22); // 2,2
}
else if (coeffDim == 2) // Vector coefficient version
{
const double D1 = coeff(0, q, e);
const double D2 = coeff(1, q, e);
const double R11 = D1*J11;
const double R12 = D1*J12;
const double R21 = D2*J21;
const double R22 = D2*J22;
y(i11,q,e) = w_detJ * ( J22*R11 - J12*R21); // 1,1
y(i12,q,e) = w_detJ * ( J22*R12 - J12*R22); // 1,2
y(i21,q,e) = w_detJ * (-J21*R11 + J11*R21); // 2,1
y(i22,q,e) = w_detJ * (-J21*R12 + J11*R22); // 2,2
}
}
});
}
// Mass operator for H(curl) and H(div) functions, using Piola transformations
// u = dF^{-T} \hat{u} in H(curl), v = (1 / det dF) dF \hat{v} in H(div).
void PAHcurlHdivMassApply3D(const int D1D,
const int D1Dtest,
const int Q1D,
const int NE,
const bool scalarCoeff,
const bool trialHcurl,
const Array<double> &_Bo,
const Array<double> &_Bc,
const Array<double> &_Bot,
const Array<double> &_Bct,
const Vector &_op,
const Vector &_x,
Vector &_y)
{
constexpr static int MAX_D1D = HCURL_MAX_D1D;
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
constexpr static int VDIM = 3;
auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
auto Bc = Reshape(_Bc.Read(), Q1D, D1D);
auto Bot = Reshape(_Bot.Read(), D1Dtest-1, Q1D);
auto Bct = Reshape(_Bct.Read(), D1Dtest, Q1D);
auto op = Reshape(_op.Read(), scalarCoeff ? 1 : 9, Q1D, Q1D, Q1D, NE);
auto x = Reshape(_x.Read(), 3*(D1D-1)*D1D*(trialHcurl ? D1D : D1D-1), NE);
auto y = Reshape(_y.ReadWrite(), 3*(D1Dtest-1)*D1Dtest*
(trialHcurl ? D1Dtest-1 : D1Dtest), NE);
MFEM_FORALL(e, NE,
{
double mass[MAX_Q1D][MAX_Q1D][MAX_Q1D][VDIM];
for (int qz = 0; qz < Q1D; ++qz)
{
for (int qy = 0; qy < Q1D; ++qy)
{
for (int qx = 0; qx < Q1D; ++qx)
{
for (int c = 0; c < VDIM; ++c)
{
mass[qz][qy][qx][c] = 0.0;
}
}
}
}
int osc = 0;
for (int c = 0; c < VDIM; ++c) // loop over x, y, z trial components
{
const int D1Dz = trialHcurl ? ((c == 2) ? D1D - 1 : D1D) :
((c == 2) ? D1D : D1D - 1);
const int D1Dy = trialHcurl ? ((c == 1) ? D1D - 1 : D1D) :
((c == 1) ? D1D : D1D - 1);
const int D1Dx = trialHcurl ? ((c == 0) ? D1D - 1 : D1D) :
((c == 0) ? D1D : D1D - 1);
for (int dz = 0; dz < D1Dz; ++dz)
{
double massXY[MAX_Q1D][MAX_Q1D];
for (int qy = 0; qy < Q1D; ++qy)
{
for (int qx = 0; qx < Q1D; ++qx)
{
massXY[qy][qx] = 0.0;
}
}
for (int dy = 0; dy < D1Dy; ++dy)
{
double massX[MAX_Q1D];
for (int qx = 0; qx < Q1D; ++qx)
{
massX[qx] = 0.0;
}
for (int dx = 0; dx < D1Dx; ++dx)
{
const double t = x(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e);
for (int qx = 0; qx < Q1D; ++qx)
{
massX[qx] += t * (trialHcurl ? ((c == 0) ? Bo(qx,dx) : Bc(qx,dx)) :
((c == 0) ? Bc(qx,dx) : Bo(qx,dx)));
}
}
for (int qy = 0; qy < Q1D; ++qy)
{
const double wy = trialHcurl ? ((c == 1) ? Bo(qy,dy) : Bc(qy,dy)) :
((c == 1) ? Bc(qy,dy) : Bo(qy,dy));
for (int qx = 0; qx < Q1D; ++qx)
{
const double wx = massX[qx];
massXY[qy][qx] += wx * wy;
}
}
}
for (int qz = 0; qz < Q1D; ++qz)
{
const double wz = trialHcurl ? ((c == 2) ? Bo(qz,dz) : Bc(qz,dz)) :
((c == 2) ? Bc(qz,dz) : Bo(qz,dz));
for (int qy = 0; qy < Q1D; ++qy)
{
for (int qx = 0; qx < Q1D; ++qx)
{
mass[qz][qy][qx][c] += massXY[qy][qx] * wz;
}
}
}
}
osc += D1Dx * D1Dy * D1Dz;
} // loop (c) over components
// Apply D operator.
for (int qz = 0; qz < Q1D; ++qz)
{
for (int qy = 0; qy < Q1D; ++qy)
{
for (int qx = 0; qx < Q1D; ++qx)
{
const double O11 = op(0,qx,qy,qz,e);
const double O12 = scalarCoeff ? 0.0 : op(1,qx,qy,qz,e);
const double O13 = scalarCoeff ? 0.0 : op(2,qx,qy,qz,e);
const double O21 = scalarCoeff ? 0.0 : op(3,qx,qy,qz,e);
const double O22 = scalarCoeff ? O11 : op(4,qx,qy,qz,e);
const double O23 = scalarCoeff ? 0.0 : op(5,qx,qy,qz,e);
const double O31 = scalarCoeff ? 0.0 : op(6,qx,qy,qz,e);
const double O32 = scalarCoeff ? 0.0 : op(7,qx,qy,qz,e);
const double O33 = scalarCoeff ? O11 : op(8,qx,qy,qz,e);
const double massX = mass[qz][qy][qx][0];
const double massY = mass[qz][qy][qx][1];
const double massZ = mass[qz][qy][qx][2];
mass[qz][qy][qx][0] = (O11*massX)+(O12*massY)+(O13*massZ);
mass[qz][qy][qx][1] = (O21*massX)+(O22*massY)+(O23*massZ);
mass[qz][qy][qx][2] = (O31*massX)+(O32*massY)+(O33*massZ);
}
}
}
for (int qz = 0; qz < Q1D; ++qz)
{
double massXY[HDIV_MAX_D1D][HDIV_MAX_D1D];
osc = 0;
for (int c = 0; c < VDIM; ++c) // loop over x, y, z test components
{
const int D1Dz = trialHcurl ? ((c == 2) ? D1Dtest : D1Dtest - 1) :
((c == 2) ? D1Dtest - 1 : D1Dtest);
const int D1Dy = trialHcurl ? ((c == 1) ? D1Dtest : D1Dtest - 1) :
((c == 1) ? D1Dtest - 1 : D1Dtest);
const int D1Dx = trialHcurl ? ((c == 0) ? D1Dtest : D1Dtest - 1) :
((c == 0) ? D1Dtest - 1 : D1Dtest);
for (int dy = 0; dy < D1Dy; ++dy)
{
for (int dx = 0; dx < D1Dx; ++dx)
{
massXY[dy][dx] = 0.0;
}
}
for (int qy = 0; qy < Q1D; ++qy)
{
double massX[HDIV_MAX_D1D];
for (int dx = 0; dx < D1Dx; ++dx)
{
massX[dx] = 0.0;
}
for (int qx = 0; qx < Q1D; ++qx)
{
for (int dx = 0; dx < D1Dx; ++dx)
{
massX[dx] += mass[qz][qy][qx][c] * (trialHcurl ?
((c == 0) ? Bct(dx,qx) : Bot(dx,qx)) :
((c == 0) ? Bot(dx,qx) : Bct(dx,qx)));
}
}
for (int dy = 0; dy < D1Dy; ++dy)
{
const double wy = trialHcurl ? ((c == 1) ? Bct(dy,qy) : Bot(dy,qy)) :
((c == 1) ? Bot(dy,qy) : Bct(dy,qy));
for (int dx = 0; dx < D1Dx; ++dx)
{
massXY[dy][dx] += massX[dx] * wy;
}
}
}
for (int dz = 0; dz < D1Dz; ++dz)
{
const double wz = trialHcurl ? ((c == 2) ? Bct(dz,qz) : Bot(dz,qz)) :
((c == 2) ? Bot(dz,qz) : Bct(dz,qz));
for (int dy = 0; dy < D1Dy; ++dy)
{
for (int dx = 0; dx < D1Dx; ++dx)
{
y(dx + ((dy + (dz * D1Dy)) * D1Dx) + osc, e) +=
massXY[dy][dx] * wz;
}
}
}
osc += D1Dx * D1Dy * D1Dz;
} // loop c
} // loop qz
}); // end of element loop
}
// Mass operator for H(curl) and H(div) functions, using Piola transformations
// u = dF^{-T} \hat{u} in H(curl), v = (1 / det dF) dF \hat{v} in H(div).
void PAHcurlHdivMassApply2D(const int D1D,
const int D1Dtest,
const int Q1D,
const int NE,
const bool scalarCoeff,
const bool trialHcurl,
const Array<double> &_Bo,
const Array<double> &_Bc,
const Array<double> &_Bot,
const Array<double> &_Bct,
const Vector &_op,
const Vector &_x,
Vector &_y)
{
constexpr static int MAX_D1D = HCURL_MAX_D1D;
constexpr static int MAX_Q1D = HCURL_MAX_Q1D;
MFEM_VERIFY(D1D <= MAX_D1D, "Error: D1D > MAX_D1D");
MFEM_VERIFY(Q1D <= MAX_Q1D, "Error: Q1D > MAX_Q1D");
constexpr static int VDIM = 2;
auto Bo = Reshape(_Bo.Read(), Q1D, D1D-1);
auto Bc = Reshape(_Bc.Read(), Q1D, D1D);
auto Bot = Reshape(_Bot.Read(), D1Dtest-1, Q1D);
auto Bct = Reshape(_Bct.Read(), D1Dtest, Q1D);
auto op = Reshape(_op.Read(), scalarCoeff ? 1 : 4, Q1D, Q1D, NE);
auto x = Reshape(_x.Read(), 2*(D1D-1)*D1D, NE);
auto y = Reshape(_y.ReadWrite(), 2*(D1Dtest-1)*D1Dtest, NE);
MFEM_FORALL(e, NE,
{
double mass[MAX_Q1D][MAX_Q1D][VDIM];
for (int qy = 0; qy < Q1D; ++qy)
{
for (int qx = 0; qx < Q1D; ++qx)
{
for (int c = 0; c < VDIM; ++c)
{
mass[qy][qx][c] = 0.0;
}
}
}
int osc = 0;
for (int c = 0; c < VDIM; ++c) // loop over x, y trial components
{
const int D1Dy = trialHcurl ? ((c == 1) ? D1D - 1 : D1D) :
((c == 1) ? D1D : D1D - 1);
const int D1Dx = trialHcurl ? ((c == 0) ? D1D - 1 : D1D) :
((c == 0) ? D1D : D1D - 1);
for (int dy = 0; dy < D1Dy; ++dy)
{
double massX[MAX_Q1D];
for (int qx = 0; qx < Q1D; ++qx)
{
massX[qx] = 0.0;
}
for (int dx = 0; dx < D1Dx; ++dx)
{
const double t = x(dx + (dy * D1Dx) + osc, e);
for (int qx = 0; qx < Q1D; ++qx)
{
massX[qx] += t * (trialHcurl ? ((c == 0) ? Bo(qx,dx) : Bc(qx,dx)) :
((c == 0) ? Bc(qx,dx) : Bo(qx,dx)));
}
}
for (int qy = 0; qy < Q1D; ++qy)
{
const double wy = trialHcurl ? ((c == 1) ? Bo(qy,dy) : Bc(qy,dy)) :
((c == 1) ? Bc(qy,dy) : Bo(qy,dy));
for (int qx = 0; qx < Q1D; ++qx)
{
mass[qy][qx][c] += massX[qx] * wy;
}
}
}
osc += D1Dx * D1Dy;
} // loop (c) over components
// Apply D operator.
for (int qy = 0; qy < Q1D; ++qy)
{
for (int qx = 0; qx < Q1D; ++qx)
{
const double O11 = op(0,qx,qy,e);
const double O12 = scalarCoeff ? 0.0 : op(1,qx,qy,e);
const double O21 = scalarCoeff ? 0.0 : op(2,qx,qy,e);
const double O22 = scalarCoeff ? O11 : op(3,qx,qy,e);
const double massX = mass[qy][qx][0];
const double massY = mass[qy][qx][1];
mass[qy][qx][0] = (O11*massX)+(O12*massY);
mass[qy][qx][1] = (O21*massX)+(O22*massY);
}
}
osc = 0;
for (int c = 0; c < VDIM; ++c) // loop over x, y test components
{
const int D1Dy = trialHcurl ? ((c == 1) ? D1Dtest : D1Dtest - 1) :
((c == 1) ? D1Dtest - 1 : D1Dtest);
const int D1Dx = trialHcurl ? ((c == 0) ? D1Dtest : D1Dtest - 1) :
((c == 0) ? D1Dtest - 1 : D1Dtest);
for (int qy = 0; qy < Q1D; ++qy)
{
double massX[HDIV_MAX_D1D];
for (int dx = 0; dx < D1Dx; ++dx)
{
massX[dx] = 0.0;
}
for (int qx = 0; qx < Q1D; ++qx)
{
for (int dx = 0; dx < D1Dx; ++dx)
{
massX[dx] += mass[qy][qx][c] * (trialHcurl ?
((c == 0) ? Bct(dx,qx) : Bot(dx,qx)) :
((c == 0) ? Bot(dx,qx) : Bct(dx,qx)));
}
}
for (int dy = 0; dy < D1Dy; ++dy)
{
const double wy = trialHcurl ? ((c == 1) ? Bct(dy,qy) : Bot(dy,qy)) :
((c == 1) ? Bot(dy,qy) : Bct(dy,qy));
for (int dx = 0; dx < D1Dx; ++dx)
{
y(dx + (dy * D1Dx) + osc, e) += massX[dx] * wy;
}
}
}
osc += D1Dx * D1Dy;
} // loop c
}); // end of element loop
}
void VectorFEMassIntegrator::AssemblePA(const FiniteElementSpace &fes)
{
// Assumes tensor-product elements
Mesh *mesh = fes.GetMesh();
const FiniteElement *fel = fes.GetFE(0);
AssemblePA(fes, fes);
}
const VectorTensorFiniteElement *el =
dynamic_cast<const VectorTensorFiniteElement*>(fel);
MFEM_VERIFY(el != NULL, "Only VectorTensorFiniteElement is supported!");
void VectorFEMassIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
const FiniteElementSpace &test_fes)
{
// Assumes tensor-product elements
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *trial_fel = trial_fes.GetFE(0);
const VectorTensorFiniteElement *trial_el =
dynamic_cast<const VectorTensorFiniteElement*>(trial_fel);
MFEM_VERIFY(trial_el != NULL, "Only VectorTensorFiniteElement is supported!");
const FiniteElement *test_fel = test_fes.GetFE(0);
const VectorTensorFiniteElement *test_el =
dynamic_cast<const VectorTensorFiniteElement*>(test_fel);
MFEM_VERIFY(test_el != NULL, "Only VectorTensorFiniteElement is supported!");
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(*el, *el,
= IntRule ? IntRule : &MassIntegrator::GetRule(*trial_el, *trial_el,
*mesh->GetElementTransformation(0));
const int dims = el->GetDim();
const int dims = trial_el->GetDim();
MFEM_VERIFY(dims == 2 || dims == 3, "");
const int symmDims = (dims * (dims + 1)) / 2; // 1x1: 1, 2x2: 3, 3x3: 6
@@ -161,53 +721,154 @@ void VectorFEMassIntegrator::AssemblePA(const FiniteElementSpace &fes)
dim = mesh->Dimension();
MFEM_VERIFY(dim == 2 || dim == 3, "");
ne = fes.GetNE();
ne = trial_fes.GetNE();
MFEM_VERIFY(ne == test_fes.GetNE(),
"Different meshes for test and trial spaces");
geom = mesh->GetGeometricFactors(*ir, GeometricFactors::JACOBIANS);
mapsC = &el->GetDofToQuad(*ir, DofToQuad::TENSOR);
mapsO = &el->GetDofToQuadOpen(*ir, DofToQuad::TENSOR);
mapsC = &trial_el->GetDofToQuad(*ir, DofToQuad::TENSOR);
mapsO = &trial_el->GetDofToQuadOpen(*ir, DofToQuad::TENSOR);
dofs1D = mapsC->ndof;
quad1D = mapsC->nqpt;
mapsCtest = &test_el->GetDofToQuad(*ir, DofToQuad::TENSOR);
mapsOtest = &test_el->GetDofToQuadOpen(*ir, DofToQuad::TENSOR);
dofs1Dtest = mapsCtest->ndof;
MFEM_VERIFY(dofs1D == mapsO->ndof + 1 && quad1D == mapsO->nqpt, "");
pa_data.SetSize(symmDims * nq * ne, Device::GetMemoryType());
trial_fetype = trial_el->GetDerivType();
test_fetype = test_el->GetDerivType();
Vector coeff(ne * nq);
const int MQsymmDim = MQ ? (MQ->GetWidth() * (MQ->GetWidth() + 1)) / 2 : 0;
const int MQfullDim = MQ ? (MQ->GetHeight() * MQ->GetWidth()) : 0;
const int MQdim = MQ ? (MQ->IsSymmetric() ? MQsymmDim : MQfullDim) : 0;
const int coeffDim = MQ ? MQdim : (VQ ? VQ->GetVDim() : 1);
symmetric = MQ ? MQ->IsSymmetric() : true;
const bool trial_curl = (trial_fetype == mfem::FiniteElement::CURL);
const bool trial_div = (trial_fetype == mfem::FiniteElement::DIV);
const bool test_curl = (test_fetype == mfem::FiniteElement::CURL);
const bool test_div = (test_fetype == mfem::FiniteElement::DIV);
if ((trial_curl && test_div) || (trial_div && test_curl))
pa_data.SetSize((coeffDim == 1 ? 1 : dim*dim) * nq * ne,
Device::GetMemoryType());
else
pa_data.SetSize((symmetric ? symmDims : MQfullDim) * nq * ne,
Device::GetMemoryType());
Vector coeff(coeffDim * ne * nq);
coeff = 1.0;
if (Q)
auto coeffh = Reshape(coeff.HostWrite(), coeffDim, nq, ne);
if (Q || VQ || MQ)
{
Vector D(VQ ? coeffDim : 0);
DenseMatrix M;
Vector Msymm;
if (MQ)
{
if (symmetric)
{
Msymm.SetSize(MQsymmDim);
}
else
{
M.SetSize(dim);
}
}
if (VQ)
{
MFEM_VERIFY(coeffDim == dim, "");
}
if (MQ)
{
MFEM_VERIFY(coeffDim == MQdim, "");
MFEM_VERIFY(MQ->GetHeight() == dim && MQ->GetWidth() == dim, "");
}
for (int e=0; e<ne; ++e)
{
ElementTransformation *tr = mesh->GetElementTransformation(e);
for (int p=0; p<nq; ++p)
{
coeff[p + (e * nq)] = Q->Eval(*tr, ir->IntPoint(p));
if (MQ)
{
if (MQ->IsSymmetric())
{
MQ->EvalSymmetric(Msymm, *tr, ir->IntPoint(p));
for (int i=0; i<MQsymmDim; ++i)
{
coeffh(i, p, e) = Msymm[i];
}
}
else
{
MQ->Eval(M, *tr, ir->IntPoint(p));
for (int i=0; i<dim; ++i)
for (int j=0; j<dim; ++j)
{
coeffh(j+(i*dim), p, e) = M(i,j);
}
}
}
else if (VQ)
{
VQ->Eval(D, *tr, ir->IntPoint(p));
for (int i=0; i<coeffDim; ++i)
{
coeffh(i, p, e) = D[i];
}
}
else
{
coeffh(0, p, e) = Q->Eval(*tr, ir->IntPoint(p));
}
}
}
}
fetype = el->GetDerivType();
if (el->GetDerivType() == mfem::FiniteElement::CURL && dim == 3)
if (trial_curl && test_curl && dim == 3)
{
PAHcurlSetup3D(quad1D, ne, ir->GetWeights(), geom->J,
PAHcurlSetup3D(quad1D, coeffDim, ne, ir->GetWeights(), geom->J,
coeff, pa_data);
}
else if (el->GetDerivType() == mfem::FiniteElement::CURL && dim == 2)
else if (trial_curl && test_curl && dim == 2)
{
PAHcurlSetup2D(quad1D, ne, ir->GetWeights(), geom->J,
PAHcurlSetup2D(quad1D, coeffDim, ne, ir->GetWeights(), geom->J,
coeff, pa_data);
}
else if (el->GetDerivType() == mfem::FiniteElement::DIV && dim == 3)
else if (trial_div && test_div && dim == 3)
{
PAHdivSetup3D(quad1D, ne, ir->GetWeights(), geom->J,
coeff, pa_data);
}
else if (el->GetDerivType() == mfem::FiniteElement::DIV && dim == 2)
else if (trial_div && test_div && dim == 2)
{
PAHdivSetup2D(quad1D, ne, ir->GetWeights(), geom->J,
coeff, pa_data);
}
else if (((trial_curl && test_div) || (trial_div && test_curl)) &&
test_fel->GetOrder() == trial_fel->GetOrder())
{
if (coeffDim == 1)
{
PAHcurlL2Setup(nq, coeffDim, ne, ir->GetWeights(), coeff, pa_data);
}
else
{
const bool tr = (trial_div && test_curl);
if (dim == 3)
PAHcurlHdivSetup3D(quad1D, coeffDim, ne, tr, ir->GetWeights(),
geom->J, coeff, pa_data);
else
PAHcurlHdivSetup2D(quad1D, coeffDim, ne, tr, ir->GetWeights(),
geom->J, coeff, pa_data);
}
}
else
{
MFEM_ABORT("Unknown kernel.");
@@ -218,12 +879,13 @@ void VectorFEMassIntegrator::AssembleDiagonalPA(Vector& diag)
{
if (dim == 3)
{
if (fetype == mfem::FiniteElement::CURL)
if (trial_fetype == mfem::FiniteElement::CURL && test_fetype == trial_fetype)
{
PAHcurlMassAssembleDiagonal3D(dofs1D, quad1D, ne,
PAHcurlMassAssembleDiagonal3D(dofs1D, quad1D, ne, symmetric,
mapsO->B, mapsC->B, pa_data, diag);
}
else if (fetype == mfem::FiniteElement::DIV)
else if (trial_fetype == mfem::FiniteElement::DIV &&
test_fetype == trial_fetype)
{
PAHdivMassAssembleDiagonal3D(dofs1D, quad1D, ne,
mapsO->B, mapsC->B, pa_data, diag);
@@ -235,12 +897,13 @@ void VectorFEMassIntegrator::AssembleDiagonalPA(Vector& diag)
}
else
{
if (fetype == mfem::FiniteElement::CURL)
if (trial_fetype == mfem::FiniteElement::CURL && test_fetype == trial_fetype)
{
PAHcurlMassAssembleDiagonal2D(dofs1D, quad1D, ne,
PAHcurlMassAssembleDiagonal2D(dofs1D, quad1D, ne, symmetric,
mapsO->B, mapsC->B, pa_data, diag);
}
else if (fetype == mfem::FiniteElement::DIV)
else if (trial_fetype == mfem::FiniteElement::DIV &&
test_fetype == trial_fetype)
{
PAHdivMassAssembleDiagonal2D(dofs1D, quad1D, ne,
mapsO->B, mapsC->B, pa_data, diag);
@@ -254,18 +917,37 @@ void VectorFEMassIntegrator::AssembleDiagonalPA(Vector& diag)
void VectorFEMassIntegrator::AddMultPA(const Vector &x, Vector &y) const
{
const bool trial_curl = (trial_fetype == mfem::FiniteElement::CURL);
const bool trial_div = (trial_fetype == mfem::FiniteElement::DIV);
const bool test_curl = (test_fetype == mfem::FiniteElement::CURL);
const bool test_div = (test_fetype == mfem::FiniteElement::DIV);
if (dim == 3)
{
if (fetype == mfem::FiniteElement::CURL)
if (trial_curl && test_curl)
{
PAHcurlMassApply3D(dofs1D, quad1D, ne, mapsO->B, mapsC->B, mapsO->Bt,
mapsC->Bt, pa_data, x, y);
PAHcurlMassApply3D(dofs1D, quad1D, ne, symmetric, mapsO->B, mapsC->B,
mapsO->Bt, mapsC->Bt, pa_data, x, y);
}
else if (fetype == mfem::FiniteElement::DIV)
else if (trial_div && test_div)
{
PAHdivMassApply3D(dofs1D, quad1D, ne, mapsO->B, mapsC->B, mapsO->Bt,
mapsC->Bt, pa_data, x, y);
}
else if (trial_curl && test_div)
{
const bool scalarCoeff = !(VQ || MQ);
PAHcurlHdivMassApply3D(dofs1D, dofs1Dtest, quad1D, ne, scalarCoeff,
true, mapsO->B, mapsC->B, mapsOtest->Bt,
mapsCtest->Bt, pa_data, x, y);
}
else if (trial_div && test_curl)
{
const bool scalarCoeff = !(VQ || MQ);
PAHcurlHdivMassApply3D(dofs1D, dofs1Dtest, quad1D, ne, scalarCoeff,
false, mapsO->B, mapsC->B, mapsOtest->Bt,
mapsCtest->Bt, pa_data, x, y);
}
else
{
MFEM_ABORT("Unknown kernel.");
@@ -273,16 +955,23 @@ void VectorFEMassIntegrator::AddMultPA(const Vector &x, Vector &y) const
}
else
{
if (fetype == mfem::FiniteElement::CURL)
if (trial_curl && test_curl)
{
PAHcurlMassApply2D(dofs1D, quad1D, ne, mapsO->B, mapsC->B, mapsO->Bt,
mapsC->Bt, pa_data, x, y);
PAHcurlMassApply2D(dofs1D, quad1D, ne, symmetric, mapsO->B, mapsC->B,
mapsO->Bt, mapsC->Bt, pa_data, x, y);
}
else if (fetype == mfem::FiniteElement::DIV)
else if (trial_div && test_div)
{
PAHdivMassApply2D(dofs1D, quad1D, ne, mapsO->B, mapsC->B, mapsO->Bt,
mapsC->Bt, pa_data, x, y);
}
else if ((trial_curl && test_div) || (trial_div && test_curl))
{
const bool scalarCoeff = !(VQ || MQ);
PAHcurlHdivMassApply2D(dofs1D, dofs1Dtest, quad1D, ne, scalarCoeff,
trial_curl, mapsO->B, mapsC->B, mapsOtest->Bt,
mapsCtest->Bt, pa_data, x, y);
}
else
{
MFEM_ABORT("Unknown kernel.");
@@ -348,12 +1037,12 @@ void MixedVectorGradientIntegrator::AssemblePA(const FiniteElementSpace
// Use the same setup functions as VectorFEMassIntegrator.
if (test_el->GetDerivType() == mfem::FiniteElement::CURL && dim == 3)
{
PAHcurlSetup3D(quad1D, ne, ir->GetWeights(), geom->J,
PAHcurlSetup3D(quad1D, 1, ne, ir->GetWeights(), geom->J,
coeff, pa_data);
}
else if (test_el->GetDerivType() == mfem::FiniteElement::CURL && dim == 2)
{
PAHcurlSetup2D(quad1D, ne, ir->GetWeights(), geom->J,
PAHcurlSetup2D(quad1D, 1, ne, ir->GetWeights(), geom->J,
coeff, pa_data);
}
else
+138 -25
View File
@@ -209,18 +209,24 @@ void GradientGridFunctionCoefficient::Eval(
GridFunc->GetGradients(T, ir, M);
}
CurlGridFunctionCoefficient::CurlGridFunctionCoefficient (
CurlGridFunctionCoefficient::CurlGridFunctionCoefficient(
const GridFunction *gf)
: VectorCoefficient ((gf) ?
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0)
: VectorCoefficient(0)
{
GridFunc = gf;
SetGridFunction(gf);
}
void CurlGridFunctionCoefficient::SetGridFunction(const GridFunction *gf)
{
GridFunc = gf; vdim = (gf) ?
gf -> FESpace() -> GetMesh() -> SpaceDimension() : 0;
if (gf)
{
int sdim = gf -> FESpace() -> GetMesh() -> SpaceDimension();
MFEM_VERIFY(sdim == 2 || sdim == 3,
"CurlGridFunctionCoefficient "
"only defind for spaces of dimension 2 or 3.");
}
GridFunc = gf;
vdim = (gf) ? (2 * gf -> FESpace() -> GetMesh() -> SpaceDimension() - 3) : 0;
}
void CurlGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
@@ -313,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)
{
@@ -416,13 +447,43 @@ double DeterminantCoefficient::Eval(ElementTransformation &T,
return ma.Det();
}
VectorSumCoefficient::VectorSumCoefficient(VectorCoefficient &A,
VectorCoefficient &B,
double _alpha, double _beta)
: VectorCoefficient(A.GetVDim()), a(&A), b(&B), alpha(_alpha), beta(_beta),
va(A.GetVDim())
VectorSumCoefficient::VectorSumCoefficient(int dim)
: VectorCoefficient(dim),
ACoef(NULL), BCoef(NULL),
A(dim), B(dim),
alphaCoef(NULL), betaCoef(NULL),
alpha(1.0), beta(1.0)
{
MFEM_ASSERT(A.GetVDim() == B.GetVDim(),
A = 0.0; B = 0.0;
}
VectorSumCoefficient::VectorSumCoefficient(VectorCoefficient &_A,
VectorCoefficient &_B,
double _alpha, double _beta)
: VectorCoefficient(_A.GetVDim()),
ACoef(&_A), BCoef(&_B),
A(_A.GetVDim()), B(_A.GetVDim()),
alphaCoef(NULL), betaCoef(NULL),
alpha(_alpha), beta(_beta)
{
MFEM_ASSERT(_A.GetVDim() == _B.GetVDim(),
"VectorSumCoefficient: "
"Arguments must have the same dimension.");
}
VectorSumCoefficient::VectorSumCoefficient(VectorCoefficient &_A,
VectorCoefficient &_B,
Coefficient &_alpha,
Coefficient &_beta)
: VectorCoefficient(_A.GetVDim()),
ACoef(&_A), BCoef(&_B),
A(_A.GetVDim()),
B(_A.GetVDim()),
alphaCoef(&_alpha),
betaCoef(&_beta),
alpha(0.0), beta(0.0)
{
MFEM_ASSERT(_A.GetVDim() == _B.GetVDim(),
"VectorSumCoefficient: "
"Arguments must have the same dimension.");
}
@@ -430,26 +491,47 @@ VectorSumCoefficient::VectorSumCoefficient(VectorCoefficient &A,
void VectorSumCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
b->Eval(V, T, ip);
if ( beta != 1.0 ) { V *= beta; }
a->Eval(va, T, ip);
V.Add(alpha, va);
V.SetSize(A.Size());
if ( ACoef) { ACoef->Eval(A, T, ip); }
if ( BCoef) { BCoef->Eval(B, T, ip); }
if (alphaCoef) { alpha = alphaCoef->Eval(T, ip); }
if ( betaCoef) { beta = betaCoef->Eval(T, ip); }
add(alpha, A, beta, B, V);
}
ScalarVectorProductCoefficient::ScalarVectorProductCoefficient(
double A,
VectorCoefficient &B)
: VectorCoefficient(B.GetVDim()), aConst(A), a(NULL), b(&B)
{}
ScalarVectorProductCoefficient::ScalarVectorProductCoefficient(
Coefficient &A,
VectorCoefficient &B)
: VectorCoefficient(B.GetVDim()), a(&A), b(&B)
: VectorCoefficient(B.GetVDim()), aConst(0.0), a(&A), b(&B)
{}
void ScalarVectorProductCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
double sa = a->Eval(T, ip);
double sa = (a == NULL) ? aConst : a->Eval(T, ip);
b->Eval(V, T, ip);
V *= sa;
}
NormalizedVectorCoefficient::NormalizedVectorCoefficient(VectorCoefficient &A,
double _tol)
: VectorCoefficient(A.GetVDim()), a(&A), tol(_tol)
{}
void NormalizedVectorCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(V, T, ip);
double nv = V.Norml2();
V *= (nv > tol) ? (1.0/nv) : 0.0;
}
VectorCrossProductCoefficient::VectorCrossProductCoefficient(
VectorCoefficient &A,
VectorCoefficient &B)
@@ -471,17 +553,18 @@ void VectorCrossProductCoefficient::Eval(Vector &V, ElementTransformation &T,
V[2] = va[0] * vb[1] - va[1] * vb[0];
}
MatVecCoefficient::MatVecCoefficient(MatrixCoefficient &A,
VectorCoefficient &B)
MatrixVectorProductCoefficient::MatrixVectorProductCoefficient(
MatrixCoefficient &A, VectorCoefficient &B)
: VectorCoefficient(A.GetHeight()), a(&A), b(&B),
ma(A.GetHeight(), A.GetWidth()), vb(B.GetVDim())
{
MFEM_ASSERT(A.GetWidth() == B.GetVDim(),
"MatVecCoefficient: Arguments have incompatible dimensions.");
"MatrixVectorProductCoefficient: "
"Arguments have incompatible dimensions.");
}
void MatVecCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
void MatrixVectorProductCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
a->Eval(ma, T, ip);
b->Eval(vb, T, ip);
@@ -517,17 +600,23 @@ void MatrixSumCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
M.Add(alpha, ma);
}
ScalarMatrixProductCoefficient::ScalarMatrixProductCoefficient(
double A,
MatrixCoefficient &B)
: MatrixCoefficient(B.GetHeight(), B.GetWidth()), aConst(A), a(NULL), b(&B)
{}
ScalarMatrixProductCoefficient::ScalarMatrixProductCoefficient(
Coefficient &A,
MatrixCoefficient &B)
: MatrixCoefficient(B.GetHeight(), B.GetWidth()), a(&A), b(&B)
: MatrixCoefficient(B.GetHeight(), B.GetWidth()), aConst(0.0), a(&A), b(&B)
{}
void ScalarMatrixProductCoefficient::Eval(DenseMatrix &M,
ElementTransformation &T,
const IntegrationPoint &ip)
{
double sa = a->Eval(T, ip);
double sa = (a == NULL) ? aConst : a->Eval(T, ip);
b->Eval(M, T, ip);
M *= sa;
}
@@ -581,6 +670,30 @@ void OuterProductCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
}
}
CrossCrossCoefficient::CrossCrossCoefficient(Coefficient &A,
VectorCoefficient &K)
: MatrixCoefficient(K.GetVDim(), K.GetVDim()), aConst(0.0), a(&A), k(&K),
vk(K.GetVDim())
{}
void CrossCrossCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip)
{
k->Eval(vk, T, ip);
M.SetSize(vk.Size(), vk.Size());
M = 0.0;
double k2 = vk*vk;
for (int i=0; i<vk.Size(); i++)
{
M(i, i) = k2;
for (int j=0; j<vk.Size(); j++)
{
M(i, j) -= vk[i] * vk[j];
}
}
M *= ((a == NULL ) ? aConst : a->Eval(T, ip) );
}
double LpNormLoop(double p, Coefficient &coeff, Mesh &mesh,
const IntegrationRule *irs[])
{
+429 -24
View File
@@ -30,7 +30,10 @@ class ParMesh;
/** @brief Base class Coefficients that optionally depend on space and time.
These are used by the BilinearFormIntegrator, LinearFormIntegrator, and
NonlinearFormIntegrator classes to represent the physical coefficients in
the PDEs that are being discretized. */
the PDEs that are being discretized. This class can also be used in a more
general way to represent functions that don't necessarily belong to a FE
space, e.g., to project onto GridFunctions to use as initial conditions,
exact solutions, etc. See, e.g., ex4 or ex22 for these uses. */
class Coefficient
{
protected:
@@ -692,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; }
@@ -715,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
@@ -723,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() { }
};
@@ -750,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;
@@ -787,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() { }
};
@@ -852,12 +887,14 @@ public:
const IntegrationPoint &ip);
};
/// Coefficients based on sums and products of other coefficients
/// Scalar coefficient defined as the sum of two scalar coefficients
/// Coefficients based on sums, products, or other functions of coefficients.
///@{
/** Scalar coefficient defined as the linear combination of two scalar
coefficients or a scalar and a scalar coefficient */
class SumCoefficient : public Coefficient
{
private:
double aConst;
Coefficient * a;
Coefficient * b;
@@ -865,33 +902,141 @@ private:
double beta;
public:
/// Construct with the two coefficients. Result is _alpha * A + _beta * B.
/// Constructor with one coefficient. Result is _alpha * A + _beta * B
SumCoefficient(double A, Coefficient &B,
double _alpha = 1.0, double _beta = 1.0)
: aConst(A), a(NULL), b(&B), alpha(_alpha), beta(_beta) { }
/// Constructor with two coefficients. Result is _alpha * A + _beta * B.
SumCoefficient(Coefficient &A, Coefficient &B,
double _alpha = 1.0, double _beta = 1.0)
: a(&A), b(&B), alpha(_alpha), beta(_beta) { }
: aConst(0.0), a(&A), b(&B), alpha(_alpha), beta(_beta) { }
/// Reset the first term in the linear combination as a constant
void SetAConst(double A) { a = NULL; aConst = A; }
/// Return the first term in the linear combination
double GetAConst() const { return aConst; }
/// Reset the first term in the linear combination
void SetACoef(Coefficient &A) { a = &A; }
/// Return the first term in the linear combination
Coefficient * GetACoef() const { return a; }
/// Reset the second term in the linear combination
void SetBCoef(Coefficient &B) { b = &B; }
/// Return the second term in the linear combination
Coefficient * GetBCoef() const { return b; }
/// Reset the factor in front of the first term in the linear combination
void SetAlpha(double _alpha) { alpha = _alpha; }
/// Return the factor in front of the first term in the linear combination
double GetAlpha() const { return alpha; }
/// Reset the factor in front of the second term in the linear combination
void SetBeta(double _beta) { beta = _beta; }
/// Return the factor in front of the second term in the linear combination
double GetBeta() const { return beta; }
/// Evaluate the coefficient at @a ip.
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{ return alpha * a->Eval(T, ip) + beta * b->Eval(T, ip); }
{
return alpha * ((a == NULL ) ? aConst : a->Eval(T, ip) )
+ beta * b->Eval(T, ip);
}
};
/// Scalar coefficient defined as the product of two scalar coefficients
/** Scalar coefficient defined as the product of two scalar coefficients or
a scalar and a scalar coefficient. */
class ProductCoefficient : public Coefficient
{
private:
double aConst;
Coefficient * a;
Coefficient * b;
public:
/// Construct with the two coefficients. Result is A * B.
/// Constructor with one coefficient. Result is A * B.
ProductCoefficient(double A, Coefficient &B)
: aConst(A), a(NULL), b(&B) { }
/// Constructor with two coefficients. Result is A * B.
ProductCoefficient(Coefficient &A, Coefficient &B)
: a(&A), b(&B) { }
: aConst(0.0), a(&A), b(&B) { }
/// Reset the first term in the product as a constant
void SetAConst(double A) { a = NULL; aConst = A; }
/// Return the first term in the product
double GetAConst() const { return aConst; }
/// Reset the first term in the product
void SetACoef(Coefficient &A) { a = &A; }
/// Return the first term in the product
Coefficient * GetACoef() const { return a; }
/// Reset the second term in the product
void SetBCoef(Coefficient &B) { b = &B; }
/// Return the second term in the product
Coefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{ return a->Eval(T, ip) * b->Eval(T, ip); }
{ return ((a == NULL ) ? aConst : a->Eval(T, ip) ) * b->Eval(T, ip); }
};
/** Scalar coefficient defined as the ratio of two scalars where one or both
scalars are scalar coefficients. */
class RatioCoefficient : public Coefficient
{
private:
double aConst;
double bConst;
Coefficient * a;
Coefficient * b;
public:
/** Initialize a coefficient which returns A / B where @a A is a
constant and @a B is a scalar coefficient */
RatioCoefficient(double A, Coefficient &B)
: aConst(A), bConst(1.0), a(NULL), b(&B) { }
/** Initialize a coefficient which returns A / B where @a A and @a B are both
scalar coefficients */
RatioCoefficient(Coefficient &A, Coefficient &B)
: aConst(0.0), bConst(1.0), a(&A), b(&B) { }
/** Initialize a coefficient which returns A / B where @a A is a
scalar coefficient and @a B is a constant */
RatioCoefficient(Coefficient &A, double B)
: aConst(0.0), bConst(B), a(&A), b(NULL) { }
/// Reset the numerator in the ratio as a constant
void SetAConst(double A) { a = NULL; aConst = A; }
/// Return the numerator of the ratio
double GetAConst() const { return aConst; }
/// Reset the denominator in the ratio as a constant
void SetBConst(double B) { b = NULL; bConst = B; }
/// Return the denominator of the ratio
double GetBConst() const { return bConst; }
/// Reset the numerator in the ratio
void SetACoef(Coefficient &A) { a = &A; }
/// Return the numerator of the ratio
Coefficient * GetACoef() const { return a; }
/// Reset the denominator in the ratio
void SetBCoef(Coefficient &B) { b = &B; }
/// Return the denominator of the ratio
Coefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
double den = (b == NULL ) ? bConst : b->Eval(T, ip);
MFEM_ASSERT(den != 0.0, "Division by zero in RatioCoefficient");
return ((a == NULL ) ? aConst : a->Eval(T, ip) ) / den;
}
};
/// Scalar coefficient defined as a scalar raised to a power
@@ -907,6 +1052,16 @@ public:
PowerCoefficient(Coefficient &A, double _p)
: a(&A), p(_p) { }
/// Reset the base coefficient
void SetACoef(Coefficient &A) { a = &A; }
/// Return the base coefficient
Coefficient * GetACoef() const { return a; }
/// Reset the exponent
void SetExponent(double _p) { p = _p; }
/// Return the exponent
double GetExponent() const { return p; }
/// Evaluate the coefficient at @a ip.
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip)
@@ -927,6 +1082,16 @@ public:
/// Construct with the two vector coefficients. Result is \f$ A \cdot B \f$.
InnerProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Reset the first vector in the inner product
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the first vector coefficient in the inner product
VectorCoefficient * GetACoef() const { return a; }
/// Reset the second vector in the inner product
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the second vector coefficient in the inner product
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip);
@@ -943,9 +1108,19 @@ private:
mutable Vector vb;
public:
/// Construct with the two vector coefficients. Result is \f$ A_x B_y - A_y * B_x; \f$.
/// Constructor with two vector coefficients. Result is \f$ A_x B_y - A_y * B_x; \f$.
VectorRotProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Reset the first vector in the product
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the first vector of the product
VectorCoefficient * GetACoef() const { return a; }
/// Reset the second vector in the product
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the second vector of the product
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip);
@@ -963,17 +1138,28 @@ public:
/// Construct with the matrix.
DeterminantCoefficient(MatrixCoefficient &A);
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Evaluate the determinant coefficient at @a ip.
virtual double Eval(ElementTransformation &T,
const IntegrationPoint &ip);
};
/// Vector coefficient defined as the sum of two vector coefficients
/// Vector coefficient defined as the linear combination of two vectors
class VectorSumCoefficient : public VectorCoefficient
{
private:
VectorCoefficient * a;
VectorCoefficient * b;
VectorCoefficient * ACoef;
VectorCoefficient * BCoef;
Vector A;
Vector B;
Coefficient * alphaCoef;
Coefficient * betaCoef;
double alpha;
double beta;
@@ -981,10 +1167,60 @@ private:
mutable Vector va;
public:
/// Construct with the two vector coefficients. Result is _alpha * A + _beta * B.
/** Constructor with no coefficients.
To be used with the various "Set" methods */
VectorSumCoefficient(int dim);
/** Constructor with two vector coefficients.
Result is _alpha * A + _beta * B */
VectorSumCoefficient(VectorCoefficient &A, VectorCoefficient &B,
double _alpha = 1.0, double _beta = 1.0);
/** Constructor with scalar coefficients.
Result is _alpha * _A + _beta * _B */
VectorSumCoefficient(VectorCoefficient &_A, VectorCoefficient &_B,
Coefficient &_alpha, Coefficient &_beta);
/// Reset the first vector coefficient
void SetACoef(VectorCoefficient &A) { ACoef = &A; }
/// Return the first vector coefficient
VectorCoefficient * GetACoef() const { return ACoef; }
/// Reset the second vector coefficient
void SetBCoef(VectorCoefficient &B) { BCoef = &B; }
/// Return the second vector coefficient
VectorCoefficient * GetBCoef() const { return BCoef; }
/// Reset the factor in front of the first vector coefficient
void SetAlphaCoef(Coefficient &A) { alphaCoef = &A; }
/// Return the factor in front of the first vector coefficient
Coefficient * GetAlphaCoef() const { return alphaCoef; }
/// Reset the factor in front of the second vector coefficient
void SetBetaCoef(Coefficient &B) { betaCoef = &B; }
/// Return the factor in front of the second vector coefficient
Coefficient * GetBetaCoef() const { return betaCoef; }
/// Reset the first vector as a constant
void SetA(const Vector &_A) { A = _A; ACoef = NULL; }
/// Return the first vector constant
const Vector & GetA() const { return A; }
/// Reset the second vector as a constant
void SetB(const Vector &_B) { B = _B; BCoef = NULL; }
/// Return the second vector constant
const Vector & GetB() const { return B; }
/// Reset the factor in front of the first vector coefficient as a constant
void SetAlpha(double _alpha) { alpha = _alpha; alphaCoef = NULL; }
/// Return the factor in front of the first vector coefficient
double GetAlpha() const { return alpha; }
/// Reset the factor in front of the second vector coefficient as a constant
void SetBeta(double _beta) { beta = _beta; betaCoef = NULL; }
/// Return the factor in front of the second vector coefficient
double GetBeta() const { return beta; }
/// Evaluate the coefficient at @a ip.
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
@@ -995,13 +1231,60 @@ public:
class ScalarVectorProductCoefficient : public VectorCoefficient
{
private:
double aConst;
Coefficient * a;
VectorCoefficient * b;
public:
/// Construct with the two coefficients. Result is A * B.
/// Constructor with constant and vector coefficient. Result is A * B.
ScalarVectorProductCoefficient(double A, VectorCoefficient &B);
/// Constructor with two coefficients. Result is A * B.
ScalarVectorProductCoefficient(Coefficient &A, VectorCoefficient &B);
/// Reset the scalar factor as a constant
void SetAConst(double A) { a = NULL; aConst = A; }
/// Return the scalar factor
double GetAConst() const { return aConst; }
/// Reset the scalar factor
void SetACoef(Coefficient &A) { a = &A; }
/// Return the scalar factor
Coefficient * GetACoef() const { return a; }
/// Reset the vector factor
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the vector factor
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
using VectorCoefficient::Eval;
};
/// Vector coefficient defined as a normalized vector field (returns v/|v|)
class NormalizedVectorCoefficient : public VectorCoefficient
{
private:
VectorCoefficient * a;
double tol;
public:
/** @brief Return a vector normalized to a length of one
This class evaluates the vector coefficient @a A and, if |A| > @a tol,
returns the normalized vector A / |A|. If |A| <= @a tol, the zero
vector is returned.
*/
NormalizedVectorCoefficient(VectorCoefficient &A, double tol = 1e-6);
/// Reset the vector coefficient
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the vector coefficient
VectorCoefficient * GetACoef() const { return a; }
/// Evaluate the coefficient at @a ip.
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
@@ -1022,6 +1305,16 @@ public:
/// Construct with the two coefficients. Result is A x B.
VectorCrossProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Reset the first term in the product
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the first term in the product
VectorCoefficient * GetACoef() const { return a; }
/// Reset the second term in the product
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the second term in the product
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the coefficient at @a ip.
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
@@ -1030,7 +1323,7 @@ public:
/** @brief Vector coefficient defined as a product of a matrix coefficient and
a vector coefficient. */
class MatVecCoefficient : public VectorCoefficient
class MatrixVectorProductCoefficient : public VectorCoefficient
{
private:
MatrixCoefficient * a;
@@ -1040,8 +1333,18 @@ private:
mutable Vector vb;
public:
/// Construct with the two coefficients. Result is A*B.
MatVecCoefficient(MatrixCoefficient &A, VectorCoefficient &B);
/// Constructor with two coefficients. Result is A*B.
MatrixVectorProductCoefficient(MatrixCoefficient &A, VectorCoefficient &B);
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Reset the vector coefficient
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the vector coefficient
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the vector coefficient at @a ip.
virtual void Eval(Vector &V, ElementTransformation &T,
@@ -1049,6 +1352,9 @@ public:
using VectorCoefficient::Eval;
};
/// Convenient alias for the MatrixVectorProductCoefficient
typedef MatrixVectorProductCoefficient MatVecCoefficient;
/// Constant matrix coefficient defined as the identity of dimension d
class IdentityMatrixCoefficient : public MatrixCoefficient
{
@@ -1065,7 +1371,7 @@ public:
const IntegrationPoint &ip);
};
/// Matrix coefficient defined as the sum of two matrix coefficients.
/// Matrix coefficient defined as the linear combination of two matrices
class MatrixSumCoefficient : public MatrixCoefficient
{
private:
@@ -1082,6 +1388,26 @@ public:
MatrixSumCoefficient(MatrixCoefficient &A, MatrixCoefficient &B,
double _alpha = 1.0, double _beta = 1.0);
/// Reset the first matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the first matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Reset the second matrix coefficient
void SetBCoef(MatrixCoefficient &B) { b = &B; }
/// Return the second matrix coefficient
MatrixCoefficient * GetBCoef() const { return b; }
/// Reset the factor in front of the first matrix coefficient
void SetAlpha(double _alpha) { alpha = _alpha; }
/// Return the factor in front of the first matrix coefficient
double GetAlpha() const { return alpha; }
/// Reset the factor in front of the second matrix coefficient
void SetBeta(double _beta) { beta = _beta; }
/// Return the factor in front of the second matrix coefficient
double GetBeta() const { return beta; }
/// Evaluate the matrix coefficient at @a ip.
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
@@ -1092,13 +1418,32 @@ public:
class ScalarMatrixProductCoefficient : public MatrixCoefficient
{
private:
double aConst;
Coefficient * a;
MatrixCoefficient * b;
public:
/// Construct with the two coefficients. Result is A*B.
/// Constructor with one coefficient. Result is A*B.
ScalarMatrixProductCoefficient(double A, MatrixCoefficient &B);
/// Constructor with two coefficients. Result is A*B.
ScalarMatrixProductCoefficient(Coefficient &A, MatrixCoefficient &B);
/// Reset the scalar factor as a constant
void SetAConst(double A) { a = NULL; aConst = A; }
/// Return the scalar factor
double GetAConst() const { return aConst; }
/// Reset the scalar factor
void SetACoef(Coefficient &A) { a = &A; }
/// Return the scalar factor
Coefficient * GetACoef() const { return a; }
/// Reset the matrix factor
void SetBCoef(MatrixCoefficient &B) { b = &B; }
/// Return the matrix factor
MatrixCoefficient * GetBCoef() const { return b; }
/// Evaluate the matrix coefficient at @a ip.
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
@@ -1114,6 +1459,11 @@ public:
/// Construct with the matrix coefficient. Result is \f$ A^T \f$.
TransposeMatrixCoefficient(MatrixCoefficient &A);
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Evaluate the matrix coefficient at @a ip.
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
@@ -1129,6 +1479,11 @@ public:
/// Construct with the matrix coefficient. Result is \f$ A^{-1} \f$.
InverseMatrixCoefficient(MatrixCoefficient &A);
/// Reset the matrix coefficient
void SetACoef(MatrixCoefficient &A) { a = &A; }
/// Return the matrix coefficient
MatrixCoefficient * GetACoef() const { return a; }
/// Evaluate the matrix coefficient at @a ip.
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
@@ -1148,11 +1503,61 @@ public:
/// Construct with two vector coefficients. Result is \f$ A B^T \f$.
OuterProductCoefficient(VectorCoefficient &A, VectorCoefficient &B);
/// Reset the first vector in the outer product
void SetACoef(VectorCoefficient &A) { a = &A; }
/// Return the first vector coefficient in the outer product
VectorCoefficient * GetACoef() const { return a; }
/// Reset the second vector in the outer product
void SetBCoef(VectorCoefficient &B) { b = &B; }
/// Return the second vector coefficient in the outer product
VectorCoefficient * GetBCoef() const { return b; }
/// Evaluate the matrix coefficient at @a ip.
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
};
/** @brief Matrix coefficient defined as -a k x k x, for a vector k and scalar a
This coefficient returns \f$a * (|k|^2 I - k \otimes k)\f$, where I is
the identity matrix and \f$\otimes\f$ indicates the outer product. This
can be evaluated for vectors of any dimension but in three
dimensions it corresponds to computing the cross product with k twice.
*/
class CrossCrossCoefficient : public MatrixCoefficient
{
private:
double aConst;
Coefficient * a;
VectorCoefficient * k;
mutable Vector vk;
public:
CrossCrossCoefficient(double A, VectorCoefficient &K);
CrossCrossCoefficient(Coefficient &A, VectorCoefficient &K);
/// Reset the scalar factor as a constant
void SetAConst(double A) { a = NULL; aConst = A; }
/// Return the scalar factor
double GetAConst() const { return aConst; }
/// Reset the scalar factor
void SetACoef(Coefficient &A) { a = &A; }
/// Return the scalar factor
Coefficient * GetACoef() const { return a; }
/// Reset the vector factor
void SetKCoef(VectorCoefficient &K) { k = &K; }
/// Return the vector factor
VectorCoefficient * GetKCoef() const { return k; }
/// Evaluate the matrix coefficient at @a ip.
virtual void Eval(DenseMatrix &M, ElementTransformation &T,
const IntegrationPoint &ip);
};
///@}
class QuadratureFunction;
+135 -53
View File
@@ -342,11 +342,10 @@ SesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
int ci)
{
FiniteElementSpace * fes = blfr->FESpace();
int vsize = fes->GetVSize();
// Allocate temporary vectors
Vector b_0(vsize); b_0 = 0.0;
Vector b_0(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!");
@@ -360,8 +359,7 @@ SesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
if (conv == ComplexOperator::BLOCK_SYMMETRIC) { b_i *= -1.0; }
int tvsize = fes->GetTrueVSize();
SparseMatrix * A_r = nullptr;
SparseMatrix * A_i = nullptr;
OperatorHandle A_r, A_i;
X.SetSize(2 * tvsize);
B.SetSize(2 * tvsize);
@@ -374,42 +372,39 @@ SesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
if (RealInteg())
{
A_r = new SparseMatrix;
blfr->SetDiagonalPolicy(diag_policy);
b_0 = b_r;
blfr->FormLinearSystem(ess_tdof_list, x_r, b_0, *A_r, X_0, B_0, ci);
blfr->FormLinearSystem(ess_tdof_list, x_r, b_0, A_r, X_0, B_0, ci);
X_r = X_0; B_r = B_0;
b_0 = b_i;
blfr->FormLinearSystem(ess_tdof_list, x_i, b_0, *A_r, X_0, B_0, ci);
blfr->FormLinearSystem(ess_tdof_list, x_i, b_0, A_r, X_0, B_0, ci);
X_i = X_0; B_i = B_0;
if (ImagInteg())
{
A_i = new SparseMatrix;
blfi->SetDiagonalPolicy(mfem::Matrix::DiagonalPolicy::DIAG_ZERO);
b_0 = 0.0;
blfi->FormLinearSystem(ess_tdof_list, x_i, b_0, *A_i, X_0, B_0, false);
blfi->FormLinearSystem(ess_tdof_list, x_i, b_0, A_i, X_0, B_0, false);
B_r -= B_0;
b_0 = 0.0;
blfi->FormLinearSystem(ess_tdof_list, x_r, b_0, *A_i, X_0, B_0, false);
blfi->FormLinearSystem(ess_tdof_list, x_r, b_0, A_i, X_0, B_0, false);
B_i += B_0;
}
}
else if (ImagInteg())
{
A_i = new SparseMatrix;
blfi->SetDiagonalPolicy(diag_policy);
b_0 = b_i;
blfi->FormLinearSystem(ess_tdof_list, x_r, b_0, *A_i, X_0, B_0, ci);
blfi->FormLinearSystem(ess_tdof_list, x_r, b_0, A_i, X_0, B_0, ci);
X_r = X_0; B_i = B_0;
b_0 = b_r; b_0 *= -1.0;
blfi->FormLinearSystem(ess_tdof_list, x_i, b_0, *A_i, X_0, B_0, ci);
blfi->FormLinearSystem(ess_tdof_list, x_i, b_0, A_i, X_0, B_0, ci);
X_i = X_0; B_r = B_0; B_r *= -1.0;
}
else
@@ -417,16 +412,55 @@ SesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
MFEM_ABORT("Real and Imaginary part of the Sesquilinear form are empty");
}
if (RealInteg() && ImagInteg())
{
// Modify RHS and offdiagonal blocks (imaginary parts of the matrix) to
// conform with standard essential BC treatment
if (A_i.Is<ConstrainedOperator>())
{
int n = ess_tdof_list.Size();
for (int k = 0; k < n; k++)
{
int j = ess_tdof_list[k];
B_r(j) = X_r(j);
B_i(j) = X_i(j);
}
A_i.As<ConstrainedOperator>()->SetDiagonalPolicy
(mfem::Operator::DiagonalPolicy::DIAG_ZERO);
}
}
if (conv == ComplexOperator::BLOCK_SYMMETRIC)
{
B_i *= -1.0;
b_i *= -1.0;
}
// A = A_r + i A_i
A.Clear();
ComplexSparseMatrix * A_sp;
A_sp = new ComplexSparseMatrix(A_r, A_i, true, true, conv);
A.Reset<ComplexSparseMatrix>(A_sp, true);
if ( A_r.Type() == Operator::MFEM_SPARSEMAT ||
A_i.Type() == Operator::MFEM_SPARSEMAT )
{
ComplexSparseMatrix * A_sp =
new ComplexSparseMatrix(A_r.As<SparseMatrix>(),
A_i.As<SparseMatrix>(),
A_r.OwnsOperator(),
A_i.OwnsOperator(),
conv);
A.Reset<ComplexSparseMatrix>(A_sp, true);
}
else
{
ComplexOperator * A_op =
new ComplexOperator(A_r.Ptr(),
A_i.Ptr(),
A_r.OwnsOperator(),
A_i.OwnsOperator(),
conv);
A.Reset<ComplexOperator>(A_op, true);
}
A_r.SetOperatorOwner(false);
A_i.SetOperatorOwner(false);
}
void
@@ -434,31 +468,60 @@ SesquilinearForm::FormSystemMatrix(const Array<int> &ess_tdof_list,
OperatorHandle &A)
{
SparseMatrix * A_r = nullptr;
SparseMatrix * A_i = nullptr;
OperatorHandle A_r, A_i;
if (RealInteg())
{
A_r = new SparseMatrix;
blfr->SetDiagonalPolicy(diag_policy);
blfr->FormSystemMatrix(ess_tdof_list, *A_r);
blfr->FormSystemMatrix(ess_tdof_list, A_r);
}
if (ImagInteg())
{
A_i = new SparseMatrix;
blfr->SetDiagonalPolicy(diag_policy);
blfi->FormSystemMatrix(ess_tdof_list, *A_i);
blfi->SetDiagonalPolicy(RealInteg() ?
mfem::Matrix::DiagonalPolicy::DIAG_ZERO :
diag_policy);
blfi->FormSystemMatrix(ess_tdof_list, A_i);
}
if (!RealInteg() && !ImagInteg())
{
MFEM_ABORT("Both Real and Imaginary part of the Sesquilinear form are empty");
}
if (RealInteg() && ImagInteg())
{
// Modify offdiagonal blocks (imaginary parts of the matrix) to conform
// with standard essential BC treatment
if (A_i.Is<ConstrainedOperator>())
{
A_i.As<ConstrainedOperator>()->SetDiagonalPolicy
(mfem::Operator::DiagonalPolicy::DIAG_ZERO);
}
}
// A = A_r + i A_i
A.Clear();
ComplexSparseMatrix * A_sp =
new ComplexSparseMatrix(A_r, A_i, true, true, conv);
A.Reset<ComplexSparseMatrix>(A_sp, true);
if ( A_r.Type() == Operator::MFEM_SPARSEMAT ||
A_i.Type() == Operator::MFEM_SPARSEMAT )
{
ComplexSparseMatrix * A_sp =
new ComplexSparseMatrix(A_r.As<SparseMatrix>(),
A_i.As<SparseMatrix>(),
A_r.OwnsOperator(),
A_i.OwnsOperator(),
conv);
A.Reset<ComplexSparseMatrix>(A_sp, true);
}
else
{
ComplexOperator * A_op =
new ComplexOperator(A_r.Ptr(),
A_i.Ptr(),
A_r.OwnsOperator(),
A_i.OwnsOperator(),
conv);
A.Reset<ComplexOperator>(A_op, true);
}
A_r.SetOperatorOwner(false);
A_i.SetOperatorOwner(false);
}
void
@@ -646,7 +709,7 @@ ParComplexLinearForm::ParComplexLinearForm(ParFiniteElementSpace *pfes,
int n = (HYPRE_AssumedPartitionCheck()) ? 2 : pfes->GetNRanks();
tdof_offsets = new HYPRE_Int[n+1];
for (int i=0; i<=n; i++)
for (int i = 0; i <= n; i++)
{
tdof_offsets[i] = 2 * tdof_offsets_fes[i];
}
@@ -654,7 +717,8 @@ ParComplexLinearForm::ParComplexLinearForm(ParFiniteElementSpace *pfes,
ParComplexLinearForm::ParComplexLinearForm(ParFiniteElementSpace *pfes,
ParLinearForm *plf_r, ParLinearForm *plf_i,
ParLinearForm *plf_r,
ParLinearForm *plf_i,
ComplexOperator::Convention
convention)
: Vector(2*(pfes->GetVSize())),
@@ -670,7 +734,7 @@ ParComplexLinearForm::ParComplexLinearForm(ParFiniteElementSpace *pfes,
int n = (HYPRE_AssumedPartitionCheck()) ? 2 : pfes->GetNRanks();
tdof_offsets = new HYPRE_Int[n+1];
for (int i=0; i<=n; i++)
for (int i = 0; i <= n; i++)
{
tdof_offsets[i] = 2 * tdof_offsets_fes[i];
}
@@ -817,7 +881,8 @@ ParSesquilinearForm::ParSesquilinearForm(ParFiniteElementSpace *pf,
{}
ParSesquilinearForm::ParSesquilinearForm(ParFiniteElementSpace *pf,
ParBilinearForm *pbfr, ParBilinearForm *pbfi,
ParBilinearForm *pbfr,
ParBilinearForm *pbfi,
ComplexOperator::Convention convention)
: conv(convention),
pblfr(new ParBilinearForm(pf,pbfr)),
@@ -913,9 +978,10 @@ ParSesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
int vsize = pfes->GetVSize();
// Allocate temporary vectors
Vector b_0(vsize); b_0 = 0.0;
Vector b_0(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);
@@ -974,25 +1040,34 @@ ParSesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
MFEM_ABORT("Real and Imaginary part of the Sesquilinear form are empty");
}
// Modify RHS and offdiagonal blocks (Imaginary parts of the matrix) to
// conform with standard essential BC treatment i.e. zero out rows and
// columns and place ones on the diagonal.
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++)
{
int j=ess_tdof_list[k];
B_r(j) = X_r(j);
B_i(j) = 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 )
{
HypreParMatrix * Ah; A_i.Get(Ah);
int n = ess_tdof_list.Size();
hypre_ParCSRMatrix * Aih =
(hypre_ParCSRMatrix *)const_cast<HypreParMatrix&>(*Ah);
for (int k=0; k<n; k++)
HypreParMatrix * Ah;
A_i.Get(Ah);
hypre_ParCSRMatrix *Aih = *Ah;
for (int k = 0; k < n; k++)
{
int j=ess_tdof_list[k];
int j = ess_tdof_list[k];
Aih->diag->data[Aih->diag->i[j]] = 0.0;
B_r(j) = X_r(j);
B_i(j) = X_i(j);
}
}
else
{
A_i.As<ConstrainedOperator>()->SetDiagonalPolicy
(mfem::Operator::DiagonalPolicy::DIAG_ZERO);
}
}
if (conv == ComplexOperator::BLOCK_SYMMETRIC)
@@ -1000,6 +1075,7 @@ ParSesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
B_i *= -1.0;
b_i *= -1.0;
}
// A = A_r + i A_i
A.Clear();
if ( A_r.Type() == Operator::Hypre_ParCSR ||
@@ -1023,6 +1099,8 @@ ParSesquilinearForm::FormLinearSystem(const Array<int> &ess_tdof_list,
conv);
A.Reset<ComplexOperator>(A_op, true);
}
A_r.SetOperatorOwner(false);
A_i.SetOperatorOwner(false);
}
void
@@ -1043,25 +1121,27 @@ ParSesquilinearForm::FormSystemMatrix(const Array<int> &ess_tdof_list,
MFEM_ABORT("Both Real and Imaginary part of the Sesquilinear form are empty");
}
// Modify offdiagonal blocks (Imaginary parts of the matrix) to conform with
// standard essential BC treatment i.e. zero out rows and columns and place
// ones on the diagonal.
if (RealInteg() && ImagInteg())
{
// Modify offdiagonal blocks (imaginary parts of the matrix) to conform
// with standard essential BC treatment
if ( A_i.Type() == Operator::Hypre_ParCSR )
{
int n = ess_tdof_list.Size();
int j;
HypreParMatrix * Ah; A_i.Get(Ah);
hypre_ParCSRMatrix * Aih =
(hypre_ParCSRMatrix *)const_cast<HypreParMatrix&>(*Ah);
for (int k=0; k<n; k++)
HypreParMatrix * Ah;
A_i.Get(Ah);
hypre_ParCSRMatrix * Aih = *Ah;
for (int k = 0; k < n; k++)
{
j=ess_tdof_list[k];
int j = ess_tdof_list[k];
Aih->diag->data[Aih->diag->i[j]] = 0.0;
}
}
else
{
A_i.As<ConstrainedOperator>()->SetDiagonalPolicy
(mfem::Operator::DiagonalPolicy::DIAG_ZERO);
}
}
// A = A_r + i A_i
@@ -1087,6 +1167,8 @@ ParSesquilinearForm::FormSystemMatrix(const Array<int> &ess_tdof_list,
conv);
A.Reset<ComplexOperator>(A_op, true);
}
A_r.SetOperatorOwner(false);
A_i.SetOperatorOwner(false);
}
void
+31 -1
View File
@@ -219,6 +219,21 @@ public:
void SetConvention(const ComplexOperator::Convention &
convention) { conv = convention; }
/// Set the desired assembly level.
/** Valid choices are:
- AssemblyLevel::FULL (default)
- AssemblyLevel::PARTIAL
- AssemblyLevel::ELEMENT
- AssemblyLevel::NONE
This method must be called before assembly. */
void SetAssemblyLevel(AssemblyLevel assembly_level)
{
blfr->SetAssemblyLevel(assembly_level);
blfi->SetAssemblyLevel(assembly_level);
}
BilinearForm & real() { return *blfr; }
BilinearForm & imag() { return *blfi; }
const BilinearForm & real() const { return *blfr; }
@@ -478,7 +493,7 @@ public:
/** Class for a parallel sesquilinear form
A sesquilinear form is a generalization of a bilinear form to complex-valued
fields. Sesquilinear forms are linear in the second argument but but the
fields. Sesquilinear forms are linear in the second argument but the
first argument involves a complex conjugate in the sense that:
a(alpha u, beta v) = conj(alpha) beta a(u, v)
@@ -524,6 +539,21 @@ public:
void SetConvention(const ComplexOperator::Convention &
convention) { conv = convention; }
/// Set the desired assembly level.
/** Valid choices are:
- AssemblyLevel::FULL (default)
- AssemblyLevel::PARTIAL
- AssemblyLevel::ELEMENT
- AssemblyLevel::NONE
This method must be called before assembly. */
void SetAssemblyLevel(AssemblyLevel assembly_level)
{
pblfr->SetAssemblyLevel(assembly_level);
pblfi->SetAssemblyLevel(assembly_level);
}
ParBilinearForm & real() { return *pblfr; }
ParBilinearForm & imag() { return *pblfi; }
const ParBilinearForm & real() const { return *pblfr; }
+40 -8
View File
@@ -415,9 +415,6 @@ void VisItDataCollection::SetMesh(MPI_Comm comm, Mesh *new_mesh)
void VisItDataCollection::RegisterField(const std::string& name,
GridFunction *gf)
{
DataCollection::RegisterField(name, gf);
field_info_map[name] = VisItFieldInfo("nodes", gf->VectorDim());
int LOD = 1;
if (gf->FESpace()->GetNURBSext())
{
@@ -431,6 +428,27 @@ void VisItDataCollection::RegisterField(const std::string& name,
}
}
DataCollection::RegisterField(name, gf);
field_info_map[name] = VisItFieldInfo("nodes", gf->VectorDim(), LOD);
visit_levels_of_detail = std::max(visit_levels_of_detail, LOD);
}
void VisItDataCollection::RegisterQField(const std::string& name,
QuadratureFunction *qf)
{
int LOD = -1;
Mesh *mesh = qf->GetSpace()->GetMesh();
for (int e=0; e<qf->GetSpace()->GetNE(); e++)
{
int locLOD = GlobGeometryRefiner.GetRefinementLevelFromElems(
mesh->GetElementBaseGeometry(e),
qf->GetElementIntRule(e).GetNPoints());
LOD = std::max(LOD,locLOD);
}
DataCollection::RegisterQField(name, qf);
field_info_map[name] = VisItFieldInfo("elements", 1, LOD);
visit_levels_of_detail = std::max(visit_levels_of_detail, LOD);
}
@@ -598,14 +616,28 @@ void VisItDataCollection::LoadFields()
// TODO: 1) load parallel GridFunction on one processor
if (serial)
{
field_map.Register(it->first, new GridFunction(mesh, file), own_data);
if ((it->second).association == "nodes")
{
field_map.Register(it->first, new GridFunction(mesh, file), own_data);
}
else if ((it->second).association == "elements")
{
q_field_map.Register(it->first, new QuadratureFunction(mesh, file), own_data);
}
}
else
{
#ifdef MFEM_USE_MPI
field_map.Register(
it->first,
new ParGridFunction(dynamic_cast<ParMesh*>(mesh), file), own_data);
if ((it->second).association == "nodes")
{
field_map.Register(
it->first,
new ParGridFunction(dynamic_cast<ParMesh*>(mesh), file), own_data);
}
else if ((it->second).association == "elements")
{
q_field_map.Register(it->first, new QuadratureFunction(mesh, file), own_data);
}
#else
error = READ_ERROR;
MFEM_WARNING("Reading parallel format in serial is not supported");
@@ -640,7 +672,7 @@ std::string VisItDataCollection::GetVisItRootString()
{
ftags["assoc"] = picojson::value((it->second).association);
ftags["comps"] = picojson::value(to_string((it->second).num_components));
ftags["lod"] = picojson::value(to_string(visit_levels_of_detail));
ftags["lod"] = picojson::value(to_string((it->second).lod));
field["path"] = picojson::value(path_str + it->first + file_ext_format);
field["tags"] = picojson::value(ftags);
fields[it->first] = picojson::value(field);
+10 -3
View File
@@ -391,9 +391,10 @@ class VisItFieldInfo
public:
std::string association;
int num_components;
VisItFieldInfo() { association = ""; num_components = 0; }
VisItFieldInfo(std::string _association, int _num_components)
{ association = _association; num_components = _num_components; }
int lod;
VisItFieldInfo() { association = ""; num_components = 0; lod = 1;}
VisItFieldInfo(std::string _association, int _num_components, int _lod = 1)
{ association = _association; num_components = _num_components; lod =_lod;}
};
/// Data collection with VisIt I/O routines
@@ -445,6 +446,12 @@ public:
/// Add a grid function to the collection and update the root file
virtual void RegisterField(const std::string& field_name, GridFunction *gf);
/// Add a quadrature function to the collection and update the root file.
/** Visualization of quadrature function is not supported in VisIt(3.12).
A patch has been sent to VisIt developers in June 2020. */
virtual void RegisterQField(const std::string& q_field_name,
QuadratureFunction *qf);
/// Set VisIt parameter: default levels of detail for the MultiresControl
void SetLevelsOfDetail(int levels_of_detail);
+94 -15
View File
@@ -552,26 +552,32 @@ void IntegrationPointTransformation::Transform (const IntegrationRule &ir1,
}
}
void FaceElementTransformations::SetIntPoint(const IntegrationPoint *ip)
void FaceElementTransformations::SetIntPoint(const IntegrationPoint *face_ip)
{
IsoparametricTransformation::SetIntPoint(ip);
IsoparametricTransformation::SetIntPoint(face_ip);
if (Elem1)
if (mask & 4)
{
Loc1.Transform(*ip, eip1);
Elem1->SetIntPoint(&eip1);
Loc1.Transform(*face_ip, eip1);
if (Elem1)
{
Elem1->SetIntPoint(&eip1);
}
}
if (Elem2)
if (mask & 8)
{
Loc2.Transform(*ip, eip2);
Elem2->SetIntPoint(&eip2);
Loc2.Transform(*face_ip, eip2);
if (Elem2)
{
Elem2->SetIntPoint(&eip2);
}
}
}
ElementTransformation &
FaceElementTransformations::GetElement1Transformation()
{
MFEM_VERIFY(mask & 1 && Elem1 != NULL, "The ElementTransformation "
MFEM_VERIFY(mask & HAVE_ELEM1 && Elem1 != NULL, "The ElementTransformation "
"for the element has not been configured for side 1.");
return *Elem1;
}
@@ -579,7 +585,7 @@ FaceElementTransformations::GetElement1Transformation()
ElementTransformation &
FaceElementTransformations::GetElement2Transformation()
{
MFEM_VERIFY(mask & 2 && Elem2 != NULL, "The ElementTransformation "
MFEM_VERIFY(mask & HAVE_ELEM2 && Elem2 != NULL, "The ElementTransformation "
"for the element has not been configured for side 2.");
return *Elem2;
}
@@ -587,7 +593,7 @@ FaceElementTransformations::GetElement2Transformation()
IntegrationPointTransformation &
FaceElementTransformations::GetIntPoint1Transformation()
{
MFEM_VERIFY(mask & 4, "The IntegrationPointTransformation "
MFEM_VERIFY(mask & HAVE_LOC1, "The IntegrationPointTransformation "
"for the element has not been configured for side 1.");
return Loc1;
}
@@ -595,7 +601,7 @@ FaceElementTransformations::GetIntPoint1Transformation()
IntegrationPointTransformation &
FaceElementTransformations::GetIntPoint2Transformation()
{
MFEM_VERIFY(mask & 8, "The IntegrationPointTransformation "
MFEM_VERIFY(mask & HAVE_LOC2, "The IntegrationPointTransformation "
"for the element has not been configured for side 2.");
return Loc2;
}
@@ -603,7 +609,7 @@ FaceElementTransformations::GetIntPoint2Transformation()
void FaceElementTransformations::Transform(const IntegrationPoint &ip,
Vector &trans)
{
MFEM_VERIFY(mask & 16, "The ElementTransformation "
MFEM_VERIFY(mask & HAVE_FACE, "The ElementTransformation "
"for the face has not been configured.");
IsoparametricTransformation::Transform(ip, trans);
}
@@ -611,7 +617,7 @@ void FaceElementTransformations::Transform(const IntegrationPoint &ip,
void FaceElementTransformations::Transform(const IntegrationRule &ir,
DenseMatrix &tr)
{
MFEM_VERIFY(mask & 16, "The ElementTransformation "
MFEM_VERIFY(mask & HAVE_FACE, "The ElementTransformation "
"for the face has not been configured.");
IsoparametricTransformation::Transform(ir, tr);
}
@@ -619,9 +625,82 @@ void FaceElementTransformations::Transform(const IntegrationRule &ir,
void FaceElementTransformations::Transform(const DenseMatrix &matrix,
DenseMatrix &result)
{
MFEM_VERIFY(mask & 16, "The ElementTransformation "
MFEM_VERIFY(mask & HAVE_FACE, "The ElementTransformation "
"for the face has not been configured.");
IsoparametricTransformation::Transform(matrix, result);
}
double FaceElementTransformations::CheckConsistency(int print_level,
std::ostream &out)
{
// Check that the face vertices are mapped to the same physical location
// when using the following three transformations:
// - the face transformation, *this
// - Loc1 + Elem1
// - Loc2 + Elem2, if present.
const bool have_face = (mask & 16);
const bool have_el1 = (mask & 1) && (mask & 4);
const bool have_el2 = (mask & 2) && (mask & 8) && (Elem2No >= 0);
if (int(have_face) + int(have_el1) + int(have_el2) < 2)
{
// need at least two different transformations to perform a check
return 0.0;
}
const IntegrationRule &v_ir = *Geometries.GetVertices(GetGeometryType());
double max_dist = 0.0;
Vector dist(v_ir.GetNPoints());
DenseMatrix coords_base, coords_el;
IntegrationRule v_eir(v_ir.GetNPoints());
if (have_face)
{
Transform(v_ir, coords_base);
if (print_level > 0)
{
out << "\nface vertex coordinates (from face transform):\n"
<< "----------------------------------------------\n";
coords_base.PrintT(out, coords_base.Height());
}
}
if (have_el1)
{
Loc1.Transform(v_ir, v_eir);
Elem1->Transform(v_eir, coords_el);
if (print_level > 0)
{
out << "\nface vertex coordinates (from element 1 transform):\n"
<< "---------------------------------------------------\n";
coords_el.PrintT(out, coords_el.Height());
}
if (have_face)
{
coords_el -= coords_base;
coords_el.Norm2(dist);
max_dist = std::max(max_dist, dist.Normlinf());
}
else
{
coords_base = coords_el;
}
}
if (have_el2)
{
Loc2.Transform(v_ir, v_eir);
Elem2->Transform(v_eir, coords_el);
if (print_level > 0)
{
out << "\nface vertex coordinates (from element 2 transform):\n"
<< "---------------------------------------------------\n";
coords_el.PrintT(out, coords_el.Height());
}
coords_el -= coords_base;
coords_el.Norm2(dist);
max_dist = std::max(max_dist, dist.Normlinf());
}
return max_dist;
}
}
+120 -11
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.
@@ -439,15 +453,57 @@ public:
void Transform (const IntegrationRule &, IntegrationRule &);
};
/** @brief A specialized ElementTransformation class representing a face and
its two neighboring elements.
This class can be used as a container for the element transformation data
needed for integrating discontinuous fields on element interfaces in a
Discontinuous Galerkin (DG) context.
The secondary purpose of this class is to enable the
GridFunction::GetValue function, and various related functions, to properly
evaluate fields with limited continuity on boundary elements.
*/
class FaceElementTransformations : public IsoparametricTransformation
{
private:
// Bitwise OR of ConfigMasks
int mask;
IntegrationPoint eip1, eip2;
protected: // interface for Mesh to be able to configure this object.
friend class Mesh;
#ifdef MFEM_USE_MPI
friend class ParMesh;
#endif
/// Set the mask indicating which portions of the object have been setup
/** The argument @a m is a bitmask used in
Mesh::GetFaceElementTransformations to indicate which portions of the
FaceElementTransformations object have been configured.
mask & 1: Elem1 is configured
mask & 2: Elem2 is configured
mask & 4: Loc1 is configured
mask & 8: Loc2 is configured
mask & 16: The Face transformation itself is configured
*/
void SetConfigurationMask(int m) { mask = m; }
public:
enum ConfigMasks
{
HAVE_ELEM1 = 1, ///< Element on side 1 is configured
HAVE_ELEM2 = 2, ///< Element on side 2 is configured
HAVE_LOC1 = 4, ///< Point transformation for side 1 is configured
HAVE_LOC2 = 8, ///< Point transformation for side 2 is configured
HAVE_FACE = 16 ///< Face transformation is configured
};
int Elem1No, Elem2No;
Geometry::Type &FaceGeom; ///< @deprecated Use GetGeometryType instead
ElementTransformation *Elem1, *Elem2;
@@ -466,10 +522,10 @@ public:
*/
void SetGeometryType(Geometry::Type g) { geom = g; }
/// Set the mask indicating which portions of the object have been setup
/** The argument @a m is a bitmask used in
Mesh::GetFaceElementTransformations to indicate which portions of the
FaceElement Transformations object have been configured.
/** @brief Return the mask defining the configuration state.
The mask value indicates which portions of FaceElementTransformations
object have been configured.
mask & 1: Elem1 is configured
mask & 2: Elem2 is configured
@@ -477,12 +533,45 @@ public:
mask & 8: Loc2 is configured
mask & 16: The Face transformation itself is configured
*/
void SetConfigurationMask(int m) { mask = m; }
int GetConfigurationMask() const { return mask; }
int GetConfigurationMask() const { return mask; }
/** @brief Set the integration point in the Face and the two neighboring
elements, if present. */
void SetIntPoint(const IntegrationPoint *ip);
elements, if present.
The point @a face_ip must be in the reference coordinate system of the
face.
*/
void SetIntPoint(const IntegrationPoint *face_ip);
/** @brief Set the integration point in the Face and the two neighboring
elements, if present.
This is a more expressive member function name than SetIntPoint, which
in this special case, does the same thing. This function can be used for
greater code clarity.
*/
inline void SetAllIntPoints(const IntegrationPoint *face_ip)
{ FaceElementTransformations::SetIntPoint(face_ip); }
/** @brief Get a const reference to the integration point in neighboring
element 1 corresponding to the currently set integration point on the
face.
This IntegrationPoint object will only contain up-to-date data if
SetIntPoint or SetAllIntPoints has been called with the latest
integration point for the face and the appropriate point transformation
has been configured. */
const IntegrationPoint &GetElement1IntPoint() { return eip1; }
/** @brief Get a const reference to the integration point in neighboring
element 2 corresponding to the currently set integration point on the
face.
This IntegrationPoint object will only contain up-to-date data if
SetIntPoint or SetAllIntPoints has been called with the latest
integration point for the face and the appropriate point transformation
has been configured. */
const IntegrationPoint &GetElement2IntPoint() { return eip2; }
virtual void Transform(const IntegrationPoint &, Vector &);
virtual void Transform(const IntegrationRule &, DenseMatrix &);
@@ -492,6 +581,26 @@ public:
ElementTransformation & GetElement2Transformation();
IntegrationPointTransformation & GetIntPoint1Transformation();
IntegrationPointTransformation & GetIntPoint2Transformation();
/** @brief Check for self-consistency: compares the result of mapping the
reference face vertices to physical coordinates using the three
transformations: face, element 1, and element 2.
@param[in] print_level If set to a positive number, print the physical
coordinates of the face vertices computed through
all available transformations: face, element 1,
and/or element 2.
@param[in,out] out The output stream to use for printing.
@returns A maximal distance between physical coordinates of face vertices
that should coincide. A successful check should return a small
number relative to the mesh extents. If less than 2 of the three
transformations are set, returns 0.
@warning This check will generally fail on periodic boundary faces.
*/
double CheckConsistency(int print_level = 0,
std::ostream &out = mfem::out);
};
/** Elem1(Loc1(x)) = Face(x) = Elem2(Loc2(x))
+167
View File
@@ -7034,6 +7034,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 +7678,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 +7727,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 +7786,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 +7841,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 +7928,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 +7987,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;
+16 -5
View File
@@ -37,7 +37,8 @@ public:
ClosedUniform = 4, ///< Nodes: x_i = i/(n-1), i=0,...,n-1
OpenHalfUniform = 5, ///< Nodes: x_i = (i+1/2)/n, i=0,...,n-1
Serendipity = 6, ///< Serendipity basis (squares / cubes)
NumBasisTypes = 7 /**< Keep track of maximum types to prevent
ClosedGL = 7, ///< Closed GaussLegendre
NumBasisTypes = 8 /**< Keep track of maximum types to prevent
hard-coding */
};
/** @brief If the input does not represents a valid BasisType, abort with an
@@ -69,6 +70,7 @@ public:
case ClosedUniform: return Quadrature1D::ClosedUniform;
case OpenHalfUniform: return Quadrature1D::OpenHalfUniform;
case Serendipity: return Quadrature1D::GaussLobatto;
case ClosedGL: return Quadrature1D::ClosedGL;
}
return Quadrature1D::Invalid;
}
@@ -82,6 +84,7 @@ public:
case Quadrature1D::OpenUniform: return OpenUniform;
case Quadrature1D::ClosedUniform: return ClosedUniform;
case Quadrature1D::OpenHalfUniform: return OpenHalfUniform;
case Quadrature1D::ClosedGL: return ClosedGL;
}
return Invalid;
}
@@ -443,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;
@@ -1847,6 +1850,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:
@@ -2097,7 +2101,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:
@@ -2106,6 +2110,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;
};
@@ -2115,7 +2121,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:
@@ -2125,6 +2131,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;
};
@@ -2134,7 +2142,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:
@@ -2143,6 +2152,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;
};
+6
View File
@@ -756,6 +756,12 @@ public:
/// Return the total number of quadrature points.
int GetSize() const { return size; }
/// Returns the mesh
inline Mesh *GetMesh() const { return mesh; }
/// Returns number of elements in the mesh.
inline int GetNE() const { return mesh->GetNE(); }
/// Get the IntegrationRule associated with mesh element @a idx.
const IntegrationRule &GetElementIntRule(int idx) const
{ return *int_rule[mesh->GetElementBaseGeometry(idx)]; }
+141 -33
View File
@@ -1344,15 +1344,14 @@ const IntegrationRule *GeometryRefiner::RefineInterior(Geometry::Type Geom,
return NULL;
}
ir = FindInIntPts(Geom, Times-1);
if (ir == NULL)
if (ir) { return ir; }
ir = new IntegrationRule(Times-1);
for (int i = 1; i < Times; i++)
{
ir = new IntegrationRule(Times-1);
for (int i = 1; i < Times; i++)
{
IntegrationPoint &ip = ir->IntPoint(i-1);
ip.x = double(i) / Times;
ip.y = ip.z = 0.0;
}
IntegrationPoint &ip = ir->IntPoint(i-1);
ip.x = double(i) / Times;
ip.y = ip.z = 0.0;
}
}
break;
@@ -1364,18 +1363,17 @@ const IntegrationRule *GeometryRefiner::RefineInterior(Geometry::Type Geom,
return NULL;
}
ir = FindInIntPts(Geom, ((Times-1)*(Times-2))/2);
if (ir == NULL)
{
ir = new IntegrationRule(((Times-1)*(Times-2))/2);
for (int k = 0, j = 1; j < Times-1; j++)
for (int i = 1; i < Times-j; i++, k++)
{
IntegrationPoint &ip = ir->IntPoint(k);
ip.x = double(i) / Times;
ip.y = double(j) / Times;
ip.z = 0.0;
}
}
if (ir) { return ir; }
ir = new IntegrationRule(((Times-1)*(Times-2))/2);
for (int k = 0, j = 1; j < Times-1; j++)
for (int i = 1; i < Times-j; i++, k++)
{
IntegrationPoint &ip = ir->IntPoint(k);
ip.x = double(i) / Times;
ip.y = double(j) / Times;
ip.z = 0.0;
}
}
break;
@@ -1386,18 +1384,17 @@ const IntegrationRule *GeometryRefiner::RefineInterior(Geometry::Type Geom,
return NULL;
}
ir = FindInIntPts(Geom, (Times-1)*(Times-1));
if (ir == NULL)
{
ir = new IntegrationRule((Times-1)*(Times-1));
for (int k = 0, j = 1; j < Times; j++)
for (int i = 1; i < Times; i++, k++)
{
IntegrationPoint &ip = ir->IntPoint(k);
ip.x = double(i) / Times;
ip.y = double(j) / Times;
ip.z = 0.0;
}
}
if (ir) { return ir; }
ir = new IntegrationRule((Times-1)*(Times-1));
for (int k = 0, j = 1; j < Times; j++)
for (int i = 1; i < Times; i++, k++)
{
IntegrationPoint &ip = ir->IntPoint(k);
ip.x = double(i) / Times;
ip.y = double(j) / Times;
ip.z = 0.0;
}
}
break;
@@ -1405,10 +1402,121 @@ const IntegrationRule *GeometryRefiner::RefineInterior(Geometry::Type Geom,
mfem_error("GeometryRefiner::RefineInterior(...)");
}
if (ir) { IntPts[Geom].Append(ir); }
MFEM_ASSERT(ir != NULL, "Failed to construct the refined IntegrationRule.");
IntPts[Geom].Append(ir);
return ir;
}
int GeometryRefiner::GetRefinementLevelFromPoints(Geometry::Type geom, int Npts)
{
switch (geom)
{
case Geometry::POINT:
{
return -1;
}
case Geometry::SEGMENT:
{
return Npts -1;
}
case Geometry::TRIANGLE:
{
for (int n = 0, np = 0; (n < 15) && (np < Npts) ; n++)
{
np = (n+1)*(n+2)/2;
if (np == Npts) { return n; }
}
return -1;
}
case Geometry::SQUARE:
{
for (int n = 0, np = 0; (n < 15) && (np < Npts) ; n++)
{
np = (n+1)*(n+1);
if (np == Npts) { return n; }
}
return -1;
}
case Geometry::CUBE:
{
for (int n = 0, np = 0; (n < 15) && (np < Npts) ; n++)
{
np = (n+1)*(n+1)*(n+1);
if (np == Npts) { return n; }
}
return -1;
}
case Geometry::TETRAHEDRON:
{
for (int n = 0, np = 0; (n < 15) && (np < Npts) ; n++)
{
np = (n+3)*(n+2)*(n+1)/6;
if (np == Npts) { return n; }
}
return -1;
}
case Geometry::PRISM:
{
for (int n = 0, np = 0; (n < 15) && (np < Npts) ; n++)
{
np = (n+1)*(n+1)*(n+2)/2;
if (np == Npts) { return n; }
}
return -1;
}
default:
{
mfem_error("Non existing Geometry.");
}
}
return -1;
}
int GeometryRefiner::GetRefinementLevelFromElems(Geometry::Type geom, int Nels)
{
switch (geom)
{
case Geometry::POINT:
{
return -1;
}
case Geometry::SEGMENT:
{
return Nels;
}
case Geometry::TRIANGLE:
case Geometry::SQUARE:
{
for (int n = 0; (n < 15) && (n*n < Nels+1) ; n++)
{
if (n*n == Nels) { return n-1; }
}
return -1;
}
case Geometry::CUBE:
case Geometry::TETRAHEDRON:
case Geometry::PRISM:
{
for (int n = 0; (n < 15) && (n*n*n < Nels+1) ; n++)
{
if (n*n*n == Nels) { return n-1; }
}
return -1;
}
default:
{
mfem_error("Non existing Geometry.");
}
}
return -1;
}
GeometryRefiner GlobGeometryRefiner;
}
+6
View File
@@ -273,6 +273,12 @@ public:
/// @note This method always uses Quadrature1D::OpenUniform points.
const IntegrationRule *RefineInterior(Geometry::Type Geom, int Times);
/// Get the Refinement level based on number of points
virtual int GetRefinementLevelFromPoints(Geometry::Type Geom, int Npts);
/// Get the Refinement level based on number of elements
virtual int GetRefinementLevelFromElems(Geometry::Type geom, int Npts);
~GeometryRefiner();
};
+322 -98
View File
@@ -397,8 +397,16 @@ const
fes->DofsToVDofs(vdim-1, dofs);
Vector DofVal(dofs.Size()), LocVec;
const FiniteElement *fe = fes->GetFE(i);
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE, "invalid FE map type");
fe->CalcShape(ip, DofVal);
if (fe->GetMapType() == FiniteElement::VALUE)
{
fe->CalcShape(ip, DofVal);
}
else
{
ElementTransformation *Tr = fes->GetElementTransformation(i);
Tr->SetIntPoint(&ip);
fe->CalcPhysShape(*Tr, DofVal);
}
GetSubVector(dofs, LocVec);
return (DofVal * LocVec);
@@ -415,10 +423,17 @@ void GridFunction::GetVectorValue(int i, const IntegrationPoint &ip,
GetSubVector(vdofs, loc_data);
if (FElem->GetRangeType() == FiniteElement::SCALAR)
{
MFEM_ASSERT(FElem->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
Vector shape(dof);
FElem->CalcShape(ip, shape);
if (FElem->GetMapType() == FiniteElement::VALUE)
{
FElem->CalcShape(ip, shape);
}
else
{
ElementTransformation *Tr = fes->GetElementTransformation(i);
Tr->SetIntPoint(&ip);
FElem->CalcPhysShape(*Tr, shape);
}
int vdim = fes->GetVDim();
val.SetSize(vdim);
for (int k = 0; k < vdim; k++)
@@ -752,19 +767,21 @@ double GridFunction::GetValue(ElementTransformation &T,
IntegrationPoint fip;
be_to_bfe(FET->GetGeometryType(), o, ip, fip);
FET->SetIntPoint(&fip);
// Compute and set the point in element 1 from fip
FET->SetAllIntPoints(&fip);
ElementTransformation & T1 = FET->GetElement1Transformation();
return GetValue(T1, T1.GetIntPoint(), comp);
}
break;
}
break;
case ElementTransformation::BDR_FACE:
{
FaceElementTransformations * FET =
dynamic_cast<FaceElementTransformations *>(&T);
// Evaluate in neighboring element for both continuous and
// discontinuous fields.
// discontinuous fields (the integration point in T1 should have
// already been set).
ElementTransformation & T1 = FET->GetElement1Transformation();
return GetValue(T1, T1.GetIntPoint(), comp);
}
@@ -888,19 +905,21 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
IntegrationPoint fip;
be_to_bfe(FET->GetGeometryType(), o, ip, fip);
FET->SetIntPoint(&fip);
// Compute and set the point in element 1 from fip
FET->SetAllIntPoints(&fip);
ElementTransformation & T1 = FET->GetElement1Transformation();
return GetVectorValue(T1, T1.GetIntPoint(), val);
}
break;
}
break;
case ElementTransformation::BDR_FACE:
{
FaceElementTransformations * FET =
dynamic_cast<FaceElementTransformations *>(&T);
// Evaluate in neighboring element for both continuous and
// discontinuous fields.
// discontinuous fields (the integration point in T1 should have
// already been set).
ElementTransformation & T1 = FET->GetElement1Transformation();
return GetVectorValue(T1, T1.GetIntPoint(), val);
}
@@ -1031,13 +1050,13 @@ int GridFunction::GetFaceVectorValues(
}
if (di == 0)
{
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 4);
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 5);
Transf->Loc1.Transform(ir, eir);
GetVectorValues(*Transf->Elem1, eir, vals, &tr);
}
else
{
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 8);
Transf = fes->GetMesh()->GetFaceElementTransformations(i, 10);
Transf->Loc2.Transform(ir, eir);
GetVectorValues(*Transf->Elem2, eir, vals, &tr);
}
@@ -1338,107 +1357,262 @@ void GridFunction::GetVectorGradientHat(
MultAtB(loc_data_mat, dshape, gh);
}
double GridFunction::GetDivergence(ElementTransformation &tr) const
double GridFunction::GetDivergence(ElementTransformation &T) const
{
double div_v;
int elNo = tr.ElementNo;
const FiniteElement *FElem = fes->GetFE(elNo);
if (FElem->GetRangeType() == FiniteElement::SCALAR)
switch (T.ElementType)
{
MFEM_ASSERT(FElem->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(tr, grad_hat);
const DenseMatrix &Jinv = tr.InverseJacobian();
div_v = 0.0;
for (int i = 0; i < Jinv.Width(); i++)
case ElementTransformation::ELEMENT:
{
for (int j = 0; j < Jinv.Height(); j++)
int elNo = T.ElementNo;
const FiniteElement *fe = fes->GetFE(elNo);
if (fe->GetRangeType() == FiniteElement::SCALAR)
{
div_v += grad_hat(i, j) * Jinv(j, i);
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(T, grad_hat);
const DenseMatrix &Jinv = T.InverseJacobian();
double div_v = 0.0;
for (int i = 0; i < Jinv.Width(); i++)
{
for (int j = 0; j < Jinv.Height(); j++)
{
div_v += grad_hat(i, j) * Jinv(j, i);
}
}
return div_v;
}
else
{
// Assuming RT-type space
Array<int> dofs;
fes->GetElementDofs(elNo, dofs);
Vector loc_data, divshape(fe->GetDof());
GetSubVector(dofs, loc_data);
fe->CalcDivShape(T.GetIntPoint(), divshape);
return (loc_data * divshape) / T.Weight();
}
}
break;
case ElementTransformation::BDR_ELEMENT:
{
// In order to properly capture the derivative of the normal component
// of the field (as well as the transverse divergence of the
// tangential compoents) we must evaluate it in the neighboring
// element.
FaceElementTransformations * FET =
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
// Boundary elements and Boundary Faces may have different
// orientations so adjust the integration point if necessary.
int o = 0;
if (fes->GetMesh()->Dimension() == 3)
{
int f;
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
}
IntegrationPoint fip;
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
// Compute and set the point in element 1 from fip
FET->SetAllIntPoints(&fip);
ElementTransformation & T1 = FET->GetElement1Transformation();
return GetDivergence(T1);
}
break;
case ElementTransformation::BDR_FACE:
{
// This must be a DG context so this dynamic cast must succeed.
FaceElementTransformations * FET =
dynamic_cast<FaceElementTransformations *>(&T);
// Evaluate in neighboring element (the integration point in T1 should
// have already been set).
ElementTransformation & T1 = FET->GetElement1Transformation();
return GetDivergence(T1);
}
break;
default:
{
MFEM_ABORT("GridFunction::GetDivergence: Unsupported element type \""
<< T.ElementType << "\"");
}
}
else
{
// Assuming RT-type space
Array<int> dofs;
fes->GetElementDofs(elNo, dofs);
Vector loc_data, divshape(FElem->GetDof());
GetSubVector(dofs, loc_data);
FElem->CalcDivShape(tr.GetIntPoint(), divshape);
div_v = (loc_data * divshape) / tr.Weight();
}
return div_v;
return 0.0; // never reached
}
void GridFunction::GetCurl(ElementTransformation &tr, Vector &curl) const
void GridFunction::GetCurl(ElementTransformation &T, Vector &curl) const
{
int elNo = tr.ElementNo;
const FiniteElement *FElem = fes->GetFE(elNo);
if (FElem->GetRangeType() == FiniteElement::SCALAR)
switch (T.ElementType)
{
MFEM_ASSERT(FElem->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(tr, grad_hat);
const DenseMatrix &Jinv = tr.InverseJacobian();
DenseMatrix grad(grad_hat.Height(), Jinv.Width()); // vdim x FElem->Dim
Mult(grad_hat, Jinv, grad);
MFEM_ASSERT(grad.Height() == grad.Width(), "");
if (grad.Height() == 3)
case ElementTransformation::ELEMENT:
{
curl.SetSize(3);
curl(0) = grad(2,1) - grad(1,2);
curl(1) = grad(0,2) - grad(2,0);
curl(2) = grad(1,0) - grad(0,1);
int elNo = T.ElementNo;
const FiniteElement *fe = fes->GetFE(elNo);
if (fe->GetRangeType() == FiniteElement::SCALAR)
{
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(T, grad_hat);
const DenseMatrix &Jinv = T.InverseJacobian();
// Dimensions of grad are vdim x FElem->Dim
DenseMatrix grad(grad_hat.Height(), Jinv.Width());
Mult(grad_hat, Jinv, grad);
MFEM_ASSERT(grad.Height() == grad.Width(), "");
if (grad.Height() == 3)
{
curl.SetSize(3);
curl(0) = grad(2,1) - grad(1,2);
curl(1) = grad(0,2) - grad(2,0);
curl(2) = grad(1,0) - grad(0,1);
}
else if (grad.Height() == 2)
{
curl.SetSize(1);
curl(0) = grad(1,0) - grad(0,1);
}
}
else
{
// Assuming ND-type space
Array<int> dofs;
fes->GetElementDofs(elNo, dofs);
Vector loc_data;
GetSubVector(dofs, loc_data);
DenseMatrix curl_shape(fe->GetDof(), fe->GetDim() == 3 ? 3 : 1);
fe->CalcCurlShape(T.GetIntPoint(), curl_shape);
curl.SetSize(curl_shape.Width());
if (curl_shape.Width() == 3)
{
double curl_hat[3];
curl_shape.MultTranspose(loc_data, curl_hat);
T.Jacobian().Mult(curl_hat, curl);
}
else
{
curl_shape.MultTranspose(loc_data, curl);
}
curl /= T.Weight();
}
}
else if (grad.Height() == 2)
break;
case ElementTransformation::BDR_ELEMENT:
{
curl.SetSize(1);
curl(0) = grad(1,0) - grad(0,1);
// In order to capture the tangential components of the curl we
// must evaluate it in the neighboring element.
FaceElementTransformations * FET =
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
// Boundary elements and Boundary Faces may have different
// orientations so adjust the integration point if necessary.
int o = 0;
if (fes->GetMesh()->Dimension() == 3)
{
int f;
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
}
IntegrationPoint fip;
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
// Compute and set the point in element 1 from fip
FET->SetAllIntPoints(&fip);
ElementTransformation & T1 = FET->GetElement1Transformation();
GetCurl(T1, curl);
}
}
else
{
// Assuming ND-type space
Array<int> dofs;
fes->GetElementDofs(elNo, dofs);
Vector loc_data;
GetSubVector(dofs, loc_data);
DenseMatrix curl_shape(FElem->GetDof(), FElem->GetDim() == 3 ? 3 : 1);
FElem->CalcCurlShape(tr.GetIntPoint(), curl_shape);
curl.SetSize(curl_shape.Width());
if (curl_shape.Width() == 3)
break;
case ElementTransformation::BDR_FACE:
{
double curl_hat[3];
curl_shape.MultTranspose(loc_data, curl_hat);
tr.Jacobian().Mult(curl_hat, curl);
// This must be a DG context so this dynamic cast must succeed.
FaceElementTransformations * FET =
dynamic_cast<FaceElementTransformations *>(&T);
// Evaluate in neighboring element (the integration point in T1 should
// have already been set).
ElementTransformation & T1 = FET->GetElement1Transformation();
GetCurl(T1, curl);
}
else
break;
default:
{
curl_shape.MultTranspose(loc_data, curl);
MFEM_ABORT("GridFunction::GetCurl: Unsupported element type \""
<< T.ElementType << "\"");
}
curl /= tr.Weight();
}
}
void GridFunction::GetGradient(ElementTransformation &tr, Vector &grad) const
void GridFunction::GetGradient(ElementTransformation &T, Vector &grad) const
{
int elNo = tr.ElementNo;
const FiniteElement *fe = fes->GetFE(elNo);
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE, "invalid FE map type");
int dim = fe->GetDim(), dof = fe->GetDof();
DenseMatrix dshape(dof, dim);
Vector lval, gh(dim);
Array<int> dofs;
switch (T.ElementType)
{
case ElementTransformation::ELEMENT:
{
const FiniteElement * fe = fes->GetFE(T.ElementNo);
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
int spaceDim = fes->GetMesh()->SpaceDimension();
int dim = fe->GetDim(), dof = fe->GetDof();
DenseMatrix dshape(dof, dim);
Vector lval, gh(dim);
Array<int> dofs;
grad.SetSize(dim);
fes->GetElementDofs(elNo, dofs);
GetSubVector(dofs, lval);
fe->CalcDShape(tr.GetIntPoint(), dshape);
dshape.MultTranspose(lval, gh);
tr.InverseJacobian().MultTranspose(gh, grad);
grad.SetSize(spaceDim);
fes->GetElementDofs(T.ElementNo, dofs);
GetSubVector(dofs, lval);
fe->CalcDShape(T.GetIntPoint(), dshape);
dshape.MultTranspose(lval, gh);
T.InverseJacobian().MultTranspose(gh, grad);
}
break;
case ElementTransformation::BDR_ELEMENT:
{
// In order to properly capture the normal component of the gradient
// as well as its tangential components we must evaluate it in the
// neighboring element.
FaceElementTransformations * FET =
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
// Boundary elements and Boundary Faces may have different
// orientations so adjust the integration point if necessary.
int o = 0;
if (fes->GetMesh()->Dimension() == 3)
{
int f;
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
}
IntegrationPoint fip;
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
// Compute and set the point in element 1 from fip
FET->SetAllIntPoints(&fip);
ElementTransformation & T1 = FET->GetElement1Transformation();
GetGradient(T1, grad);
}
break;
case ElementTransformation::BDR_FACE:
{
// This must be a DG context so this dynamic cast must succeed.
FaceElementTransformations * FET =
dynamic_cast<FaceElementTransformations *>(&T);
// Evaluate in neighboring element (the integration point in T1 should
// have already been set).
ElementTransformation & T1 = FET->GetElement1Transformation();
GetGradient(T1, grad);
}
break;
default:
{
MFEM_ABORT("GridFunction::GetGradient: Unsupported element type \""
<< T.ElementType << "\"");
}
}
}
void GridFunction::GetGradients(ElementTransformation &tr,
@@ -1467,15 +1641,65 @@ void GridFunction::GetGradients(ElementTransformation &tr,
}
void GridFunction::GetVectorGradient(
ElementTransformation &tr, DenseMatrix &grad) const
ElementTransformation &T, DenseMatrix &grad) const
{
MFEM_ASSERT(fes->GetFE(tr.ElementNo)->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(tr, grad_hat);
const DenseMatrix &Jinv = tr.InverseJacobian();
grad.SetSize(grad_hat.Height(), Jinv.Width());
Mult(grad_hat, Jinv, grad);
switch (T.ElementType)
{
case ElementTransformation::ELEMENT:
{
MFEM_ASSERT(fes->GetFE(T.ElementNo)->GetMapType() ==
FiniteElement::VALUE, "invalid FE map type");
DenseMatrix grad_hat;
GetVectorGradientHat(T, grad_hat);
const DenseMatrix &Jinv = T.InverseJacobian();
grad.SetSize(grad_hat.Height(), Jinv.Width());
Mult(grad_hat, Jinv, grad);
}
break;
case ElementTransformation::BDR_ELEMENT:
{
// In order to capture the normal component of the gradient we
// must evaluate it in the neighboring element.
FaceElementTransformations * FET =
fes->GetMesh()->GetBdrFaceTransformations(T.ElementNo);
// Boundary elements and Boundary Faces may have different
// orientations so adjust the integration point if necessary.
int o = 0;
if (fes->GetMesh()->Dimension() == 3)
{
int f;
fes->GetMesh()->GetBdrElementFace(T.ElementNo, &f, &o);
}
IntegrationPoint fip;
be_to_bfe(FET->GetGeometryType(), o, T.GetIntPoint(), fip);
// Compute and set the point in element 1 from fip
FET->SetAllIntPoints(&fip);
ElementTransformation & T1 = FET->GetElement1Transformation();
GetVectorGradient(T1, grad);
}
break;
case ElementTransformation::BDR_FACE:
{
// This must be a DG context so this dynamic cast must succeed.
FaceElementTransformations * FET =
dynamic_cast<FaceElementTransformations *>(&T);
// Evaluate in neighboring element (the integration point in T1 should
// have already been set).
ElementTransformation & T1 = FET->GetElement1Transformation();
GetVectorGradient(T1, grad);
}
break;
default:
{
MFEM_ABORT("GridFunction::GetVectorGradient: "
"Unsupported element type \"" << T.ElementType << "\"");
}
}
}
void GridFunction::GetElementAverages(GridFunction &avgs) const
+9 -7
View File
@@ -105,7 +105,7 @@ public:
have the same size.
@note Defining this method overwrites the implicitly defined copy
assignemnt operator. */
assignment operator. */
GridFunction &operator=(const GridFunction &rhs)
{ return operator=((const Vector &)rhs); }
@@ -162,7 +162,8 @@ public:
int vdim = 1) const;
/** Return a vector value from within the given element. */
void GetVectorValue(int i, const IntegrationPoint &ip, Vector &val) const;
virtual void GetVectorValue(int i, const IntegrationPoint &ip,
Vector &val) const;
///@}
/** @name Element Index Get Values Methods
@@ -208,13 +209,14 @@ public:
///@{
/** Return a scalar value from within the element indicated by the
ElementTransformation Object. */
double GetValue(ElementTransformation &T, const IntegrationPoint &ip,
int comp = 0, Vector *tr = NULL) const;
virtual double GetValue(ElementTransformation &T, const IntegrationPoint &ip,
int comp = 0, Vector *tr = NULL) const;
/** Return a vector value from within the element indicated by the
ElementTransformation Object. */
void GetVectorValue(ElementTransformation &T, const IntegrationPoint &ip,
Vector &val, Vector *tr = NULL) const;
virtual void GetVectorValue(ElementTransformation &T,
const IntegrationPoint &ip,
Vector &val, Vector *tr = NULL) const;
///@}
/** @name ElementTransformation Get Values Methods
@@ -712,7 +714,7 @@ public:
the same size.
@note Defining this method overwrites the implicitly defined copy
assignemnt operator. */
assignment operator. */
QuadratureFunction &operator=(const QuadratureFunction &v);
/// Get the IntegrationRule associated with mesh element @a idx.
+1
View File
@@ -192,6 +192,7 @@ void FindPointsGSLIB::Interpolate(Array<unsigned int> &codes,
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++)
{
+25
View File
@@ -618,6 +618,26 @@ void QuadratureFunctions1D::OpenHalfUniform(const int np, IntegrationRule* ir)
CalculateUniformWeights(ir, Quadrature1D::OpenHalfUniform);
}
void QuadratureFunctions1D::ClosedGL(const int np, IntegrationRule* ir)
{
ir->SetSize(np);
ir->IntPoint(0).x = 0.0;
ir->IntPoint(np-1).x = 1.0;
if ( np > 2 )
{
IntegrationRule gl_ir;
GaussLegendre(np-1, &gl_ir);
for (int i = 1; i < np-1; ++i)
{
ir->IntPoint(i).x = (gl_ir.IntPoint(i-1).x + gl_ir.IntPoint(i).x)/2;
}
}
CalculateUniformWeights(ir, Quadrature1D::ClosedGL);
}
void QuadratureFunctions1D::GivePolyPoints(const int np, double *pts,
const int type)
{
@@ -650,6 +670,11 @@ void QuadratureFunctions1D::GivePolyPoints(const int np, double *pts,
OpenHalfUniform(np, &ir);
break;
}
case Quadrature1D::ClosedGL:
{
ClosedGL(np, &ir);
break;
}
default:
{
MFEM_ABORT("Asking for an unknown type of 1D Quadrature points, "
+3 -1
View File
@@ -272,6 +272,7 @@ public:
void OpenUniform(const int np, IntegrationRule *ir);
void ClosedUniform(const int np, IntegrationRule *ir);
void OpenHalfUniform(const int np, IntegrationRule *ir);
void ClosedGL(const int np, IntegrationRule *ir);
///@}
/// A helper function that will play nice with Poly_1D::OpenPoints and
@@ -293,7 +294,8 @@ public:
GaussLobatto = 1,
OpenUniform = 2, ///< aka open Newton-Cotes
ClosedUniform = 3, ///< aka closed Newton-Cotes
OpenHalfUniform = 4 ///< aka "open half" Newton-Cotes
OpenHalfUniform = 4, ///< aka "open half" Newton-Cotes
ClosedGL = 5 ///< aka closed Gauss Legendre
};
/** @brief If the Quadrature1D type is not closed return Invalid; otherwise
return type. */
+91 -19
View File
@@ -97,6 +97,8 @@ static void InitCeedNonTensorBasisAndRestriction(const FiniteElementSpace &fes,
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());
const TensorBasisElement * tfe =
@@ -128,7 +130,15 @@ static void InitCeedNonTensorBasisAndRestriction(const FiniteElementSpace &fes,
const int el_offset = fe->GetDof() * i;
for (int j = 0; j < fe->GetDof(); j++)
{
tp_el_dof[j + el_offset] = el_dof.GetJ()[dof_map[j] + el_offset];
if (compstride == 1)
{
tp_el_dof[j + el_offset] = fes.GetVDim()*
el_dof.GetJ()[dof_map[j] + el_offset];
}
else
{
tp_el_dof[j + el_offset] = el_dof.GetJ()[dof_map[j] + el_offset];
}
}
}
}
@@ -157,20 +167,23 @@ static void InitCeedNonTensorBasisAndRestriction(const FiniteElementSpace &fes,
{
for (int i = 0; i < P; i++)
{
tp_el_dof[i + e*P] = el_dof.GetJ()[i + e*P];
if (compstride == 1)
{
tp_el_dof[i + e*P] = fes.GetVDim()*el_dof.GetJ()[i + e*P];
}
else
{
tp_el_dof[i + e*P] = el_dof.GetJ()[i + e*P];
}
}
}
}
CeedBasisCreateH1(ceed, GetCeedTopology(fe->GetGeomType()), fes.GetVDim(),
fe->GetDof(), ir.GetNPoints(), shape.GetData(),
grad.GetData(), qref.GetData(), qweight.GetData(), basis);
CeedInterlaceMode imode = CEED_NONINTERLACED;
if (fes.GetOrdering()==Ordering::byVDIM)
{
imode = CEED_INTERLACED;
}
CeedElemRestrictionCreate(ceed, imode, mesh->GetNE(), fe->GetDof(),
fes.GetNDofs(), fes.GetVDim(), CEED_MEM_HOST, CEED_COPY_VALUES,
CeedElemRestrictionCreate(ceed, mesh->GetNE(), fe->GetDof(), fes.GetVDim(),
compstride, (fes.GetVDim())*(fes.GetNDofs()),
CEED_MEM_HOST, CEED_COPY_VALUES,
tp_el_dof.GetData(), restr);
}
@@ -215,6 +228,7 @@ static void InitCeedTensorBasisAndRestriction(const FiniteElementSpace &fes,
grad1d.GetData(), qref1d.GetData(),
qweight1d.GetData(), basis);
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());
for (int i = 0; i < mesh->GetNE(); i++)
@@ -222,16 +236,20 @@ static void InitCeedTensorBasisAndRestriction(const FiniteElementSpace &fes,
const int el_offset = fe->GetDof() * i;
for (int j = 0; j < fe->GetDof(); j++)
{
tp_el_dof[j + el_offset] = el_dof.GetJ()[dof_map[j] + el_offset];
if (compstride == 1)
{
tp_el_dof[j + el_offset] = fes.GetVDim()*
el_dof.GetJ()[dof_map[j] + el_offset];
}
else
{
tp_el_dof[j + el_offset] = el_dof.GetJ()[dof_map[j] + el_offset];
}
}
}
CeedInterlaceMode imode = CEED_NONINTERLACED;
if (fes.GetOrdering()==Ordering::byVDIM)
{
imode = CEED_INTERLACED;
}
CeedElemRestrictionCreate(ceed, imode, mesh->GetNE(), fe->GetDof(),
fes.GetNDofs(), fes.GetVDim(), CEED_MEM_HOST, CEED_COPY_VALUES,
CeedElemRestrictionCreate(ceed, mesh->GetNE(), fe->GetDof(), fes.GetVDim(),
compstride, (fes.GetVDim())*(fes.GetNDofs()),
CEED_MEM_HOST, CEED_COPY_VALUES,
tp_el_dof.GetData(), restr);
}
@@ -298,8 +316,9 @@ void CeedPAAssemble(const CeedPAOperator& op,
CeedBasisGetNumQuadraturePoints(ceedData.basis, &nqpts);
const int qdatasize = op.qdatasize;
CeedElemRestrictionCreateStrided(ceed, nelem, nqpts, nelem*nqpts, qdatasize,
CEED_STRIDES_BACKEND, &ceedData.restr_i);
CeedElemRestrictionCreateStrided(ceed, nelem, nqpts, qdatasize,
nelem*nqpts*qdatasize, CEED_STRIDES_BACKEND,
&ceedData.restr_i);
CeedVectorCreate(ceed, mesh->GetNodes()->Size(), &ceedData.node_coords);
CeedVectorSetArray(ceedData.node_coords, CEED_MEM_HOST, CEED_USE_POINTER,
@@ -396,6 +415,59 @@ void CeedPAAssemble(const CeedPAOperator& op,
CeedVectorCreate(ceed, fes.GetNDofs(), &ceedData.v);
}
void CeedAddMultPA(const CeedData *ceedDataPtr,
const Vector &x,
Vector &y)
{
const CeedScalar *x_ptr;
CeedScalar *y_ptr;
CeedMemType mem;
CeedGetPreferredMemType(internal::ceed, &mem);
if ( Device::Allows(Backend::CUDA) && mem==CEED_MEM_DEVICE )
{
x_ptr = x.Read();
y_ptr = y.ReadWrite();
}
else
{
x_ptr = x.HostRead();
y_ptr = y.HostReadWrite();
mem = CEED_MEM_HOST;
}
CeedVectorSetArray(ceedDataPtr->u, mem, CEED_USE_POINTER,
const_cast<CeedScalar*>(x_ptr));
CeedVectorSetArray(ceedDataPtr->v, mem, CEED_USE_POINTER, y_ptr);
CeedOperatorApplyAdd(ceedDataPtr->oper, ceedDataPtr->u, ceedDataPtr->v,
CEED_REQUEST_IMMEDIATE);
CeedVectorTakeArray(ceedDataPtr->u, mem, const_cast<CeedScalar**>(&x_ptr));
CeedVectorTakeArray(ceedDataPtr->v, mem, &y_ptr);
}
void CeedAssembleDiagonalPA(const CeedData *ceedDataPtr,
Vector &diag)
{
CeedScalar *d_ptr;
CeedMemType mem;
CeedGetPreferredMemType(internal::ceed, &mem);
if ( Device::Allows(Backend::CUDA) && mem==CEED_MEM_DEVICE )
{
d_ptr = diag.ReadWrite();
}
else
{
d_ptr = diag.HostReadWrite();
mem = CEED_MEM_HOST;
}
CeedVectorSetArray(ceedDataPtr->v, mem, CEED_USE_POINTER, d_ptr);
CeedOperatorLinearAssembleAddDiagonal(ceedDataPtr->oper, ceedDataPtr->v,
CEED_REQUEST_IMMEDIATE);
CeedVectorTakeArray(ceedDataPtr->v, mem, &d_ptr);
}
} // namespace mfem
#endif // MFEM_USE_CEED
+10
View File
@@ -16,6 +16,7 @@
#ifdef MFEM_USE_CEED
#include "../../general/device.hpp"
#include "../../linalg/vector.hpp"
#include <ceed.h>
namespace mfem
@@ -144,6 +145,15 @@ const std::string &GetCeedPath();
void CeedPAAssemble(const CeedPAOperator& op,
CeedData& ceedData);
/** @brief Function that applies a libCEED PA operator. */
void CeedAddMultPA(const CeedData *ceedDataPtr,
const Vector &x,
Vector &y);
/** @brief Function that assembles a libCEED PA operator diagonal. */
void CeedAssembleDiagonalPA(const CeedData *ceedDataPtr,
Vector &diag);
/** @brief Function that determines if a CEED kernel should be used, based on
the current mfem::Device configuration. */
inline bool DeviceCanUseCeed()
+2 -1
View File
@@ -199,7 +199,8 @@ void LinearForm::Assemble()
void LinearForm::Update(FiniteElementSpace *f, Vector &v, int v_offset)
{
fes = f;
NewDataAndSize((double *)v + v_offset, fes->GetVSize());
NewMemoryAndSize(Memory<double>(v.GetMemory(), v_offset, f->GetVSize()),
f->GetVSize(), false);
ResetDeltaLocations();
}
+197 -25
View File
@@ -63,6 +63,53 @@ void DomainLFIntegrator::AssembleDeltaElementVect(
elvect *= delta->EvalDelta(Trans, Trans.GetIntPoint());
}
void DomainLFGradIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
int dof = el.GetDof();
int spaceDim = Tr.GetSpaceDim();
dshape.SetSize(dof, spaceDim);
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int intorder = 2 * el.GetOrder();
ir = &IntRules.Get(el.GetGeomType(), intorder);
}
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Tr.SetIntPoint(&ip);
el.CalcPhysDShape(Tr, dshape);
Q.Eval(Qvec, Tr, ip);
Qvec *= ip.weight * Tr.Weight();
dshape.AddMult(Qvec, elvect);
}
}
void DomainLFGradIntegrator::AssembleDeltaElementVect(
const FiniteElement &fe, ElementTransformation &Trans, Vector &elvect)
{
MFEM_ASSERT(vec_delta != NULL,"coefficient must be VectorDeltaCoefficient");
int dof = fe.GetDof();
int spaceDim = Trans.GetSpaceDim();
dshape.SetSize(dof, spaceDim);
fe.CalcPhysDShape(Trans, dshape);
vec_delta->EvalDelta(Qvec, Trans, Trans.GetIntPoint());
elvect.SetSize(dof);
dshape.Mult(Qvec, elvect);
}
void BoundaryLFIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
@@ -112,10 +159,13 @@ void BoundaryLFIntegrator::AssembleRHSElementVect(
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
IntegrationPoint eip;
Tr.Loc1.Transform(ip, eip);
Tr.Face->SetIntPoint (&ip);
// Set the integration point in the face and the neighboring element
Tr.SetAllIntPoints(&ip);
// Access the neighboring element's integration point
const IntegrationPoint &eip = Tr.GetElement1IntPoint();
double val = Tr.Face->Weight() * ip.weight * Q.Eval(*Tr.Face, ip);
el.CalcShape(eip, shape);
@@ -255,7 +305,6 @@ void VectorDomainLFIntegrator::AssembleDeltaElementVect(
MultVWt(shape, Qvec, elvec_as_mat);
}
void VectorBoundaryLFIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
@@ -313,10 +362,12 @@ void VectorBoundaryLFIntegrator::AssembleRHSElementVect(
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
IntegrationPoint eip;
Tr.Loc1.Transform(ip, eip);
Tr.SetIntPoint(&ip);
// Set the integration point in the face and the neighboring element
Tr.SetAllIntPoints(&ip);
// Access the neighboring element's integration point
const IntegrationPoint &eip = Tr.GetElement1IntPoint();
// Use Tr transformation in case Q depends on boundary attribute
Q.Eval(vec, Tr, ip);
@@ -332,7 +383,6 @@ void VectorBoundaryLFIntegrator::AssembleRHSElementVect(
}
}
void VectorFEDomainLFIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
@@ -362,7 +412,6 @@ void VectorFEDomainLFIntegrator::AssembleRHSElementVect(
QF.Eval (vec, Tr, ip);
vec *= ip.weight * Tr.Weight();
vshape.AddMult (vec, elvect);
}
}
@@ -383,6 +432,125 @@ void VectorFEDomainLFIntegrator::AssembleDeltaElementVect(
vshape.Mult(vec, elvect);
}
void VectorFEDomainLFCurlIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
int dof = el.GetDof();
int spaceDim = Tr.GetSpaceDim();
int n=(spaceDim == 3)? spaceDim : 1;
curlshape.SetSize(dof,n);
vec.SetSize(n);
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int intorder = 2*el.GetOrder();
ir = &IntRules.Get(el.GetGeomType(), intorder);
}
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Tr.SetIntPoint (&ip);
el.CalcPhysCurlShape(Tr, curlshape);
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);
}
}
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
}
int dof = fe.GetDof();
int n=(spaceDim == 3)? spaceDim : 1;
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
}
}
void VectorFEDomainLFDivIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
int dof = el.GetDof();
divshape.SetSize(dof); // vector of size dof
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int intorder = 2 * el.GetOrder();
ir = &IntRules.Get(el.GetGeomType(), intorder);
}
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Tr.SetIntPoint (&ip);
double val = Tr.Weight() * Q.Eval(Tr, ip);
el.CalcPhysDivShape(Tr, divshape);
add(elvect, ip.weight * val, divshape, elvect);
}
}
void VectorFEDomainLFDivIntegrator::AssembleDeltaElementVect(
const FiniteElement &fe, ElementTransformation &Trans, Vector &elvect)
{
MFEM_ASSERT(delta != NULL, "coefficient must be DeltaCoefficient");
elvect.SetSize(fe.GetDof());
fe.CalcPhysDivShape(Trans, elvect);
elvect *= delta->EvalDelta(Trans, Trans.GetIntPoint());
}
void VectorBoundaryFluxLFIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
@@ -448,7 +616,6 @@ void VectorFEBoundaryFluxLFIntegrator::AssembleRHSElementVect(
}
}
void VectorFEBoundaryTangentLFIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
@@ -483,7 +650,6 @@ void VectorFEBoundaryTangentLFIntegrator::AssembleRHSElementVect(
}
}
void BoundaryFlowIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
@@ -522,11 +688,13 @@ void BoundaryFlowIntegrator::AssembleRHSElementVect(
for (int p = 0; p < ir->GetNPoints(); p++)
{
const IntegrationPoint &ip = ir->IntPoint(p);
IntegrationPoint eip;
Tr.Loc1.Transform(ip, eip);
el.CalcShape(eip, shape);
Tr.SetIntPoint(&ip);
// Set the integration point in the face and the neighboring element
Tr.SetAllIntPoints(&ip);
// Access the neighboring element's integration point
const IntegrationPoint &eip = Tr.GetElement1IntPoint();
el.CalcShape(eip, shape);
// Use Tr.Elem1 transformation for u so that it matches the coefficient
// used with the ConvectionIntegrator and/or the DGTraceIntegrator.
@@ -548,7 +716,6 @@ void BoundaryFlowIntegrator::AssembleRHSElementVect(
}
}
void DGDirichletLFIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
@@ -592,10 +759,13 @@ void DGDirichletLFIntegrator::AssembleRHSElementVect(
for (int p = 0; p < ir->GetNPoints(); p++)
{
const IntegrationPoint &ip = ir->IntPoint(p);
IntegrationPoint eip;
Tr.Loc1.Transform(ip, eip);
Tr.SetIntPoint(&ip);
// Set the integration point in the face and the neighboring element
Tr.SetAllIntPoints(&ip);
// Access the neighboring element's integration point
const IntegrationPoint &eip = Tr.GetElement1IntPoint();
if (dim == 1)
{
nor(0) = 2*eip.x - 1.0;
@@ -614,14 +784,14 @@ void DGDirichletLFIntegrator::AssembleRHSElementVect(
{
if (Q)
{
w *= Q->Eval(Tr, ip);
w *= Q->Eval(*Tr.Elem1, eip);
}
ni.Set(w, nor);
}
else
{
nh.Set(w, nor);
MQ->Eval(mq, Tr, ip);
MQ->Eval(mq, *Tr.Elem1, eip);
mq.MultTranspose(nh, ni);
}
CalcAdjugate(Tr.Elem1->Jacobian(), adjJ);
@@ -637,7 +807,6 @@ void DGDirichletLFIntegrator::AssembleRHSElementVect(
}
}
void DGElasticityDirichletLFIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
@@ -686,9 +855,12 @@ void DGElasticityDirichletLFIntegrator::AssembleRHSElementVect(
for (int pi = 0; pi < ir->GetNPoints(); ++pi)
{
const IntegrationPoint &ip = ir->IntPoint(pi);
IntegrationPoint eip;
Tr.Loc1.Transform(ip, eip);
Tr.SetIntPoint(&ip);
// Set the integration point in the face and the neighboring element
Tr.SetAllIntPoints(&ip);
// Access the neighboring element's integration point
const IntegrationPoint &eip = Tr.GetElement1IntPoint();
// Evaluate the Dirichlet b.c. using the face transformation.
uD.Eval(u_dir, Tr, ip);
+78 -1
View File
@@ -119,6 +119,33 @@ public:
using LinearFormIntegrator::AssembleRHSElementVect;
};
/// Class for domain integrator L(v) := (f, grad v)
class DomainLFGradIntegrator : public DeltaLFIntegrator
{
private:
Vector shape, Qvec;
VectorCoefficient &Q;
DenseMatrix dshape;
public:
/// Constructs the domain integrator (Q, grad v)
DomainLFGradIntegrator(VectorCoefficient &QF)
: DeltaLFIntegrator(QF), Q(QF) { }
/** Given a particular Finite Element and a transformation (Tr)
computes the element right hand side element vector, elvect. */
virtual void AssembleRHSElementVect(const FiniteElement &el,
ElementTransformation &Tr,
Vector &elvect);
virtual void AssembleDeltaElementVect(const FiniteElement &fe,
ElementTransformation &Trans,
Vector &elvect);
using LinearFormIntegrator::AssembleRHSElementVect;
};
/// Class for boundary integration L(v) := (g, v)
class BoundaryLFIntegrator : public LinearFormIntegrator
{
@@ -252,6 +279,56 @@ public:
using LinearFormIntegrator::AssembleRHSElementVect;
};
/// \f$ (Q, curl v)_{\Omega} \f$ for Nedelec Elements)
class VectorFEDomainLFCurlIntegrator : public DeltaLFIntegrator
{
private:
VectorCoefficient *QF=nullptr;
Coefficient *Q=nullptr;
DenseMatrix curlshape;
Vector vec;
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,
Vector &elvect);
virtual void AssembleDeltaElementVect(const FiniteElement &fe,
ElementTransformation &Trans,
Vector &elvect);
using LinearFormIntegrator::AssembleRHSElementVect;
};
/// \f$ (Q, div v)_{\Omega} \f$ for RT Elements)
class VectorFEDomainLFDivIntegrator : public DeltaLFIntegrator
{
private:
Vector divshape;
Coefficient &Q;
public:
/// Constructs the domain integrator (Q, div v)
VectorFEDomainLFDivIntegrator(Coefficient &QF)
: DeltaLFIntegrator(QF), Q(QF) { }
/** Given a particular Finite Element and a transformation (Tr)
computes the element right hand side element vector, elvect. */
virtual void AssembleRHSElementVect(const FiniteElement &el,
ElementTransformation &Tr,
Vector &elvect);
virtual void AssembleDeltaElementVect(const FiniteElement &fe,
ElementTransformation &Trans,
Vector &elvect);
using LinearFormIntegrator::AssembleRHSElementVect;
};
/** \f$ (f, v \cdot n)_{\partial\Omega} \f$ for vector test function
v=(v1,...,vn) where all vi are in the same scalar FE space and f is a
@@ -283,7 +360,7 @@ class VectorFEBoundaryFluxLFIntegrator : public LinearFormIntegrator
private:
Coefficient *F;
Vector shape;
int oa, ob; // these contol the quadrature order, see DomainLFIntegrator
int oa, ob; // these control the quadrature order, see DomainLFIntegrator
public:
VectorFEBoundaryFluxLFIntegrator(int a = 1, int b = -1)
+11 -4
View File
@@ -135,11 +135,18 @@ void Multigrid::SetOperator(const Operator& op)
MFEM_ABORT("SetOperator not supported in Multigrid");
}
void Multigrid::SmoothingStep(int level) const
void Multigrid::SmoothingStep(int level, bool transpose) const
{
GetOperatorAtLevel(level)->Mult(*Y[level], *R[level]); // r = A x
subtract(*X[level], *R[level], *R[level]); // r = b - A x
GetSmootherAtLevel(level)->Mult(*R[level], *Z[level]); // z = S r
if (transpose)
{
GetSmootherAtLevel(level)->MultTranspose(*R[level], *Z[level]); // z = S r
}
else
{
GetSmootherAtLevel(level)->Mult(*R[level], *Z[level]); // z = S r
}
add(*Y[level], 1.0, *Z[level], *Y[level]); // x = x + S (b - A x)
}
@@ -153,7 +160,7 @@ void Multigrid::Cycle(int level) const
for (int i = 0; i < preSmoothingSteps; i++)
{
SmoothingStep(level);
SmoothingStep(level, false);
}
// Compute residual
@@ -187,7 +194,7 @@ void Multigrid::Cycle(int level) const
// Post-smooth
for (int i = 0; i < postSmoothingSteps; i++)
{
SmoothingStep(level);
SmoothingStep(level, true);
}
}
+1 -1
View File
@@ -108,7 +108,7 @@ public:
private:
/// Application of a smoothing step at particular level
void SmoothingStep(int level) const;
void SmoothingStep(int level, bool transpose) const;
/// Application of a cycle at particular level
void Cycle(int level) const;
+11 -11
View File
@@ -933,6 +933,17 @@ Operator &BlockNonlinearForm::GetGradientBlocked(const BlockVector &bx) const
}
}
if (!Grads(0,0)->Finalized())
{
for (int i=0; i<fes.Size(); ++i)
{
for (int j=0; j<fes.Size(); ++j)
{
Grads(i,j)->Finalize(skip_zeros);
}
}
}
for (int s=0; s<fes.Size(); ++s)
{
for (int i = 0; i < ess_vdofs[s]->Size(); ++i)
@@ -952,17 +963,6 @@ Operator &BlockNonlinearForm::GetGradientBlocked(const BlockVector &bx) const
}
}
if (!Grads(0,0)->Finalized())
{
for (int i=0; i<fes.Size(); ++i)
{
for (int j=0; j<fes.Size(); ++j)
{
Grads(i,j)->Finalize(skip_zeros);
}
}
}
for (int i=0; i<fes.Size(); ++i)
{
for (int j=0; j<fes.Size(); ++j)
+4 -3
View File
@@ -198,8 +198,9 @@ void ParBilinearForm::AssembleSharedFaces(int skip_zeros)
for (int i = 0; i < nfaces; i++)
{
T = pmesh->GetSharedFaceTransformations(i);
int Elem2NbrNo = T->Elem2No - pmesh->GetNE();
pfes->GetElementVDofs(T->Elem1No, vdofs1);
pfes->GetFaceNbrElementVDofs(T->Elem2No, vdofs2);
pfes->GetFaceNbrElementVDofs(Elem2NbrNo, vdofs2);
vdofs1.Copy(vdofs_all);
for (int j = 0; j < vdofs2.Size(); j++)
{
@@ -216,7 +217,7 @@ void ParBilinearForm::AssembleSharedFaces(int skip_zeros)
for (int k = 0; k < fbfi.Size(); k++)
{
fbfi[k]->AssembleFaceMatrix(*pfes->GetFE(T->Elem1No),
*pfes->GetFaceNbrFE(T->Elem2No),
*pfes->GetFaceNbrFE(Elem2NbrNo),
*T, elemmat);
if (keep_nbr_block)
{
@@ -240,7 +241,7 @@ void ParBilinearForm::Assemble(int skip_zeros)
BilinearForm::Assemble(skip_zeros);
if (fbfi.Size() > 0)
if (!ext && fbfi.Size() > 0)
{
AssembleSharedFaces(skip_zeros);
}
+7 -4
View File
@@ -1172,7 +1172,7 @@ void ParFiniteElementSpace::GetFaceNbrFaceVDofs(int i, Array<int> &vdofs) const
{
// Works for NC mesh where 'i' is an index returned by
// ParMesh::GetSharedFace() such that i >= Mesh::GetNumFaces(), i.e. 'i' is
// the index of a ghost.
// the index of a ghost face.
MFEM_ASSERT(Nonconforming() && i >= pmesh->GetNumFaces(), "");
int el1, el2, inf1, inf2;
pmesh->GetFaceElements(i, &el1, &el2);
@@ -1212,11 +1212,14 @@ const FiniteElement *ParFiniteElementSpace::GetFaceNbrFE(int i) const
const FiniteElement *ParFiniteElementSpace::GetFaceNbrFaceFE(int i) const
{
// Works for NC mesh where 'i' is an index returned by
// ParMesh::GetSharedFace() such that i >= Mesh::GetNumFaces(), i.e. 'i' is
// the index of a ghost face.
// Works in tandem with GetFaceNbrFaceVDofs() defined above.
MFEM_ASSERT(Nonconforming() && !NURBSext, "");
Geometry::Type geom = (pmesh->Dimension() == 2) ?
Geometry::SEGMENT : Geometry::SQUARE;
return fec->FiniteElementForGeometry(geom);
Geometry::Type face_geom = pmesh->GetFaceGeometryType(i);
return fec->FiniteElementForGeometry(face_geom);
}
void ParFiniteElementSpace::Lose_Dof_TrueDof_Matrix()
+2
View File
@@ -347,6 +347,8 @@ public:
const FiniteElement *GetFaceNbrFE(int i) const;
const FiniteElement *GetFaceNbrFaceFE(int i) const;
const HYPRE_Int *GetFaceNbrGlobalDofMap() { return face_nbr_glob_dof_map; }
ElementTransformation *GetFaceNbrElementTransformation(int i) const
{ return pmesh->GetFaceNbrElementTransformation(i); }
void Lose_Dof_TrueDof_Matrix();
void LoseDofOffsets() { dof_offsets.LoseData(); }
+180 -6
View File
@@ -214,7 +214,7 @@ void ParGridFunction::ExchangeFaceNbrData()
ParMesh *pmesh = pfes->GetParMesh();
face_nbr_data.SetSize(pfes->GetFaceNbrVSize());
Vector send_data(pfes->send_face_nbr_ldof.Size_of_connections());
send_data.SetSize(pfes->send_face_nbr_ldof.Size_of_connections());
int *send_offset = pfes->send_face_nbr_ldof.GetI();
const int *d_send_ldof = mfem::Read(pfes->send_face_nbr_ldof.GetJMemory(),
@@ -271,6 +271,7 @@ const
{
int fes_vdim = pfes->GetVDim();
pfes->GetFaceNbrElementVDofs(nbr_el_no, dofs);
const FiniteElement *fe = pfes->GetFaceNbrFE(nbr_el_no);
if (fes_vdim > 1)
{
int s = dofs.Size()/fes_vdim;
@@ -283,7 +284,17 @@ const
face_nbr_data.GetSubVector(dofs, LocVec);
DofVal.SetSize(dofs.Size());
}
pfes->GetFaceNbrFE(nbr_el_no)->CalcShape(ip, DofVal);
if (fe->GetMapType() == FiniteElement::VALUE)
{
fe->CalcShape(ip, DofVal);
}
else
{
ElementTransformation *Tr =
pfes->GetFaceNbrElementTransformation(nbr_el_no);
Tr->SetIntPoint(&ip);
fe->CalcPhysShape(*Tr, DofVal);
}
}
else
{
@@ -291,14 +302,175 @@ const
fes->DofsToVDofs(vdim-1, dofs);
DofVal.SetSize(dofs.Size());
const FiniteElement *fe = fes->GetFE(i);
MFEM_ASSERT(fe->GetMapType() == FiniteElement::VALUE, "invalid FE map type");
fe->CalcShape(ip, DofVal);
if (fe->GetMapType() == FiniteElement::VALUE)
{
fe->CalcShape(ip, DofVal);
}
else
{
ElementTransformation *Tr = fes->GetElementTransformation(i);
Tr->SetIntPoint(&ip);
fe->CalcPhysShape(*Tr, DofVal);
}
GetSubVector(dofs, LocVec);
}
return (DofVal * LocVec);
}
void ParGridFunction::GetVectorValue(int i, const IntegrationPoint &ip,
Vector &val) const
{
int nbr_el_no = i - pfes->GetParMesh()->GetNE();
if (nbr_el_no >= 0)
{
Array<int> dofs;
pfes->GetFaceNbrElementVDofs(nbr_el_no, dofs);
Vector loc_data;
face_nbr_data.GetSubVector(dofs, loc_data);
const FiniteElement *FElem = pfes->GetFaceNbrFE(nbr_el_no);
int dof = FElem->GetDof();
if (FElem->GetRangeType() == FiniteElement::SCALAR)
{
Vector shape(dof);
if (FElem->GetMapType() == FiniteElement::VALUE)
{
FElem->CalcShape(ip, shape);
}
else
{
ElementTransformation *Tr =
pfes->GetParMesh()->GetFaceNbrElementTransformation(nbr_el_no);
Tr->SetIntPoint(&ip);
FElem->CalcPhysShape(*Tr, shape);
}
int vdim = fes->GetVDim();
val.SetSize(vdim);
for (int k = 0; k < vdim; k++)
{
val(k) = shape * ((const double *)loc_data + dof * k);
}
}
else
{
int spaceDim = fes->GetMesh()->SpaceDimension();
DenseMatrix vshape(dof, spaceDim);
ElementTransformation *Tr =
pfes->GetParMesh()->GetFaceNbrElementTransformation(nbr_el_no);
Tr->SetIntPoint(&ip);
FElem->CalcVShape(*Tr, vshape);
val.SetSize(spaceDim);
vshape.MultTranspose(loc_data, val);
}
}
else
{
GridFunction::GetVectorValue(i, ip, val);
}
}
double ParGridFunction::GetValue(ElementTransformation &T,
const IntegrationPoint &ip,
int comp, Vector *tr) const
{
// We can assume faces and edges are local
if (T.ElementType != ElementTransformation::ELEMENT)
{
return GridFunction::GetValue(T, ip, comp, tr);
}
// Check for evaluation in a local element
int nbr_el_no = T.ElementNo - pfes->GetParMesh()->GetNE();
if (nbr_el_no < 0)
{
return GridFunction::GetValue(T, ip, comp, tr);
}
// Evaluate using DoFs from a neighboring element
if (tr)
{
T.SetIntPoint(&ip);
T.Transform(ip, *tr);
}
Array<int> dofs;
const FiniteElement * fe = pfes->GetFaceNbrFE(nbr_el_no);
pfes->GetFaceNbrElementVDofs(nbr_el_no, dofs);
pfes->DofsToVDofs(comp-1, dofs);
Vector DofVal(dofs.Size()), LocVec;
if (fe->GetMapType() == FiniteElement::VALUE)
{
fe->CalcShape(ip, DofVal);
}
else
{
fe->CalcPhysShape(T, DofVal);
}
face_nbr_data.GetSubVector(dofs, LocVec);
return (DofVal * LocVec);
}
void ParGridFunction::GetVectorValue(ElementTransformation &T,
const IntegrationPoint &ip,
Vector &val, Vector *tr) const
{
// We can assume faces and edges are local
if (T.ElementType != ElementTransformation::ELEMENT)
{
return GridFunction::GetVectorValue(T, ip, val, tr);
}
// Check for evaluation in a local element
int nbr_el_no = T.ElementNo - pfes->GetParMesh()->GetNE();
if (nbr_el_no < 0)
{
return GridFunction::GetVectorValue(T, ip, val, tr);
}
// Evaluate using DoFs from a neighboring element
if (tr)
{
T.SetIntPoint(&ip);
T.Transform(ip, *tr);
}
Array<int> vdofs;
pfes->GetFaceNbrElementVDofs(nbr_el_no, vdofs);
const FiniteElement *fe = pfes->GetFaceNbrFE(nbr_el_no);
int dof = fe->GetDof();
Vector loc_data;
face_nbr_data.GetSubVector(vdofs, loc_data);
if (fe->GetRangeType() == FiniteElement::SCALAR)
{
Vector shape(dof);
if (fe->GetMapType() == FiniteElement::VALUE)
{
fe->CalcShape(ip, shape);
}
else
{
fe->CalcPhysShape(T, shape);
}
int vdim = pfes->GetVDim();
val.SetSize(vdim);
for (int k = 0; k < vdim; k++)
{
val(k) = shape * ((const double *)loc_data + dof * k);
}
}
else
{
int spaceDim = pfes->GetMesh()->SpaceDimension();
DenseMatrix vshape(dof, spaceDim);
fe->CalcVShape(T, vshape);
val.SetSize(spaceDim);
vshape.MultTranspose(loc_data, val);
}
}
void ParGridFunction::ProjectCoefficient(Coefficient &coeff)
{
DeltaCoefficient *delta_c = dynamic_cast<DeltaCoefficient *>(&coeff);
@@ -539,7 +711,9 @@ void ParGridFunction::SaveAsOne(std::ostream &out)
int *nfdofs = new int[NRanks];
int *nrdofs = new int[NRanks];
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();
@@ -640,7 +814,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;
+17
View File
@@ -38,6 +38,11 @@ protected:
initialized by ExchangeFaceNbrData(). */
Vector face_nbr_data;
/** @brief Vector used as an MPI buffer to send face-neighbor data
in ExchangeFaceNbrData() to neighboring processors. */
//TODO: Use temporary memory to avoid CUDA malloc allocation cost.
Vector send_data;
void ProjectBdrCoefficient(Coefficient *coeff[], VectorCoefficient *vcoeff,
Array<int> &attr);
@@ -204,6 +209,18 @@ public:
double GetValue(ElementTransformation &T)
{ return GetValue(T.ElementNo, T.GetIntPoint()); }
// Redefine to handle the case when T describes a face-neighbor element
virtual double GetValue(ElementTransformation &T, const IntegrationPoint &ip,
int comp = 0, Vector *tr = NULL) const;
virtual void GetVectorValue(int i, const IntegrationPoint &ip,
Vector &val) const;
// Redefine to handle the case when T describes a face-neighbor element
virtual void GetVectorValue(ElementTransformation &T,
const IntegrationPoint &ip,
Vector &val, Vector *tr = NULL) const;
using GridFunction::ProjectCoefficient;
virtual void ProjectCoefficient(Coefficient &coeff);
+3 -2
View File
@@ -64,12 +64,13 @@ void ParNonlinearForm::Mult(const Vector &x, Vector &y) const
for (int i = 0; i < n_shared_faces; i++)
{
tr = pmesh->GetSharedFaceTransformations(i, true);
int Elem2NbrNo = tr->Elem2No - pmesh->GetNE();
fe1 = pfes->GetFE(tr->Elem1No);
fe2 = pfes->GetFaceNbrFE(tr->Elem2No);
fe2 = pfes->GetFaceNbrFE(Elem2NbrNo);
pfes->GetElementVDofs(tr->Elem1No, vdofs1);
pfes->GetFaceNbrElementVDofs(tr->Elem2No, vdofs2);
pfes->GetFaceNbrElementVDofs(Elem2NbrNo, vdofs2);
el_x.SetSize(vdofs1.Size() + vdofs2.Size());
X.GetSubVector(vdofs1, el_x.GetData());
+136 -57
View File
@@ -27,35 +27,24 @@ ParL2FaceRestriction::ParL2FaceRestriction(const ParFiniteElementSpace &fes,
ElementDofOrdering e_ordering,
FaceType type,
L2FaceValues m)
: fes(fes),
nf(fes.GetNFbyType(type)),
vdim(fes.GetVDim()),
byvdim(fes.GetOrdering() == Ordering::byVDIM),
ndofs(fes.GetNDofs()),
dof(nf>0 ?
fes.GetTraceElement(0, fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof()
: 0),
m(m),
nfdofs(nf*dof),
scatter_indices1(nf*dof),
scatter_indices2(m==L2FaceValues::DoubleValued?nf*dof:0),
offsets(ndofs+1),
gather_indices((m==L2FaceValues::DoubleValued? 2 : 1)*nf*dof)
: L2FaceRestriction(fes, type, m)
{
if (nf==0) { return; }
// If fespace == L2
const FiniteElement *fe = fes.GetFE(0);
const ParFiniteElementSpace &pfes =
static_cast<const ParFiniteElementSpace&>(this->fes);
const FiniteElement *fe = pfes.GetFE(0);
const TensorBasisElement *tfe = dynamic_cast<const TensorBasisElement*>(fe);
MFEM_VERIFY(tfe != NULL &&
(tfe->GetBasisType()==BasisType::GaussLobatto ||
tfe->GetBasisType()==BasisType::Positive),
"Only Gauss-Lobatto and Bernstein basis are supported in "
"ParL2FaceRestriction.");
MFEM_VERIFY(fes.GetMesh()->Conforming(),
MFEM_VERIFY(pfes.GetMesh()->Conforming(),
"Non-conforming meshes not yet supported with partial assembly.");
// Assuming all finite elements are using Gauss-Lobatto dofs
height = (m==L2FaceValues::DoubleValued? 2 : 1)*vdim*nf*dof;
width = fes.GetVSize();
width = pfes.GetVSize();
const bool dof_reorder = (e_ordering == ElementDofOrdering::LEXICOGRAPHIC);
if (!dof_reorder)
{
@@ -63,32 +52,32 @@ ParL2FaceRestriction::ParL2FaceRestriction(const ParFiniteElementSpace &fes,
}
if (dof_reorder && nf > 0)
{
for (int f = 0; f < fes.GetNF(); ++f)
for (int f = 0; f < pfes.GetNF(); ++f)
{
const FiniteElement *fe =
fes.GetTraceElement(f, fes.GetMesh()->GetFaceBaseGeometry(f));
pfes.GetTraceElement(f, pfes.GetMesh()->GetFaceBaseGeometry(f));
const TensorBasisElement* el =
dynamic_cast<const TensorBasisElement*>(fe);
if (el) { continue; }
mfem_error("Finite element not suitable for lexicographic ordering");
}
}
const Table& e2dTable = fes.GetElementToDofTable();
const Table& e2dTable = pfes.GetElementToDofTable();
const int* elementMap = e2dTable.GetJ();
Array<int> faceMap1(dof), faceMap2(dof);
int e1, e2;
int inf1, inf2;
int face_id1, face_id2;
int orientation;
const int dof1d = fes.GetFE(0)->GetOrder()+1;
const int elem_dofs = fes.GetFE(0)->GetDof();
const int dim = fes.GetMesh()->SpaceDimension();
const int dof1d = pfes.GetFE(0)->GetOrder()+1;
const int elem_dofs = pfes.GetFE(0)->GetDof();
const int dim = pfes.GetMesh()->SpaceDimension();
// Computation of scatter indices
int f_ind=0;
for (int f = 0; f < fes.GetNF(); ++f)
for (int f = 0; f < pfes.GetNF(); ++f)
{
fes.GetMesh()->GetFaceElements(f, &e1, &e2);
fes.GetMesh()->GetFaceInfos(f, &inf1, &inf2);
pfes.GetMesh()->GetFaceElements(f, &e1, &e2);
pfes.GetMesh()->GetFaceInfos(f, &inf1, &inf2);
if (dof_reorder)
{
orientation = inf1 % 64;
@@ -136,7 +125,7 @@ ParL2FaceRestriction::ParL2FaceRestriction(const ParFiniteElementSpace &fes,
{
const int se2 = -1 - e2;
Array<int> sharedDofs;
fes.GetFaceNbrElementVDofs(se2, sharedDofs);
pfes.GetFaceNbrElementVDofs(se2, sharedDofs);
for (int d = 0; d < dof; ++d)
{
const int pd = PermuteFaceL2(dim, face_id1, face_id2,
@@ -180,10 +169,10 @@ ParL2FaceRestriction::ParL2FaceRestriction(const ParFiniteElementSpace &fes,
offsets[i] = 0;
}
f_ind = 0;
for (int f = 0; f < fes.GetNF(); ++f)
for (int f = 0; f < pfes.GetNF(); ++f)
{
fes.GetMesh()->GetFaceElements(f, &e1, &e2);
fes.GetMesh()->GetFaceInfos(f, &inf1, &inf2);
pfes.GetMesh()->GetFaceElements(f, &e1, &e2);
pfes.GetMesh()->GetFaceInfos(f, &inf1, &inf2);
if ((type==FaceType::Interior && (e2>=0 || (e2<0 && inf2>=0))) ||
(type==FaceType::Boundary && e2<0 && inf2<0) )
{
@@ -222,10 +211,10 @@ ParL2FaceRestriction::ParL2FaceRestriction(const ParFiniteElementSpace &fes,
offsets[i] += offsets[i - 1];
}
f_ind = 0;
for (int f = 0; f < fes.GetNF(); ++f)
for (int f = 0; f < pfes.GetNF(); ++f)
{
fes.GetMesh()->GetFaceElements(f, &e1, &e2);
fes.GetMesh()->GetFaceInfos(f, &inf1, &inf2);
pfes.GetMesh()->GetFaceElements(f, &e1, &e2);
pfes.GetMesh()->GetFaceInfos(f, &inf1, &inf2);
if ((type==FaceType::Interior && (e2>=0 || (e2<0 && inf2>=0))) ||
(type==FaceType::Boundary && e2<0 && inf2<0) )
{
@@ -272,8 +261,10 @@ ParL2FaceRestriction::ParL2FaceRestriction(const ParFiniteElementSpace &fes,
void ParL2FaceRestriction::Mult(const Vector& x, Vector& y) const
{
const ParFiniteElementSpace &pfes =
static_cast<const ParFiniteElementSpace&>(this->fes);
ParGridFunction x_gf;
x_gf.MakeRef(const_cast<ParFiniteElementSpace*>(&fes),
x_gf.MakeRef(const_cast<ParFiniteElementSpace*>(&pfes),
const_cast<Vector&>(x), 0);
x_gf.ExchangeFaceNbrData();
@@ -337,34 +328,122 @@ void ParL2FaceRestriction::Mult(const Vector& x, Vector& y) const
}
}
void ParL2FaceRestriction::MultTranspose(const Vector& x, Vector& y) const
static MFEM_HOST_DEVICE int AddNnz(const int iE, int *I, const int dofs)
{
// Assumes all elements have the same number of dofs
const int nd = dof;
const int vd = vdim;
const bool t = byvdim;
const int dofs = nfdofs;
auto d_offsets = offsets.Read();
auto d_indices = gather_indices.Read();
auto d_x = Reshape(x.Read(), nd, vd, 2, nf);
auto d_y = Reshape(y.Write(), t?vd:ndofs, t?ndofs:vd);
MFEM_FORALL(i, ndofs,
int val = AtomicAdd(I[iE],dofs);
return val;
}
void ParL2FaceRestriction::FillI(SparseMatrix &mat,
SparseMatrix &face_mat) const
{
const int face_dofs = dof;
const int Ndofs = ndofs;
auto d_indices1 = scatter_indices1.Read();
auto d_indices2 = scatter_indices2.Read();
auto I = mat.ReadWriteI();
auto I_face = face_mat.ReadWriteI();
MFEM_FORALL(i, ne*elemDofs*vdim+1,
{
const int offset = d_offsets[i];
const int nextOffset = d_offsets[i + 1];
for (int c = 0; c < vd; ++c)
I_face[i] = 0;
});
MFEM_FORALL(fdof, nf*face_dofs,
{
const int f = fdof/face_dofs;
const int iF = fdof%face_dofs;
const int iE1 = d_indices1[f*face_dofs+iF];
if (iE1 < Ndofs)
{
double dofValue = 0;
for (int j = offset; j < nextOffset; ++j)
for (int jF = 0; jF < face_dofs; jF++)
{
int idx_j = d_indices[j];
bool isE1 = idx_j < dofs;
idx_j = isE1 ? idx_j : idx_j - dofs;
dofValue += isE1 ?
d_x(idx_j % nd, c, 0, idx_j / nd)
:d_x(idx_j % nd, c, 1, idx_j / nd);
const int jE2 = d_indices2[f*face_dofs+jF];
if (jE2 < Ndofs)
{
AddNnz(iE1,I,1);
}
else
{
AddNnz(iE1,I_face,1);
}
}
}
const int iE2 = d_indices2[f*face_dofs+iF];
if (iE2 < Ndofs)
{
for (int jF = 0; jF < face_dofs; jF++)
{
const int jE1 = d_indices1[f*face_dofs+jF];
if (jE1 < Ndofs)
{
AddNnz(iE2,I,1);
}
else
{
AddNnz(iE2,I_face,1);
}
}
}
});
}
void ParL2FaceRestriction::FillJAndData(const Vector &ea_data,
SparseMatrix &mat,
SparseMatrix &face_mat) const
{
const int face_dofs = dof;
const int Ndofs = ndofs;
auto d_indices1 = scatter_indices1.Read();
auto d_indices2 = scatter_indices2.Read();
auto mat_fea = Reshape(ea_data.Read(), face_dofs, face_dofs, 2, nf);
auto I = mat.ReadWriteI();
auto I_face = face_mat.ReadWriteI();
auto J = mat.WriteJ();
auto J_face = face_mat.WriteJ();
auto Data = mat.WriteData();
auto Data_face = face_mat.WriteData();
MFEM_FORALL(fdof, nf*face_dofs,
{
const int f = fdof/face_dofs;
const int iF = fdof%face_dofs;
const int iE1 = d_indices1[f*face_dofs+iF];
if (iE1 < Ndofs)
{
for (int jF = 0; jF < face_dofs; jF++)
{
const int jE2 = d_indices2[f*face_dofs+jF];
if (jE2 < Ndofs)
{
const int offset = AddNnz(iE1,I,1);
J[offset] = jE2;
Data[offset] = mat_fea(jF,iF,1,f);
}
else
{
const int offset = AddNnz(iE1,I_face,1);
J_face[offset] = jE2-Ndofs;
Data_face[offset] = mat_fea(jF,iF,1,f);
}
}
}
const int iE2 = d_indices2[f*face_dofs+iF];
if (iE2 < Ndofs)
{
for (int jF = 0; jF < face_dofs; jF++)
{
const int jE1 = d_indices1[f*face_dofs+jF];
if (jE1 < Ndofs)
{
const int offset = AddNnz(iE2,I,1);
J[offset] = jE1;
Data[offset] = mat_fea(jF,iF,0,f);
}
else
{
const int offset = AddNnz(iE2,I_face,1);
J_face[offset] = jE1-Ndofs;
Data_face[offset] = mat_fea(jF,iF,0,f);
}
}
d_y(t?c:i,t?i:c) += dofValue;
}
});
}
+9 -16
View File
@@ -26,28 +26,21 @@ class ParFiniteElementSpace;
/// Operator that extracts Face degrees of freedom in parallel.
/** Objects of this type are typically created and owned by FiniteElementSpace
objects, see FiniteElementSpace::GetFaceRestriction(). */
class ParL2FaceRestriction : public Operator
class ParL2FaceRestriction : public L2FaceRestriction
{
protected:
const ParFiniteElementSpace &fes;
const int nf;
const int vdim;
const bool byvdim;
const int ndofs;
const int dof;
const L2FaceValues m;
const int nfdofs;
Array<int> scatter_indices1;
Array<int> scatter_indices2;
Array<int> offsets;
Array<int> gather_indices;
public:
ParL2FaceRestriction(const ParFiniteElementSpace&, ElementDofOrdering,
FaceType type,
L2FaceValues m = L2FaceValues::DoubleValued);
void Mult(const Vector &x, Vector &y) const;
void MultTranspose(const Vector &x, Vector &y) const;
/** Fill the I array of SparseMatrix corresponding to the sparsity pattern
given by this ParL2FaceRestriction. */
void FillI(SparseMatrix &mat, SparseMatrix &face_mat) const;
/** Fill the J and Data arrays of SparseMatrix corresponding to the sparsity
pattern given by this ParL2FaceRestriction, and the values of ea_data. */
void FillJAndData(const Vector &ea_data,
SparseMatrix &mat,
SparseMatrix &face_mat) const;
};
}

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