Compare commits

...
691 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 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
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 b5d35f9870 Merge branch 'master' into slepc-dev 2020-06-24 10:08:13 -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
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
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
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
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
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
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
stefanhenneking bc795fc99a Adding PA option to example ex22. 2020-06-19 16:18:49 -05:00
stefanhenneking 5d80f8e195 Using OperatorHandle for SesquilinearForm to enable PA. 2020-06-19 15:58:54 -05: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
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
Jonathan Wong c85d34c34a corrected typo and added documentation that @jandrej suggested 2020-06-17 17:05:30 -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
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
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 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
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
Yohann Dudouit 5ebc924b20 Add parallel support for DG face terms. 2020-06-09 19:56:33 -07:00
Yohann Dudouit e975ad2950 Revert iteration count in ex1 to be different. 2020-06-09 14:37:19 -07:00
Jonathan Wong 58997c32bd initialized N_Vector pointer to struct type to NULL 2020-06-09 14:07:26 -07:00
Jonathan Wong c0395c6371 tidy up parallel output for advection_diffusion problem 2020-06-09 13:21:25 -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
Yohann Dudouit dee42c559a AppVeyor... 2020-06-08 17:19:56 -07:00
Yohann Dudouit 33c28f7591 Try to make AppVeyor happy... 2020-06-08 17:00:20 -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
Yohann Dudouit db626777be make style 2020-06-08 13:31:42 -07:00
Yohann Dudouit b3f4e5bb0b Remove magic number. 2020-06-08 12:59:00 -07:00
Yohann Dudouit 04f1d562b7 Revert ex1 and ex1p. 2020-06-08 12:38: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
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
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
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
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
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
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
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
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
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
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
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
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
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
Arturo Vargas b686dbb897 Update bilininteg_mass.cpp 2020-04-30 18:10:29 -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
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
183 changed files with 17419 additions and 4216 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
+49 -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
@@ -113,6 +135,17 @@ New and updated examples and miniapps
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.
@@ -120,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.
@@ -132,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;
}
+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;
+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);
+24 -15
View File
@@ -21,8 +21,11 @@
// 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
@@ -164,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;
@@ -193,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",
@@ -329,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(
@@ -565,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>();
@@ -596,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
{
+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
+25
View File
@@ -319,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)
{
+38 -3
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() { }
};
+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);
+17 -3
View File
@@ -77,6 +77,9 @@ public:
ElementTransformation();
/** @brief Force the reevaluation of the Jacobian in the next call. */
void Reset() { EvalState = 0; }
/** @brief Set the integration point @a ip that weights and Jacobians will
be evaluated at. */
void SetIntPoint(const IntegrationPoint *ip)
@@ -357,9 +360,17 @@ private:
// Evaluate the Hessian of the transformation at the IntPoint and store it
// in d2Fdx2.
virtual const DenseMatrix &EvalHessian();
public:
IsoparametricTransformation() : FElem(NULL) {}
/// Set the element that will be used to compute the transformations
void SetFE(const FiniteElement *FE) { FElem = FE; geom = FE->GetGeomType(); }
void SetFE(const FiniteElement *FE)
{
MFEM_ASSERT(FE != NULL, "Must provide a valid FiniteElement object!");
EvalState = (FE != FElem) ? 0 : EvalState;
FElem = FE; geom = FE->GetGeomType();
}
/// Get the current element used to compute the transformations
const FiniteElement* GetFE() const { return FElem; }
@@ -374,12 +385,15 @@ public:
the column-vector of all basis functions evaluated at \f$ \hat x \f$ .
The columns of @a P represent the control points in physical space
defining the transformation. */
void SetPointMat(const DenseMatrix &pm) { PointMat = pm; }
void SetPointMat(const DenseMatrix &pm) { PointMat = pm; EvalState = 0; }
/// Return the stored point matrix.
const DenseMatrix &GetPointMat() const { return PointMat; }
/// Write access to the stored point matrix. Use with caution.
/// @brief Write access to the stored point matrix. Use with caution.
/** If the point matrix is altered using this member function the Reset
function should also be called to force the reevaluation of the
Jacobian, etc.. */
DenseMatrix &GetPointMat() { return PointMat; }
/// Set the FiniteElement Geometry for the reference elements being used.
+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();
};
+20 -5
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++)
+4 -3
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
@@ -713,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.
+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();
}
+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)
+1 -1
View File
@@ -241,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);
}
+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(); }
+77 -5
View File
@@ -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,73 @@ 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
@@ -641,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();
@@ -742,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;
+3
View File
@@ -213,6 +213,9 @@ public:
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,
+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;
};
}
+14 -8
View File
@@ -62,6 +62,7 @@ void QuadratureInterpolator::Eval2D(
const int nq = maps.nqpt;
const int ND = T_ND ? T_ND : nd;
const int NQ = T_NQ ? T_NQ : nq;
const int NMAX = NQ > ND ? NQ : ND;
const int VDIM = T_VDIM ? T_VDIM : vdim;
MFEM_VERIFY(ND <= MAX_ND2D, "");
MFEM_VERIFY(NQ <= MAX_NQ2D, "");
@@ -72,22 +73,24 @@ void QuadratureInterpolator::Eval2D(
auto val = Reshape(q_val.Write(), NQ, VDIM, NE);
auto der = Reshape(q_der.Write(), NQ, VDIM, 2, NE);
auto det = Reshape(q_det.Write(), NQ, NE);
MFEM_FORALL(e, NE,
MFEM_FORALL_2D(e, NE, NMAX, 1, 1,
{
const int ND = T_ND ? T_ND : nd;
const int NQ = T_NQ ? T_NQ : nq;
const int VDIM = T_VDIM ? T_VDIM : vdim;
constexpr int max_ND = T_ND ? T_ND : MAX_ND2D;
constexpr int max_VDIM = T_VDIM ? T_VDIM : MAX_VDIM2D;
double s_E[max_VDIM*max_ND];
for (int d = 0; d < ND; d++)
MFEM_SHARED double s_E[max_VDIM*max_ND];
MFEM_FOREACH_THREAD(d, x, ND)
{
for (int c = 0; c < VDIM; c++)
{
s_E[c+d*VDIM] = E(d,c,e);
}
}
for (int q = 0; q < NQ; ++q)
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(q, x, NQ)
{
if (eval_flags & VALUES)
{
@@ -150,6 +153,7 @@ void QuadratureInterpolator::Eval3D(
const int nq = maps.nqpt;
const int ND = T_ND ? T_ND : nd;
const int NQ = T_NQ ? T_NQ : nq;
const int NMAX = NQ > ND ? NQ : ND;
const int VDIM = T_VDIM ? T_VDIM : vdim;
MFEM_VERIFY(ND <= MAX_ND3D, "");
MFEM_VERIFY(NQ <= MAX_NQ3D, "");
@@ -160,22 +164,24 @@ void QuadratureInterpolator::Eval3D(
auto val = Reshape(q_val.Write(), NQ, VDIM, NE);
auto der = Reshape(q_der.Write(), NQ, VDIM, 3, NE);
auto det = Reshape(q_det.Write(), NQ, NE);
MFEM_FORALL(e, NE,
MFEM_FORALL_2D(e, NE, NMAX, 1, 1,
{
const int ND = T_ND ? T_ND : nd;
const int NQ = T_NQ ? T_NQ : nq;
const int VDIM = T_VDIM ? T_VDIM : vdim;
constexpr int max_ND = T_ND ? T_ND : MAX_ND3D;
constexpr int max_VDIM = T_VDIM ? T_VDIM : MAX_VDIM3D;
double s_E[max_VDIM*max_ND];
for (int d = 0; d < ND; d++)
MFEM_SHARED double s_E[max_VDIM*max_ND];
MFEM_FOREACH_THREAD(d, x, ND)
{
for (int c = 0; c < VDIM; c++)
{
s_E[c+d*VDIM] = E(d,c,e);
}
}
for (int q = 0; q < NQ; ++q)
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(q, x, NQ)
{
if (eval_flags & VALUES)
{
+421 -52
View File
@@ -17,55 +17,6 @@
namespace mfem
{
L2ElementRestriction::L2ElementRestriction(const FiniteElementSpace &fes)
: ne(fes.GetNE()),
vdim(fes.GetVDim()),
byvdim(fes.GetOrdering() == Ordering::byVDIM),
ndof(ne > 0 ? fes.GetFE(0)->GetDof() : 0),
ndofs(fes.GetNDofs())
{
height = vdim*ne*ndof;
width = vdim*ne*ndof;
}
void L2ElementRestriction::Mult(const Vector &x, Vector &y) const
{
const int nd = ndof;
const int vd = vdim;
const bool t = byvdim;
auto d_x = Reshape(x.Read(), t?vd:ndofs, t?ndofs:vd);
auto d_y = Reshape(y.Write(), nd, vd, ne);
MFEM_FORALL(i, ndofs,
{
const int idx = i;
const int dof = idx % nd;
const int e = idx / nd;
for (int c = 0; c < vd; ++c)
{
d_y(dof, c, e) = d_x(t?c:idx, t?idx:c);
}
});
}
void L2ElementRestriction::MultTranspose(const Vector &x, Vector &y) const
{
const int nd = ndof;
const int vd = vdim;
const bool t = byvdim;
auto d_x = Reshape(x.Read(), nd, vd, ne);
auto d_y = Reshape(y.Write(), t?vd:ndofs, t?ndofs:vd);
MFEM_FORALL(i, ndofs,
{
const int idx = i;
const int dof = idx % nd;
const int e = idx / nd;
for (int c = 0; c < vd; ++c)
{
d_y(t?c:idx,t?idx:c) = d_x(dof, c, e);
}
});
}
ElementRestriction::ElementRestriction(const FiniteElementSpace &f,
ElementDofOrdering e_ordering)
: fes(f),
@@ -281,7 +232,309 @@ void ElementRestriction::BooleanMask(Vector& y) const
}
}
/// Return the face degrees of freedom returned in Lexicographic order.
void ElementRestriction::FillSparseMatrix(const Vector &mat_ea,
SparseMatrix &mat) const
{
mat.GetMemoryI().New(mat.Height()+1, mat.GetMemoryI().GetMemoryType());
const int nnz = FillI(mat);
mat.GetMemoryJ().New(nnz, mat.GetMemoryJ().GetMemoryType());
mat.GetMemoryData().New(nnz, mat.GetMemoryData().GetMemoryType());
FillJAndData(mat_ea, mat);
}
template <int MaxNbNbr>
static MFEM_HOST_DEVICE int GetMinElt(const int *my_elts, const int nbElts,
const int *nbr_elts, const int nbrNbElts)
{
// Building the intersection
int inter[MaxNbNbr];
int cpt = 0;
for (int i = 0; i < nbElts; i++)
{
const int e_i = my_elts[i];
for (int j = 0; j < nbrNbElts; j++)
{
if (e_i==nbr_elts[j])
{
inter[cpt] = e_i;
cpt++;
}
}
}
// Finding the minimum
int min = inter[0];
for (int i = 1; i < cpt; i++)
{
if (inter[i] < min)
{
min = inter[i];
}
}
return min;
}
/** Returns the index where a non-zero entry should be added and increment the
number of non-zeros for the row i_L. */
static MFEM_HOST_DEVICE int GetAndIncrementNnzIndex(const int i_L, int* I)
{
int ind = AtomicAdd(I[i_L],1);
return ind;
}
int ElementRestriction::FillI(SparseMatrix &mat) const
{
static constexpr int Max = MaxNbNbr;
const int all_dofs = ndofs;
const int vd = vdim;
const int elt_dofs = dof;
auto I = mat.ReadWriteI();
auto d_offsets = offsets.Read();
auto d_indices = indices.Read();
auto d_gatherMap = gatherMap.Read();
MFEM_FORALL(i_L, vd*all_dofs+1,
{
I[i_L] = 0;
});
MFEM_FORALL(e, ne,
{
for (int i = 0; i < elt_dofs; i++)
{
int i_elts[Max];
const int i_E = e*elt_dofs + i;
const int i_L = d_gatherMap[i_E];
const int i_offset = d_offsets[i_L];
const int i_nextOffset = d_offsets[i_L+1];
const int i_nbElts = i_nextOffset - i_offset;
for (int e_i = 0; e_i < i_nbElts; ++e_i)
{
const int i_E = d_indices[i_offset+e_i];
i_elts[e_i] = i_E/elt_dofs;
}
for (int j = 0; j < elt_dofs; j++)
{
const int j_E = e*elt_dofs + j;
const int j_L = d_gatherMap[j_E];
const int j_offset = d_offsets[j_L];
const int j_nextOffset = d_offsets[j_L+1];
const int j_nbElts = j_nextOffset - j_offset;
if (i_nbElts == 1 || j_nbElts == 1) // no assembly required
{
GetAndIncrementNnzIndex(i_L, I);
}
else // assembly required
{
int j_elts[Max];
for (int e_j = 0; e_j < j_nbElts; ++e_j)
{
const int j_E = d_indices[j_offset+e_j];
const int elt = j_E/elt_dofs;
j_elts[e_j] = elt;
}
int min_e = GetMinElt<Max>(i_elts, i_nbElts, j_elts, j_nbElts);
if (e == min_e) // add the nnz only once
{
GetAndIncrementNnzIndex(i_L, I);
}
}
}
}
});
// We need to sum the entries of I, we do it on CPU as it is very sequential.
auto h_I = mat.HostReadWriteI();
const int nTdofs = vd*all_dofs;
int sum = 0;
for (int i = 0; i < nTdofs; i++)
{
const int nnz = h_I[i];
h_I[i] = sum;
sum+=nnz;
}
h_I[nTdofs] = sum;
// We return the number of nnz
return h_I[nTdofs];
}
void ElementRestriction::FillJAndData(const Vector &ea_data,
SparseMatrix &mat) const
{
static constexpr int Max = MaxNbNbr;
const int all_dofs = ndofs;
const int vd = vdim;
const int elt_dofs = dof;
auto I = mat.ReadWriteI();
auto J = mat.WriteJ();
auto Data = mat.WriteData();
auto d_offsets = offsets.Read();
auto d_indices = indices.Read();
auto d_gatherMap = gatherMap.Read();
auto mat_ea = Reshape(ea_data.Read(), elt_dofs, elt_dofs, ne);
MFEM_FORALL(e, ne,
{
for (int i = 0; i < elt_dofs; i++)
{
int i_elts[Max];
int i_B[Max];
const int i_E = e*elt_dofs + i;
const int i_L = d_gatherMap[i_E];
const int i_offset = d_offsets[i_L];
const int i_nextOffset = d_offsets[i_L+1];
const int i_nbElts = i_nextOffset - i_offset;
for (int e_i = 0; e_i < i_nbElts; ++e_i)
{
const int i_E = d_indices[i_offset+e_i];
i_elts[e_i] = i_E/elt_dofs;
i_B[e_i] = i_E%elt_dofs;
}
for (int j = 0; j < elt_dofs; j++)
{
const int j_E = e*elt_dofs + j;
const int j_L = d_gatherMap[j_E];
const int j_offset = d_offsets[j_L];
const int j_nextOffset = d_offsets[j_L+1];
const int j_nbElts = j_nextOffset - j_offset;
if (i_nbElts == 1 || j_nbElts == 1) // no assembly required
{
const int nnz = GetAndIncrementNnzIndex(i_L, I);
J[nnz] = j_L;
Data[nnz] = mat_ea(j,i,e);
}
else // assembly required
{
int j_elts[Max];
int j_B[Max];
for (int e_j = 0; e_j < j_nbElts; ++e_j)
{
const int j_E = d_indices[j_offset+e_j];
const int elt = j_E/elt_dofs;
j_elts[e_j] = elt;
j_B[e_j] = j_E%elt_dofs;
}
int min_e = GetMinElt<Max>(i_elts, i_nbElts, j_elts, j_nbElts);
if (e == min_e) // add the nnz only once
{
double val = 0.0;
for (int i = 0; i < i_nbElts; i++)
{
const int e_i = i_elts[i];
const int i_Bloc = i_B[i];
for (int j = 0; j < j_nbElts; j++)
{
const int e_j = j_elts[j];
const int j_Bloc = j_B[j];
if (e_i == e_j)
{
val += mat_ea(j_Bloc, i_Bloc, e_i);
}
}
}
const int nnz = GetAndIncrementNnzIndex(i_L, I);
J[nnz] = j_L;
Data[nnz] = val;
}
}
}
}
});
// We need to shift again the entries of I, we do it on CPU as it is very
// sequential.
auto h_I = mat.HostReadWriteI();
const int size = vd*all_dofs;
for (int i = 0; i < size; i++)
{
h_I[size-i] = h_I[size-(i+1)];
}
h_I[0] = 0;
}
L2ElementRestriction::L2ElementRestriction(const FiniteElementSpace &fes)
: ne(fes.GetNE()),
vdim(fes.GetVDim()),
byvdim(fes.GetOrdering() == Ordering::byVDIM),
ndof(ne > 0 ? fes.GetFE(0)->GetDof() : 0),
ndofs(fes.GetNDofs())
{
height = vdim*ne*ndof;
width = vdim*ne*ndof;
}
void L2ElementRestriction::Mult(const Vector &x, Vector &y) const
{
const int nd = ndof;
const int vd = vdim;
const bool t = byvdim;
auto d_x = Reshape(x.Read(), t?vd:ndofs, t?ndofs:vd);
auto d_y = Reshape(y.Write(), nd, vd, ne);
MFEM_FORALL(i, ndofs,
{
const int idx = i;
const int dof = idx % nd;
const int e = idx / nd;
for (int c = 0; c < vd; ++c)
{
d_y(dof, c, e) = d_x(t?c:idx, t?idx:c);
}
});
}
void L2ElementRestriction::MultTranspose(const Vector &x, Vector &y) const
{
const int nd = ndof;
const int vd = vdim;
const bool t = byvdim;
auto d_x = Reshape(x.Read(), nd, vd, ne);
auto d_y = Reshape(y.Write(), t?vd:ndofs, t?ndofs:vd);
MFEM_FORALL(i, ndofs,
{
const int idx = i;
const int dof = idx % nd;
const int e = idx / nd;
for (int c = 0; c < vd; ++c)
{
d_y(t?c:idx,t?idx:c) = d_x(dof, c, e);
}
});
}
void L2ElementRestriction::FillI(SparseMatrix &mat) const
{
const int elem_dofs = ndof;
const int vd = vdim;
auto I = mat.WriteI();
MFEM_FORALL(dof, ne*elem_dofs*vd,
{
I[dof] = elem_dofs;
});
}
static MFEM_HOST_DEVICE int AddNnz(const int iE, int *I, const int dofs)
{
int val = AtomicAdd(I[iE],dofs);
return val;
}
void L2ElementRestriction::FillJAndData(const Vector &ea_data,
SparseMatrix &mat) const
{
const int elem_dofs = ndof;
const int vd = vdim;
auto I = mat.ReadWriteI();
auto J = mat.WriteJ();
auto Data = mat.WriteData();
auto mat_ea = Reshape(ea_data.Read(), elem_dofs, elem_dofs, ne);
MFEM_FORALL(iE, ne*elem_dofs*vd,
{
const int offset = AddNnz(iE,I,elem_dofs);
const int e = iE/elem_dofs;
const int i = iE%elem_dofs;
for (int j = 0; j < elem_dofs; j++)
{
J[offset+j] = e*elem_dofs+j;
Data[offset+j] = mat_ea(j,i,e);
}
});
}
// Return the face degrees of freedom returned in Lexicographic order.
void GetFaceDofs(const int dim, const int face_id,
const int dof1d, Array<int> &faceMap)
{
@@ -700,7 +953,7 @@ static int PermuteFace3D(const int face_id1, const int face_id2,
return ToLexOrdering3D(face_id2, size1d, new_i, new_j);
}
/// Permute dofs or quads on a face for e2 to match with the ordering of e1
// Permute dofs or quads on a face for e2 to match with the ordering of e1
int PermuteFaceL2(const int dim, const int face_id1,
const int face_id2, const int orientation,
const int size1d, const int index)
@@ -720,23 +973,32 @@ int PermuteFaceL2(const int dim, const int face_id1,
}
L2FaceRestriction::L2FaceRestriction(const FiniteElementSpace &fes,
const ElementDofOrdering e_ordering,
const FaceType type,
const L2FaceValues m)
: fes(fes),
nf(fes.GetNFbyType(type)),
ne(fes.GetNE()),
vdim(fes.GetVDim()),
byvdim(fes.GetOrdering() == Ordering::byVDIM),
ndofs(fes.GetNDofs()),
dof(nf > 0 ?
fes.GetTraceElement(0, fes.GetMesh()->GetFaceBaseGeometry(0))->GetDof()
: 0),
elemDofs(fes.GetFE(0)->GetDof()),
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::L2FaceRestriction(const FiniteElementSpace &fes,
const ElementDofOrdering e_ordering,
const FaceType type,
const L2FaceValues m)
: L2FaceRestriction(fes, type, m)
{
// If fespace == L2
const FiniteElement *fe = fes.GetFE(0);
@@ -1034,6 +1296,113 @@ void L2FaceRestriction::MultTranspose(const Vector& x, Vector& y) const
}
}
void L2FaceRestriction::FillI(SparseMatrix &mat,
SparseMatrix &face_mat) const
{
const int face_dofs = dof;
auto d_indices1 = scatter_indices1.Read();
auto d_indices2 = scatter_indices2.Read();
auto I = mat.ReadWriteI();
MFEM_FORALL(fdof, nf*face_dofs,
{
const int iE1 = d_indices1[fdof];
const int iE2 = d_indices2[fdof];
AddNnz(iE1,I,face_dofs);
AddNnz(iE2,I,face_dofs);
});
}
void L2FaceRestriction::FillJAndData(const Vector &ea_data,
SparseMatrix &mat,
SparseMatrix &face_mat) const
{
const int face_dofs = dof;
auto d_indices1 = scatter_indices1.Read();
auto d_indices2 = scatter_indices2.Read();
auto I = mat.ReadWriteI();
auto mat_fea = Reshape(ea_data.Read(), face_dofs, face_dofs, 2, nf);
auto J = mat.WriteJ();
auto Data = 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];
const int iE2 = d_indices2[f*face_dofs+iF];
const int offset1 = AddNnz(iE1,I,face_dofs);
const int offset2 = AddNnz(iE2,I,face_dofs);
for (int jF = 0; jF < face_dofs; jF++)
{
const int jE1 = d_indices1[f*face_dofs+jF];
const int jE2 = d_indices2[f*face_dofs+jF];
J[offset2+jF] = jE1;
J[offset1+jF] = jE2;
Data[offset2+jF] = mat_fea(jF,iF,0,f);
Data[offset1+jF] = mat_fea(jF,iF,1,f);
}
});
}
void L2FaceRestriction::AddFaceMatricesToElementMatrices(Vector &fea_data,
Vector &ea_data) const
{
const int face_dofs = dof;
const int elem_dofs = elemDofs;
const int NE = ne;
if (m==L2FaceValues::DoubleValued)
{
auto d_indices1 = scatter_indices1.Read();
auto d_indices2 = scatter_indices2.Read();
auto mat_fea = Reshape(fea_data.Read(), face_dofs, face_dofs, 2, nf);
auto mat_ea = Reshape(ea_data.ReadWrite(), elem_dofs, elem_dofs, ne);
MFEM_FORALL(f, nf,
{
const int e1 = d_indices1[f*face_dofs]/elem_dofs;
const int e2 = d_indices2[f*face_dofs]/elem_dofs;
for (int j = 0; j < face_dofs; j++)
{
const int jB1 = d_indices1[f*face_dofs+j]%elem_dofs;
for (int i = 0; i < face_dofs; i++)
{
const int iB1 = d_indices1[f*face_dofs+i]%elem_dofs;
AtomicAdd(mat_ea(iB1,jB1,e1), mat_fea(i,j,0,f));
}
}
if (e2 < NE)
{
for (int j = 0; j < face_dofs; j++)
{
const int jB2 = d_indices2[f*face_dofs+j]%elem_dofs;
for (int i = 0; i < face_dofs; i++)
{
const int iB2 = d_indices2[f*face_dofs+i]%elem_dofs;
AtomicAdd(mat_ea(iB2,jB2,e2), mat_fea(i,j,1,f));
}
}
}
});
}
else
{
auto d_indices = scatter_indices1.Read();
auto mat_fea = Reshape(fea_data.Read(), face_dofs, face_dofs, nf);
auto mat_ea = Reshape(ea_data.ReadWrite(), elem_dofs, elem_dofs, ne);
MFEM_FORALL(f, nf,
{
const int e = d_indices[f*face_dofs]/elem_dofs;
for (int j = 0; j < face_dofs; j++)
{
const int jE = d_indices[f*face_dofs+j]%elem_dofs;
for (int i = 0; i < face_dofs; i++)
{
const int iE = d_indices[f*face_dofs+i]%elem_dofs;
AtomicAdd(mat_ea(iE,jE,e), mat_fea(i,j,f));
}
}
});
}
}
int ToLexOrdering(const int dim, const int face_id, const int size1d,
const int index)
{
+39 -1
View File
@@ -30,6 +30,11 @@ enum class L2FaceValues : bool {SingleValued, DoubleValued};
objects, see FiniteElementSpace::GetElementRestriction(). */
class ElementRestriction : public Operator
{
private:
/** This number defines the maximum number of elements any dof can belong to
for the FillSparseMatrix method. */
static const int MaxNbNbr = 16;
protected:
const FiniteElementSpace &fes;
const int ne;
@@ -59,6 +64,16 @@ public:
emulate SetSubVector and its transpose on GPUs. This method is running on
the host, since the `processed` array requires a large shared memory. */
void BooleanMask(Vector& y) const;
/// Fill a Sparse Matrix with Element Matrices.
void FillSparseMatrix(const Vector &mat_ea, SparseMatrix &mat) const;
/** Fill the I array of SparseMatrix corresponding to the sparsity pattern
given by this ElementRestriction. */
int FillI(SparseMatrix &mat) const;
/** Fill the J and Data arrays of SparseMatrix corresponding to the sparsity
pattern given by this ElementRestriction, and the values of ea_data. */
void FillJAndData(const Vector &ea_data, SparseMatrix &mat) const;
};
/// Operator that converts L2 FiniteElementSpace L-vectors to E-vectors.
@@ -77,6 +92,12 @@ public:
L2ElementRestriction(const FiniteElementSpace&);
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 ElementRestriction. */
void FillI(SparseMatrix &mat) const;
/** Fill the J and Data arrays of SparseMatrix corresponding to the sparsity
pattern given by this L2FaceRestriction, and the values of ea_data. */
void FillJAndData(const Vector &ea_data, SparseMatrix &mat) const;
};
/// Operator that extracts Face degrees of freedom.
@@ -111,10 +132,12 @@ class L2FaceRestriction : public Operator
protected:
const FiniteElementSpace &fes;
const int nf;
const int ne;
const int vdim;
const bool byvdim;
const int ndofs;
const int dof;
const int elemDofs;
const L2FaceValues m;
const int nfdofs;
Array<int> scatter_indices1;
@@ -122,12 +145,27 @@ protected:
Array<int> offsets;
Array<int> gather_indices;
L2FaceRestriction(const FiniteElementSpace&,
const FaceType,
const L2FaceValues m = L2FaceValues::DoubleValued);
public:
L2FaceRestriction(const FiniteElementSpace&, const ElementDofOrdering,
const FaceType,
const L2FaceValues m = L2FaceValues::DoubleValued);
void Mult(const Vector &x, Vector &y) const;
virtual 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 L2FaceRestriction. */
virtual void FillI(SparseMatrix &mat, SparseMatrix &face_mat) const;
/** Fill the J and Data arrays of SparseMatrix corresponding to the sparsity
pattern given by this L2FaceRestriction, and the values of ea_data. */
virtual void FillJAndData(const Vector &ea_data,
SparseMatrix &mat,
SparseMatrix &face_mat) const;
/// This methods adds the DG face matrices to the element matrices.
void AddFaceMatricesToElementMatrices(Vector &fea_data,
Vector &ea_data) const;
};
// Return the face degrees of freedom returned in Lexicographic order.
+534 -96
View File
@@ -927,9 +927,20 @@ void TargetConstructor::ComputeElementTargets(int e_id, const FiniteElement &fe,
}
}
void TargetConstructor::ComputeElementTargetsGradient(const IntegrationRule &ir,
const Vector &elfun,
IsoparametricTransformation &Tpr,
DenseTensor &dJtr) const
{
MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
// TODO: Compute derivative for targets with GIVEN_SHAPE or/and GIVEN_SIZE
for (int i = 0; i < Tpr.GetFE()->GetDim()*ir.GetNPoints(); i++) { dJtr(i) = 0.; }
}
void AnalyticAdaptTC::SetAnalyticTargetSpec(Coefficient *sspec,
VectorCoefficient *vspec,
MatrixCoefficient *mspec)
TMOPMatrixCoefficient *mspec)
{
scalar_tspec = sspec;
vector_tspec = vspec;
@@ -970,6 +981,39 @@ void AnalyticAdaptTC::ComputeElementTargets(int e_id, const FiniteElement &fe,
}
}
void AnalyticAdaptTC::ComputeElementTargetsGradient(const IntegrationRule &ir,
const Vector &elfun,
IsoparametricTransformation &Tpr,
DenseTensor &dJtr) const
{
const FiniteElement *fe = Tpr.GetFE();
DenseMatrix point_mat;
point_mat.UseExternalData(elfun.GetData(), fe->GetDof(), fe->GetDim());
switch (target_type)
{
case GIVEN_FULL:
{
MFEM_VERIFY(matrix_tspec != NULL,
"Target type GIVEN_FULL requires a TMOPMatrixCoefficient.");
for (int d = 0; d < fe->GetDim(); d++)
{
for (int i = 0; i < ir.GetNPoints(); i++)
{
const IntegrationPoint &ip = ir.IntPoint(i);
Tpr.SetIntPoint(&ip);
DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
matrix_tspec->EvalGrad(dJtr_i, Tpr, ip, d);
}
}
break;
}
default:
MFEM_ABORT("Incompatible target type for analytic adaptation!");
}
}
#ifdef MFEM_USE_MPI
void DiscreteAdaptTC::FinalizeParDiscreteTargetSpec(const ParGridFunction
&tspec_)
@@ -1168,7 +1212,7 @@ void DiscreteAdaptTC::UpdateTargetSpecificationAtNode(const FiniteElement &el,
Array<int> dofs;
tspec_fes->GetElementDofs(T.ElementNo, dofs);
const int cnt = tspec.Size()/ncomp; //dofs per scalar-field
const int cnt = tspec.Size()/ncomp; // dofs per scalar-field
for (int i = 0; i < ncomp; i++)
{
@@ -1196,6 +1240,9 @@ void DiscreteAdaptTC::ComputeElementTargets(int e_id, const FiniteElement &fe,
DenseTensor &Jtr) const
{
MFEM_VERIFY(tspec_fesv, "No target specifications have been set.");
const int dim = fe.GetDim(),
nqp = ir.GetNPoints();
Jtrcomp.SetSize(dim, dim, 4*nqp);
switch (target_type)
{
@@ -1205,7 +1252,7 @@ void DiscreteAdaptTC::ComputeElementTargets(int e_id, const FiniteElement &fe,
const DenseMatrix &Wideal =
Geometries.GetGeomToPerfGeomJac(fe.GetGeomType());
const int dim = Wideal.Height(),
ndofs = tspec_fes->GetFE(0)->GetDof(),
ndofs = tspec_fes->GetFE(e_id)->GetDof(),
ntspec_dofs = ndofs*ncomp;
Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
@@ -1216,25 +1263,32 @@ void DiscreteAdaptTC::ComputeElementTargets(int e_id, const FiniteElement &fe,
tspec_fesv->GetElementVDofs(e_id, dofs);
tspec.GetSubVector(dofs, tspec_vals);
for (int i = 0; i < ir.GetNPoints(); i++)
for (int q = 0; q < nqp; q++)
{
const IntegrationPoint &ip = ir.IntPoint(i);
const IntegrationPoint &ip = ir.IntPoint(q);
tspec_fes->GetFE(e_id)->CalcShape(ip, shape);
Jtr(i) = Wideal; //Initialize to identity
Jtr(q) = Wideal; // Initialize to identity
for (int d = 0; d < 4; d++)
{
DenseMatrix Jtrcomp_q(Jtrcomp.GetData(d + 4*q), dim, dim);
Jtrcomp_q = Wideal; // Initialize to identity
}
if (sizeidx != -1) //Set size
if (sizeidx != -1) // Set size
{
par_vals.SetDataAndSize(tspec_vals.GetData()+sizeidx*ndofs, ndofs);
const double min_size = par_vals.Min();
MFEM_VERIFY(min_size > 0.0,
"Non-positive size propagated in the target definition.");
const double size = std::max(shape * par_vals, min_size);
Jtr(i).Set(std::pow(size, 1.0/dim), Jtr(i));
} //Done size
Jtr(q).Set(std::pow(size, 1.0/dim), Jtr(q));
DenseMatrix Jtrcomp_q(Jtrcomp.GetData(0 + 4*q), dim, dim);
Jtrcomp_q = Jtr(q);
} // Done size
if (target_type == IDEAL_SHAPE_GIVEN_SIZE) { continue; }
if (aspectratioidx != -1) //Set aspect ratio
if (aspectratioidx != -1) // Set aspect ratio
{
if (dim == 2)
{
@@ -1262,12 +1316,13 @@ void DiscreteAdaptTC::ComputeElementTargets(int e_id, const FiniteElement &fe,
D_rho(1,1) = pow(rho2,2./3.);
D_rho(2,2) = pow(rho3,2./3.);
}
DenseMatrix Jtrcomp_q(Jtrcomp.GetData(1 + 4*q), dim, dim);
Jtrcomp_q = D_rho;
DenseMatrix Temp = Jtr(q);
Mult(D_rho, Temp, Jtr(q));
} // Done aspect ratio
DenseMatrix Temp = Jtr(i);
Mult(D_rho, Temp, Jtr(i));
} //Done aspect ratio
if (skewidx != -1) //Set skew
if (skewidx != -1) // Set skew
{
if (dim == 2)
{
@@ -1303,12 +1358,13 @@ void DiscreteAdaptTC::ComputeElementTargets(int e_id, const FiniteElement &fe,
Q_phi(2,2) = sin(phi13)*sin(chi);
}
DenseMatrix Jtrcomp_q(Jtrcomp.GetData(2 + 4*q), dim, dim);
Jtrcomp_q = Q_phi;
DenseMatrix Temp = Jtr(q);
Mult(Q_phi, Temp, Jtr(q));
} // Done skew
DenseMatrix Temp = Jtr(i);
Mult(Q_phi, Temp, Jtr(i));
} // done skew
if (orientationidx != -1) //Set orientation
if (orientationidx != -1) // Set orientation
{
if (dim == 2)
{
@@ -1333,33 +1389,28 @@ void DiscreteAdaptTC::ComputeElementTargets(int e_id, const FiniteElement &fe,
const double psi = shape * par_vals_c2;
const double beta = shape * par_vals_c3;
DenseMatrix R_tp(dim), R_beta(dim), R_theta(dim);
double ct = cos(theta), st = sin(theta),
cp = cos(psi), sp = sin(psi);
R_tp(0,0) = ct*sp;
R_tp(1,0) = st*sp;
R_tp(2,0) = cp;
cp = cos(psi), sp = sin(psi),
cb = cos(beta), sb = sin(beta);
R_tp(0,1) = -(ct*st*sp*sp)/(1+cp);
R_tp(1,1) = cp+(pow(ct,2.)*pow(sp,2.))/(1+cp);
R_tp(2,1) = -st*sp;
R_theta = 0.;
R_theta(0,0) = ct*sp;
R_theta(1,0) = st*sp;
R_theta(2,0) = cp;
R_tp(0,2) = -cp-(pow(st,2.)*pow(sp,2.))/(1+cp);
R_tp(1,2) = -R_tp(0,1);
R_tp(2,2) = ct*sp;
R_theta(0,1) = -st*cb + ct*cp*sb;
R_theta(1,1) = ct*cb + st*cp*sb;
R_theta(2,1) = -sp*sb;
R_beta = 0.;
R_beta(0,0) = 1.;
R_beta(1,1) = cos(beta);
R_beta(1,2) = -sin(beta);
R_beta(2,1) = sin(beta);
R_beta(2,2) = cos(beta);
Mult(R_tp, R_beta, R_theta);
R_theta(0,0) = -st*sb - ct*cp*cb;
R_theta(1,0) = ct*sb - st*cp*cb;
R_theta(2,0) = sp*cb;
}
DenseMatrix Temp = Jtr(i);
Mult(R_theta, Temp, Jtr(i));
} // done orientation
DenseMatrix Jtrcomp_q(Jtrcomp.GetData(3 + 4*q), dim, dim);
Jtrcomp_q = R_theta;
DenseMatrix Temp = Jtr(q);
Mult(R_theta, Temp, Jtr(q));
} // Done orientation
}
break;
}
@@ -1368,6 +1419,353 @@ void DiscreteAdaptTC::ComputeElementTargets(int e_id, const FiniteElement &fe,
}
}
void DiscreteAdaptTC::ComputeElementTargetsGradient(const IntegrationRule &ir,
const Vector &elfun,
IsoparametricTransformation &Tpr,
DenseTensor &dJtr) const
{
MFEM_ASSERT(target_type == IDEAL_SHAPE_UNIT_SIZE || nodes != NULL, "");
MFEM_VERIFY(tspec_fesv, "No target specifications have been set.");
dJtr = 0.;
const int e_id = Tpr.ElementNo;
const FiniteElement *fe = Tpr.GetFE();
switch (target_type)
{
case IDEAL_SHAPE_GIVEN_SIZE:
case GIVEN_SHAPE_AND_SIZE:
{
const DenseMatrix &Wideal =
Geometries.GetGeomToPerfGeomJac(fe->GetGeomType());
const int dim = Wideal.Height(),
ndofs = fe->GetDof(),
ntspec_dofs = ndofs*ncomp;
Vector shape(ndofs), tspec_vals(ntspec_dofs), par_vals,
par_vals_c1(ndofs), par_vals_c2(ndofs), par_vals_c3(ndofs);
Array<int> dofs;
DenseMatrix dD_rho(dim), dQ_phi(dim), dR_theta(dim);
DenseMatrix dQ_phi13(dim), dQ_phichi(dim); // dQ_phi is used for dQ/dphi12 in 3D
DenseMatrix dR_psi(dim), dR_beta(dim);
tspec_fesv->GetElementVDofs(e_id, dofs);
tspec.GetSubVector(dofs, tspec_vals);
DenseMatrix grad_e_c1(ndofs, dim),
grad_e_c2(ndofs, dim),
grad_e_c3(ndofs, dim);
Vector grad_ptr_c1(grad_e_c1.GetData(), ndofs*dim),
grad_ptr_c2(grad_e_c2.GetData(), ndofs*dim),
grad_ptr_c3(grad_e_c3.GetData(), ndofs*dim);
DenseMatrix grad_phys; // This will be (dof x dim, dof).
fe->ProjectGrad(*fe, Tpr, grad_phys);
for (int i = 0; i < ir.GetNPoints(); i++)
{
const IntegrationPoint &ip = ir.IntPoint(i);
DenseMatrix Jtrcomp_s(Jtrcomp.GetData(0 + 4*i), dim, dim); // size
DenseMatrix Jtrcomp_d(Jtrcomp.GetData(1 + 4*i), dim, dim); // aspect-ratio
DenseMatrix Jtrcomp_q(Jtrcomp.GetData(2 + 4*i), dim, dim); // skew
DenseMatrix Jtrcomp_r(Jtrcomp.GetData(3 + 4*i), dim, dim); // orientation
DenseMatrix work1(dim), work2(dim), work3(dim);
if (sizeidx != -1) // Set size
{
par_vals.SetDataAndSize(tspec_vals.GetData()+sizeidx*ndofs, ndofs);
grad_phys.Mult(par_vals, grad_ptr_c1);
Vector grad_q(dim);
tspec_fes->GetFE(e_id)->CalcShape(ip, shape);
grad_e_c1.MultTranspose(shape, grad_q);
const double min_size = par_vals.Min();
MFEM_VERIFY(min_size > 0.0,
"Non-positive size propagated in the target definition.");
const double size = std::max(shape * par_vals, min_size);
double dz_dsize = (1./dim)*pow(size, 1./dim - 1.);
Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
Mult(Jtrcomp_r, work1, work2); // R*Q*D
for (int d = 0; d < dim; d++)
{
DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
work1 = Wideal;
work1.Set(dz_dsize, work1); // dz/dsize
work1 *= grad_q(d); // dz/dsize*dsize/dx
AddMult(work1, work2, dJtr_i); // dz/dx*R*Q*D
}
} // Done size
if (target_type == IDEAL_SHAPE_GIVEN_SIZE) { continue; }
if (aspectratioidx != -1) // Set aspect ratio
{
if (dim == 2)
{
par_vals.SetDataAndSize(tspec_vals.GetData()+
aspectratioidx*ndofs, ndofs);
grad_phys.Mult(par_vals, grad_ptr_c1);
Vector grad_q(dim);
tspec_fes->GetFE(e_id)->CalcShape(ip, shape);
grad_e_c1.MultTranspose(shape, grad_q);
const double aspectratio = shape * par_vals;
dD_rho = 0.;
dD_rho(0,0) = -0.5*pow(aspectratio,-1.5);
dD_rho(1,1) = 0.5*pow(aspectratio,-0.5);
Mult(Jtrcomp_s, Jtrcomp_r, work1); // z*R
Mult(work1, Jtrcomp_q, work2); // z*R*Q
for (int d = 0; d < dim; d++)
{
DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
work1 = dD_rho;
work1 *= grad_q(d); // work1 = dD/drho*drho/dx
AddMult(work2, work1, dJtr_i); // z*R*Q*dD/dx
}
}
else // 3D
{
par_vals.SetDataAndSize(tspec_vals.GetData()+
aspectratioidx*ndofs, ndofs*3);
par_vals_c1.SetData(par_vals.GetData());
par_vals_c2.SetData(par_vals.GetData()+ndofs);
par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
grad_phys.Mult(par_vals_c1, grad_ptr_c1);
grad_phys.Mult(par_vals_c2, grad_ptr_c2);
grad_phys.Mult(par_vals_c3, grad_ptr_c3);
Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
tspec_fes->GetFE(e_id)->CalcShape(ip, shape);
grad_e_c1.MultTranspose(shape, grad_q1);
grad_e_c2.MultTranspose(shape, grad_q2);
grad_e_c3.MultTranspose(shape, grad_q3);
const double rho1 = shape * par_vals_c1;
const double rho2 = shape * par_vals_c2;
const double rho3 = shape * par_vals_c3;
dD_rho = 0.;
dD_rho(0,0) = (2./3.)*pow(rho1,-1./3.);
dD_rho(1,1) = (2./3.)*pow(rho2,-1./3.);
dD_rho(2,2) = (2./3.)*pow(rho3,-1./3.);
Mult(Jtrcomp_s, Jtrcomp_r, work1); // z*R
Mult(work1, Jtrcomp_q, work2); // z*R*Q
for (int d = 0; d < dim; d++)
{
DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
work1 = dD_rho;
work1(0,0) *= grad_q1(d);
work1(1,2) *= grad_q2(d);
work1(2,2) *= grad_q3(d);
// work1 = dD/dx = dD/drho1*drho1/dx + dD/drho2*drho2/dx
AddMult(work2, work1, dJtr_i); // z*R*Q*dD/dx
}
}
} // Done aspect ratio
if (skewidx != -1) // Set skew
{
if (dim == 2)
{
par_vals.SetDataAndSize(tspec_vals.GetData()+
skewidx*ndofs, ndofs);
grad_phys.Mult(par_vals, grad_ptr_c1);
Vector grad_q(dim);
tspec_fes->GetFE(e_id)->CalcShape(ip, shape);
grad_e_c1.MultTranspose(shape, grad_q);
const double skew = shape * par_vals;
dQ_phi = 0.;
dQ_phi(0,0) = 1.;
dQ_phi(0,1) = -sin(skew);
dQ_phi(1,1) = cos(skew);
Mult(Jtrcomp_s, Jtrcomp_r, work2); // z*R
for (int d = 0; d < dim; d++)
{
DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
work1 = dQ_phi;
work1 *= grad_q(d); // work1 = dQ/dphi*dphi/dx
Mult(work1, Jtrcomp_d, work3); // dQ/dx*D
AddMult(work2, work3, dJtr_i); // z*R*dQ/dx*D
}
}
else
{
par_vals.SetDataAndSize(tspec_vals.GetData()+
skewidx*ndofs, ndofs*3);
par_vals_c1.SetData(par_vals.GetData());
par_vals_c2.SetData(par_vals.GetData()+ndofs);
par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
grad_phys.Mult(par_vals_c1, grad_ptr_c1);
grad_phys.Mult(par_vals_c2, grad_ptr_c2);
grad_phys.Mult(par_vals_c3, grad_ptr_c3);
Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
tspec_fes->GetFE(e_id)->CalcShape(ip, shape);
grad_e_c1.MultTranspose(shape, grad_q1);
grad_e_c2.MultTranspose(shape, grad_q2);
grad_e_c3.MultTranspose(shape, grad_q3);
const double phi12 = shape * par_vals_c1;
const double phi13 = shape * par_vals_c2;
const double chi = shape * par_vals_c3;
dQ_phi = 0.;
dQ_phi(0,0) = 1.;
dQ_phi(0,1) = -sin(phi12);
dQ_phi(1,1) = cos(phi12);
dQ_phi13 = 0.;
dQ_phi13(0,2) = -sin(phi13);
dQ_phi13(1,2) = cos(phi13)*cos(chi);
dQ_phi13(2,2) = cos(phi13)*sin(chi);
dQ_phichi = 0.;
dQ_phichi(1,2) = -sin(phi13)*sin(chi);
dQ_phichi(2,2) = sin(phi13)*cos(chi);
Mult(Jtrcomp_s, Jtrcomp_r, work2); // z*R
for (int d = 0; d < dim; d++)
{
DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
work1 = dQ_phi;
work1 *= grad_q1(d); // work1 = dQ/dphi12*dphi12/dx
work1.Add(grad_q2(d), dQ_phi13); // + dQ/dphi13*dphi13/dx
work1.Add(grad_q3(d), dQ_phichi); // + dQ/dchi*dchi/dx
Mult(work1, Jtrcomp_d, work3); // dQ/dx*D
AddMult(work2, work3, dJtr_i); // z*R*dQ/dx*D
}
}
} // Done skew
if (orientationidx != -1) // Set orientation
{
if (dim == 2)
{
par_vals.SetDataAndSize(tspec_vals.GetData()+
orientationidx*ndofs, ndofs);
grad_phys.Mult(par_vals, grad_ptr_c1);
Vector grad_q(dim);
tspec_fes->GetFE(e_id)->CalcShape(ip, shape);
grad_e_c1.MultTranspose(shape, grad_q);
const double theta = shape * par_vals;
dR_theta(0,0) = -sin(theta);
dR_theta(0,1) = -cos(theta);
dR_theta(1,0) = cos(theta);
dR_theta(1,1) = -sin(theta);
Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
Mult(Jtrcomp_s, work1, work2); // z*Q*D
for (int d = 0; d < dim; d++)
{
DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
work1 = dR_theta;
work1 *= grad_q(d); // work1 = dR/dtheta*dtheta/dx
AddMult(work1, work2, dJtr_i); // z*dR/dx*Q*D
}
}
else
{
par_vals.SetDataAndSize(tspec_vals.GetData()+
orientationidx*ndofs, ndofs*3);
par_vals_c1.SetData(par_vals.GetData());
par_vals_c2.SetData(par_vals.GetData()+ndofs);
par_vals_c3.SetData(par_vals.GetData()+2*ndofs);
grad_phys.Mult(par_vals_c1, grad_ptr_c1);
grad_phys.Mult(par_vals_c2, grad_ptr_c2);
grad_phys.Mult(par_vals_c3, grad_ptr_c3);
Vector grad_q1(dim), grad_q2(dim), grad_q3(dim);
tspec_fes->GetFE(e_id)->CalcShape(ip, shape);
grad_e_c1.MultTranspose(shape, grad_q1);
grad_e_c2.MultTranspose(shape, grad_q2);
grad_e_c3.MultTranspose(shape, grad_q3);
const double theta = shape * par_vals_c1;
const double psi = shape * par_vals_c2;
const double beta = shape * par_vals_c3;
const double ct = cos(theta), st = sin(theta),
cp = cos(psi), sp = sin(psi),
cb = cos(beta), sb = sin(beta);
dR_theta = 0.;
dR_theta(0,0) = -st*sp;
dR_theta(1,0) = ct*sp;
dR_theta(2,0) = 0;
dR_theta(0,1) = -ct*cb - st*cp*sb;
dR_theta(1,1) = -st*cb + ct*cp*sb;
dR_theta(2,1) = 0.;
dR_theta(0,0) = -ct*sb + st*cp*cb;
dR_theta(1,0) = -st*sb - ct*cp*cb;
dR_theta(2,0) = 0.;
dR_beta = 0.;
dR_beta(0,0) = 0.;
dR_beta(1,0) = 0.;
dR_beta(2,0) = 0.;
dR_beta(0,1) = st*sb + ct*cp*cb;
dR_beta(1,1) = -ct*sb + st*cp*cb;
dR_beta(2,1) = -sp*cb;
dR_beta(0,0) = -st*cb + ct*cp*sb;
dR_beta(1,0) = ct*cb + st*cp*sb;
dR_beta(2,0) = 0.;
dR_psi = 0.;
dR_psi(0,0) = ct*cp;
dR_psi(1,0) = st*cp;
dR_psi(2,0) = -sp;
dR_psi(0,1) = 0. - ct*sp*sb;
dR_psi(1,1) = 0. + st*sp*sb;
dR_psi(2,1) = -cp*sb;
dR_psi(0,0) = 0. + ct*sp*cb;
dR_psi(1,0) = 0. + st*sp*cb;
dR_psi(2,0) = cp*cb;
Mult(Jtrcomp_q, Jtrcomp_d, work1); // Q*D
Mult(Jtrcomp_s, work1, work2); // z*Q*D
for (int d = 0; d < dim; d++)
{
DenseMatrix &dJtr_i = dJtr(i + d*ir.GetNPoints());
work1 = dR_theta;
work1 *= grad_q1(d); // work1 = dR/dtheta*dtheta/dx
work1.Add(grad_q2(d), dR_psi); // +dR/dpsi*dpsi/dx
work1.Add(grad_q3(d), dR_beta); // +dR/dbeta*dbeta/dx
AddMult(work1, work2, dJtr_i); // z*dR/dx*Q*D
}
}
} // Done orientation
}
break;
}
default:
MFEM_ABORT("Incompatible target type for discrete adaptation!");
}
Jtrcomp.Clear();
}
void DiscreteAdaptTC::UpdateGradientTargetSpecification(const Vector &x,
const double dx,
bool use_flag)
@@ -1570,11 +1968,11 @@ double TMOP_Integrator::GetElementEnergy(const FiniteElement &el,
Jpt.SetSize(dim);
PMatI.UseExternalData(elfun.GetData(), dof, dim);
const IntegrationRule *ir = EnergyIntegrationRule(el);
const IntegrationRule &ir = EnergyIntegrationRule(el);
energy = 0.0;
DenseTensor Jtr(dim, dim, ir->GetNPoints());
targetC->ComputeElementTargets(T.ElementNo, el, *ir, elfun, Jtr);
DenseTensor Jtr(dim, dim, ir.GetNPoints());
targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
// Limited case.
Vector shape, p, p0, d_vals;
@@ -1591,11 +1989,11 @@ double TMOP_Integrator::GetElementEnergy(const FiniteElement &el,
nodes0->GetSubVector(pos_dofs, pos0V);
if (lim_dist)
{
lim_dist->GetValues(T.ElementNo, *ir, d_vals);
lim_dist->GetValues(T.ElementNo, ir, d_vals);
}
else
{
d_vals.SetSize(ir->GetNPoints()); d_vals = 1.0;
d_vals.SetSize(ir.GetNPoints()); d_vals = 1.0;
}
}
@@ -1621,13 +2019,13 @@ double TMOP_Integrator::GetElementEnergy(const FiniteElement &el,
Vector zeta_q, zeta0_q;
if (adaptive_limiting)
{
zeta->GetValues(T.ElementNo, *ir, zeta_q);
zeta_0->GetValues(T.ElementNo, *ir, zeta0_q);
zeta->GetValues(T.ElementNo, ir, zeta_q);
zeta_0->GetValues(T.ElementNo, ir, zeta0_q);
}
for (int i = 0; i < ir->GetNPoints(); i++)
for (int i = 0; i < ir.GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
const IntegrationPoint &ip = ir.IntPoint(i);
const DenseMatrix &Jtr_i = Jtr(i);
metric->SetTargetJacobian(Jtr_i);
CalcInverse(Jtr_i, Jrt);
@@ -1697,6 +2095,7 @@ void TMOP_Integrator::AssembleElementVectorExact(const FiniteElement &el,
{
const int dof = el.GetDof(), dim = el.GetDim();
DenseMatrix Amat(dim), work1(dim), work2(dim);
DSh.SetSize(dof, dim);
DS.SetSize(dof, dim);
Jrt.SetSize(dim);
@@ -1706,20 +2105,21 @@ void TMOP_Integrator::AssembleElementVectorExact(const FiniteElement &el,
elvect.SetSize(dof*dim);
PMatO.UseExternalData(elvect.GetData(), dof, dim);
const IntegrationRule *ir = ActionIntegrationRule(el);
const int nqp = ir->GetNPoints();
const IntegrationRule &ir = ActionIntegrationRule(el);
const int nqp = ir.GetNPoints();
elvect = 0.0;
Vector weights(nqp);
DenseTensor Jtr(dim, dim, nqp);
targetC->ComputeElementTargets(T.ElementNo, el, *ir, elfun, Jtr);
DenseTensor dJtr(dim, dim, dim*nqp);
targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
// Limited case.
DenseMatrix pos0;
Vector shape, p, p0, d_vals, grad;
shape.SetSize(dof);
if (coeff0)
{
shape.SetSize(dof);
p.SetSize(dim);
p0.SetSize(dim);
pos0.SetSize(dof, dim);
@@ -1729,7 +2129,7 @@ void TMOP_Integrator::AssembleElementVectorExact(const FiniteElement &el,
nodes0->GetSubVector(pos_dofs, pos0V);
if (lim_dist)
{
lim_dist->GetValues(T.ElementNo, *ir, d_vals);
lim_dist->GetValues(T.ElementNo, ir, d_vals);
}
else
{
@@ -1739,7 +2139,7 @@ void TMOP_Integrator::AssembleElementVectorExact(const FiniteElement &el,
// Define ref->physical transformation, when a Coefficient is specified.
IsoparametricTransformation *Tpr = NULL;
if (coeff1 || coeff0 || zeta)
if (coeff1 || coeff0 || zeta || exact_action)
{
Tpr = new IsoparametricTransformation;
Tpr->SetFE(&el);
@@ -1747,11 +2147,19 @@ void TMOP_Integrator::AssembleElementVectorExact(const FiniteElement &el,
Tpr->ElementType = ElementTransformation::ELEMENT;
Tpr->Attribute = T.Attribute;
Tpr->GetPointMat().Transpose(PMatI); // PointMat = PMatI^T
if (exact_action)
{
targetC->ComputeElementTargetsGradient(ir, elfun, *Tpr, dJtr);
}
}
Vector d_detW_dx(dim);
Vector d_Winv_dx(dim);
for (int q = 0; q < nqp; q++)
{
const IntegrationPoint &ip = ir->IntPoint(q);
const IntegrationPoint &ip = ir.IntPoint(q);
const DenseMatrix &Jtr_q = Jtr(q);
metric->SetTargetJacobian(Jtr_q);
CalcInverse(Jtr_q, Jrt);
@@ -1767,13 +2175,44 @@ void TMOP_Integrator::AssembleElementVectorExact(const FiniteElement &el,
if (coeff1) { weight_m *= coeff1->Eval(*Tpr, ip); }
P *= weight_m;
AddMultABt(DS, P, PMatO);
AddMultABt(DS, P, PMatO); // w_q det(W) dmu/dx : dA/dx Winv
// TODO: derivatives of adaptivity-based targets.
if (exact_action)
{
el.CalcShape(ip, shape);
// Derivatives of adaptivity-based targets.
// First term: w_q d*(Det W)/dx * mu(T)
// d(Det W)/dx = det(W)*Tr[Winv*dW/dx]
DenseMatrix dwdx(dim);
for (int d = 0; d < dim; d++)
{
const DenseMatrix &dJtr_q = dJtr(q + d * nqp);
Mult(Jrt, dJtr_q, dwdx );
d_detW_dx(d) = dwdx.Trace();
}
d_detW_dx *= weight_m*metric->EvalW(Jpt); // *[w_q*det(W)]*mu(T)
// Second term: w_q det(W) dmu/dx : AdWinv/dx
// dWinv/dx = -Winv*dW/dx*Winv
MultAtB(PMatI, DSh, Amat);
for (int d = 0; d < dim; d++)
{
const DenseMatrix &dJtr_q = dJtr(q + d*nqp);
Mult(Jrt, dJtr_q, work1); // Winv*dw/dx
Mult(work1, Jrt, work2); // Winv*dw/dx*Winv
Mult(Amat, work2, work1); // A*Winv*dw/dx*Winv
MultAtB(P, work1, work2); // dmu/dT^T*A*Winv*dw/dx*Winv
d_Winv_dx(d) = work2.Trace(); // Tr[dmu/dT : AWinv*dw/dx*Winv]
}
d_Winv_dx *= -weight_m; // Include (-) factor as well
d_detW_dx += d_Winv_dx;
AddMultVWt(shape, d_detW_dx, PMatO);
}
if (coeff0)
{
el.CalcShape(ip, shape);
if (!exact_action) { el.CalcShape(ip, shape); }
PMatI.MultTranspose(shape, p);
pos0.MultTranspose(shape, p0);
lim_func->Eval_d1(p, p0, d_vals(q), grad);
@@ -1782,7 +2221,7 @@ void TMOP_Integrator::AssembleElementVectorExact(const FiniteElement &el,
}
}
if (zeta) { AssembleElemVecAdaptLim(el, weights, *Tpr, *ir, PMatO); }
if (zeta) { AssembleElemVecAdaptLim(el, weights, *Tpr, ir, PMatO); }
delete Tpr;
}
@@ -1801,13 +2240,13 @@ void TMOP_Integrator::AssembleElementGradExact(const FiniteElement &el,
PMatI.UseExternalData(elfun.GetData(), dof, dim);
elmat.SetSize(dof*dim);
const IntegrationRule *ir = GradientIntegrationRule(el);
const int nqp = ir->GetNPoints();
const IntegrationRule &ir = GradientIntegrationRule(el);
const int nqp = ir.GetNPoints();
elmat = 0.0;
Vector weights(nqp);
DenseTensor Jtr(dim, dim, nqp);
targetC->ComputeElementTargets(T.ElementNo, el, *ir, elfun, Jtr);
targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
// Limited case.
DenseMatrix pos0, grad_grad;
@@ -1824,7 +2263,7 @@ void TMOP_Integrator::AssembleElementGradExact(const FiniteElement &el,
nodes0->GetSubVector(pos_dofs, pos0V);
if (lim_dist)
{
lim_dist->GetValues(T.ElementNo, *ir, d_vals);
lim_dist->GetValues(T.ElementNo, ir, d_vals);
}
else
{
@@ -1846,7 +2285,7 @@ void TMOP_Integrator::AssembleElementGradExact(const FiniteElement &el,
for (int q = 0; q < nqp; q++)
{
const IntegrationPoint &ip = ir->IntPoint(q);
const IntegrationPoint &ip = ir.IntPoint(q);
const DenseMatrix &Jtr_q = Jtr(q);
metric->SetTargetJacobian(Jtr_q);
CalcInverse(Jtr_q, Jrt);
@@ -1863,7 +2302,6 @@ void TMOP_Integrator::AssembleElementGradExact(const FiniteElement &el,
// TODO: derivatives of adaptivity-based targets.
// TODO optimize by symmetry.
if (coeff0)
{
el.CalcShape(ip, shape);
@@ -1889,7 +2327,7 @@ void TMOP_Integrator::AssembleElementGradExact(const FiniteElement &el,
}
}
if (zeta) { AssembleElemGradAdaptLim(el, weights, *Tpr, *ir, elmat); }
if (zeta) { AssembleElemGradAdaptLim(el, weights, *Tpr, ir, elmat); }
delete Tpr;
}
@@ -2060,10 +2498,10 @@ void TMOP_Integrator::AssembleElementVectorFD(const FiniteElement &el,
// Contributions from adaptive limiting (exact derivatives).
if (zeta)
{
const IntegrationRule *ir = ActionIntegrationRule(el);
const int nqp = ir->GetNPoints();
const IntegrationRule &ir = ActionIntegrationRule(el);
const int nqp = ir.GetNPoints();
DenseTensor Jtr(dim, dim, nqp);
targetC->ComputeElementTargets(T.ElementNo, el, *ir, elfun, Jtr);
targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
IsoparametricTransformation Tpr;
Tpr.SetFE(&el);
@@ -2075,11 +2513,11 @@ void TMOP_Integrator::AssembleElementVectorFD(const FiniteElement &el,
Vector weights(nqp);
for (int q = 0; q < nqp; q++)
{
weights(q) = ir->IntPoint(q).weight * Jtr(q).Det();
weights(q) = ir.IntPoint(q).weight * Jtr(q).Det();
}
PMatO.UseExternalData(elvect.GetData(), dof, dim);
AssembleElemVecAdaptLim(el, weights, Tpr, *ir, PMatO);
AssembleElemVecAdaptLim(el, weights, Tpr, ir, PMatO);
}
}
@@ -2156,10 +2594,10 @@ void TMOP_Integrator::AssembleElementGradFD(const FiniteElement &el,
// Contributions from adaptive limiting.
if (zeta)
{
const IntegrationRule *ir = GradientIntegrationRule(el);
const int nqp = ir->GetNPoints();
const IntegrationRule &ir = GradientIntegrationRule(el);
const int nqp = ir.GetNPoints();
DenseTensor Jtr(dim, dim, nqp);
targetC->ComputeElementTargets(T.ElementNo, el, *ir, elfun, Jtr);
targetC->ComputeElementTargets(T.ElementNo, el, ir, elfun, Jtr);
IsoparametricTransformation Tpr;
Tpr.SetFE(&el);
@@ -2171,10 +2609,10 @@ void TMOP_Integrator::AssembleElementGradFD(const FiniteElement &el,
Vector weights(nqp);
for (int q = 0; q < nqp; q++)
{
weights(q) = ir->IntPoint(q).weight * Jtr(q).Det();
weights(q) = ir.IntPoint(q).weight * Jtr(q).Det();
}
AssembleElemGradAdaptLim(el, weights, Tpr, *ir, elmat);
AssembleElemGradAdaptLim(el, weights, Tpr, ir, elmat);
}
}
@@ -2204,35 +2642,35 @@ void TMOP_Integrator::ComputeNormalizationEnergies(const GridFunction &x,
Array<int> vdofs;
Vector x_vals;
const FiniteElementSpace* const fes = x.FESpace();
const FiniteElement *fe = fes->GetFE(0);
const int dof = fes->GetFE(0)->GetDof(), dim = fes->GetFE(0)->GetDim();
DSh.SetSize(dof, dim);
const int dim = fes->GetMesh()->Dimension();
Jrt.SetSize(dim);
Jpr.SetSize(dim);
Jpt.SetSize(dim);
const IntegrationRule *ir = EnergyIntegrationRule(*fe);
DenseTensor Jtr(dim, dim, ir->GetNPoints());
metric_energy = 0.0;
lim_energy = 0.0;
for (int i = 0; i < fes->GetNE(); i++)
{
fe = fes->GetFE(i);
const FiniteElement *fe = fes->GetFE(i);
const IntegrationRule &ir = EnergyIntegrationRule(*fe);
const int nqp = ir.GetNPoints();
DenseTensor Jtr(dim, dim, nqp);
const int dof = fe->GetDof();
DSh.SetSize(dof, dim);
fes->GetElementVDofs(i, vdofs);
x.GetSubVector(vdofs, x_vals);
PMatI.UseExternalData(x_vals.GetData(), dof, dim);
targetC->ComputeElementTargets(i, *fe, *ir, x_vals, Jtr);
targetC->ComputeElementTargets(i, *fe, ir, x_vals, Jtr);
for (int i = 0; i < ir->GetNPoints(); i++)
for (int q = 0; q < nqp; q++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
metric->SetTargetJacobian(Jtr(i));
CalcInverse(Jtr(i), Jrt);
const double weight = ip.weight * Jtr(i).Det();
const IntegrationPoint &ip = ir.IntPoint(q);
metric->SetTargetJacobian(Jtr(q));
CalcInverse(Jtr(q), Jrt);
const double weight = ip.weight * Jtr(q).Det();
fe->CalcDShape(ip, DSh);
MultAtB(PMatI, DSh, Jpr);
@@ -2253,9 +2691,9 @@ void TMOP_Integrator::ComputeMinJac(const Vector &x,
const FiniteElementSpace &fes)
{
const FiniteElement *fe = fes.GetFE(0);
const IntegrationRule *ir = EnergyIntegrationRule(*fe);
const IntegrationRule &ir = EnergyIntegrationRule(*fe);
const int NE = fes.GetMesh()->GetNE(), dim = fe->GetDim(),
dof = fe->GetDof(), nsp = ir->GetNPoints();
dof = fe->GetDof(), nsp = ir.GetNPoints();
Array<int> xdofs(dof * dim);
DenseMatrix Jpr(dim), dshape(dof, dim), pos(dof, dim);
@@ -2272,7 +2710,7 @@ void TMOP_Integrator::ComputeMinJac(const Vector &x,
detv_sum = 0.;
for (int j = 0; j < nsp; j++)
{
fes.GetFE(i)->CalcDShape(ir->IntPoint(j), dshape);
fes.GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
MultAtB(pos, dshape, Jpr);
detv_sum += std::fabs(Jpr.Det());
}
+66 -11
View File
@@ -677,6 +677,25 @@ public:
const IntegrationRule &ir,
const Vector &elfun,
DenseTensor &Jtr) const;
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir,
const Vector &elfun,
IsoparametricTransformation &Tpr,
DenseTensor &dJtr) const;
};
class TMOPMatrixCoefficient : public MatrixCoefficient
{
public:
explicit TMOPMatrixCoefficient(int dim) : MatrixCoefficient(dim, dim) { }
/** @brief Evaluate the derivative of the matrix coefficient with respect to
@a comp in the element described by @a T at the point @a ip, storing the
result in @a K. */
virtual void EvalGrad(DenseMatrix &K, ElementTransformation &T,
const IntegrationPoint &ip, int comp) = 0;
virtual ~TMOPMatrixCoefficient() { }
};
class AnalyticAdaptTC : public TargetConstructor
@@ -685,7 +704,7 @@ protected:
// Analytic target specification.
Coefficient *scalar_tspec;
VectorCoefficient *vector_tspec;
MatrixCoefficient *matrix_tspec;
TMOPMatrixCoefficient *matrix_tspec;
public:
AnalyticAdaptTC(TargetType ttype)
@@ -694,7 +713,7 @@ public:
virtual void SetAnalyticTargetSpec(Coefficient *sspec,
VectorCoefficient *vspec,
MatrixCoefficient *mspec);
TMOPMatrixCoefficient *mspec);
/** @brief Given an element and quadrature rule, computes ref->target
transformation Jacobians for each quadrature point in the element.
@@ -703,6 +722,11 @@ public:
const IntegrationRule &ir,
const Vector &elfun,
DenseTensor &Jtr) const;
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir,
const Vector &elfun,
IsoparametricTransformation &Tpr,
DenseTensor &dJtr) const;
};
#ifdef MFEM_USE_MPI
@@ -724,13 +748,17 @@ protected:
// eta1(x+h,y), eta2(x+h,y) ... etan(x+h,y), eta1(x,y+h), eta2(x,y+h) ...
// same for tspec_pert2h and tspec_pertmix.
// Components of Target Jacobian at each quadrature point of an element. This
// is required for computation of the derivative using chain rule.
mutable DenseTensor Jtrcomp;
// Note: do not use the Nodes of this space as they may not be on the
// positions corresponding to the values of tspec.
const FiniteElementSpace *tspec_fes;
const FiniteElementSpace *tspec_fesv;
// These flags can be used by outside functions to avoid recomputing
// the tspec and tspec_perth fields again on the same mesh.
// These flags can be used by outside functions to avoid recomputing the
// tspec and tspec_perth fields again on the same mesh.
bool good_tspec, good_tspec_grad, good_tspec_hess;
// Evaluation of the discrete target specification on different meshes.
@@ -837,6 +865,11 @@ public:
const IntegrationRule &ir,
const Vector &elfun,
DenseTensor &Jtr) const;
virtual void ComputeElementTargetsGradient(const IntegrationRule &ir,
const Vector &elfun,
IsoparametricTransformation &Tpr,
DenseTensor &dJtr) const;
};
class TMOPNewtonSolver;
@@ -857,6 +890,10 @@ protected:
TMOP_QualityMetric *metric; // not owned
const TargetConstructor *targetC; // not owned
// Custom integration rules.
IntegrationRules *IntegRules;
int integ_order;
// Weight Coefficient multiplying the quality metric term.
Coefficient *coeff1; // not owned, if NULL -> coeff1 is 1.
// Normalization factor for the metric term.
@@ -889,6 +926,9 @@ protected:
// Specifies that ComputeElementTargets is being called by a FD function.
// It's used to skip terms that have exact derivative calculations.
bool fd_call_flag;
// Compute the exact action of the Integrator (includes derivative of the
// target with respect to spatial position)
bool exact_action;
Array <Vector *> ElemDer; //f'(x)
Array <Vector *> ElemPertEnergy; //f(x+h)
@@ -952,17 +992,21 @@ protected:
nodes0 = NULL; coeff0 = NULL; lim_dist = NULL; lim_func = NULL;
}
const IntegrationRule *EnergyIntegrationRule(const FiniteElement &el) const
const IntegrationRule &EnergyIntegrationRule(const FiniteElement &el) const
{
return (IntRule) ? IntRule
/* */ : &(IntRules.Get(el.GetGeomType(), 2*el.GetOrder() + 3));
if (IntegRules)
{
return IntegRules->Get(el.GetGeomType(), integ_order);
}
return (IntRule) ? *IntRule
/* */ : IntRules.Get(el.GetGeomType(), 2*el.GetOrder() + 3);
}
const IntegrationRule *ActionIntegrationRule(const FiniteElement &el) const
const IntegrationRule &ActionIntegrationRule(const FiniteElement &el) const
{
// TODO the energy most likely needs less integration points.
return EnergyIntegrationRule(el);
}
const IntegrationRule *GradientIntegrationRule(const FiniteElement &el) const
const IntegrationRule &GradientIntegrationRule(const FiniteElement &el) const
{
// TODO the action and energy most likely need less integration points.
return EnergyIntegrationRule(el);
@@ -972,17 +1016,25 @@ public:
/** @param[in] m TMOP_QualityMetric that will be integrated (not owned).
@param[in] tc Target-matrix construction algorithm to use (not owned). */
TMOP_Integrator(TMOP_QualityMetric *m, TargetConstructor *tc)
: metric(m), targetC(tc),
: metric(m), targetC(tc), IntegRules(NULL), integ_order(-1),
coeff1(NULL), metric_normal(1.0),
nodes0(NULL), coeff0(NULL),
lim_dist(NULL), lim_func(NULL), lim_normal(1.0),
zeta_0(NULL), zeta(NULL), coeff_zeta(NULL), adapt_eval(NULL),
discr_tc(dynamic_cast<DiscreteAdaptTC *>(tc)),
fdflag(false), dxscale(1.0e3), fd_call_flag(false)
fdflag(false), dxscale(1.0e3), fd_call_flag(false), exact_action(false)
{ }
~TMOP_Integrator();
/// Prescribe a set of integration rules; relevant for mixed meshes.
/** This function has priority over SetIntRule(), if both are called. */
void SetIntegrationRules(IntegrationRules &irules, int order)
{
IntegRules = &irules;
integ_order = order;
}
/// Sets a scaling Coefficient for the quality metric term of the integrator.
/** With this addition, the integrator becomes
@f$ \int w1 W(Jpt) dx @f$.
@@ -1066,6 +1118,9 @@ public:
void SetFDhScale(double _dxscale) { dxscale = _dxscale; }
bool GetFDFlag() const { return fdflag; }
double GetFDh() const { return dx; }
/** @brief Flag to control if exact action of Integration is effected. */
void SetExactActionFlag(bool flag_) { exact_action = flag_; }
};
class TMOPComboIntegrator : public NonlinearFormIntegrator
+29 -15
View File
@@ -176,8 +176,8 @@ SerialAdvectorCGOper::SerialAdvectorCGOper(const Vector &x_start,
MassIntegrator *Minteg = new MassIntegrator;
M.AddDomainIntegrator(Minteg);
M.Assemble();
M.Finalize();
M.Assemble(0);
M.Finalize(0);
}
void SerialAdvectorCGOper::Mult(const Vector &ind, Vector &di_dt) const
@@ -220,8 +220,8 @@ ParAdvectorCGOper::ParAdvectorCGOper(const Vector &x_start,
MassIntegrator *Minteg = new MassIntegrator;
M.AddDomainIntegrator(Minteg);
M.Assemble();
M.Finalize();
M.Assemble(0);
M.Finalize(0);
}
void ParAdvectorCGOper::Mult(const Vector &ind, Vector &di_dt) const
@@ -353,13 +353,12 @@ double TMOPNewtonSolver::ComputeScalingFactor(const Vector &x,
energy_in = nlf->GetEnergy(x);
}
const int NE = fes->GetMesh()->GetNE(), dim = fes->GetFE(0)->GetDim(),
dof = fes->GetFE(0)->GetDof(), nsp = ir.GetNPoints();
Array<int> xdofs(dof * dim);
DenseMatrix Jpr(dim), dshape(dof, dim), pos(dof, dim);
Vector posV(pos.Data(), dof * dim);
Vector x_out_loc(fes->GetVSize());
const int NE = fes->GetMesh()->GetNE(), dim = fes->GetMesh()->Dimension();
Array<int> xdofs;
DenseMatrix Jpr(dim);
// Get the local prolongation of the solution vector.
Vector x_out_loc(fes->GetVSize());
if (serial)
{
const SparseMatrix *cP = fes->GetConformingProlongation();
@@ -373,15 +372,23 @@ double TMOPNewtonSolver::ComputeScalingFactor(const Vector &x,
}
#endif
// Check if the starting mesh (given by x) is inverted.
// Note that x hasn't been modified by the Newton update yet.
double min_detJ = infinity();
for (int i = 0; i < NE; i++)
{
const int dof = fes->GetFE(i)->GetDof();
DenseMatrix dshape(dof, dim), pos(dof, dim);
Vector posV(pos.Data(), dof * dim);
fes->GetElementVDofs(i, xdofs);
x_out_loc.GetSubVector(xdofs, posV);
const IntegrationRule &irule = GetIntegrationRule(*fes->GetFE(i));
const int nsp = irule.GetNPoints();
for (int j = 0; j < nsp; j++)
{
fes->GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
fes->GetFE(i)->CalcDShape(irule.IntPoint(j), dshape);
MultAtB(pos, dshape, Jpr);
min_detJ = std::min(min_detJ, Jpr.Det());
}
@@ -394,18 +401,18 @@ double TMOPNewtonSolver::ComputeScalingFactor(const Vector &x,
p_nlf->ParFESpace()->GetComm());
}
#endif
bool untangling = false;
if (min_detJ_all <= 0) { untangling = true; }
const bool untangling = (min_detJ_all <= 0) ? true : false;
const bool have_b = (b.Size() == Height());
Vector x_out(x.Size());
bool x_out_ok = false;
double scale = 1.0, energy_out = 0.0;
double norm0 = Norm(r);
const double norm0 = Norm(r);
const double detJ_factor = (solver_type == 1) ? 0.25 : 0.5;
// Perform the line search.
for (int i = 0; i < 12; i++)
{
add(x, -scale, c, x_out);
@@ -429,11 +436,18 @@ double TMOPNewtonSolver::ComputeScalingFactor(const Vector &x,
int jac_ok = 1;
for (int i = 0; i < NE; i++)
{
const int dof = fes->GetFE(i)->GetDof();
DenseMatrix dshape(dof, dim), pos(dof, dim);
Vector posV(pos.Data(), dof * dim);
fes->GetElementVDofs(i, xdofs);
x_out_loc.GetSubVector(xdofs, posV);
const IntegrationRule &irule = GetIntegrationRule(*fes->GetFE(i));
const int nsp = irule.GetNPoints();
for (int j = 0; j < nsp; j++)
{
fes->GetFE(i)->CalcDShape(ir.IntPoint(j), dshape);
fes->GetFE(i)->CalcDShape(irule.IntPoint(j), dshape);
MultAtB(pos, dshape, Jpr);
if (Jpr.Det() <= 0.0) { jac_ok = 0; goto break2; }
}
+25 -2
View File
@@ -118,16 +118,39 @@ protected:
// Quadrature points that are checked for negative Jacobians etc.
const IntegrationRule &ir;
// These fields are relevant for mixed meshes.
IntegrationRules *IntegRules;
int integ_order;
const IntegrationRule &GetIntegrationRule(const FiniteElement &el) const
{
if (IntegRules)
{
return IntegRules->Get(el.GetGeomType(), integ_order);
}
return ir;
}
void UpdateDiscreteTC(const TMOP_Integrator &ti, const Vector &x_new) const;
public:
#ifdef MFEM_USE_MPI
TMOPNewtonSolver(MPI_Comm comm, const IntegrationRule &irule, int type = 0)
: LBFGSSolver(comm), solver_type(type), parallel(true), ir(irule) { }
: LBFGSSolver(comm), solver_type(type), parallel(true),
ir(irule), IntegRules(NULL), integ_order(-1) { }
#endif
TMOPNewtonSolver(const IntegrationRule &irule, int type = 0)
: LBFGSSolver(), solver_type(type), parallel(false), ir(irule) { }
: LBFGSSolver(), solver_type(type), parallel(false),
ir(irule), IntegRules(NULL), integ_order(-1) { }
/// Prescribe a set of integration rules; relevant for mixed meshes.
/** If called, this function has priority over the IntegrationRule given to
the constructor of the class. */
void SetIntegrationRules(IntegrationRules &irules, int order)
{
IntegRules = &irules;
integ_order = order;
}
virtual double ComputeScalingFactor(const Vector &x, const Vector &b) const;
+1
View File
@@ -32,6 +32,7 @@ list(APPEND SRCS
list(APPEND HDRS
array.hpp
backends.hpp
binaryio.hpp
cuda.hpp
device.hpp
+3 -3
View File
@@ -36,9 +36,9 @@ void Swap(Array<T> &, Array<T> &);
Abstract data type Array.
Array<T> is an automatically increasing array containing elements of the
generic type T. The allocated size may be larger then the logical size
of the array.
The elements can be accessed by the [] operator, the range is 0 to size-1.
generic type T, which must be a POD (plain old data) type. The allocated size
may be larger then the logical size of the array. The elements can be
accessed by the [] operator, the range is 0 to size-1.
*/
template <class T>
class Array

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