Compare commits

...
Author SHA1 Message Date
Cosmin G. Petra 3ded358f84 fixed comment 2022-12-29 10:51:12 -08:00
Cosmin G. Petra 08de4f5e87 finished draft of interfaces and added "usage" examples 2022-12-29 10:43:33 -08:00
Cosmin G. Petra 3fe97ad740 sketch of the interfaces needed for contact solvers 2022-12-28 15:20:22 -08:00
Tzanio Kolev e90e6e2b75 Merge pull request #3385 from mfem/gh-actions-homebrew-fix
Fix GitHub actions failure on MacOS
2022-12-28 10:17:17 -08:00
Veselin Dobrevand@tzanio fb3d72ce89 Add reviewer suggested comments
Co-authored-by: @tzanio
2022-12-28 10:08:50 -08:00
Tzanio Kolev 2e89831b1e Merge branch 'master' into gh-actions-homebrew-fix 2022-12-27 14:33:26 -08:00
Veselin Dobrev ac1f88ee74 Merge pull request #3369 from mfem/feature/kweiss/caliper-dependencies
Adds support for optional caliper dependencies to build system
2022-12-25 19:21:05 -08:00
Veselin Dobrev 652e2ba386 GitHub actions: test MacOS fix 2022-12-24 16:15:52 -08:00
Veselin Dobrev 4756a9c405 Fix GitHub actions failure on MacOS 2022-12-24 15:39:40 -08:00
Kenneth Weiss 46f64bf75f Merge branch 'master' into feature/kweiss/caliper-dependencies 2022-12-21 10:58:53 -08:00
Kenneth Weiss 326a4177b4 Adds lib64 library paths for caliper, adiak and gotcha
Per PR suggestion.
2022-12-21 10:58:25 -08:00
Kenneth Weiss fcb9f6b4c2 Use find_package for adiak and gotcha dependencies in CMake build system
Per PR suggestion from Veselin.
2022-12-21 10:29:46 -08:00
Tzanio Kolev e16e2a916f Merge pull request #3373 from mfem/delete_noret
Modify Delete_ to not return a value
2022-12-19 15:24:44 -08:00
Tzanio Kolev c4f16f478b Merge pull request #3372 from mfem/enzyme_alloc
Add Enzyme info for allocation mechanisms
2022-12-19 15:23:33 -08:00
Tzanio Kolev bf8ec1a218 Merge pull request #3334 from mfem/bugfix/submesh-bdr-l2
Adding SubMesh support for discontinuous fields with vdim > 1
2022-12-17 19:17:24 -08:00
William S. Moses 973b42c57a Simplify 2022-12-16 17:19:02 -05:00
Veselin Dobrev 0ee0e55a92 Fix the Caliper tests defined in CMake 2022-12-15 18:33:42 -08:00
Tzanio Kolev 1f16c7a309 make style 2022-12-15 16:39:10 -08:00
William S. Moses ef42d3994a Add Enzyme info for allocation mechanisms 2022-12-15 18:07:34 -05:00
William S. Moses 0f75a95372 Modifiy Delete_ to not return a value 2022-12-15 18:06:16 -05:00
Kenneth Weiss 09331236d2 Adds support for optional caliper dependencies in cmake build system
If a user's caliper is built against `adiak` or `gotcha`, they can supply
`ADIAK_DIR` and/or `GOTCHA_DIR` config variables.
2022-12-14 12:18:52 -08:00
Kenneth Weiss be9f6a0d07 Adds support for optional caliper dependencies in make build system
If a user's caliper is built against `adiak` or `gotcha`, they can supply
`ADIAK_DIR` and/or `GOTCHA_DIR` config variables.
2022-12-14 12:18:42 -08:00
Stowell, Mark L 30fffb8cc6 Merge remote-tracking branch 'origin/master' into bugfix/submesh-bdr-l2 2022-12-12 14:46:43 -08:00
Stowell, Mark L b6c88d5b24 Hard coding dimension in unit test to avoid errors in Windows build 2022-12-12 11:59:46 -08:00
Tzanio Kolev e6ba86462c Merge pull request #3349 from mfem/l2-integral-support
Adding support for map type INTEGRAL in GridFunction::GetNodalValues
2022-12-12 08:12:50 -08:00
Tzanio Kolev 26444a366d Merge pull request #3348 from mfem/cmake-strumpack-metis-fix
Fix CMake TPLs ordering issue
2022-12-12 08:12:24 -08:00
Tzanio Kolev c5f51d0f12 Merge branch 'master' into bugfix/submesh-bdr-l2 2022-12-11 16:04:33 -08:00
Tzanio Kolev 05ed8c68cc Merge branch 'master' into cmake-strumpack-metis-fix 2022-12-11 16:03:10 -08:00
Tzanio Kolev 6f61468a93 Merge branch 'master' into l2-integral-support 2022-12-11 16:03:00 -08:00
Tzanio Kolev 881534e227 Merge pull request #3322 from mfem/tmop_exp_limiter
Exponential limiter integration [tmop_exp_limiter]
2022-12-11 16:02:15 -08:00
Tzanio Kolev 3155b5c7dc Merge pull request #3347 from mfem/fix-hip-compile
Fix hip compilation
2022-12-11 16:00:48 -08:00
Tzanio Kolev a2f529621c Merge pull request #3132 from mfem/ncmesh-pyramid-dev
NCMesh pyramid dev
2022-12-11 15:19:02 -08:00
Tzanio Kolev 3578622e42 Merge branch 'master' into ncmesh-pyramid-dev 2022-12-11 15:18:03 -08:00
Tzanio Kolev 371e625677 Updated CHANGELOG, other minor edits 2022-12-11 15:13:42 -08:00
Veselin Dobrev 9a7f764ac7 In the CMake build system, fixed broken build when NetCDF is
enabled and left some notes about future improvements.
2022-12-09 16:25:32 -08:00
Stowell, Mark L 58021339c0 Merge remote-tracking branch 'origin/master' into l2-integral-support
# Conflicts:
#	fem/gridfunc.cpp
2022-12-09 13:20:58 -08:00
Veselin Dobrev 640b86a094 Remove CMake version checks for versions older than the new
minimum required version, 3.8.

In defaults.mk, use C++14 when STRUMPACK is enabled, similar to CMake.
2022-12-09 10:52:45 -08:00
Tzanio Kolev 449b3e3393 Merge branch 'master' into cmake-strumpack-metis-fix 2022-12-09 09:04:35 -08:00
Tzanio Kolev 7d2eddd603 Merge branch 'master' into fix-hip-compile 2022-12-09 09:00:45 -08:00
Tzanio Kolev 975c0f2eab Merge pull request #3343 from mfem/geom-factors-dox-update
Document that Get(Face)GeometricFactors might return stale data
2022-12-09 08:57:55 -08:00
Tzanio Kolev a3aa202f36 Merge pull request #3194 from mfem/vector-remove-implicit-conversion
Deprecate implicit conversion from `Vector` to `double *`
2022-12-09 08:54:29 -08:00
Tzanio Kolev cc8e2de479 Merge branch 'master' into cmake-strumpack-metis-fix 2022-12-09 08:45:50 -08:00
Sebastian Grimberg e2e1d6428e Make suggested changes for CMake builds: Bumps CMake version to 3.8 for correct CMAKE_CXX_STANDARD handling, corrects use of OpenMP flags for test builds. 2022-12-08 14:21:47 -08:00
Stowell, Mark L 44b3ed9b21 Merge remote-tracking branch 'origin/master' into bugfix/submesh-bdr-l2 2022-12-08 12:22:44 -08:00
Veselin Dobrev 7f7dc51c70 Merge branch 'master' into l2-integral-support 2022-12-08 10:29:59 -08:00
Stowell, Mark L 81e38c3f54 Removing soon to be deprecated casts 2022-12-08 09:42:33 -08:00
Tzanio Kolev 74700f5bc8 Merge branch 'master' into vector-remove-implicit-conversion 2022-12-07 15:06:58 -08:00
Tzanio Kolev 5b173dc044 Merge pull request #3352 from mfem/vector-random-seed-removal
Removing global random seed in vector
2022-12-07 15:05:49 -08:00
Stowell, Mark L b04ce9e375 Removing GetRangeType etc from derived FE collection classes 2022-12-07 11:24:31 -08:00
Stowell, Mark L b43cf3b1fe Implementing GetRangeType etc in FiniteElementCollection base class 2022-12-07 11:24:01 -08:00
Stowell, Mark L 0b773a9f23 Adding FiniteElementCollection::FiniteElementForDim 2022-12-07 10:31:15 -08:00
Vladimir Z Tomov ae2f95d946 style. 2022-12-07 09:35:25 -08:00
Vladimir Z Tomov 4a4e135c1a Merge branch 'master' into tmop_exp_limiter 2022-12-07 09:28:50 -08:00
Veselin Dobrev 575547df7d Merge branch 'master' into cmake-strumpack-metis-fix 2022-12-06 17:04:23 -08:00
Veselin Dobrev 40b577d192 Merge pull request #3294 from mfem/doxygen-subdirs
Include several subdirectories in Doxygen docs
2022-12-06 16:40:28 -08:00
Will Pazner dcd8b0907f Merge remote-tracking branch 'origin/master' into vector-remove-implicit-conversion
# Conflicts:
#	CHANGELOG
#	fem/fe/fe_nd.cpp
#	fem/fe/fe_rt.cpp
2022-12-06 11:54:32 -08:00
Will Pazner 9e1c1ebc29 Merge pull request #3333 from mfem/vector-remove-implicit-conversion-tweaks
Various simplifications, tweaks, and fixes for PR #3194
2022-12-06 11:51:40 -08:00
Tzanio Kolev 615d13658e Merge branch 'master' into doxygen-subdirs 2022-12-06 11:32:02 -08:00
Tzanio Kolev 5ed071c026 Merge branch 'master' into geom-factors-dox-update 2022-12-06 11:24:07 -08:00
Tzanio Kolev db03d1e390 Merge branch 'master' into vector-random-seed-removal 2022-12-06 11:23:43 -08:00
Tzanio Kolev 7a24255cdb Merge branch 'master' into ncmesh-pyramid-dev 2022-12-06 10:28:44 -08:00
Tzanio Kolev f23b8135f5 Merge pull request #3287 from mfem/superlu-strumpack-cuda-fix
SuperLU_DIST and STRUMPACK with HYPRE+CUDA
2022-12-06 10:25:25 -08:00
Veselin Dobrev 84512a4733 [SQUASH MERGE] Fix GitHub CI failures with the new ubuntu-latest (#3351)
* Disable the test 'ubuntu-latest-cmake-opt-par-int32' which is
failing with 'ubuntu-latest' == 'ubuntu-22.04' to see if the
other tests pass.

* GH actions: update some action versions to fix warnings plus
some other tweaks

* GH actions: update more action versions to fix warnings

* GH actions: testing

* GH actions: testing

* GH actions: testing CMake fix

* GH actions: testing Doxygen fix
2022-12-06 10:20:12 -08:00
Tzanio Kolev 0c8a5d6530 Merge pull request #3353 from mfem/ceed-fix
Use renamed functions when libCEED version >= 0.10.2
2022-12-06 10:19:17 -08:00
Michael C Tyler Stees c1a78025ff Added missing parenthesis in limiting function and second derivative. 2022-12-06 09:06:18 -08:00
Veselin Dobrev 0eedd780f2 Merge branch 'master' into superlu-strumpack-cuda-fix 2022-12-05 15:24:12 -08:00
Aaron Fisher 21b7787aef Merge branch 'master' into ncmesh-pyramid-dev 2022-12-05 14:59:41 -08:00
Veselin Dobrev 44380ab02a Add calls to Mesh::NodesUpdated in both versions of Mesh::Transform 2022-12-05 02:30:45 -08:00
Veselin DobrevandsamuelpmishLLNL 8cdd2bb0c8 Doxygen tweak in Mesh::NodesUpdated
Co-authored-by: samuelpmishLLNL <61714427+samuelpmishLLNL@users.noreply.github.com>
2022-12-05 02:29:51 -08:00
Vladimir Z Tomov 8b5aa791e4 Added unit test for the expo limiting (failing, Mike will fix it). 2022-12-04 17:55:31 -08:00
Tzanio Kolev 70afda9c06 Merge pull request #3321 from mfem/rm-mesquite
Removed Mesquite support
2022-12-04 14:55:01 -08:00
Aaron Fisher 8bc44a8087 make style 2022-12-02 14:54:17 -08:00
Aaron Fisher ae93ec6887 Removed non-working anisotropic refinement of pyramids code. 2022-12-02 14:46:46 -08:00
Will Pazner caf638a3d3 Use renamed functions when libCEED version >= 0.10.2 2022-12-02 12:47:09 -08:00
Socratis Petrides aaec27a9ea removing global random seed in vector 2022-12-02 11:19:57 -08:00
Tzanio KolevandsamuelpmishLLNL 83dbeae7ab Update mesh/mesh.hpp
Co-authored-by: samuelpmishLLNL <61714427+samuelpmishLLNL@users.noreply.github.com>
2022-12-01 11:23:42 -08:00
Tzanio Kolev 3cd881e8b6 Merge branch 'master' into rm-mesquite 2022-12-01 11:20:50 -08:00
Veselin Dobrev 5b9dd0b42f Update doxygen docs based on reviewer feedback 2022-11-30 22:46:06 -08:00
Veselin Dobrevand@sebastiangrimberg 6947b3a639 In CMakeLists.txt, when removing duplicates from TPL_LIBRARIES,
keep the last occurrence instead of the first.

In the CMake function mfem_find_package, make sure the C++ standard
is used when calling check_cxx_source_compiles.

Fix a warning in STRUMPACKSolver::Mult.

Co-authored-by: @sebastiangrimberg
2022-11-30 18:34:12 -08:00
Stowell, Mark L 41a7679f19 Merge remote-tracking branch 'origin/master' into l2-integral-support 2022-11-30 10:46:25 -08:00
Stowell, Mark L 2b700c87d9 Improving doxygen comments 2022-11-30 10:33:45 -08:00
Stowell, Mark L 0d2f94be20 Exposing FiniteElement characteristics through FE_Collection 2022-11-30 10:18:19 -08:00
Michael C Tyler Stees 9c19c54114 Remove extra new line 2022-11-30 09:07:51 -08:00
Tzanio Kolev 8591e38a71 Merge pull request #3313 from mfem/sjg/dof-trans-cleanup
Fix minor copy-paste errors in DofTransformation
2022-11-30 08:02:32 -08:00
Tzanio Kolev acd46692a0 Merge pull request #3329 from mfem/bugfix/visit-dc-rfind
Bug fix for VisItDataCollection name parsing
2022-11-30 08:02:18 -08:00
Tzanio Kolev ca6588da7d Merge pull request #3305 from mfem/cmake-cuda-rdc-fix
Fix for CMake linking with TPLs built with CUDA relocatable device code (RDC)
2022-11-30 08:01:37 -08:00
Tzanio Kolev c60295e9c0 Merge pull request #3306 from mfem/cray-hip-gmake-support
Fix the building of the unit tests when using Cray HIP compilers
2022-11-30 08:01:04 -08:00
Stowell, Mark L a0bd50266c Adding support for map type INTEGRAL in GridFunction::GetNodalValues 2022-11-29 16:28:02 -08:00
Veselin Dobrev c2133437dd In CMakeLists.txt, move STRUMPACK before METIS in the list MFEM_TPLS 2022-11-28 21:13:55 -08:00
Tom Stitt 0c42f3751d fixes "no known conversion from 'int **' to 'void **'" compilation error during hip compilation 2022-11-28 16:49:22 -08:00
Tzanio Kolev 7830ee7877 Merge branch 'master' into bugfix/visit-dc-rfind 2022-11-28 14:32:19 -08:00
Tzanio Kolev 2196e61f4e Merge branch 'master' into rm-mesquite 2022-11-27 18:06:24 -08:00
Tzanio Kolev 42e979ebb6 Merge pull request #3337 from mfem/GradToCurl2D-fix
GradToCurl fix for vector and scalar valued curl.
2022-11-27 18:03:39 -08:00
Tzanio Kolev 5e0ffd933b Merge pull request #3268 from mfem/add-dist-solver
Fast distance solver
2022-11-27 18:02:56 -08:00
Tzanio Kolev 2d9850c642 Merge pull request #3278 from mfem/sjg/gslib-fix
Resolve compiler warnings in gslib.cpp
2022-11-27 18:01:51 -08:00
Tzanio Kolev 1301ed24fc Merge pull request #3290 from mfem/hipsparse-include-fix
Fix a warning with HIP >= 5.2.0
2022-11-27 18:01:21 -08:00
Veselin Dobrev 9b29c316e3 Update the doxygen docs of Mesh::GetGeometricFactors and
Mesh::GetFaceGeometricFactors to explicitly state that the
returned pointer to internal object may be invalidated by
some mesh operations.

Other small doxygen tweaks.
2022-11-26 19:46:03 -08:00
Vladimir Z Tomov cbdf014edf Reviewer comments. 2022-11-22 23:38:51 -08:00
Stowell, Mark L 7a277b6606 CHANGELOG entry 2022-11-22 14:03:04 -08:00
Stowell, Mark L 8976fe0284 Marking VisItDataCollection methods with "override" where appropriate 2022-11-22 13:49:08 -08:00
Tzanio Kolev 1e17003af3 Merge pull request #3315 from mfem/fix-vismesh
Fixed `common::VisualizeMesh`
2022-11-22 08:57:46 -08:00
Socratis Petrides 818041228c fix MixedCurlIntegrator 2022-11-21 20:34:13 -08:00
Socratis Petrides cb5d670e01 revert changes in GradToCurl. Add new method for Vector-valued GradToCurl in 2D 2022-11-21 17:04:13 -08:00
Stowell, Mark L 8ef4bef094 Adding SubMesh support for discontinuous fields with vdim > 1 2022-11-20 14:12:58 -08:00
Veselin Dobrev 972a4c227e Various simplifications, tweaks, and fixes 2022-11-19 14:18:43 -08:00
Stowell, Mark L 6730ffeb6f Setting pad_digits_rank even in serial 2022-11-18 09:39:31 -08:00
Stowell, Mark L e33dd78845 Fixing pad digits calls in unit test 2022-11-17 15:58:41 -08:00
Stowell, Mark L 7b5b871eea Adding pad digits options to other DataCollection related tools 2022-11-17 15:25:47 -08:00
Stowell, Mark L d7b2c4a7b2 Declaring SetPadDigits* as virtual 2022-11-17 15:25:09 -08:00
Stowell, Mark L 77a745bd28 Modifying get-values to support arbitrary cycle number padding 2022-11-17 10:54:20 -08:00
Will Pazner 3027566eb5 Merge pull request #3327 from mfem/vector-distance-hostread
Add const Vector& overload for Distance
2022-11-16 10:45:47 -08:00
Stowell, Mark L a58aafb743 Search string from the end to extract data collection name 2022-11-16 10:35:28 -08:00
Tzanio Kolev b09cc38df9 Merge pull request #3288 from mfem/hiop-nvcc-warnings-fix
Fix nvcc warnings when HiOp integration is enabled
2022-11-16 10:27:42 -08:00
Will Pazner facf28e24c Add const Vector& overload for Distance 2022-11-16 09:52:23 -08:00
Vladimir Z Tomov 5913021d50 Removed dummy GridFunctions. 2022-11-15 23:59:41 -08:00
Tzanio Kolev 3fca8798f6 Merge pull request #3304 from mfem/fix-clang-warnings
Fix some clang 14 warnings
2022-11-15 16:20:41 -08:00
Tzanio Kolev 6a71b32f04 Merge pull request #3317 from mfem/hip-miniapps-build-fix
Fix two issues affecting the miniapps building with HIP enabled
2022-11-15 16:19:57 -08:00
Will Pazner 8ee9011b29 Merge pull request #3172 from mfem/yohann/sort+test
Add sorting of sparse matrix when assembled on device.
2022-11-14 09:37:30 -08:00
Michael C Tyler Stees 86530f1d5b Adding exponential limiter option in fem/tmop.hpp and partial assembly support. 2022-11-14 07:44:37 -08:00
Will Pazner b3a57feaae Use Device::IsEnabled and add explanation in ex1 and ex1p 2022-11-13 16:02:32 -08:00
Will Pazner fee80f9280 Revise comment for BilinearForm::EnableSparseMatrixSorting 2022-11-13 16:02:01 -08:00
Tzanio Kolev 49c8ff3a3b Small edit in CHANGELOG 2022-11-13 12:00:26 -08:00
Vladimir Z Tomov 2c7ecb75e2 Removed Mesquite. 2022-11-10 19:51:50 -08:00
Veselin Dobrev 19105ba702 Fix two issues affecting the miniapps building with HIP enabled:
- the 'hooke' miniapp crashes the AMD HIP compiler, so for now
  we disabled it when building with HIP
- the building of the shared 'mfem-common' library was broken since
  the XLINKER make variable was left undefined with HIP enabled.
2022-11-10 00:15:09 -08:00
Tzanio Kolev 37b61aab9d Merge pull request #3303 from mfem/disconnected-mesh-fix
Fix partitioning error for disconnected meshes with METIS 5
2022-11-09 07:45:03 -08:00
Vladimir Z Tomov 725c2db36a Fixed common::VisualizeMesh(). 2022-11-08 23:29:49 -08:00
Sebastian Grimberg 646d73b980 Fix minor copy-paste errors in DofTransformation 2022-11-08 12:35:25 -08:00
Tzanio Kolev 55ccded864 Merge pull request #3307 from mfem/petsc-warning-fix
Fix PETSc 3.18.0 deprecation warning about MATTRANSPOSEMAT
2022-11-08 10:21:32 -08:00
Tzanio Kolev 4227521a52 Merge pull request #3309 from mfem/stefanozampini/fix-nonzeroguess-ksp
PetscLinearSolver: respect command line option for nonzero initial guess
2022-11-08 10:21:09 -08:00
Tzanio Kolev b9d166a4a4 Merge pull request #3302 from mfem/fix-doxygen-dgdiffusion
Fix Doxygen formatting for DGDiffusionIntegrator
2022-11-08 10:20:18 -08:00
Will Pazner 40c49ed992 Merge pull request #3297 from mfem/artv3/quadspacebase-init
Initalize order in quadrature space base class
2022-11-07 20:45:55 -08:00
Yohann Dudouit 6e70e2883b Set diagonal policy to DIAG_ONE when using Full assembly. 2022-11-07 12:32:53 -08:00
Yohann Dudouit affa9185bd Set the diagonal policy to DIAG_ONE in ex1 and ex1p. 2022-11-07 11:17:26 -08:00
Stefano Zampini c5c9a002c0 PetscLinearSolver: respect command line option for nonzero initial guess 2022-11-07 10:40:39 +03:00
Tzanio Kolev 0043dc833e Merge branch 'doxygen-subdirs' of github.com:mfem/mfem into doxygen-subdirs 2022-11-06 12:42:02 -08:00
Tzanio Kolev 14c43e1f98 Fix Doxygen comments 2022-11-06 12:40:56 -08:00
Veselin Dobrev 319d383af9 Fix PETSc 3.18.0 deprecation warning about MATTRANSPOSEMAT 2022-11-05 19:49:20 -07:00
Will Pazner 059cb2ce80 Remove unused variable in ParNCMesh::MemoryUsage 2022-11-05 13:47:19 -07:00
Will Pazner aa40b0b819 Suppress unused variable warning 2022-11-05 13:46:53 -07:00
Will Pazner d264a57850 Remove unused variable in Mesh::PrintVTU 2022-11-05 13:39:06 -07:00
Will Pazner 24825a5d26 Replace sprintf with snprintf 2022-11-05 13:38:42 -07:00
Veselin Dobrev 18e02de412 When partitioning a disconnected mesh with METIS 5, disable
the option for contiguous partitions which generates an error.
2022-11-04 23:45:47 -07:00
Will Pazner a1f2a79c3a Fix Doxygen formatting for DGDiffusionIntegrator 2022-11-04 12:18:52 -07:00
Will Pazner a6830a367a Merge remote-tracking branch 'origin/master' into yohann/sort+test 2022-11-04 09:55:29 -07:00
Veselin Dobrev 7176ad1ddd Add MFEM_USE_SUPERLU5 to the list of variables that will be
written to config.hpp and config.mk.

Also print MFEM_USE_SUPERLU5 when running 'make info'.
2022-11-04 01:40:32 -07:00
Julian Andrej cdc9408d27 more doxygen 2022-11-03 17:29:28 -07:00
Julian Andrej 322aa742d2 changed doxygen comment 2022-11-03 17:04:50 -07:00
Arturo Vargas 092180b3f7 Update qspace.cpp 2022-11-02 21:19:12 -07:00
Veselin Dobrev 65d28896cb Merge pull request #3281 from mfem/bugfix/qfunc_inline
Bug fix related to qfunction.cpp
2022-11-02 21:03:04 -07:00
Arturo Vargas 1fb13fe1a4 initalize order and size in quadrature space base 2022-11-02 16:39:14 -07:00
Veselin Dobrev 716d97e535 Ensure MUMPS and MKL CPardiso can use hypre matrices in GPU
memory by moving them temporarily to CPU memory.
2022-11-01 20:33:17 -07:00
Tzanio Kolev 9cd66faee6 Include several subdirectories in Doxygen docs 2022-11-01 19:10:28 -07:00
Veselin Dobrev f3c390fc1e To support building with HIP using the Cray compilers (which
need the -xhip flag) move the $(MFEM_FLAGS) argument (that
contains the -xhip flag) before the file(s) to be compiled.
2022-11-01 13:07:27 -07:00
Vladimir Z Tomov b0048a2ccb Merge branch 'master' into add-dist-solver 2022-10-31 14:44:11 -07:00
Vladimir Z Tomov 90ef7e72ef Compilation error in the diffusion example due to the interface change. 2022-10-31 14:42:38 -07:00
Veselin Dobrev 7940fbea51 Add closing #endif forgotten in the previous commit 2022-10-30 16:57:56 -07:00
Veselin Dobrev 6c0d431f90 Fix a warning with HIP >= 5.2.0 to include <hipsparse/hipsparse.h>
instead of just <hisparse.h>
2022-10-30 16:44:11 -07:00
Veselin Dobrev a7501a08d6 Fix style 2022-10-29 21:01:34 -07:00
Veselin Dobrev d7e03640d9 Fix nvcc warnings when HiOp integration is enabled 2022-10-29 12:24:36 -07:00
Veselin Dobrev 87596eaa38 Ensure SuperLU_DIST and STRUMPACK can use hypre matrices in GPU
memory by moving them temporarily to CPU memory.
2022-10-29 08:22:30 -07:00
Robert Carson 6e9f62ca86 bug fix qfunction inline funcs in wrong file 2022-10-28 14:31:02 -04:00
Tzanio Kolev 2eb2061fb0 Merge pull request #3270 from mfem/mondrian-miniapp-fix
Fix bug in mondrian miniapp
2022-10-28 09:23:54 -07:00
Veselin Dobrev 297ee682d4 Fix a linking issue in the CMake build system when using newer
CMake versions (e.g. 3.18 and later) and linking with CUDA
libraries compiled with relocatable device code (rdc). Some
older versions of hypre were built with CUDA rdc (e.g. 2.22.x)
and the build with CMake 3.18 and hypre-2.22.x was failing.

This fix will probably be needed if we are linking with any
other TPLs built with CUDA rdc.
2022-10-27 15:17:00 -07:00
Sebastian Grimberg b1dec1eda0 Resolve compiler warnings in gslib.cpp 2022-10-27 13:16:50 -07:00
Sebastian Grimberg ab4bd64a5e Fix bug in mondrian miniapp 2022-10-25 16:29:49 -07:00
Vladimir Z Tomov ea9c2d2b8f style. 2022-10-24 19:05:11 -07:00
Vladimir Z Tomov b1383e0f80 Use OrthoSolver. 2022-10-24 18:19:11 -07:00
Vladimir Z Tomov b0573f4cec Updated to use IterativeSolver::PrintLevel. 2022-10-24 18:05:33 -07:00
Vladimir Z Tomov 021532cebf 1d sample run, better eps value for gradient calculations. 2022-10-24 16:37:59 -07:00
Tzanio Kolev d84884d13c Merge pull request #3266 from mfem/new-dev-version-4.5.1
Update version numbers to 4.5.1 -- a new development version
2022-10-24 09:41:30 -07:00
Veselin Dobrev 6328e8b38c Update version numbers to 4.5.1 -- a new development version 2022-10-24 07:06:54 -07:00
Vladimir Z Tomov 93d87c5a90 Added a simple normalization solver, error computations. 2022-10-21 17:08:56 -07:00
Yohann Dudouit 612a94aef7 Add EnableSparseMatrixSorting in ex1 and ex1p. 2022-10-20 09:47:05 -07:00
Aaron Fisher bf287d6ae5 Fixed a comment. 2022-09-20 08:12:53 -07:00
Aaron Fisher 462842eea9 Merge branch 'master' into ncmesh-pyramid-dev 2022-09-20 08:11:01 -07:00
Will Pazner 86e9298c5a Fix deprecation warnings in ParTransferMap 2022-09-19 12:21:07 -07:00
Will Pazner f0d7789836 Merge remote-tracking branch 'origin/master' into vector-remove-implicit-conversion 2022-09-19 12:02:56 -07:00
Will Pazner 883120f0e9 Fix deprecation warning when LAPACK is enabled 2022-09-19 11:59:36 -07:00
Yohann 9ac1f3eec6 Rename SortSparseMatrix to EnableSparseMatrixSorting.
- Add a boolean parameter to enable/disable
- Also sort on CPU
2022-09-16 15:27:59 +02:00
Yohann 7c9710b559 Use SortSparseMatrix in test_fa_determinism. 2022-09-12 18:24:58 +02:00
Yohann 409e743bc4 Change sparse matrix sorting interface.
- Rename method to `SortSparseMatrix`.
- Default behavior is to not sort the sparse matrices.
- Improve documentation.
2022-09-12 15:57:36 +02:00
Yohann ccd01f2c58 Set ntrials to 2 in test_fa_determinism. 2022-09-12 15:49:25 +02:00
Will Pazner bfc871481f Remove implicit Vector conversions in tests, miniapps, examples 2022-09-06 13:20:56 -07:00
Will Pazner 5a455dd141 Deprecate Vector implicit conversion to double* 2022-09-06 13:05:38 -07:00
Yohann Dudouit c4f5897b20 Use Cu/Hip allocations to avoid int overflow with Memory interface. 2022-09-01 10:29:36 -07:00
Yohann Dudouit 03ce7c1d4a Set ntrials to 1. 2022-08-31 18:00:29 -07:00
Yohann Dudouit 7404fbbaf1 Replace DEVICE_MASK with ~CPU_MASK. 2022-08-31 17:59:16 -07:00
Yohann Dudouit 5a18775378 Merge branch 'yohann/sort+test' of https://github.com/mfem/mfem into yohann/sort+test 2022-08-31 17:21:07 -07:00
Yohann Dudouit f1a2fc2295 Factor out isSorted. 2022-08-31 17:21:03 -07:00
YohannandWill Pazner cff4473374 Update fem/bilinearform.hpp
Co-authored-by: Will Pazner <11493037+pazner@users.noreply.github.com>
2022-08-31 17:19:08 -07:00
Yohann Dudouit dabae076c5 Reactivate full assembly sample runs in ex1 and ex1p. 2022-08-25 13:36:46 -07:00
Yohann Dudouit a49b8a5a63 Merge branch 'master' into yohann/sort+test 2022-08-25 13:35:30 -07:00
Yohann Dudouit 3a62136a70 Remove SortRows from HypreParMatrix. 2022-08-25 13:25:20 -07:00
Yohann Dudouit 1fe908294d Add method to disable sparse matrix sorting on device. 2022-08-25 13:17:54 -07:00
Yohann Dudouit 96f8aa4a89 Fix sorting of sparse matrices with hip. 2022-08-25 10:07:03 -07:00
Will Pazner 44663ed239 Clean up determinism test 2022-08-24 10:00:45 -07:00
Will Pazner 231ec7961d Add determinism test 2022-08-24 10:00:44 -07:00
Yohann Dudouit d7b5d07cce Create temporary cusparseMatDescr_t for sorting. 2022-08-23 17:37:46 -07:00
Yohann Dudouit 8029a5ace0 Use Arrays instead of Memory objects. 2022-08-23 17:37:14 -07:00
Yohann Dudouit 78ac894623 Use class methods to read and write. 2022-08-23 17:36:44 -07:00
Yohann Dudouit 6cd171ae05 Use Capacity instead of Size. 2022-08-23 17:33:30 -07:00
Yohann Dudouit 9f035181c1 Update SortColumnIndices to be device aware. 2022-08-23 15:27:28 -07:00
Aaron Fisher 15680b2052 make style 2022-08-11 12:32:20 -07:00
Aaron Fisher 64737fad46 Merge branch 'ncmesh-pyramid-dev' of github.com:mfem/mfem into ncmesh-pyramid-dev 2022-08-11 10:19:29 -07:00
Aaron Fisher dd0b13ec5a Fixed the deref table after I reshuffled the elements. 2022-08-11 10:18:55 -07:00
Aaron Fisher 1b4480552c make style 2022-08-10 16:36:00 -07:00
Aaron Fisher 0e24a2840a Reordered the refined pyramid elements to put the tets at the end. 2022-08-10 16:33:22 -07:00
Aaron Fisher 3add57b2f1 Merge branch 'ncmesh-pyramid-dev' of github.com:mfem/mfem into ncmesh-pyramid-dev 2022-08-10 14:44:38 -07:00
Aaron Fisher e8df0436ef Fixed problems that unit testing uncovered. 2022-08-10 14:40:06 -07:00
Aaron Fisher 35afe5a468 make style 2022-08-05 19:36:09 -07:00
Aaron Fisher c8adac90f5 Added a unit test to make sure mesh volume is preserved on reference elements. 2022-08-05 16:27:30 -07:00
Aaron Fisher b3eaee247c Added pyramid support to ncmesh. 2022-08-05 15:44:25 -07:00
Yohann Dudouit c39b1a905b Call sorting on "local" matrices. 2022-07-26 12:06:18 -07:00
Yohann Dudouit fa62bc0bd1 Use hypre_CSRMatrixSortRow. 2022-07-26 11:52:31 -07:00
124 changed files with 2590 additions and 2367 deletions
+1 -1
View File
@@ -62,7 +62,7 @@ jobs:
- name: GHCR Login
if: (github.event_name != 'pull_request')
uses: docker/login-action@v1
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
+16 -19
View File
@@ -94,7 +94,7 @@ jobs:
# This external action allows to interrupt a workflow already running on
# the same branch to save resource
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.0
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
@@ -102,7 +102,7 @@ jobs:
# /home/runner/work/mfem/mfem/mfem
# Note: Done now to access "install-hypre" and "install-metis" actions.
- name: checkout mfem
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
path: ${{ env.MFEM_TOP_DIR }}
# Fetch the complete history for codecov to access commits ID
@@ -115,25 +115,25 @@ jobs:
if: matrix.mpi == 'par' && matrix.os == 'ubuntu-latest'
run: |
sudo apt-get install mpich libmpich-dev
export MAKE_CXX_FLAG="MPICXX=mpic++"
- name: get lcov (Linux)
if: matrix.codecov == 'YES' && matrix.os == 'ubuntu-latest'
run: |
sudo apt-get install lcov
- name: Set up Homebrew
if: ( matrix.mpi == 'par' || matrix.codecov == 'YES' ) && matrix.os == 'macos-latest'
uses: Homebrew/actions/setup-homebrew@c4aafe8c4620bf08883dd4679c374f11e73329d3
# Keep the following section in case we need it again in the future,
# see: https://github.com/mfem/mfem/pull/3385#discussion_r1058013032
# - name: Set up Homebrew
# if: ( matrix.mpi == 'par' || matrix.codecov == 'YES' ) && matrix.os == 'macos-latest'
# uses: Homebrew/actions/setup-homebrew@master
- name: get MPI (MacOS)
if: matrix.mpi == 'par' && matrix.os == 'macos-latest'
run: |
export HOMEBREW_NO_INSTALL_CLEANUP=1
brew install openmpi
export MAKE_CXX_FLAG="MPICXX=mpic++"
- name: get MPI (MacOS)
- name: get lcov (MacOS)
if: matrix.codecov == 'YES' && matrix.os == 'macos-latest'
run: |
export HOMEBREW_NO_INSTALL_CLEANUP=1
@@ -141,14 +141,14 @@ jobs:
- name: get MPI (Windows)
if: matrix.mpi == 'par' && matrix.os == 'windows-latest'
uses: mpi4py/setup-mpi@v1.0.3
uses: mpi4py/setup-mpi@v1.1.2
# Get Hypre through cache, or build it.
# Install will only run on cache miss.
- name: cache hypre
id: hypre-cache
if: matrix.mpi == 'par'
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ${{ env.HYPRE_TOP_DIR }}
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-${{ matrix.hypre-target }}-v2.2
@@ -176,7 +176,7 @@ jobs:
- name: cache metis
id: metis-cache
if: matrix.mpi == 'par' && matrix.os != 'windows-latest'
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ${{ env.METIS_TOP_DIR }}
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
@@ -190,12 +190,13 @@ jobs:
- name: cache vcpkg (Windows)
id: vcpkg-cache
if: matrix.os == 'windows-latest'
uses: actions/cache@v3
with:
path: vcpkg_cache
key: ${{ runner.os }}-${{ matrix.mpi }}-vcpkg-v1
- name: prepare binary cache location
- name: prepare vcpkg binary cache location (Windows)
if: matrix.os == 'windows-latest' && steps.vcpkg-cache.outputs.cache-hit != 'true'
run: |
mkdir -p vcpkg_cache
@@ -230,11 +231,7 @@ jobs:
run: |
cd ${{ env.MFEM_TOP_DIR }} && make check
- name: unit tests
if: matrix.build-system == 'make' && matrix.target == 'opt'
run: |
cd ${{ env.MFEM_TOP_DIR }} && make unittest
# Note: 'tests' include the unit tests
- name: tests
if: matrix.build-system == 'make' && matrix.target == 'opt'
run: |
@@ -247,7 +244,7 @@ jobs:
cd ${{ env.MFEM_TOP_DIR }} && cmake --build build --target check --config ${CTEST_CONFIG}
shell: bash
- name: cmake unit tests (Ubuntu 20.04)
- name: cmake unit tests (Ubuntu)
if: matrix.build-system == 'cmake' && matrix.target == 'opt' && matrix.os == 'ubuntu-latest'
run: |
CTEST_CONFIG="Release"
@@ -265,7 +262,7 @@ jobs:
# Code coverage (process and upload reports)
- name: codecov
if: matrix.codecov == 'YES'
uses: mfem/github-actions/upload-coverage@v2.0
uses: mfem/github-actions/upload-coverage@v2.2
with:
name: ${{ matrix.os }}-${{ matrix.build-system }}-${{ matrix.target }}-${{ matrix.mpi }}-${{ matrix.hypre-target }}
project_dir: ${{ env.MFEM_TOP_DIR }}
+4 -5
View File
@@ -35,23 +35,22 @@ jobs:
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.0
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
- name: checkout MFEM
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
path: mfem
- name: Get MPI (Linux)
run: |
sudo apt-get install mpich libmpich-dev
export MAKE_CXX_FLAG="MPICXX=mpic++"
- name: Cache Hypre Install
id: hypre-cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ${{ env.HYPRE_TOP_DIR }}
key: ${{ runner.os }}-build-${{ env.HYPRE_TOP_DIR }}-v2.2
@@ -66,7 +65,7 @@ jobs:
- name: Cache Metis Install
id: metis-cache
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ${{ env.METIS_TOP_DIR }}
key: ${{ runner.os }}-build-${{ env.METIS_TOP_DIR }}-v2.2
+8 -5
View File
@@ -34,12 +34,12 @@ jobs:
github.event.pull_request.head.repo.full_name != github.repository)
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.9.0
uses: styfle/cancel-workflow-action@0.11.0
with:
access_token: ${{ github.token }}
- name: checkout mfem
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: copyright check
id: copyright
@@ -84,7 +84,7 @@ jobs:
github.event.pull_request.head.repo.full_name != github.repository)
steps:
- name: checkout mfem
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: get astyle
run: |
@@ -101,11 +101,14 @@ jobs:
github.event.pull_request.head.repo.full_name != github.repository)
steps:
- name: checkout mfem
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: get doxygen and graphviz
run: |
sudo apt-get install doxygen graphviz
- name: update doxygen config file
run: |
cd doc
doxygen -u CodeDocumentation.conf.in
@@ -123,7 +126,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: checkout mfem
uses: actions/checkout@v2
uses: actions/checkout@v3
with:
fetch-depth: 0
+45
View File
@@ -8,6 +8,51 @@
https://mfem.org
Version 4.5.1 (development)
===========================
Meshing improvements
--------------------
- Added support for pyramids in non-conforming meshes. Currently only isotropic
refinement is supported in this case.
Discretization improvements
---------------------------
- TBD
Linear and nonlinear solvers
----------------------------
- Added a fast normalization-based distance solver, see the Distance miniapp
in the miniapps/shifted/ directory.
New and updated examples and miniapps
-------------------------------------
- TBD
Integrations, testing and documentation
---------------------------------------
- Removed the support for the Mesquite toolkit. We recommend using MFEM's TMOP
functionality instead for mesh optimization. See the mesh-optimizer miniapp.
Miscellaneous
-------------
- VisItDataCollection now correctly handles collection names containing
underscores.
- VisItDataCollection::SetPadDigits() no longer alters the number of digits
used to represent the MPI rank because VisIt seems to require 6 digits.
This parameter can still be explicitly overridden with
VisItDataCollection::SetPadDigitsRank().
API changes
-----------
- The implicit cast methods of class Vector to 'double *' and 'const double *'
have been deprecated and generate deprecation warnings if used. They will be
removed in a future release.
Version 4.5, released on October 22, 2022
=========================================
+36 -40
View File
@@ -10,7 +10,9 @@
# CONTRIBUTING.md for details.
# The variable CMAKE_CXX_STANDARD and related were introduced in CMake v3.1
cmake_minimum_required(VERSION 3.1)
# Version 3.8 fixes the handling of CMAKE_CXX_STANDARD for try_compile.
# Version 3.8 or newer is required for direct CUDA support.
cmake_minimum_required(VERSION 3.8)
set(USER_CONFIG "${CMAKE_CURRENT_SOURCE_DIR}/config/user.cmake" CACHE PATH
"Path to optional user configuration file.")
@@ -51,7 +53,7 @@ project(mfem NONE)
# Current version of MFEM, see also `makefile`.
# mfem_VERSION = (string)
# MFEM_VERSION = (int) [automatically derived from mfem_VERSION]
set(${PROJECT_NAME}_VERSION 4.5.0)
set(${PROJECT_NAME}_VERSION 4.5.1)
# Prohibit in-source build
if (${PROJECT_SOURCE_DIR} STREQUAL ${PROJECT_BINARY_DIR})
@@ -66,8 +68,7 @@ set(XSDK_ENABLE_C OFF)
set(XSDK_ENABLE_Fortran OFF)
# Check if we need to enable C or Fortran.
if (CMAKE_VERSION VERSION_LESS 3.2 OR
MFEM_USE_CONDUIT OR
if (MFEM_USE_CONDUIT OR
MFEM_USE_SIDRE OR
MFEM_USE_PETSC)
# This seems to be needed by:
@@ -81,11 +82,9 @@ if (MFEM_USE_STRUMPACK)
# Just needed to find the MPI_Fortran libraries to link with
set(XSDK_ENABLE_Fortran ON)
endif()
# SUNDIALS >= 6.4.0 requires C++14:
if (MFEM_USE_SUNDIALS AND ("${CMAKE_CXX_STANDARD}" LESS "14"))
set(CMAKE_CXX_STANDARD 14)
endif()
if (MFEM_USE_GINKGO AND ("${CMAKE_CXX_STANDARD}" LESS "14"))
# SUNDIALS, STRUMPACK, and Ginkgo require C++14:
if ((MFEM_USE_SUNDIALS OR MFEM_USE_STRUMPACK OR MFEM_USE_GINKGO) AND
("${CMAKE_CXX_STANDARD}" LESS "14"))
set(CMAKE_CXX_STANDARD 14)
endif()
@@ -103,8 +102,6 @@ if (MFEM_USE_CUDA)
if (MFEM_USE_HIP)
message(FATAL_ERROR " *** MFEM_USE_HIP cannot be combined with MFEM_USE_CUDA.")
endif()
# 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})
@@ -199,6 +196,26 @@ if (MFEM_USE_HIP)
find_package(HIPSPARSE REQUIRED)
endif()
# OpenMP
if (MFEM_USE_OPENMP OR MFEM_USE_LEGACY_OPENMP)
if (NOT MFEM_THREAD_SAFE AND MFEM_USE_LEGACY_OPENMP)
message(FATAL_ERROR " *** MFEM_USE_LEGACY_OPENMP requires MFEM_THREAD_SAFE=ON.")
endif()
find_package(OpenMP REQUIRED)
set(OPENMP_LIBRARIES ${OpenMP_CXX_LIBRARIES})
if(APPLE)
# On macOS, the compiler needs additional help to find the <omp.h> header.
# See issue #2642 for more information.
set(OPENMP_INCLUDE_DIRS ${OpenMP_CXX_INCLUDE_DIRS})
endif(APPLE)
if (OPENMP_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
if (MFEM_USE_CUDA)
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=${OpenMP_CXX_FLAGS}")
endif()
endif()
endif()
# MPI -> hypre; PETSc (optional)
if (MFEM_USE_MPI)
find_package(MPI REQUIRED)
@@ -264,20 +281,6 @@ if (MFEM_USE_LAPACK)
find_package(LAPACK REQUIRED)
endif()
# OpenMP
if (MFEM_USE_OPENMP OR MFEM_USE_LEGACY_OPENMP)
if (NOT MFEM_THREAD_SAFE AND MFEM_USE_LEGACY_OPENMP)
message(FATAL_ERROR " *** MFEM_USE_LEGACY_OPENMP requires MFEM_THREAD_SAFE=ON.")
endif()
find_package(OpenMP REQUIRED)
set(OPENMP_LIBRARIES ${OpenMP_CXX_LIBRARIES})
if(APPLE)
# On macOS, the compiler needs additional help to find the <omp.h> header.
# See issue #2642 for more information.
set(OPENMP_INCLUDE_DIRS ${OpenMP_CXX_INCLUDE_DIRS})
endif(APPLE)
endif()
# SuiteSparse (before SUNDIALS which may depend on KLU)
if (MFEM_USE_SUITESPARSE)
find_package(SuiteSparse REQUIRED
@@ -296,11 +299,6 @@ if (MFEM_USE_SUNDIALS)
find_package(SUNDIALS REQUIRED ${SUNDIALS_COMPONENTS})
endif()
# Mesquite
if (MFEM_USE_MESQUITE)
find_package(Mesquite REQUIRED)
endif()
# SuperLU_DIST can only be enabled in parallel
if (MFEM_USE_SUPERLU)
if (MFEM_USE_MPI)
@@ -488,6 +486,10 @@ endif()
# an ALIAS target is missing?
# Call Stack (most recent call first):
# CMakeLists.txt:474 (mfem_add_library)
#
# NOTE: We need to figure out which TPL library adds the dependency on
# "Threads::Threads" and call the next line only when that TPL library is
# enabled. -V. Dobrev
find_package(Threads REQUIRED)
# List all possible libraries in order of dependencies.
@@ -495,8 +497,8 @@ find_package(Threads REQUIRED)
# With newer versions of SuiteSparse which include METIS header using 64-bit
# integers, the METIS header (with 32-bit indices, as used by mfem) needs to
# be before SuiteSparse.
set(MFEM_TPLS OPENMP HYPRE LAPACK BLAS SuperLUDist METIS SuiteSparse SUNDIALS
PETSC SLEPC MESQUITE MUMPS STRUMPACK AXOM FMS CONDUIT Ginkgo GNUTLS GSLIB
set(MFEM_TPLS OPENMP HYPRE LAPACK BLAS SuperLUDist STRUMPACK METIS SuiteSparse
SUNDIALS PETSC SLEPC MUMPS AXOM FMS CONDUIT Ginkgo GNUTLS GSLIB
NETCDF MPFR PUMI HIOP POSIXCLOCKS MFEMBacktrace ZLIB OCCA CEED RAJA UMPIRE
ADIOS2 CUBLAS CUSPARSE MKL_CPARDISO AMGX CALIPER CODIPACK BENCHMARK PARELAG
MPI_CXX HIP HIPSPARSE MOONOLITH BLITZ ALGOIM ENZYME)
@@ -511,18 +513,12 @@ foreach(TPL IN LISTS MFEM_TPLS)
list(APPEND TPL_INCLUDE_DIRS ${${TPL}_INCLUDE_DIRS})
endif()
endforeach(TPL)
list(REVERSE TPL_LIBRARIES)
list(REMOVE_DUPLICATES TPL_LIBRARIES)
list(REVERSE TPL_LIBRARIES)
list(REMOVE_DUPLICATES TPL_INCLUDE_DIRS)
# message(STATUS "TPL_INCLUDE_DIRS = ${TPL_INCLUDE_DIRS}")
if (OPENMP_FOUND)
message(STATUS "MFEM: using package OpenMP")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
if (MFEM_USE_CUDA)
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xcompiler=${OpenMP_CXX_FLAGS}")
endif()
endif()
message(STATUS "MFEM build type: CMAKE_BUILD_TYPE = ${CMAKE_BUILD_TYPE}")
message(STATUS "MFEM version: v${MFEM_VERSION_STRING}")
message(STATUS "MFEM git string: ${MFEM_GIT_STRING}")
-11
View File
@@ -337,10 +337,6 @@ MFEM_USE_SUNDIALS = YES/NO
library. When enabled, this option uses the SUNDIALS_* library options,
see below.
MFEM_USE_MESQUITE = YES/NO
Enable MFEM functionality based on the Mesquite library. When enabled, this
option uses the MESQUITE_* library options, see below.
MFEM_USE_SUITESPARSE = YES/NO
Enable MFEM functionality based on the SuiteSparse library. Currently, this
option adds the classes UMFPackSolver and KLUSolver (both sparse serial
@@ -636,11 +632,6 @@ The specific libraries and their options are:
Options: SUNDIALS_OPT, SUNDIALS_LIB.
Versions: SUNDIALS >= 5.0.0, SUNDIALS >= 5.4.0 for CUDA support.
- Mesquite (optional), used when MFEM_USE_MESQUITE = YES.
URL: http://trilinos.org/oldsite/packages/mesquite
Options: MESQUITE_OPT, MESQUITE_LIB.
The Mesquite support is deprecated and will be removed in the future.
- SuiteSparse (optional), used when MFEM_USE_SUITESPARSE = YES.
URL: http://faculty.cse.tamu.edu/davis/suitesparse.html
Options: SUITESPARSE_OPT, SUITESPARSE_LIB.
@@ -969,7 +960,6 @@ MFEM_USE_LEGACY_OPENMP
MFEM_USE_OPENMP
MFEM_USE_MEMALLOC
MFEM_TIMER_TYPE - Set automatically, can be overwritten.
MFEM_USE_MESQUITE
MFEM_USE_SUITESPARSE
MFEM_USE_SUPERLU
MFEM_USE_MUMPS
@@ -1034,7 +1024,6 @@ The CMake build system adds auto-detection for the following packages/libraries:
- HYPRE
- METIS - The option MFEM_USE_METIS_5 is auto-detected.
- ParMETIS
- MESQUITE
- SuiteSparse
- SuperLUDist, STRUMPACK
- Ginkgo
-4
View File
@@ -212,10 +212,6 @@ IF (DEFINED TPL_ENABLE_SUNDIALS)
SET(MFEM_USE_SUNDIALS ${TPL_ENABLE_SUNDIALS} CACHE BOOL "Enable SUNDIALS usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_MESQUITE)
SET(MFEM_USE_MESQUITE ${TPL_ENABLE_MESQUITE} CACHE BOOL "Enable MESQUITE usage" FORCE)
ENDIF()
IF (DEFINED TPL_ENABLE_SUITESPARSE)
SET(MFEM_USE_SUITESPARSE ${TPL_ENABLE_SUITESPARSE} CACHE BOOL "Enable SuiteSparse usage" FORCE)
ENDIF()
-1
View File
@@ -29,7 +29,6 @@ set(MFEM_USE_LEGACY_OPENMP @MFEM_USE_LEGACY_OPENMP@)
set(MFEM_USE_MEMALLOC @MFEM_USE_MEMALLOC@)
set(MFEM_TIMER_TYPE @MFEM_TIMER_TYPE@)
set(MFEM_USE_SUNDIALS @MFEM_USE_SUNDIALS@)
set(MFEM_USE_MESQUITE @MFEM_USE_MESQUITE@)
set(MFEM_USE_SUITESPARSE @MFEM_USE_SUITESPARSE@)
set(MFEM_USE_SUPERLU @MFEM_USE_SUPERLU@)
set(MFEM_USE_MUMPS @MFEM_USE_MUMPS@)
-3
View File
@@ -77,9 +77,6 @@
// Internal MFEM option: enable group/batch allocation for some small objects.
#cmakedefine MFEM_USE_MEMALLOC
// Enable MFEM functionality based on the Mesquite library.
#cmakedefine MFEM_USE_MESQUITE
// Enable MFEM functionality based on the SuiteSparse library.
#cmakedefine MFEM_USE_SUITESPARSE
+19 -4
View File
@@ -16,7 +16,22 @@
include(MfemCmakeUtilities)
mfem_find_package(Caliper CALIPER CALIPER_DIR
"include" "caliper/cali.h"
"lib" "caliper"
"Paths to headers required by Caliper."
"Libraries required by Caliper.")
"include" "caliper/cali.h"
"lib" "caliper"
"Paths to headers required by Caliper."
"Libraries required by Caliper.")
# Append adiak path/lib if the user provided ADIAK_DIR
if(ADIAK_DIR AND EXISTS ${ADIAK_DIR})
find_package(adiak NO_DEFAULT_PATH REQUIRED PATHS ${ADIAK_DIR}/lib/cmake/adiak ${ADIAK_DIR})
list(APPEND CALIPER_INCLUDE_DIRS ${adiak_INCLUDE_DIRS})
list(APPEND CALIPER_LIBRARIES ${adiak_LIBRARIES})
endif()
# Append gotcha path/lib if the user provided GOTCHA_DIR
if(GOTCHA_DIR AND EXISTS ${GOTCHA_DIR})
find_package(gotcha NO_DEFAULT_PATH REQUIRED PATHS ${GOTCHA_DIR}/lib/cmake/gotcha ${GOTCHA_DIR})
list(APPEND CALIPER_INCLUDE_DIRS ${gotcha_INCLUDE_DIRS})
list(APPEND CALIPER_LIBRARIES ${gotcha_LIBRARIES})
endif()
+17 -4
View File
@@ -14,9 +14,21 @@
# - HDF5_LIBRARIES - The HDF5 libraries
# - HDF5_INCLUDE_DIRS - The HDF5 include directories
# NOTE: Using this FindHDF5.cmake instead of the CMake provided version may lead
# to issues with some TPL libraries that depend (or may depend) on HDF5.
# For this reason, we should consider removing this file, or at least
# making it use the CMake provided version by default and apply the logic
# below only when specifically requested by a user. -V. Dobrev
# First Check for HDF5_DIR
if(NOT HDF5_DIR)
MESSAGE(FATAL_ERROR "Could not find HDF5. HDF5 support needs explicit HDF5_DIR")
message(FATAL_ERROR
"Could not find HDF5. HDF5 support needs explicit HDF5_DIR")
endif()
if (NOT HDF5_FIND_QUIETLY)
message(STATUS "Looking for HDF5 ...")
message(STATUS " in HDF5_DIR = ${HDF5_DIR}")
endif()
# Find includes
@@ -50,8 +62,9 @@ include(FindPackageHandleStandardArgs)
# Handle the QUIETLY and REQUIRED arguments and set HDF5_FOUND to TRUE if all
# listed variables are TRUE
find_package_handle_standard_args(HDF5 DEFAULT_MSG
find_package_handle_standard_args(HDF5
" *** HDF5 not found. Please set HDF5_DIR."
HDF5_LIBRARIES
HDF5_INCLUDE_DIRS
__HDF5_LIBRARY
__HDF5_HL_LIBRARY
HDF5_LIBRARIES )
__HDF5_HL_LIBRARY)
-20
View File
@@ -1,20 +0,0 @@
# Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.
# Defines the following variables:
# - MESQUITE_FOUND
# - MESQUITE_LIBRARIES
# - MESQUITE_INCLUDE_DIRS
include(MfemCmakeUtilities)
mfem_find_package(Mesquite MESQUITE MESQUITE_DIR
"include" "Mesquite_all_headers.hpp" "lib" "mesquite"
"Paths to headers required by Mesquite." "Libraries required by Mesquite.")
+8 -2
View File
@@ -17,18 +17,24 @@
include(MfemCmakeUtilities)
# FindHDF5.cmake uses HDF5_ROOT, so we "translate" from the MFEM convention
set(HDF5_ROOT ${HDF5_DIR} CACHE PATH "")
# (MFEM's FindHDF5.cmake does not need HDF5_ROOT)
# set(HDF5_ROOT ${HDF5_DIR} CACHE PATH "")
# We need to guard against the case where HDF5 was already found but without
# the HL extensions (in which case mfem_find_package will treat the package
# as already having been found), so we reset the variable to force FindHDF5.cmake
# to be called for a second time
set(HDF5_FOUND OFF)
enable_language(C) # FindHDF5.cmake uses the C compiler
mfem_find_package(NetCDF NETCDF NETCDF_DIR "include" netcdf.h "lib" netcdf
"Paths to headers required by NetCDF." "Libraries required by NetCDF.")
# The HL extension libraries are in a separate variable and must precede
# the "regular" hdf5 library, as hdf5_hl depends on hdf5
# The netcdf library will always be the first element of NETCDF_LIBRARIES
# and we need to insert after that library but before the hdf5 library, so
# position 1 is used
list(INSERT NETCDF_LIBRARIES 1 ${HDF5_C_LIBRARY_hdf5_hl})
# (MFEM's FindHDF5.cmake does not set HDF5_C_LIBRARY_hdf5_hl and the HL library
# is already added to NETCDF_LIBRARIES)
# list(INSERT NETCDF_LIBRARIES 1 ${HDF5_C_LIBRARY_hdf5_hl})
+11 -24
View File
@@ -46,6 +46,10 @@ endfunction()
# Wrapper for add_executable
macro(mfem_add_executable NAME)
add_executable(${NAME} ${ARGN})
if (MFEM_USE_CUDA)
set_target_properties(${NAME} PROPERTIES
CUDA_RESOLVE_DEVICE_SYMBOLS ON)
endif()
endmacro()
# Wrapper for add_library
@@ -158,27 +162,12 @@ macro(add_mfem_miniapp MFEM_EXE_NAME)
# Append the additional libraries and options
if (LIBRARIES_LIST)
if(CMAKE_VERSION VERSION_GREATER 2.8.11)
target_link_libraries(${MFEM_EXE_NAME} PRIVATE ${LIBRARIES_LIST})
else()
target_link_libraries(${MFEM_EXE_NAME} ${LIBRARIES_LIST})
endif()
target_link_libraries(${MFEM_EXE_NAME} PRIVATE ${LIBRARIES_LIST})
endif()
if (EXTRA_OPTIONS_LIST)
string(REPLACE ";" " " EXTRA_OPTIONS_STRING "${EXTRA_OPTIONS_LIST}")
message(STATUS "${MFEM_EXE_NAME}: add flags \"${EXTRA_OPTIONS_STRING}\"")
if(CMAKE_VERSION VERSION_GREATER 2.8.11)
target_compile_options(${MFEM_EXE_NAME} PRIVATE ${EXTRA_OPTIONS_LIST})
else()
get_target_property(THIS_COMPILE_FLAGS ${MFEM_EXE_NAME} COMPILE_FLAGS)
if (THIS_COMPILE_FLAGS)
set(THIS_COMPILE_FLAGS "${THIS_COMPILE_FLAGS} ${EXTRA_OPTIONS_STRING}")
else()
set(THIS_COMPILE_FLAGS "${EXTRA_OPTIONS_STRING}")
endif()
set_target_properties(${MFEM_EXE_NAME}
PROPERTIES COMPILE_FLAGS ${THIS_COMPILE_FLAGS})
endif()
target_compile_options(${MFEM_EXE_NAME} PRIVATE ${EXTRA_OPTIONS_LIST})
endif()
if (EXTRA_DEFINES_LIST)
target_compile_definitions(${MFEM_EXE_NAME} PRIVATE ${EXTRA_DEFINES_LIST})
@@ -187,17 +176,15 @@ macro(add_mfem_miniapp MFEM_EXE_NAME)
# Handle the MPI separately
if (MFEM_USE_MPI)
# Add MPI_CXX_LIBRARIES, in case this target does not link with mfem.
if(CMAKE_VERSION VERSION_GREATER 2.8.11)
target_link_libraries(${MFEM_EXE_NAME} PRIVATE ${MPI_CXX_LIBRARIES})
else()
target_link_libraries(${MFEM_EXE_NAME} ${MPI_CXX_LIBRARIES})
endif()
target_link_libraries(${MFEM_EXE_NAME} PRIVATE ${MPI_CXX_LIBRARIES})
if (MPI_CXX_INCLUDE_PATH)
target_include_directories(${MFEM_EXE_NAME} PRIVATE ${MPI_CXX_INCLUDE_PATH})
endif()
if (MPI_CXX_COMPILE_FLAGS)
target_compile_options(${MFEM_EXE_NAME} PRIVATE ${MPI_CXX_COMPILE_FLAGS})
separate_arguments(MPI_CXX_COMPILE_ARGS UNIX_COMMAND
"${MPI_CXX_COMPILE_FLAGS}")
target_compile_options(${MFEM_EXE_NAME} PRIVATE ${MPI_CXX_COMPILE_ARGS})
endif()
if (MPI_CXX_LINK_FLAGS)
@@ -878,7 +865,7 @@ function(mfem_export_mk_files)
set(CONFIG_MK_BOOL_VARS MFEM_USE_MPI MFEM_USE_METIS MFEM_USE_METIS_5
MFEM_DEBUG MFEM_USE_EXCEPTIONS MFEM_USE_ZLIB MFEM_USE_LIBUNWIND
MFEM_USE_LAPACK MFEM_THREAD_SAFE MFEM_USE_LEGACY_OPENMP MFEM_USE_OPENMP
MFEM_USE_MEMALLOC MFEM_USE_SUNDIALS MFEM_USE_MESQUITE MFEM_USE_SUITESPARSE
MFEM_USE_MEMALLOC MFEM_USE_SUNDIALS MFEM_USE_SUITESPARSE
MFEM_USE_SUPERLU MFEM_USE_SUPERLU5 MFEM_USE_MUMPS MFEM_USE_STRUMPACK
MFEM_USE_GINKGO MFEM_USE_AMGX MFEM_USE_GNUTLS MFEM_USE_NETCDF
MFEM_USE_PETSC MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_FMS
-3
View File
@@ -85,9 +85,6 @@
// Enable MFEM functionality based on the SUNDIALS libraries.
// #define MFEM_USE_SUNDIALS
// Enable MFEM functionality based on the Mesquite library.
// #define MFEM_USE_MESQUITE
// Enable MFEM functionality based on the SuiteSparse library.
// #define MFEM_USE_SUITESPARSE
-1
View File
@@ -29,7 +29,6 @@ MFEM_USE_OPENMP = @MFEM_USE_OPENMP@
MFEM_USE_MEMALLOC = @MFEM_USE_MEMALLOC@
MFEM_TIMER_TYPE = @MFEM_TIMER_TYPE@
MFEM_USE_SUNDIALS = @MFEM_USE_SUNDIALS@
MFEM_USE_MESQUITE = @MFEM_USE_MESQUITE@
MFEM_USE_SUITESPARSE = @MFEM_USE_SUITESPARSE@
MFEM_USE_SUPERLU = @MFEM_USE_SUPERLU@
MFEM_USE_SUPERLU5 = @MFEM_USE_SUPERLU5@
+1 -4
View File
@@ -30,7 +30,6 @@ option(MFEM_USE_OPENMP "Enable the OpenMP backend" OFF)
option(MFEM_USE_LEGACY_OPENMP "Enable legacy OpenMP usage" OFF)
option(MFEM_USE_MEMALLOC "Enable the internal MEMALLOC option." ON)
option(MFEM_USE_SUNDIALS "Enable SUNDIALS usage" OFF)
option(MFEM_USE_MESQUITE "Enable MESQUITE usage" OFF)
option(MFEM_USE_SUITESPARSE "Enable SuiteSparse usage" OFF)
option(MFEM_USE_SUPERLU "Enable SuperLU_DIST usage" OFF)
option(MFEM_USE_SUPERLU5 "Use the old SuperLU_DIST 5.1 version" OFF)
@@ -124,9 +123,6 @@ set(SUNDIALS_DIR "${MFEM_DIR}/../sundials-5.0.0/instdir" CACHE PATH
# set(SUNDIALS_REQUIRED_PACKAGES "SuiteSparse/KLU/AMD/BTF/COLAMD/config"
# CACHE STRING "Additional packages required by SUNDIALS.")
set(MESQUITE_DIR "${MFEM_DIR}/../mesquite-2.99" CACHE PATH
"Path to the Mesquite library.")
set(SuiteSparse_DIR "${MFEM_DIR}/../SuiteSparse" CACHE PATH
"Path to the SuiteSparse library.")
set(SuiteSparse_REQUIRED_PACKAGES "BLAS" "METIS"
@@ -188,6 +184,7 @@ set(GNUTLS_DIR "" CACHE PATH "Path to the GnuTLS library.")
set(GSLIB_DIR "" CACHE PATH "Path to the GSLIB library.")
set(HDF5_DIR "/usr" CACHE PATH "Path to the HDF5 library.")
set(NETCDF_DIR "" CACHE PATH "Path to the NetCDF library.")
set(NetCDF_REQUIRED_PACKAGES "HDF5/C/HL" CACHE STRING
"Additional packages required by NetCDF.")
+14 -7
View File
@@ -131,7 +131,6 @@ MFEM_USE_LEGACY_OPENMP = NO
MFEM_USE_MEMALLOC = YES
MFEM_TIMER_TYPE = $(if $(NOTMAC),2,4)
MFEM_USE_SUNDIALS = NO
MFEM_USE_MESQUITE = NO
MFEM_USE_SUITESPARSE = NO
MFEM_USE_SUPERLU = NO
MFEM_USE_SUPERLU5 = NO
@@ -270,11 +269,6 @@ endif
# If SUNDIALS was built with KLU:
# MFEM_USE_SUITESPARSE = YES
# MESQUITE library configuration
MESQUITE_DIR = @MFEM_DIR@/../mesquite-2.99
MESQUITE_OPT = -I$(MESQUITE_DIR)/include
MESQUITE_LIB = -L$(MESQUITE_DIR)/lib -lmesquite
# SuiteSparse library configuration
LIB_RT = $(if $(NOTMAC),-lrt,)
SUITESPARSE_DIR = @MFEM_DIR@/../SuiteSparse
@@ -324,6 +318,9 @@ MUMPS_LIB = $(XLINKER)-rpath,$(MUMPS_DIR)/lib -L$(MUMPS_DIR)/lib -ldmumps\
# STRUMPACK library configuration
STRUMPACK_DIR = @MFEM_DIR@/../STRUMPACK-build
ifeq ($(MFEM_USE_STRUMPACK),YES)
BASE_FLAGS = -std=c++14
endif
STRUMPACK_OPT = -I$(STRUMPACK_DIR)/include $(SCOTCH_OPT)
# If STRUMPACK was build with OpenMP support, the following may be need:
# STRUMPACK_OPT += $(OPENMP_OPT)
@@ -476,7 +473,17 @@ OCCA_LIB = $(XLINKER)-rpath,$(OCCA_DIR)/lib -L$(OCCA_DIR)/lib -locca
# CALIPER library configuration
CALIPER_DIR = @MFEM_DIR@/../caliper
CALIPER_OPT = -I$(CALIPER_DIR)/include
CALIPER_LIB = $(XLINKER)-rpath,$(CALIPER_DIR)/lib64 -L$(CALIPER_DIR)/lib64 -lcaliper
CALIPER_LIB = $(XLINKER)-rpath,$(CALIPER_DIR)/lib64 $(XLINKER)-rpath,$(CALIPER_DIR)/lib -L$(CALIPER_DIR)/lib64 -L$(CALIPER_DIR)/lib -lcaliper
ifdef ADIAK_DIR
CALIPER_OPT += -I$(ADIAK_DIR)/include
CALIPER_LIB += $(XLINKER)-rpath,$(ADIAK_DIR)/lib64 $(XLINKER)-rpath,$(ADIAK_DIR)/lib -L$(ADIAK_DIR)/lib64 -L$(ADIAK_DIR)/lib -ladiak
endif
ifdef GOTCHA_DIR
CALIPER_OPT += -I$(GOTCHA_DIR)/include
CALIPER_LIB += $(XLINKER)-rpath,$(GOTCHA_DIR)/lib64 $(XLINKER)-rpath,$(GOTCHA_DIR)/lib -L$(GOTCHA_DIR)/lib64 -L$(GOTCHA_DIR)/lib -lgotcha
endif
# BLITZ library configuration
BLITZ_DIR = @MFEM_DIR@/../blitz
+25 -7
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = "MFEM"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = v4.5.0
PROJECT_NUMBER = v4.5.1
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
@@ -763,36 +763,54 @@ INPUT = @MFEM_SOURCE_DIR@/doc/CodeDocumentation.dox \
@MFEM_SOURCE_DIR@/config \
@MFEM_SOURCE_DIR@/general \
@MFEM_SOURCE_DIR@/linalg \
@MFEM_SOURCE_DIR@/linalg/simd \
@MFEM_SOURCE_DIR@/mesh \
@MFEM_SOURCE_DIR@/mesh/submesh \
@MFEM_SOURCE_DIR@/fem \
@MFEM_SOURCE_DIR@/fem/moonolith \
@MFEM_SOURCE_DIR@/fem/ceed \
@MFEM_SOURCE_DIR@/fem/ceed/integrators \
@MFEM_SOURCE_DIR@/fem/ceed/integrators/convection \
@MFEM_SOURCE_DIR@/fem/ceed/integrators/diffusion \
@MFEM_SOURCE_DIR@/fem/ceed/integrators/mass \
@MFEM_SOURCE_DIR@/fem/ceed/integrators/nlconvection \
@MFEM_SOURCE_DIR@/fem/ceed/interface \
@MFEM_SOURCE_DIR@/fem/ceed/solvers \
@MFEM_SOURCE_DIR@/fem/fe \
@MFEM_SOURCE_DIR@/fem/lor \
@MFEM_SOURCE_DIR@/fem/moonolith \
@MFEM_SOURCE_DIR@/fem/qinterp \
@MFEM_SOURCE_DIR@/fem/tmop \
@MFEM_SOURCE_DIR@/examples \
@MFEM_SOURCE_DIR@/examples/caliper \
@MFEM_SOURCE_DIR@/examples/amgx \
@MFEM_SOURCE_DIR@/examples/caliper \
@MFEM_SOURCE_DIR@/examples/ginkgo \
@MFEM_SOURCE_DIR@/examples/moonolith \
@MFEM_SOURCE_DIR@/examples/hiop \
@MFEM_SOURCE_DIR@/examples/moonolith \
@MFEM_SOURCE_DIR@/examples/petsc \
@MFEM_SOURCE_DIR@/examples/pumi \
@MFEM_SOURCE_DIR@/examples/sundials \
@MFEM_SOURCE_DIR@/examples/superlu \
@MFEM_SOURCE_DIR@/miniapps/adjoint \
@MFEM_SOURCE_DIR@/miniapps/autodiff \
@MFEM_SOURCE_DIR@/miniapps/common \
@MFEM_SOURCE_DIR@/miniapps/electromagnetics \
@MFEM_SOURCE_DIR@/miniapps/gslib \
@MFEM_SOURCE_DIR@/miniapps/hooke \
@MFEM_SOURCE_DIR@/miniapps/hooke/kernels \
@MFEM_SOURCE_DIR@/miniapps/hooke/materials \
@MFEM_SOURCE_DIR@/miniapps/hooke/operators \
@MFEM_SOURCE_DIR@/miniapps/hooke/preconditioners \
@MFEM_SOURCE_DIR@/miniapps/meshing \
@MFEM_SOURCE_DIR@/miniapps/mtop \
@MFEM_SOURCE_DIR@/miniapps/autodiff \
@MFEM_SOURCE_DIR@/miniapps/multidomain \
@MFEM_SOURCE_DIR@/miniapps/navier \
@MFEM_SOURCE_DIR@/miniapps/nurbs \
@MFEM_SOURCE_DIR@/miniapps/parelag \
@MFEM_SOURCE_DIR@/miniapps/performance \
@MFEM_SOURCE_DIR@/miniapps/shifted \
@MFEM_SOURCE_DIR@/miniapps/solvers \
@MFEM_SOURCE_DIR@/miniapps/tools \
@MFEM_SOURCE_DIR@/miniapps/toys \
@MFEM_SOURCE_DIR@/miniapps/parelag
@MFEM_SOURCE_DIR@/miniapps/toys
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
+2 -2
View File
@@ -33,13 +33,13 @@ add_mfem_examples(CALIPER_EXE_SRCS ${PREFIX})
if (MFEM_ENABLE_TESTING)
foreach(SRC_FILE ${CALIPER_EXE_SRCS})
get_filename_component(SRC_FILENAME ${SRC_FILE} NAME)
string(REPLACE ".cpp" "" TEST_NAME ${SRC_FILENAME})
string(REPLACE ".cpp" "" TEST_NAME ${PREFIX}${SRC_FILENAME})
set(THIS_TEST_OPTIONS "-no-vis")
if (NOT (${TEST_NAME} MATCHES ".*p$"))
add_test(NAME ${TEST_NAME}_ser
COMMAND ${TEST_NAME} ${THIS_TEST_OPTIONS})
COMMAND $<TARGET_FILE:${TEST_NAME}> ${THIS_TEST_OPTIONS})
else()
add_test(NAME ${TEST_NAME}_np=${MFEM_MPI_NP}
COMMAND ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${MFEM_MPI_NP}
+9 -2
View File
@@ -30,7 +30,7 @@
//
// Device sample runs:
// ex1 -pa -d cuda
// * ex1 -fa -d cuda
// ex1 -fa -d cuda
// ex1 -pa -d raja-cuda
// * ex1 -pa -d raja-hip
// ex1 -pa -d occa-cuda
@@ -192,7 +192,14 @@ int main(int argc, char *argv[])
// domain integrator.
BilinearForm a(&fespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
if (fa) { a.SetAssemblyLevel(AssemblyLevel::FULL); }
if (fa)
{
a.SetAssemblyLevel(AssemblyLevel::FULL);
// Sort the matrix column indices when running on GPU or with OpenMP (i.e.
// when Device::IsEnabled() returns true). This makes the results
// bit-for-bit deterministic at the cost of somewhat longer run time.
a.EnableSparseMatrixSorting(Device::IsEnabled());
}
a.AddDomainIntegrator(new DiffusionIntegrator(one));
// 10. Assemble the bilinear form and the corresponding linear system,
+9 -2
View File
@@ -30,7 +30,7 @@
//
// Device sample runs:
// mpirun -np 4 ex1p -pa -d cuda
// * mpirun -np 4 ex1p -fa -d cuda
// mpirun -np 4 ex1p -fa -d cuda
// mpirun -np 4 ex1p -pa -d occa-cuda
// mpirun -np 4 ex1p -pa -d raja-omp
// mpirun -np 4 ex1p -pa -d ceed-cpu
@@ -219,7 +219,14 @@ int main(int argc, char *argv[])
// Diffusion domain integrator.
ParBilinearForm a(&fespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
if (fa) { a.SetAssemblyLevel(AssemblyLevel::FULL); }
if (fa)
{
a.SetAssemblyLevel(AssemblyLevel::FULL);
// Sort the matrix column indices when running on GPU or with OpenMP (i.e.
// when Device::IsEnabled() returns true). This makes the results
// bit-for-bit deterministic at the cost of somewhat longer run time.
a.EnableSparseMatrixSorting(Device::IsEnabled());
}
a.AddDomainIntegrator(new DiffusionIntegrator(one));
// 12. Assemble the parallel bilinear form and the corresponding linear
+1
View File
@@ -14,4 +14,5 @@
-mg_levels_esteig_ksp_type cg
-mg_levels_esteig_ksp_max_it 10
-mg_levels_ksp_chebyshev_esteig 0,0.05,0,1.05
-pc_gamg_use_sa_esteig 0
-mg_levels_pc_type sor
+1
View File
@@ -124,6 +124,7 @@ void BilinearForm::SetAssemblyLevel(AssemblyLevel assembly_level)
case AssemblyLevel::LEGACY:
break;
case AssemblyLevel::FULL:
SetDiagonalPolicy( DIAG_ONE ); // Only diagonal policy supported on device
ext = new FABilinearFormExtension(this);
break;
case AssemblyLevel::ELEMENT:
+18
View File
@@ -80,6 +80,9 @@ protected:
/** @brief Extension for supporting Full Assembly (FA), Element Assembly (EA),
Partial Assembly (PA), or Matrix Free assembly (MF). */
BilinearFormExtension *ext;
/** Indicates if the sparse matrix is sorted after assembly when using
Full Assembly (FA). */
bool sort_sparse_matrix = false;
/** @brief Indicates the Mesh::sequence corresponding to the current state of
the BilinearForm. */
@@ -181,6 +184,21 @@ public:
If used, this method must be called before assembly. */
void SetAssemblyLevel(AssemblyLevel assembly_level);
/** @brief Force the sparse matrix column indices to be sorted when using
AssemblyLevel::FULL.
When assembling on device the assembly algorithm uses atomic operations
to insert values in the sparse matrix, which can result in different
column index orderings across runs. Calling this method with @a enable_it
set to @a true forces a sorting algorithm to be called at the end of the
assembly procedure to ensure sorted column indices (and therefore
deterministic results).
*/
void EnableSparseMatrixSorting(bool enable_it)
{
sort_sparse_matrix = enable_it;
}
/// Returns the assembly level
AssemblyLevel GetAssemblyLevel() const { return assembly; }
+4
View File
@@ -955,6 +955,10 @@ void FABilinearFormExtension::Assemble()
}
a->mat = mat;
}
if ( a->sort_sparse_matrix )
{
a->mat->SortColumnIndices();
}
}
+2 -2
View File
@@ -2338,7 +2338,7 @@ void MixedCurlIntegrator::AssembleElementMatrix2(
if (spaceH1)
{
dshape.SetSize(trial_dof,dim);
curlshape.SetSize(dim*trial_dof,1);
curlshape.SetSize(trial_dof,dim);
dimc = dim;
}
else
@@ -2367,7 +2367,7 @@ void MixedCurlIntegrator::AssembleElementMatrix2(
if (spaceH1)
{
trial_fe.CalcPhysDShape(Trans, dshape);
dshape.GradToCurl(curlshape);
dshape.GradToVectorCurl2D(curlshape);
}
else
{
+2 -2
View File
@@ -3059,8 +3059,8 @@ public:
/** Integrator for the DG form:
- < {(Q grad(u)).n}, [v] > + sigma < [u], {(Q grad(v)).n} >
+ kappa < {h^{-1} Q} [u], [v] >,
- < {(Q grad(u)).n}, [v] > + sigma < [u], {(Q grad(v)).n} >
+ kappa < {h^{-1} Q} [u], [v] >
where Q is a scalar or matrix diffusion coefficient and u, v are the trial
and test spaces, respectively. The parameters sigma and kappa determine the
+1
View File
@@ -47,6 +47,7 @@ void InitRestrictionWithIndices(const FiniteElementSpace &fes,
/** @brief Initialize a strided CeedElemRestriction
@param[in] fes Input finite element space.
@param[in] nelem is the number of elements.
@param[in] nqpts is the total number of quadrature points.
@param[in] qdatasize is the number of data per quadrature point.
+4
View File
@@ -140,7 +140,11 @@ int CeedOperatorGetActiveField(CeedOperator oper, CeedOperatorField *field)
CeedOperator *subops;
if (isComposite)
{
#if CEED_VERSION_GE(0, 10, 2)
ierr = CeedCompositeOperatorGetSubList(oper, &subops); CeedChk(ierr);
#else
ierr = CeedOperatorGetSubList(oper, &subops); CeedChk(ierr);
#endif
ierr = CeedOperatorGetQFunction(subops[0], &qf); CeedChk(ierr);
}
else
+6 -1
View File
@@ -275,9 +275,14 @@ CeedOperator CoarsenCeedCompositeOperator(
&op_coarse); PCeedChk(ierr);
int nsub;
ierr = CeedOperatorGetNumSub(op, &nsub); PCeedChk(ierr);
CeedOperator *subops;
#if CEED_VERSION_GE(0, 10, 2)
ierr = CeedCompositeOperatorGetNumSub(op, &nsub); PCeedChk(ierr);
ierr = CeedCompositeOperatorGetSubList(op, &subops); PCeedChk(ierr);
#else
ierr = CeedOperatorGetNumSub(op, &nsub); PCeedChk(ierr);
ierr = CeedOperatorGetSubList(op, &subops); PCeedChk(ierr);
#endif
for (int isub=0; isub<nsub; ++isub)
{
CeedOperator subop = subops[isub];
+5
View File
@@ -310,8 +310,13 @@ int CeedOperatorFullAssemble(CeedOperator op, SparseMatrix **mat)
{
CeedInt numsub;
CeedOperator *subops;
#if CEED_VERSION_GE(0, 10, 2)
CeedCompositeOperatorGetNumSub(op, &numsub);
ierr = CeedCompositeOperatorGetSubList(op, &subops); CeedChk(ierr);
#else
CeedOperatorGetNumSub(op, &numsub);
ierr = CeedOperatorGetSubList(op, &subops); CeedChk(ierr);
#endif
for (int i = 0; i < numsub; ++i)
{
ierr = CeedSingleOperatorFullAssemble(subops[i], out); CeedChk(ierr);
+1
View File
@@ -66,6 +66,7 @@ int CeedBasisATPMGCoarsen(CeedBasis basisin, CeedBasis* basisout,
@param[in] coarse_er CeedElemRestriction for coarse operator
(see CeedATPMGElemRestriction)
@param[out] coarse_basis_out CeedBasis for coarser operator
@param[out] basis_ctof_out CeedBasis describing interpolation from coarse to fine
@param[out] out coarsened CeedOperator
*/
int CeedATPMGOperator(CeedOperator oper, int order_reduction,
+1 -1
View File
@@ -724,7 +724,7 @@ void VisItDataCollection::ParseVisItRootString(const std::string& json)
// Set the DataCollection::name using the mesh path
std::string path = mesh.get("path").get<std::string>();
size_t right_sep = path.find('_');
size_t right_sep = path.rfind('_');
if (right_sep == std::string::npos)
{
error = READ_ERROR;
+18 -9
View File
@@ -338,11 +338,12 @@ public:
/// Set the precision (number of digits) used for the text output of doubles
void SetPrecision(int prec) { precision = prec; }
/// Set the number of digits used for both the cycle and the MPI rank
void SetPadDigits(int digits) { pad_digits_cycle=pad_digits_rank = digits; }
virtual void SetPadDigits(int digits)
{ pad_digits_cycle=pad_digits_rank = digits; }
/// Set the number of digits used for the cycle
void SetPadDigitsCycle(int digits) { pad_digits_cycle = digits; }
virtual void SetPadDigitsCycle(int digits) { pad_digits_cycle = digits; }
/// Set the number of digits used for the MPI rank in filenames
void SetPadDigitsRank(int digits) { pad_digits_rank = digits; }
virtual void SetPadDigitsRank(int digits) { pad_digits_rank = digits; }
/// Set the desired output mesh and data format.
/** See the enumeration #Format for valid options. Derived classes can define
their own format enumerations and override this method to perform input
@@ -441,21 +442,29 @@ public:
#endif
/// Set/change the mesh associated with the collection
virtual void SetMesh(Mesh *new_mesh);
virtual void SetMesh(Mesh *new_mesh) override;
#ifdef MFEM_USE_MPI
/// Set/change the mesh associated with the collection.
virtual void SetMesh(MPI_Comm comm, Mesh *new_mesh);
virtual void SetMesh(MPI_Comm comm, Mesh *new_mesh) override;
#endif
/// Add a grid function to the collection and update the root file
virtual void RegisterField(const std::string& field_name, GridFunction *gf);
virtual void RegisterField(const std::string& field_name,
GridFunction *gf) override;
/// 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);
QuadratureFunction *qf) override;
/// Set the number of digits used for both the cycle and the MPI rank
/// @note VisIt seems to require 6 pad digits for the MPI rank. Therefore,
/// this function uses this default value. This behavior can be overridden
/// by calling SetPadDigitsCycle() and SetPadDigitsRank() instead.
virtual void SetPadDigits(int digits) override
{ pad_digits_cycle=digits; pad_digits_rank=6; }
/// Set VisIt parameter: default levels of detail for the MultiresControl
void SetLevelsOfDetail(int levels_of_detail);
@@ -468,13 +477,13 @@ public:
void DeleteAll();
/// Save the collection and a VisIt root file
virtual void Save();
virtual void Save() override;
/// Save a VisIt root file for the collection
void SaveRootFile();
/// Load the collection based on its VisIt data (described in its root file)
virtual void Load(int cycle_ = 0);
virtual void Load(int cycle_ = 0) override;
/// We will delete the mesh and fields if we own them
virtual ~VisItDataCollection() {}
+10 -4
View File
@@ -339,8 +339,11 @@ ND_TriDofTransformation::TransformDual(double *v) const
void
ND_TriDofTransformation::InvTransformDual(double *v) const
{
int nedofs = order; // number of DoFs per edge
int nfdofs = order*(order-1); // number of DoFs per face
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 1,
"Face orientations are unset in ND_TriDofTransformation");
double data[2];
Vector v2(data, 2);
@@ -432,8 +435,11 @@ ND_TetDofTransformation::TransformDual(double *v) const
void
ND_TetDofTransformation::InvTransformDual(double *v) const
{
int nedofs = order; // number of DoFs per edge
int nfdofs = order*(order-1); // number of DoFs per face
// Return immediately when no face DoFs are present
if (nfdofs < 2) { return; }
MFEM_VERIFY(Fo.Size() >= 4,
"Face orientations are unset in ND_TetDofTransformation");
double data[2];
Vector v2(data, 2);
+6 -7
View File
@@ -618,7 +618,7 @@ void InvertLinearTrans(ElementTransformation &trans,
double store[3];
Vector v(store, x.Size());
pt.Get(v, x.Size());
pt.Get(store, x.Size());
v -= x;
trans.InverseJacobian().Mult(v, x);
@@ -954,8 +954,8 @@ void VectorFiniteElement::Project_RT(
{
Trans.SetIntPoint(&Nodes.IntPoint(k));
// dof_k = nk^t adj(J) xk
Vector vk(vc.GetData()+k*sdim, sdim);
dofs(k) = Trans.AdjugateJacobian().InnerProduct(vk, nk + d2n[k]*dim);
dofs(k) = Trans.AdjugateJacobian().InnerProduct(
&vc[k*sdim], nk + d2n[k]*dim);
if (!square_J) { dofs(k) /= Trans.Weight(); }
}
}
@@ -1171,9 +1171,8 @@ void VectorFiniteElement::Project_ND(
for (int k = 0; k < dof; k++)
{
Trans.SetIntPoint(&Nodes.IntPoint(k));
Vector vk(vc.GetData()+k*dim, dim);
// dof_k = xk^t J tk
dofs(k) = Trans.Jacobian().InnerProduct(tk + d2t[k]*dim, vk);
dofs(k) = Trans.Jacobian().InnerProduct(tk + d2t[k]*dim, &vc[k*dim]);
}
}
@@ -1320,7 +1319,7 @@ void VectorFiniteElement::LocalL2Projection_RT(
double w = ip.weight;
this->CalcVShape(ip, fine_shape);
Trans.Transform(ip, v);
tr_ip.Set(v, dim);
tr_ip.Set(v.GetData(), dim);
cfe.CalcVShape(tr_ip, coarse_shape);
AddMult_a_AAt(w, fine_shape, fine_mass);
@@ -1407,7 +1406,7 @@ void VectorFiniteElement::LocalL2Projection_ND(
const IntegrationPoint &ip = ir.IntPoint(i);
this->CalcVShape(ip, fine_shape);
Trans.Transform(ip, v);
tr_ip.Set(v, dim);
tr_ip.Set(v.GetData(), dim);
cfe.CalcVShape(tr_ip, coarse_shape);
AddMult_a_AAt(ip.weight, fine_shape, fine_mass);
+31 -1
View File
@@ -256,7 +256,7 @@ protected:
public:
/// Enumeration for range_type and deriv_range_type
enum RangeType { SCALAR, VECTOR };
enum RangeType { UNKNOWN_RANGE_TYPE = -1, SCALAR, VECTOR };
/** @brief Enumeration for MapType: defines how reference functions are
mapped to physical space.
@@ -270,6 +270,8 @@ public:
*/
enum MapType
{
UNKNOWN_MAP_TYPE = -1, /**< Used to distinguish an unset MapType variable
from the known values below. */
VALUE, /**< For scalar fields; preserves point values
\f$ u(x) = \hat u(\hat x) \f$ */
INTEGRAL, /**< For scalar fields; preserves volume integrals
@@ -1091,6 +1093,11 @@ public:
// { CalcLegendre(p, x, u); }
{ CalcChebyshev(p, x, u); }
/** @brief Evaluate the values of a hierarchical 1D basis at point x
hierarchical = k-th basis function is degree k polynomial */
static void CalcBasis(const int p, const double x, Vector &u)
{ CalcBasis(p, x, u.GetData()); }
/// Evaluate the values and derivatives of a hierarchical 1D basis at point @a x
static void CalcBasis(const int p, const double x, double *u, double *d)
// { CalcMono(p, x, u, d); }
@@ -1098,6 +1105,11 @@ public:
// { CalcLegendre(p, x, u, d); }
{ CalcChebyshev(p, x, u, d); }
/** @brief Evaluate the values and derivatives of a hierarchical 1D basis at
point @a x. */
static void CalcBasis(const int p, const double x, Vector &u, Vector &d)
{ CalcBasis(p, x, u.GetData(), d.GetData()); }
/// Evaluate the values, derivatives and second derivatives of a hierarchical 1D basis at point x
static void CalcBasis(const int p, const double x, double *u, double *d,
double *dd)
@@ -1106,6 +1118,12 @@ public:
// { CalcLegendre(p, x, u, d); }
{ CalcChebyshev(p, x, u, d, dd); }
/** @brief Evaluate the values, derivatives and second derivatives of a
hierarchical 1D basis at point @a x. */
static void CalcBasis(const int p, const double x, Vector &u, Vector &d,
Vector &dd)
{ CalcBasis(p, x, u.GetData(), d.GetData(), dd.GetData()); }
/// Evaluate a representation of a Delta function at point x
static double CalcDelta(const int p, const double x)
{ return pow(x, (double) p); }
@@ -1135,12 +1153,24 @@ public:
static void CalcBernstein(const int p, const double x, double *u)
{ CalcBinomTerms(p, x, 1. - x, u); }
/** @brief Compute the values of the Bernstein basis functions of order
@a p at coordinate @a x and store the results in the already allocated
@a u array. */
static void CalcBernstein(const int p, const double x, Vector &u)
{ CalcBernstein(p, x, u.GetData()); }
/** @brief Compute the values and derivatives of the Bernstein basis functions
of order @a p at coordinate @a x and store the results in the already allocated
@a u and @a d arrays. */
static void CalcBernstein(const int p, const double x, double *u, double *d)
{ CalcBinomTerms(p, x, 1. - x, u, d); }
/** @brief Compute the values and derivatives of the Bernstein basis
functions of order @a p at coordinate @a x and store the results in the
already allocated @a u and @a d arrays. */
static void CalcBernstein(const int p, const double x, Vector &u, Vector &d)
{ CalcBernstein(p, x, u.GetData(), d.GetData()); }
static void CalcLegendre(const int p, const double x, double *u);
static void CalcLegendre(const int p, const double x, double *u, double *d);
+6
View File
@@ -319,6 +319,9 @@ void ND_HexahedronElement::CalcVShape(const IntegrationPoint &ip,
if (obasis1d.IsIntegratedType())
{
#ifdef MFEM_THREAD_SAFE
Vector dshape_cx(p + 1), dshape_cy(p + 1), dshape_cz(p + 1);
#endif
cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
cbasis1d.Eval(ip.z, shape_cz, dshape_cz);
@@ -661,6 +664,9 @@ void ND_QuadrilateralElement::CalcVShape(const IntegrationPoint &ip,
if (obasis1d.IsIntegratedType())
{
#ifdef MFEM_THREAD_SAFE
Vector dshape_cx(p + 1), dshape_cy(p + 1);
#endif
cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
obasis1d.ScaleIntegrated(false);
+5 -5
View File
@@ -212,7 +212,7 @@ void BiQuadPos2DFiniteElement::GetLocalInterpolation(
void BiQuadPos2DFiniteElement::Project(
Coefficient &coeff, ElementTransformation &Trans, Vector &dofs) const
{
double *d = dofs;
double *d = dofs.GetData();
for (int i = 0; i < 9; i++)
{
@@ -382,8 +382,8 @@ void H1Pos_QuadrilateralElement::CalcShape(const IntegrationPoint &ip,
Vector shape_x(p+1), shape_y(p+1);
#endif
Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData() );
Poly_1D::CalcBernstein(p, ip.y, shape_y.GetData() );
Poly_1D::CalcBernstein(p, ip.x, shape_x);
Poly_1D::CalcBernstein(p, ip.y, shape_y);
// Reorder so that vertices are at the beginning of the list
for (int o = 0, j = 0; j <= p; j++)
@@ -402,8 +402,8 @@ void H1Pos_QuadrilateralElement::CalcDShape(const IntegrationPoint &ip,
Vector shape_x(p+1), shape_y(p+1), dshape_x(p+1), dshape_y(p+1);
#endif
Poly_1D::CalcBernstein(p, ip.x, shape_x.GetData(), dshape_x.GetData() );
Poly_1D::CalcBernstein(p, ip.y, shape_y.GetData(), dshape_y.GetData() );
Poly_1D::CalcBernstein(p, ip.x, shape_x, dshape_x);
Poly_1D::CalcBernstein(p, ip.y, shape_y, dshape_y);
// Reorder so that vertices are at the beginning of the list
for (int o = 0, j = 0; j <= p; j++)
+6
View File
@@ -150,6 +150,9 @@ void RT_QuadrilateralElement::CalcVShape(const IntegrationPoint &ip,
if (obasis1d.IsIntegratedType())
{
#ifdef MFEM_THREAD_SAFE
Vector dshape_cx(pp1 + 1), dshape_cy(pp1 + 1);
#endif
cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
obasis1d.ScaleIntegrated(false);
@@ -478,6 +481,9 @@ void RT_HexahedronElement::CalcVShape(const IntegrationPoint &ip,
if (obasis1d.IsIntegratedType())
{
#ifdef MFEM_THREAD_SAFE
Vector dshape_cx(pp1 + 1), dshape_cy(pp1 + 1), dshape_cz(pp1 + 1);
#endif
cbasis1d.Eval(ip.x, shape_cx, dshape_cx);
cbasis1d.Eval(ip.y, shape_cy, dshape_cy);
cbasis1d.Eval(ip.z, shape_cz, dshape_cz);
+64
View File
@@ -22,6 +22,70 @@ namespace mfem
using namespace std;
const FiniteElement *
FiniteElementCollection::FiniteElementForDim(int dim) const
{
for (int g = Geometry::DimStart[dim]; g < Geometry::DimStart[dim+1]; g++)
{
const FiniteElement *fe = FiniteElementForGeometry((Geometry::Type)g);
if (fe != NULL)
{
return fe;
}
}
return NULL;
}
int FiniteElementCollection::GetRangeType(int dim) const
{
const FiniteElement *fe = FiniteElementForDim(dim);
if (fe)
{
return fe->GetRangeType();
}
return FiniteElement::UNKNOWN_RANGE_TYPE;
}
int FiniteElementCollection::GetDerivRangeType(int dim) const
{
const FiniteElement *fe = FiniteElementForDim(dim);
if (fe)
{
return fe->GetDerivRangeType();
}
return FiniteElement::UNKNOWN_RANGE_TYPE;
}
int FiniteElementCollection::GetMapType(int dim) const
{
const FiniteElement *fe = FiniteElementForDim(dim);
if (fe)
{
return fe->GetMapType();
}
return FiniteElement::UNKNOWN_MAP_TYPE;
}
int FiniteElementCollection::GetDerivType(int dim) const
{
const FiniteElement *fe = FiniteElementForDim(dim);
if (fe)
{
return fe->GetDerivType();
}
return FiniteElement::NONE;
}
int FiniteElementCollection::GetDerivMapType(int dim) const
{
const FiniteElement *fe = FiniteElementForDim(dim);
if (fe)
{
return fe->GetDerivMapType();
}
return FiniteElement::UNKNOWN_MAP_TYPE;
}
int FiniteElementCollection::HasFaceDofs(Geometry::Type geom, int p) const
{
switch (geom)
+19
View File
@@ -51,6 +51,14 @@ public:
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const = 0;
/** @brief Returns the first non-NULL FiniteElement for the given dimension
@note Repeatedly calls FiniteElementForGeometry in the order defined in
the Geometry::Type enumeration.
*/
virtual const FiniteElement *
FiniteElementForDim(int dim) const;
virtual int DofForGeometry(Geometry::Type GeomType) const = 0;
/** @brief Returns an array, say p, that maps a local permuted index i to a
@@ -66,6 +74,17 @@ public:
virtual int GetContType() const = 0;
/** @note The following methods provide the same information as the
corresponding methods of the FiniteElement base class.
@{
*/
virtual int GetRangeType(int dim) const;
virtual int GetDerivRangeType(int dim) const;
virtual int GetMapType(int dim) const;
virtual int GetDerivType(int dim) const;
virtual int GetDerivMapType(int dim) const;
/** @} */
int HasFaceDofs(Geometry::Type geom, int p) const;
virtual const FiniteElement *TraceFiniteElementForGeometry(
+1 -1
View File
@@ -1920,7 +1920,7 @@ DataCollectionToFmsDataCollection(DataCollection *mfem_dc,
FMS_NODAL_GAUSS_CLOSED, 1);
err |= FmsDataCollectionAddField(*dc, "Coords", &fcoords);
err |= FmsFieldSet(fcoords, fdcoords, mmesh->SpaceDimension(), FMS_BY_NODES,
FMS_DOUBLE, mverts);
FMS_DOUBLE, mverts.HostRead());
err |= FmsComponentSetCoordinates(volume, fcoords);
}
+24 -15
View File
@@ -416,13 +416,24 @@ void GridFunction::GetNodalValues(int i, Array<double> &nval, int vdim) const
if (FElem->GetRangeType() == FiniteElement::SCALAR)
{
MFEM_ASSERT(FElem->GetMapType() == FiniteElement::VALUE,
"invalid FE map type");
Vector shape(dof);
for (k = 0; k < n; k++)
if (FElem->GetMapType() == FiniteElement::VALUE)
{
FElem->CalcShape(ElemVert->IntPoint(k), shape);
nval[k] = shape * ((const double *)loc_data + dof * vdim);
for (k = 0; k < n; k++)
{
FElem->CalcShape(ElemVert->IntPoint(k), shape);
nval[k] = shape * (&loc_data[dof * vdim]);
}
}
else
{
ElementTransformation *Tr = fes->GetElementTransformation(i);
for (k = 0; k < n; k++)
{
Tr->SetIntPoint(&ElemVert->IntPoint(k));
FElem->CalcPhysShape(*Tr, shape);
nval[k] = shape * (&loc_data[dof * vdim]);
}
}
}
else
@@ -495,7 +506,7 @@ void GridFunction::GetVectorValue(int i, const IntegrationPoint &ip,
val.SetSize(vdim);
for (int k = 0; k < vdim; k++)
{
val(k) = shape * ((const double *)loc_data + dof * k);
val(k) = shape * (&loc_data[dof * k]);
}
}
else
@@ -1027,7 +1038,7 @@ void GridFunction::GetVectorValue(ElementTransformation &T,
val.SetSize(vdim);
for (int k = 0; k < vdim; k++)
{
val(k) = shape * ((const double *)loc_data + dof * k);
val(k) = shape * (&loc_data[dof * k]);
}
}
else
@@ -1078,7 +1089,7 @@ void GridFunction::GetVectorValues(ElementTransformation &T,
for (int k = 0; k < vdim; k++)
{
vals(k,j) = shape * ((const double *)loc_data + dof * k);
vals(k,j) = shape * (&loc_data[dof * k]);
}
}
}
@@ -1181,8 +1192,7 @@ void GridFunction::GetValuesFrom(const GridFunction &orig_func)
orig_fe->CalcShape(ip, shape);
for (d = 0; d < vdim; d++)
{
loc_values(d*dof+j) =
shape * ((const double *)orig_loc_values + d * odof) ;
loc_values(d*dof+j) = shape * (&orig_loc_values[d * odof]);
}
}
if (doftrans)
@@ -1224,8 +1234,7 @@ void GridFunction::GetBdrValuesFrom(const GridFunction &orig_func)
orig_fe->CalcShape(ip, shape);
for (d = 0; d < vdim; d++)
{
loc_values(d*dof+j) =
shape * ((const double *)orig_loc_values + d * odof);
loc_values(d*dof+j) = shape * (&orig_loc_values[d * odof]);
}
}
SetSubVector(vdofs, loc_values);
@@ -4099,16 +4108,16 @@ void TensorProductLegendre(int dim, // input
// Map x to [0, 1] to use CalcLegendre since it uses shifted Legendre Polynomials.
double x1 = (x(0) - xmin(0))/(xmax(0)-xmin(0)), x2, x3;
Vector poly_x(order+1), poly_y(order+1), poly_z(order+1);
poly1d.CalcLegendre(order, x1, poly_x);
poly1d.CalcLegendre(order, x1, poly_x.GetData());
if (dim > 1)
{
x2 = (x(1)-xmin(1))/(xmax(1)-xmin(1));
poly1d.CalcLegendre(order, x2, poly_y);
poly1d.CalcLegendre(order, x2, poly_y.GetData());
}
if (dim == 3)
{
x3 = (x(2)-xmin(2))/(xmax(2)-xmin(2));
poly1d.CalcLegendre(order, x3, poly_z);
poly1d.CalcLegendre(order, x3, poly_z.GetData());
}
int basis_dimension = static_cast<int>(pow(order+1,dim));
+41 -29
View File
@@ -179,24 +179,27 @@ void FindPointsGSLIB::FindPoints(const Vector &point_pos,
gsl_ref.SetSize(points_cnt * dim);
gsl_dist.SetSize(points_cnt);
const double *xv_base[dim];
unsigned xv_stride[dim];
for (int d = 0; d < dim; d++)
auto xvFill = [&](const double *xv_base[], unsigned xv_stride[], int dim)
{
if (point_pos_ordering == Ordering::byNODES)
for (int d = 0; d < dim; d++)
{
xv_base[d] = point_pos.GetData() + d*points_cnt;
xv_stride[d] = sizeof(double);
if (point_pos_ordering == Ordering::byNODES)
{
xv_base[d] = point_pos.GetData() + d*points_cnt;
xv_stride[d] = sizeof(double);
}
else
{
xv_base[d] = point_pos.GetData() + d;
xv_stride[d] = dim*sizeof(double);
}
}
else
{
xv_base[d] = point_pos.GetData() + d;
xv_stride[d] = dim*sizeof(double);
}
}
};
if (dim == 2)
{
const double *xv_base[2];
unsigned xv_stride[2];
xvFill(xv_base, xv_stride, dim);
findpts_2(gsl_code.GetData(), sizeof(unsigned int),
gsl_proc.GetData(), sizeof(unsigned int),
gsl_elem.GetData(), sizeof(unsigned int),
@@ -204,8 +207,11 @@ void FindPointsGSLIB::FindPoints(const Vector &point_pos,
gsl_dist.GetData(), sizeof(double),
xv_base, xv_stride, points_cnt, fdata2D);
}
else
else // dim == 3
{
const double *xv_base[3];
unsigned xv_stride[3];
xvFill(xv_base, xv_stride, dim);
findpts_3(gsl_code.GetData(), sizeof(unsigned int),
gsl_proc.GetData(), sizeof(unsigned int),
gsl_elem.GetData(), sizeof(unsigned int),
@@ -1080,7 +1086,7 @@ void FindPointsGSLIB::InterpolateGeneral(const GridFunction &field_in,
sarray_transfer(struct send_pt, sendpt, proc, 1, cr);
sdpt = (struct send_pt *)sendpt->ptr;
for (int index = 0; index < sendpt->n; index++)
for (int index = 0; index < static_cast<int>(sendpt->n); index++)
{
int idx = field_in.FESpace()->GetOrdering() == Ordering::byNODES ?
sdpt->index + j*nptorig :
@@ -1194,24 +1200,27 @@ void OversetFindPointsGSLIB::FindPoints(const Vector &point_pos,
gsl_ref.SetSize(points_cnt * dim);
gsl_dist.SetSize(points_cnt);
const double *xv_base[dim];
unsigned xv_stride[dim];
for (int d = 0; d < dim; d++)
auto xvFill = [&](const double *xv_base[], unsigned xv_stride[], int dim)
{
if (point_pos_ordering == Ordering::byNODES)
for (int d = 0; d < dim; d++)
{
xv_base[d] = point_pos.GetData() + d*points_cnt;
xv_stride[d] = sizeof(double);
if (point_pos_ordering == Ordering::byNODES)
{
xv_base[d] = point_pos.GetData() + d*points_cnt;
xv_stride[d] = sizeof(double);
}
else
{
xv_base[d] = point_pos.GetData() + d;
xv_stride[d] = dim*sizeof(double);
}
}
else
{
xv_base[d] = point_pos.GetData() + d;
xv_stride[d] = dim*sizeof(double);
}
}
};
if (dim == 2)
{
const double *xv_base[2];
unsigned xv_stride[2];
xvFill(xv_base, xv_stride, dim);
findptsms_2(gsl_code.GetData(), sizeof(unsigned int),
gsl_proc.GetData(), sizeof(unsigned int),
gsl_elem.GetData(), sizeof(unsigned int),
@@ -1221,8 +1230,11 @@ void OversetFindPointsGSLIB::FindPoints(const Vector &point_pos,
point_id.GetData(), sizeof(unsigned int), &match,
points_cnt, fdata2D);
}
else
else // dim == 3
{
const double *xv_base[3];
unsigned xv_stride[3];
xvFill(xv_base, xv_stride, dim);
findptsms_3(gsl_code.GetData(), sizeof(unsigned int),
gsl_proc.GetData(), sizeof(unsigned int),
gsl_elem.GetData(), sizeof(unsigned int),
+2 -2
View File
@@ -1032,12 +1032,12 @@ void WhiteGaussianNoiseDomainLFIntegrator::AssembleRHSElementVect
massinteg.AssembleElementMatrix(el, Tr, *M);
CholeskyFactors chol(M->Data());
chol.Factor(M->Height());
chol.LMult(n,1,elvect);
chol.LMult(n,1,elvect.GetData());
}
else
{
CholeskyFactors chol(L[iel]->Data());
chol.LMult(n,1,elvect);
chol.LMult(n,1,elvect.GetData());
}
}
+1 -1
View File
@@ -2606,7 +2606,7 @@ int ParFiniteElementSpace
if (dump < 10)
{
char fname[100];
sprintf(fname, "dofs%02d.txt", MyRank);
snprintf(fname, 100, "dofs%02d.txt", MyRank);
std::ofstream f(fname);
DebugDumpDOFs(f, deps, dof_group, dof_owner, finalized);
dump++;
+12 -12
View File
@@ -151,14 +151,14 @@ void ParGridFunction::ParallelAverage(Vector &tv) const
{
MFEM_VERIFY(pfes->Conforming(), "not implemented for NC meshes");
pfes->GetProlongationMatrix()->MultTranspose(*this, tv);
pfes->DivideByGroupSize(tv);
pfes->DivideByGroupSize(tv.HostReadWrite());
}
void ParGridFunction::ParallelAverage(HypreParVector &tv) const
{
MFEM_VERIFY(pfes->Conforming(), "not implemented for NC meshes");
pfes->GetProlongationMatrix()->MultTranspose(*this, tv);
pfes->DivideByGroupSize(tv);
pfes->DivideByGroupSize(tv.HostReadWrite());
}
HypreParVector *ParGridFunction::ParallelAverage() const
@@ -353,7 +353,7 @@ void ParGridFunction::GetVectorValue(int i, const IntegrationPoint &ip,
val.SetSize(vdim);
for (int k = 0; k < vdim; k++)
{
val(k) = shape * ((const double *)loc_data + dof * k);
val(k) = shape * (&loc_data[dof * k]);
}
}
else
@@ -468,7 +468,7 @@ void ParGridFunction::GetVectorValue(ElementTransformation &T,
val.SetSize(vdim);
for (int k = 0; k < vdim; k++)
{
val(k) = shape * ((const double *)loc_data + dof * k);
val(k) = shape * (&loc_data[dof * k]);
}
}
else
@@ -644,9 +644,9 @@ void ParGridFunction::ProjectBdrCoefficient(
// Count the values globally.
GroupCommunicator &gcomm = pfes->GroupComm();
gcomm.Reduce<int>(values_counter, GroupCommunicator::Sum);
gcomm.Reduce<int>(values_counter.HostReadWrite(), GroupCommunicator::Sum);
// Accumulate the values globally.
gcomm.Reduce<double>(values, GroupCommunicator::Sum);
gcomm.Reduce<double>(values.HostReadWrite(), GroupCommunicator::Sum);
// Only the values in the master are guaranteed to be correct!
for (int i = 0; i < values.Size(); i++)
{
@@ -682,9 +682,9 @@ void ParGridFunction::ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
// Count the values globally.
GroupCommunicator &gcomm = pfes->GroupComm();
gcomm.Reduce<int>(values_counter, GroupCommunicator::Sum);
gcomm.Reduce<int>(values_counter.HostReadWrite(), GroupCommunicator::Sum);
// Accumulate the values globally.
gcomm.Reduce<double>(values, GroupCommunicator::Sum);
gcomm.Reduce<double>(values.HostReadWrite(), GroupCommunicator::Sum);
// Only the values in the master are guaranteed to be correct!
for (int i = 0; i < values.Size(); i++)
{
@@ -1109,11 +1109,11 @@ void ParGridFunction::ComputeFlux(
SumFluxAndCount(blfi, flux, count, wcoef, subdomain);
// Accumulate flux and counts in parallel
ffes->GroupComm().Reduce<double>(flux, GroupCommunicator::Sum);
ffes->GroupComm().Bcast<double>(flux);
ffes->GroupComm().Reduce<double>(flux.HostReadWrite(), GroupCommunicator::Sum);
ffes->GroupComm().Bcast<double>(flux.HostReadWrite());
ffes->GroupComm().Reduce<int>(count, GroupCommunicator::Sum);
ffes->GroupComm().Bcast<int>(count);
ffes->GroupComm().Reduce<int>(count.HostReadWrite(), GroupCommunicator::Sum);
ffes->GroupComm().Bcast<int>(count.HostReadWrite());
// complete averaging
for (int i = 0; i < count.Size(); i++)
-25
View File
@@ -44,31 +44,6 @@ QuadratureFunction::QuadratureFunction(Mesh *mesh, std::istream &in)
Load(in, vdim*qspace->GetSize());
}
void QuadratureFunction::SetSpace(QuadratureSpaceBase *qspace_, int vdim_)
{
if (qspace_ != qspace)
{
if (own_qspace) { delete qspace; }
qspace = qspace_;
own_qspace = false;
}
vdim = (vdim_ < 0) ? vdim : vdim_;
SetSize(vdim*qspace->GetSize());
}
void QuadratureFunction::SetSpace(
QuadratureSpaceBase *qspace_, double *qf_data, int vdim_)
{
if (qspace_ != qspace)
{
if (own_qspace) { delete qspace; }
qspace = qspace_;
own_qspace = false;
}
vdim = (vdim_ < 0) ? vdim : vdim_;
NewDataAndSize(qf_data, vdim*qspace->GetSize());
}
void QuadratureFunction::Save(std::ostream &os) const
{
GetSpace()->Save(os);
+28
View File
@@ -262,6 +262,34 @@ inline void QuadratureFunction::GetValues(
}
}
inline void QuadratureFunction::SetSpace(QuadratureSpaceBase *qspace_,
int vdim_)
{
if (qspace_ != qspace)
{
if (own_qspace) { delete qspace; }
qspace = qspace_;
own_qspace = false;
}
vdim = (vdim_ < 0) ? vdim : vdim_;
SetSize(vdim*qspace->GetSize());
}
inline void QuadratureFunction::SetSpace(
QuadratureSpaceBase *qspace_, double *qf_data, int vdim_)
{
if (qspace_ != qspace)
{
if (own_qspace) { delete qspace; }
qspace = qspace_;
own_qspace = false;
}
vdim = (vdim_ < 0) ? vdim : vdim_;
NewDataAndSize(qf_data, vdim*qspace->GetSize());
}
} // namespace mfem
#endif
+1 -1
View File
@@ -16,7 +16,7 @@ namespace mfem
QuadratureSpaceBase::QuadratureSpaceBase(Mesh &mesh_, Geometry::Type geom,
const IntegrationRule &ir)
: mesh(mesh_)
: mesh(mesh_), order(ir.GetOrder())
{
for (int g = 0; g < Geometry::NumGeom; g++)
{
+4 -3
View File
@@ -349,7 +349,7 @@ void StaticCondensation::ReduceRHS(const Vector &b, Vector &sc_b) const
LUFactors lu(const_cast<double*>((const double*)A_data) + A_offsets[i],
const_cast<int*>((const int*)A_ipiv) + A_ipiv_offsets[i]);
lu.LSolve(npd, 1, b_p);
lu.LSolve(npd, 1, b_p.GetData());
if (symm)
{
@@ -527,8 +527,9 @@ void StaticCondensation::ComputeSolution(
LUFactors lu(const_cast<double*>((const double*)A_data) + A_offsets[i],
const_cast<int*>((const int*)A_ipiv) + A_ipiv_offsets[i]);
lu.LSolve(npd, 1, b_p);
lu.BlockBackSolve(npd, ned, 1, lu.data + npd*npd, s_e, b_p);
lu.LSolve(npd, 1, b_p.GetData());
lu.BlockBackSolve(npd, ned, 1, lu.data + npd*npd, s_e.GetData(),
b_p.GetData());
for (int j = 0; j < npd; j++)
{
+53
View File
@@ -1105,6 +1105,59 @@ public:
virtual ~TMOP_QuadraticLimiter() { }
};
/// Exponential limiter function in TMOP_Integrator.
class TMOP_ExponentialLimiter : public TMOP_LimiterFunction
{
public:
virtual double Eval(const Vector &x, const Vector &x0, double dist) const
{
MFEM_ASSERT(x.Size() == x0.Size(), "Bad input.");
return exp(10.0*((x.DistanceSquaredTo(x0) / (dist * dist))-1.0));
}
virtual void Eval_d1(const Vector &x, const Vector &x0, double dist,
Vector &d1) const
{
MFEM_ASSERT(x.Size() == x0.Size(), "Bad input.");
d1.SetSize(x.Size());
double dist_squared = dist*dist;
subtract(20.0*exp(10.0*((x.DistanceSquaredTo(x0) / dist_squared) - 1.0)) /
dist_squared, x, x0, d1);
}
virtual void Eval_d2(const Vector &x, const Vector &x0, double dist,
DenseMatrix &d2) const
{
MFEM_ASSERT(x.Size() == x0.Size(), "Bad input.");
Vector tmp;
tmp.SetSize(x.Size());
double dist_squared = dist*dist;
double dist_squared_squared = dist_squared*dist_squared;
double f = exp(10.0*((x.DistanceSquaredTo(x0) / dist_squared)-1.0));
subtract(x,x0,tmp);
d2.SetSize(x.Size());
d2(0,0) = ((400.0*tmp(0)*tmp(0)*f)/dist_squared_squared)+(20.0*f/dist_squared);
d2(1,1) = ((400.0*tmp(1)*tmp(1)*f)/dist_squared_squared)+(20.0*f/dist_squared);
d2(0,1) = (400.0*tmp(0)*tmp(1)*f)/dist_squared_squared;
d2(1,0) = d2(0,1);
if (x.Size() == 3)
{
d2(0,2) = (400.0*tmp(0)*tmp(2)*f)/dist_squared_squared;
d2(1,2) = (400.0*tmp(1)*tmp(2)*f)/dist_squared_squared;
d2(2,0) = d2(0,2);
d2(2,1) = d2(1,2);
d2(2,2) = ((400.0*tmp(2)*tmp(2)*f)/dist_squared_squared)+(20.0*f/dist_squared);
}
}
virtual ~TMOP_ExponentialLimiter() { }
};
class FiniteElementCollection;
class FiniteElementSpace;
class ParFiniteElementSpace;
+3 -2
View File
@@ -58,8 +58,9 @@ void TMOP_Integrator::AssemblePA_Limiting()
MFEM_VERIFY(PA.enabled, "AssemblePA_Limiting but PA is not enabled!");
MFEM_VERIFY(lim_func, "No TMOP_LimiterFunction specification!")
MFEM_VERIFY(dynamic_cast<TMOP_QuadraticLimiter*>(lim_func),
"Only TMOP_QuadraticLimiter is supported");
MFEM_VERIFY(dynamic_cast<TMOP_QuadraticLimiter*>(lim_func) ||
dynamic_cast<TMOP_ExponentialLimiter*>(lim_func),
"Only TMOP_QuadraticLimiter and TMOP_ExponentialLimiter are supported");
const FiniteElementSpace *fes = PA.fes;
const int NE = PA.ne;
+60 -7
View File
@@ -25,8 +25,12 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_C0_2D,
const int NE,
const DenseTensor &j_,
const Array<double> &w_,
const Array<double> &b_,
const Array<double> &bld_,
const Vector &x0_,
const Vector &x1_,
Vector &h0_,
const bool exp_lim,
const int d1d,
const int q1d)
{
@@ -41,8 +45,11 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_C0_2D,
Reshape(c0_.Read(), Q1D, Q1D, NE);
const auto LD = Reshape(lim_dist.Read(), D1D, D1D, NE);
const auto J = Reshape(j_.Read(), DIM, DIM, Q1D, Q1D, NE);
const auto W = Reshape(w_.Read(), Q1D, Q1D);
const auto b = Reshape(b_.Read(), Q1D, D1D);
const auto bld = Reshape(bld_.Read(), Q1D, D1D);
const auto W = Reshape(w_.Read(), Q1D, Q1D);
const auto X0 = Reshape(x0_.Read(), D1D, D1D, DIM, NE);
const auto X1 = Reshape(x1_.Read(), D1D, D1D, DIM, NE);
auto H0 = Reshape(h0_.Write(), DIM, DIM, Q1D, Q1D, NE);
@@ -54,19 +61,37 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_C0_2D,
constexpr int MQ1 = T_Q1D ? T_Q1D : T_MAX;
constexpr int MD1 = T_D1D ? T_D1D : T_MAX;
MFEM_SHARED double B[MQ1*MD1];
MFEM_SHARED double BLD[MQ1*MD1];
MFEM_SHARED double XY[NBZ][MD1*MD1];
MFEM_SHARED double DQ[NBZ][MD1*MQ1];
MFEM_SHARED double QQ[NBZ][MQ1*MQ1];
kernels::internal::LoadX<MD1,NBZ>(e,D1D,LD,XY);
MFEM_SHARED double XY0[2][NBZ][MD1*MD1];
MFEM_SHARED double DQ0[2][NBZ][MD1*MQ1];
MFEM_SHARED double QQ0[2][NBZ][MQ1*MQ1];
MFEM_SHARED double XY1[2][NBZ][MD1*MD1];
MFEM_SHARED double DQ1[2][NBZ][MD1*MQ1];
MFEM_SHARED double QQ1[2][NBZ][MQ1*MQ1];
kernels::internal::LoadX<MD1,NBZ>(e,D1D,LD,XY);
kernels::internal::LoadX<MD1,NBZ>(e,D1D,X0,XY0);
kernels::internal::LoadX<MD1,NBZ>(e,D1D,X1,XY1);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,B);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,bld,BLD);
kernels::internal::EvalX<MD1,MQ1,NBZ>(D1D,Q1D,BLD,XY,DQ);
kernels::internal::EvalY<MD1,MQ1,NBZ>(D1D,Q1D,BLD,DQ,QQ);
kernels::internal::EvalX<MD1,MQ1,NBZ>(D1D,Q1D,B,XY0,DQ0);
kernels::internal::EvalY<MD1,MQ1,NBZ>(D1D,Q1D,B,DQ0,QQ0);
kernels::internal::EvalX<MD1,MQ1,NBZ>(D1D,Q1D,B,XY1,DQ1);
kernels::internal::EvalY<MD1,MQ1,NBZ>(D1D,Q1D,B,DQ1,QQ1);
MFEM_FOREACH_THREAD(qy,y,Q1D)
{
MFEM_FOREACH_THREAD(qx,x,Q1D)
@@ -77,15 +102,37 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_C0_2D,
const double coeff0 = const_c0 ? C0(0,0,0) : C0(qx,qy,e);
const double weight_m = weight * lim_normal * coeff0;
double D;
double D, p0[2], p1[2];
kernels::internal::PullEval<MQ1,NBZ>(Q1D,qx,qy,QQ,D);
kernels::internal::PullEval<MQ1,NBZ>(Q1D,qx,qy,QQ0,p0);
kernels::internal::PullEval<MQ1,NBZ>(Q1D,qx,qy,QQ1,p1);
const double dist = D; // GetValues, default comp set to 0
// lim_func->Eval_d2(p1, p0, d_vals(q), grad_grad);
// d2.Diag(1.0 / (dist * dist), x.Size());
const double c = 1.0 / (dist * dist);
double grad_grad[4];
kernels::Diag<2>(c, grad_grad);
if (!exp_lim)
{
// d2.Diag(1.0 / (dist * dist), x.Size());
const double c = 1.0 / (dist * dist);
kernels::Diag<2>(c, grad_grad);
}
else
{
double tmp[2];
kernels::Subtract<2>(1.0, p1, p0, tmp);
double dsq = kernels::DistanceSquared<2>(p1,p0);
double dist_squared = dist*dist;
double dist_squared_squared = dist_squared*dist_squared;
double f = exp(10.0*((dsq / dist_squared)-1.0));
grad_grad[0] = ((400.0*tmp[0]*tmp[0]*f)/dist_squared_squared)+
(20.0*f/dist_squared);
grad_grad[1] = (400.0*tmp[0]*tmp[1]*f)/dist_squared_squared;
grad_grad[2] = grad_grad[1];
grad_grad[3] = ((400.0*tmp[1]*tmp[1]*f)/dist_squared_squared)+
(20.0*f/dist_squared);
}
ConstDeviceMatrix gg(grad_grad,DIM,DIM);
for (int i = 0; i < DIM; i++)
@@ -111,11 +158,17 @@ void TMOP_Integrator::AssembleGradPA_C0_2D(const Vector &X) const
const Vector &LD = PA.LD;
const DenseTensor &J = PA.Jtr;
const Array<double> &W = PA.ir->GetWeights();
const Array<double> &B = PA.maps->B;
const Array<double> &BLD = PA.maps_lim->B;
const Vector &C0 = PA.C0;
const Vector &X0 = PA.X0;
Vector &H0 = PA.H0;
MFEM_LAUNCH_TMOP_KERNEL(SetupGradPA_C0_2D,id,ln,LD,C0,N,J,W,BLD,H0);
auto el = dynamic_cast<TMOP_ExponentialLimiter *>(lim_func);
const bool exp_lim = (el) ? true : false;
MFEM_LAUNCH_TMOP_KERNEL(SetupGradPA_C0_2D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,H0,
exp_lim);
}
} // namespace mfem
+71 -6
View File
@@ -25,8 +25,12 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_Kernel_C0_3D,
const int NE,
const DenseTensor &j_,
const Array<double> &w_,
const Array<double> &b_,
const Array<double> &bld_,
const Vector &x0_,
const Vector &x1_,
Vector &h0_,
const bool exp_lim,
const int d1d,
const int q1d)
{
@@ -40,8 +44,11 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_Kernel_C0_3D,
Reshape(c0_.Read(), Q1D, Q1D, Q1D, NE);
const auto LD = Reshape(lim_dist.Read(), D1D, D1D, D1D, NE);
const auto J = Reshape(j_.Read(), DIM, DIM, Q1D, Q1D, Q1D, NE);
const auto W = Reshape(w_.Read(), Q1D, Q1D, Q1D);
const auto b = Reshape(b_.Read(), Q1D, D1D);
const auto bld = Reshape(bld_.Read(), Q1D, D1D);
const auto W = Reshape(w_.Read(), Q1D, Q1D, Q1D);
const auto X0 = Reshape(x0_.Read(), D1D, D1D, D1D, DIM, NE);
const auto X1 = Reshape(x1_.Read(), D1D, D1D, D1D, DIM, NE);
auto H0 = Reshape(h0_.Write(), DIM, DIM, Q1D, Q1D, Q1D, NE);
@@ -54,6 +61,7 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_Kernel_C0_3D,
constexpr int MD1 = T_D1D ? T_D1D : T_MAX;
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
MFEM_SHARED double B[MQ1*MD1];
MFEM_SHARED double sBLD[MQ1*MD1];
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,bld,sBLD);
ConstDeviceMatrix BLD(sBLD, D1D, Q1D);
@@ -65,12 +73,34 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_Kernel_C0_3D,
DeviceCube DQQ(sm0, MD1,MQ1,MQ1);
DeviceCube QQQ(sm1, MQ1,MQ1,MQ1);
MFEM_SHARED double DDD0[3][MD1*MD1*MD1];
MFEM_SHARED double DDQ0[3][MD1*MD1*MQ1];
MFEM_SHARED double DQQ0[3][MD1*MQ1*MQ1];
MFEM_SHARED double QQQ0[3][MQ1*MQ1*MQ1];
MFEM_SHARED double DDD1[3][MD1*MD1*MD1];
MFEM_SHARED double DDQ1[3][MD1*MD1*MQ1];
MFEM_SHARED double DQQ1[3][MD1*MQ1*MQ1];
MFEM_SHARED double QQQ1[3][MQ1*MQ1*MQ1];
kernels::internal::LoadX(e,D1D,LD,DDD);
kernels::internal::LoadX<MD1>(e,D1D,X0,DDD0);
kernels::internal::LoadX<MD1>(e,D1D,X1,DDD1);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,B);
kernels::internal::EvalX(D1D,Q1D,BLD,DDD,DDQ);
kernels::internal::EvalY(D1D,Q1D,BLD,DDQ,DQQ);
kernels::internal::EvalZ(D1D,Q1D,BLD,DQQ,QQQ);
kernels::internal::EvalX<MD1,MQ1>(D1D,Q1D,B,DDD0,DDQ0);
kernels::internal::EvalY<MD1,MQ1>(D1D,Q1D,B,DDQ0,DQQ0);
kernels::internal::EvalZ<MD1,MQ1>(D1D,Q1D,B,DQQ0,QQQ0);
kernels::internal::EvalX<MD1,MQ1>(D1D,Q1D,B,DDD1,DDQ1);
kernels::internal::EvalY<MD1,MQ1>(D1D,Q1D,B,DDQ1,DQQ1);
kernels::internal::EvalZ<MD1,MQ1>(D1D,Q1D,B,DQQ1,QQQ1);
MFEM_FOREACH_THREAD(qz,z,Q1D)
{
MFEM_FOREACH_THREAD(qy,y,Q1D)
@@ -83,15 +113,44 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_Kernel_C0_3D,
const double coeff0 = const_c0 ? C0(0,0,0,0) : C0(qx,qy,qz,e);
const double weight_m = weight * lim_normal * coeff0;
double D;
double D, p0[3], p1[3];
kernels::internal::PullEval(qx,qy,qz,QQQ,D);
kernels::internal::PullEval<MQ1>(Q1D,qx,qy,qz,QQQ0,p0);
kernels::internal::PullEval<MQ1>(Q1D,qx,qy,qz,QQQ1,p1);
const double dist = D; // GetValues, default comp set to 0
// lim_func->Eval_d2(p1, p0, d_vals(q), grad_grad);
// d2.Diag(1.0 / (dist * dist), x.Size());
const double c = 1.0 / (dist * dist);
double grad_grad[9];
kernels::Diag<3>(c, grad_grad);
if (!exp_lim)
{
// d2.Diag(1.0 / (dist * dist), x.Size());
const double c = 1.0 / (dist * dist);
kernels::Diag<3>(c, grad_grad);
}
else
{
double tmp[3];
kernels::Subtract<3>(1.0, p1, p0, tmp);
double dsq = kernels::DistanceSquared<3>(p1,p0);
double dist_squared = dist*dist;
double dist_squared_squared = dist_squared*dist_squared;
double f = exp(10.0*((dsq / dist_squared)-1.0));
grad_grad[0] = ((400.0*tmp[0]*tmp[0]*f)/dist_squared_squared)+
(20.0*f/dist_squared);
grad_grad[1] = (400.0*tmp[0]*tmp[1]*f)/dist_squared_squared;
grad_grad[2] = (400.0*tmp[0]*tmp[2]*f)/dist_squared_squared;
grad_grad[3] = grad_grad[1];
grad_grad[4] = ((400.0*tmp[1]*tmp[1]*f)/dist_squared_squared)+
(20.0*f/dist_squared);
grad_grad[5] = (400.0*tmp[1]*tmp[2]*f)/dist_squared_squared;
grad_grad[6] = grad_grad[2];
grad_grad[7] = grad_grad[5];
grad_grad[8] = ((400.0*tmp[2]*tmp[2]*f)/dist_squared_squared)+
(20.0*f/dist_squared);
}
ConstDeviceMatrix gg(grad_grad,DIM,DIM);
for (int i = 0; i < DIM; i++)
@@ -117,11 +176,17 @@ void TMOP_Integrator::AssembleGradPA_C0_3D(const Vector &X) const
const Vector &LD = PA.LD;
const DenseTensor &J = PA.Jtr;
const Array<double> &W = PA.ir->GetWeights();
const Array<double> &B = PA.maps->B;
const Array<double> &BLD = PA.maps_lim->B;
const Vector &C0 = PA.C0;
const Vector &X0 = PA.X0;
Vector &H0 = PA.H0;
MFEM_LAUNCH_TMOP_KERNEL(SetupGradPA_Kernel_C0_3D,id,ln,LD,C0,N,J,W,BLD,H0);
auto el = dynamic_cast<TMOP_ExponentialLimiter *>(lim_func);
const bool exp_lim = (el) ? true : false;
MFEM_LAUNCH_TMOP_KERNEL(SetupGradPA_Kernel_C0_3D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,
H0,exp_lim);
}
} // namespace mfem
+28 -3
View File
@@ -30,6 +30,7 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultPA_Kernel_C0_2D,
const Vector &x0_,
const Vector &x1_,
Vector &y_,
const bool exp_lim,
const int d1d,
const int q1d)
{
@@ -110,14 +111,35 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultPA_Kernel_C0_2D,
const double dist = ld; // GetValues, default comp set to 0
double d1[2];
// Eval_d1
// Eval_d1 (Quadratic Limiter)
// subtract(1.0 / (dist * dist), x, x0, d1);
// z = a * (x - y)
// grad = a * (x - x0)
const double a = 1.0 / (dist * dist);
// Eval_d1 (Exponential Limiter)
// double dist_squared = dist*dist;
// subtract(20.0*exp(10.0*((x.DistanceSquaredTo(x0) / dist_squared) - 1.0)) /
// dist_squared, x, x0, d1);
// z = a * (x - y)
// grad = a * (x - x0)
double a = 0.0;
const double w = weight * lim_normal * coeff0;
const double dist_squared = dist * dist;
if (!exp_lim)
{
a = 1.0 / dist_squared;
}
else
{
double dsq = kernels::DistanceSquared<2>(p1,p0) / dist_squared;
a = 20.0*exp(10.0*(dsq - 1.0))/dist_squared;
}
kernels::Subtract<2>(w*a, p1, p0, d1);
kernels::internal::PushEval<MQ1,NBZ>(Q1D,qx,qy,d1,QQ0);
}
}
MFEM_SYNC_THREAD;
@@ -143,8 +165,11 @@ void TMOP_Integrator::AddMultPA_C0_2D(const Vector &X, Vector &Y) const
MFEM_VERIFY(PA.maps_lim->nqpt == Q1D, "");
const Vector &X0 = PA.X0;
const Vector &C0 = PA.C0;
auto el = dynamic_cast<TMOP_ExponentialLimiter *>(lim_func);
const bool exp_lim = (el) ? true : false;
MFEM_LAUNCH_TMOP_KERNEL(AddMultPA_Kernel_C0_2D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,Y);
MFEM_LAUNCH_TMOP_KERNEL(AddMultPA_Kernel_C0_2D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,Y,
exp_lim);
}
} // namespace mfem
+26 -3
View File
@@ -30,6 +30,7 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultPA_Kernel_C0_3D,
const Vector &x0_,
const Vector &x1_,
Vector &y_,
const bool exp_lim,
const int d1d,
const int q1d)
{
@@ -117,13 +118,32 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultPA_Kernel_C0_3D,
kernels::internal::PullEval<MQ1>(Q1D,qx,qy,qz,QQQ1,p1);
double d1[3];
// Eval_d1
// Eval_d1 (Quadratic Limiter)
// subtract(1.0 / (dist * dist), x, x0, d1);
// z = a * (x - y)
// grad = a * (x - x0)
// Eval_d1 (Exponential Limiter)
// double dist_squared = dist*dist;
// subtract(20.0*exp(10.0*((x.DistanceSquaredTo(x0) / dist_squared) - 1.0)) /
// dist_squared, x, x0, d1);
// z = a * (x - y)
// grad = a * (x - x0)
const double dist = D; // GetValues, default comp set to 0
const double a = 1.0 / (dist * dist);
double a = 0.0;
const double w = weight * lim_normal * coeff0;
const double dist_squared = dist * dist;
if (!exp_lim)
{
a = 1.0 / dist_squared;
}
else
{
double dsq = kernels::DistanceSquared<3>(p1,p0) / dist_squared;
a = 20.0*exp(10.0*(dsq - 1.0))/dist_squared;
}
kernels::Subtract<3>(w*a, p1, p0, d1);
kernels::internal::PushEval<MQ1>(Q1D,qx,qy,qz,d1,QQQ0);
}
@@ -153,8 +173,11 @@ void TMOP_Integrator::AddMultPA_C0_3D(const Vector &X, Vector &Y) const
MFEM_VERIFY(PA.maps_lim->nqpt == Q1D, "");
const Vector &X0 = PA.X0;
const Vector &C0 = PA.C0;
auto el = dynamic_cast<TMOP_ExponentialLimiter *>(lim_func);
const bool exp_lim = (el) ? true : false;
MFEM_LAUNCH_TMOP_KERNEL(AddMultPA_Kernel_C0_3D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,Y);
MFEM_LAUNCH_TMOP_KERNEL(AddMultPA_Kernel_C0_3D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,Y,
exp_lim);
}
} // namespace mfem
+20 -4
View File
@@ -31,6 +31,7 @@ MFEM_REGISTER_TMOP_KERNELS(double, EnergyPA_C0_2D,
const Vector &x1_,
const Vector &ones,
Vector &energy,
const bool exp_lim,
const int d1d,
const int q1d)
{
@@ -107,9 +108,20 @@ MFEM_REGISTER_TMOP_KERNELS(double, EnergyPA_C0_2D,
kernels::internal::PullEval<MQ1,NBZ>(Q1D,qx,qy,QQ0,p0);
kernels::internal::PullEval<MQ1,NBZ>(Q1D,qx,qy,QQ1,p1);
const double dist = ld; // GetValues, default comp set to 0
const double id2 = 0.5 / (dist*dist);
const double dsq = kernels::DistanceSquared<2>(p1,p0) * id2;
E(qx,qy,e) = weight * lim_normal * dsq * coeff0;
double id2 = 0.0;
double dsq = 0.0;
if (!exp_lim)
{
id2 = 0.5 / (dist*dist);
dsq = kernels::DistanceSquared<2>(p1,p0) * id2;
E(qx,qy,e) = weight * lim_normal * dsq * coeff0;
}
else
{
id2 = 1.0 / (dist*dist);
dsq = kernels::DistanceSquared<2>(p1,p0) * id2;
E(qx,qy,e) = weight * lim_normal * exp(10.0*(dsq-1.0)) * coeff0;
}
}
}
});
@@ -135,7 +147,11 @@ double TMOP_Integrator::GetLocalStateEnergyPA_C0_2D(const Vector &X) const
const Vector &O = PA.O;
Vector &E = PA.E;
MFEM_LAUNCH_TMOP_KERNEL(EnergyPA_C0_2D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,O,E);
auto el = dynamic_cast<TMOP_ExponentialLimiter *>(lim_func);
const bool exp_lim = (el) ? true : false;
MFEM_LAUNCH_TMOP_KERNEL(EnergyPA_C0_2D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,O,E,
exp_lim);
}
} // namespace mfem
+20 -5
View File
@@ -31,6 +31,7 @@ MFEM_REGISTER_TMOP_KERNELS(double, EnergyPA_C0_3D,
const Vector &x1_,
const Vector &ones,
Vector &energy,
const bool exp_lim,
const int d1d,
const int q1d)
{
@@ -118,10 +119,20 @@ MFEM_REGISTER_TMOP_KERNELS(double, EnergyPA_C0_3D,
kernels::internal::PullEval<MQ1>(Q1D,qx,qy,qz,QQQ1,p1);
const double dist = D; // GetValues, default comp set to 0
const double id2 = 0.5 / (dist*dist);
const double dsq = kernels::DistanceSquared<3>(p1,p0) * id2;
E(qx,qy,qz,e) = weight * lim_normal * dsq * coeff0;
double id2 = 0.0;
double dsq = 0.0;
if (!exp_lim)
{
id2 = 0.5 / (dist*dist);
dsq = kernels::DistanceSquared<3>(p1,p0) * id2;
E(qx,qy,qz,e) = weight * lim_normal * dsq * coeff0;
}
else
{
id2 = 1.0 / (dist*dist);
dsq = kernels::DistanceSquared<3>(p1,p0) * id2;
E(qx,qy,qz,e) = weight * lim_normal * exp(10.0*(dsq-1.0)) * coeff0;
}
}
}
}
@@ -148,7 +159,11 @@ double TMOP_Integrator::GetLocalStateEnergyPA_C0_3D(const Vector &X) const
const Vector &O = PA.O;
Vector &E = PA.E;
MFEM_LAUNCH_TMOP_KERNEL(EnergyPA_C0_3D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,O,E);
auto el = dynamic_cast<TMOP_ExponentialLimiter *>(lim_func);
const bool exp_lim = (el) ? true : false;
MFEM_LAUNCH_TMOP_KERNEL(EnergyPA_C0_3D,id,ln,LD,C0,N,J,W,B,BLD,X0,X,O,E,
exp_lim);
}
} // namespace mfem
+4
View File
@@ -61,6 +61,10 @@ void mfem_error(const char *msg = NULL);
/// Function called by the macro MFEM_WARNING.
void mfem_warning(const char *msg = NULL);
#ifdef MFEM_USE_ENZYME
static void* __enzyme_inactive_global_err = (void*)mfem_error;
static void* __enzyme_inactive_global_warn = (void*)mfem_warning;
#endif
}
#ifndef _MFEM_FUNC_NAME
+5 -5
View File
@@ -310,10 +310,11 @@ inline uintptr_t MmuLengthP(const void *ptr, const size_t bytes)
/// The protected access error, used for the host
static void MmuError(int, siginfo_t *si, void*)
{
constexpr size_t buf_size = 64;
fflush(0);
char str[64];
char str[buf_size];
const void *ptr = si->si_addr;
sprintf(str, "Error while accessing address %p!", ptr);
snprintf(str, buf_size, "Error while accessing address %p!", ptr);
mfem::out << std::endl << "An illegal memory access was made!";
MFEM_ABORT(str);
}
@@ -907,7 +908,7 @@ void MemoryManager::SetDeviceMemoryType_(void *h_ptr, unsigned flags,
}
}
MemoryType MemoryManager::Delete_(void *h_ptr, MemoryType h_mt, unsigned flags)
void MemoryManager::Delete_(void *h_ptr, MemoryType h_mt, unsigned flags)
{
const bool alias = flags & Mem::ALIAS;
const bool registered = flags & Mem::REGISTERED;
@@ -924,7 +925,7 @@ MemoryType MemoryManager::Delete_(void *h_ptr, MemoryType h_mt, unsigned flags)
MFEM_ASSERT(registered || !(owns_host || owns_device || owns_internal) ||
(!(owns_device || owns_internal) && h_ptr == nullptr),
"invalid Memory state");
if (!mm.exists || !registered) { return h_mt; }
if (!mm.exists || !registered) { return; }
if (alias)
{
if (owns_internal)
@@ -945,7 +946,6 @@ MemoryType MemoryManager::Delete_(void *h_ptr, MemoryType h_mt, unsigned flags)
mm.Erase(h_ptr, owns_device);
}
}
return h_mt;
}
void MemoryManager::DeleteDevice_(void *h_ptr, unsigned & flags)
+25 -5
View File
@@ -644,9 +644,8 @@ private: // Static methods used by the Memory<T> class
static void SetDeviceMemoryType_(void *h_ptr, unsigned flags,
MemoryType d_mt);
/// Un-register and free memory identified by its host pointer. Returns the
/// memory type of the host pointer.
static MemoryType Delete_(void *h_ptr, MemoryType mt, unsigned flags);
/// Un-register and free memory identified by its host pointer.
static void Delete_(void *h_ptr, MemoryType mt, unsigned flags);
/// Free device memory identified by its host pointer
static void DeleteDevice_(void *h_ptr, unsigned & flags);
@@ -828,6 +827,23 @@ public:
static MemoryType GetHostMemoryType() { return host_mem_type; }
static MemoryType GetDeviceMemoryType() { return device_mem_type; }
#ifdef MFEM_USE_ENZYME
static void myfree(void* mem, MemoryType MT, unsigned &flags)
{
MemoryManager::Delete_(mem, MT, flags);
}
__attribute__((used))
inline static void* __enzyme_allocation_like1[4] = {(void*)static_cast<void*(*)(void*, size_t, MemoryType, unsigned&)>(MemoryManager::New_),
(void*)1, (void*)"-1,2,3", (void*)myfree
};
__attribute__((used))
inline static void* __enzyme_allocation_like2[4] = {(void*)static_cast<void*(*)(void*, size_t, MemoryType, MemoryType, unsigned, unsigned&)>(MemoryManager::New_),
(void*)1, (void*)"-1,2,4", (void*)MemoryManager::Delete_
};
__attribute__((used))
inline static void* __enzyme_function_like[2] = {(void*)MemoryManager::Delete_, (void*)"free"};
#endif
};
@@ -1007,8 +1023,12 @@ inline void Memory<T>::Delete()
const bool mt_host = h_mt == MemoryType::HOST;
const bool std_delete = !registered && mt_host;
if (std_delete ||
MemoryManager::Delete_((void*)h_ptr, h_mt, flags) == MemoryType::HOST)
if (!std_delete)
{
MemoryManager::Delete_((void*)h_ptr, h_mt, flags);
}
if (mt_host)
{
if (flags & OWNS_HOST) { delete [] h_ptr; }
}
-3
View File
@@ -112,9 +112,6 @@ const char *GetConfigStr()
#ifdef MFEM_USE_MEMALLOC
"MFEM_USE_MEMALLOC\n"
#endif
#ifdef MFEM_USE_MESQUITE
"MFEM_USE_MESQUITE\n"
#endif
#ifdef MFEM_USE_METIS
"MFEM_USE_METIS\n"
#endif
+2 -2
View File
@@ -60,9 +60,9 @@ namespace strict_fstream
{
// Overloaded error checks to handle POSIX and GNU strerror_r
inline char* check_strerror_r(int r, char* buff, int err)
inline char* check_strerror_r(int r, char* buff, size_t buff_size)
{
if (r) { sprintf(buff, "unknown error: %d", err); }
if (r) { snprintf(buff, buff_size, "unknown error: %d", r); }
return buff;
}
+4 -4
View File
@@ -51,14 +51,14 @@ Eliminator::Eliminator(const SparseMatrix& B, const Array<int>& lagrange_tdofs_,
void Eliminator::Eliminate(const Vector& vin, Vector& vout) const
{
Bp.Mult(vin, vout);
Bsinverse.Solve(Bs.Height(), 1, vout);
Bsinverse.Solve(Bs.Height(), 1, vout.GetData());
vout *= -1.0;
}
void Eliminator::EliminateTranspose(const Vector& vin, Vector& vout) const
{
Vector work(vin);
BsTinverse.Solve(Bs.Height(), 1, work);
BsTinverse.Solve(Bs.Height(), 1, work.GetData());
Bp.MultTranspose(work, vout);
vout *= -1.0;
}
@@ -66,14 +66,14 @@ void Eliminator::EliminateTranspose(const Vector& vin, Vector& vout) const
void Eliminator::LagrangeSecondary(const Vector& vin, Vector& vout) const
{
vout = vin;
Bsinverse.Solve(Bs.Height(), 1, vout);
Bsinverse.Solve(Bs.Height(), 1, vout.GetData());
}
void Eliminator::LagrangeSecondaryTranspose(const Vector& vin,
Vector& vout) const
{
vout = vin;
BsTinverse.Solve(Bs.Height(), 1, vout);
BsTinverse.Solve(Bs.Height(), 1, vout.GetData());
}
void Eliminator::ExplicitAssembly(DenseMatrix& mat) const
+2
View File
@@ -55,7 +55,9 @@ void CPardisoSolver::SetOperator(const Operator &op)
auto parcsr_op = static_cast<hypre_ParCSRMatrix *>(
const_cast<HypreParMatrix &>(hypreParMat));
hypreParMat.HostRead();
hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
hypreParMat.HypreRead();
#if MFEM_HYPRE_VERSION >= 21600
hypre_CSRMatrixBigJtoJ(csr_op);
#endif
+53 -11
View File
@@ -175,12 +175,26 @@ void DenseMatrix::Mult(const double *x, double *y) const
kernels::Mult(height, width, Data(), x, y);
}
void DenseMatrix::Mult(const double *x, Vector &y) const
{
MFEM_ASSERT(height == y.Size(), "incompatible dimensions");
Mult(x, y.GetData());
}
void DenseMatrix::Mult(const Vector &x, double *y) const
{
MFEM_ASSERT(width == x.Size(), "incompatible dimensions");
Mult(x.GetData(), y);
}
void DenseMatrix::Mult(const Vector &x, Vector &y) const
{
MFEM_ASSERT(height == y.Size() && width == x.Size(),
"incompatible dimensions");
Mult((const double *)x, (double *)y);
Mult(x.GetData(), y.GetData());
}
double DenseMatrix::operator *(const DenseMatrix &m) const
@@ -213,12 +227,26 @@ void DenseMatrix::MultTranspose(const double *x, double *y) const
}
}
void DenseMatrix::MultTranspose(const double *x, Vector &y) const
{
MFEM_ASSERT(width == y.Size(), "incompatible dimensions");
MultTranspose(x, y.GetData());
}
void DenseMatrix::MultTranspose(const Vector &x, double *y) const
{
MFEM_ASSERT(height == x.Size(), "incompatible dimensions");
MultTranspose(x.GetData(), y);
}
void DenseMatrix::MultTranspose(const Vector &x, Vector &y) const
{
MFEM_ASSERT(height == x.Size() && width == y.Size(),
"incompatible dimensions");
MultTranspose((const double *)x, (double *)y);
MultTranspose(x.GetData(), y.GetData());
}
void DenseMatrix::AddMult(const Vector &x, Vector &y) const
@@ -226,8 +254,8 @@ void DenseMatrix::AddMult(const Vector &x, Vector &y) const
MFEM_ASSERT(height == y.Size() && width == x.Size(),
"incompatible dimensions");
const double *xp = x, *d_col = data;
double *yp = y;
const double *xp = x.GetData(), *d_col = data;
double *yp = y.GetData();
for (int col = 0; col < width; col++)
{
double x_col = xp[col];
@@ -262,8 +290,8 @@ void DenseMatrix::AddMult_a(double a, const Vector &x, Vector &y) const
MFEM_ASSERT(height == y.Size() && width == x.Size(),
"incompatible dimensions");
const double *xp = x, *d_col = data;
double *yp = y;
const double *xp = x.GetData(), *d_col = data;
double *yp = y.GetData();
for (int col = 0; col < width; col++)
{
const double x_col = a*xp[col];
@@ -1181,7 +1209,7 @@ void DenseMatrix::SingularValues(Vector &sv) const
int n = Width();
double *a = copy_of_this.data;
sv.SetSize(min(m, n));
double *s = sv;
double *s = sv.GetData();
double *u = NULL;
double *vt = NULL;
double *work = NULL;
@@ -1459,10 +1487,10 @@ void DenseMatrix::GradToCurl(DenseMatrix &curl)
int j = i+n;
// curl of (Ui,0)
curl(i,0) = y;
curl(i,0) = -y;
// curl of (0,Ui)
curl(j,0) = -x;
curl(j,0) = x;
}
}
else
@@ -1495,6 +1523,20 @@ void DenseMatrix::GradToCurl(DenseMatrix &curl)
}
}
void DenseMatrix::GradToVectorCurl2D(DenseMatrix &curl)
{
MFEM_VERIFY(Width() == 2,
"DenseMatrix::GradToVectorCurl2D(...): dimension must be 2")
int n = Height();
// rotate gradient
for (int i = 0; i < n; i++)
{
curl(i,0) = (*this)(i,1);
curl(i,1) = -(*this)(i,0);
}
}
void DenseMatrix::GradToDiv(Vector &div)
{
MFEM_ASSERT(Width()*Height() == div.Size(), "incompatible Vector 'div'!");
@@ -4176,10 +4218,10 @@ const
{
int n = SizeI(), ne = SizeK();
const int *I = elem_dof.GetI(), *J = elem_dof.GetJ(), *dofs;
const double *d_col = tdata;
const double *d_col = mfem::HostRead(tdata, n*SizeJ()*ne);
double *yp = y.HostReadWrite();
double x_col;
const double *xp = x;
const double *xp = x.HostRead();
// the '4' here can be tuned for given platform and compiler
if (n <= 4)
{
+26 -2
View File
@@ -141,12 +141,24 @@ public:
/// Matrix vector multiplication.
void Mult(const double *x, double *y) const;
/// Matrix vector multiplication.
void Mult(const double *x, Vector &y) const;
/// Matrix vector multiplication.
void Mult(const Vector &x, double *y) const;
/// Matrix vector multiplication.
virtual void Mult(const Vector &x, Vector &y) const;
/// Multiply a vector with the transpose matrix.
void MultTranspose(const double *x, double *y) const;
/// Multiply a vector with the transpose matrix.
void MultTranspose(const double *x, Vector &y) const;
/// Multiply a vector with the transpose matrix.
void MultTranspose(const Vector &x, double *y) const;
/// Multiply a vector with the transpose matrix.
virtual void MultTranspose(const Vector &x, Vector &y) const;
@@ -180,7 +192,7 @@ public:
/// Compute y^t A x
double InnerProduct(const Vector &x, const Vector &y) const
{ return InnerProduct((const double *)x, (const double *)y); }
{ return InnerProduct(x.GetData(), y.GetData()); }
/// Returns a pointer to the inverse matrix.
virtual MatrixInverse *Inverse() const;
@@ -236,6 +248,13 @@ public:
/// Take the 2-norm of the columns of A and store in v
void Norm2(double *v) const;
/// Take the 2-norm of the columns of A and store in v
void Norm2(Vector &v) const
{
MFEM_ASSERT(v.Size() == Width(), "incompatible Vector size!");
Norm2(v.GetData());
}
/// Compute the norm ||A|| = max_{ij} |A_{ij}|
double MaxMaxNorm() const;
@@ -325,8 +344,13 @@ public:
/** Given a DShape matrix (from a scalar FE), stored in *this, returns the
CurlShape matrix. If *this is a N by D matrix, then curl is a D*N by
D*(D-1)/2 matrix. The size of curl must be set outside. The dimension D
can be either 2 or 3. */
can be either 2 or 3. In 2D this computes the scalar-valued curl of a
2D vector field */
void GradToCurl(DenseMatrix &curl);
/** Given a DShape matrix (from a scalar FE), stored in *this, returns the
CurlShape matrix. This computes the vector-valued curl of a scalar field.
*this is N by 2 matrix and curl is N by 2 matrix as well. */
void GradToVectorCurl2D(DenseMatrix &curl);
/** Given a DShape matrix (from a scalar FE), stored in *this,
returns the DivShape vector. If *this is a N by dim matrix,
then div is a dim*N vector. The size of div must be set
+6
View File
@@ -92,6 +92,8 @@ public:
* internally in HiOp. */
virtual bool get_starting_point(const hiop::size_type &n, double *x0);
using hiop::hiopInterfaceBase::get_starting_point;
virtual bool get_vars_info(const hiop::size_type &n, double *xlow, double* xupp,
NonlinearityType* type);
@@ -136,6 +138,8 @@ public:
const hiop::index_type *idx_cons,
const double *x, bool new_x, double *cons);
using hiop::hiopInterfaceBase::eval_cons;
/** Evaluates the Jacobian of the subset of constraints indicated by
* idx_cons. The idx_cons is assumed to be of size num_cons.
* Example: if cons[c] = C(x)[idx_cons[c]] where c = 0 .. num_cons-1, then
@@ -152,6 +156,8 @@ public:
const hiop::index_type *idx_cons,
const double *x, bool new_x, double *Jac);
using hiop::hiopInterfaceDenseConstraints::eval_Jac_cons;
/** Specifies column partitioning for distributed memory vectors.
* Process p owns vector entries with indices cols[p] to cols[p+1]-1,
* where p = 0 .. nranks-1. The cols array is of size nranks + 1.
+2
View File
@@ -42,7 +42,9 @@ void MUMPSSolver::SetOperator(const Operator &op)
auto parcsr_op = (hypre_ParCSRMatrix *) const_cast<HypreParMatrix &>(*APtr);
APtr->HostRead();
hypre_CSRMatrix *csr_op = hypre_MergeDiagAndOffd(parcsr_op);
APtr->HypreRead();
#if MFEM_HYPRE_VERSION >= 21600
hypre_CSRMatrixBigJtoJ(csr_op);
#endif
+28 -15
View File
@@ -1335,7 +1335,12 @@ void PetscParMatrix::ConvertOperator(MPI_Comm comm, const Operator &op, Mat* A,
PetscBool ismatis;
#endif
#if PETSC_VERSION_LT(3,18,0)
ierr = PetscObjectTypeCompare((PetscObject)(pA->A),MATTRANSPOSEMAT,&istrans);
#else
ierr = PetscObjectTypeCompare((PetscObject)(pA->A),MATTRANSPOSEVIRTUAL,
&istrans);
#endif
CCHKERRQ(pA->GetComm(),ierr);
if (!istrans)
{
@@ -2850,37 +2855,43 @@ void PetscBCHandler::ZeroBC(const Vector &x, Vector &y)
// PetscLinearSolver methods
PetscLinearSolver::PetscLinearSolver(MPI_Comm comm, const std::string &prefix,
bool wrapin)
: PetscSolver(), Solver(), wrap(wrapin)
bool wrapin, bool iter_mode)
: PetscSolver(), Solver(0,iter_mode), wrap(wrapin)
{
KSP ksp;
ierr = KSPCreate(comm,&ksp); CCHKERRQ(comm,ierr);
obj = (PetscObject)ksp;
ierr = PetscObjectGetClassId(obj,&cid); PCHKERRQ(obj,ierr);
ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
ierr = KSPSetInitialGuessNonzero(ksp, (PetscBool)iterative_mode);
PCHKERRQ(ksp, ierr);
}
PetscLinearSolver::PetscLinearSolver(const PetscParMatrix &A,
const std::string &prefix)
: PetscSolver(), Solver(), wrap(false)
const std::string &prefix, bool iter_mode)
: PetscSolver(), Solver(0,iter_mode), wrap(false)
{
KSP ksp;
ierr = KSPCreate(A.GetComm(),&ksp); CCHKERRQ(A.GetComm(),ierr);
obj = (PetscObject)ksp;
ierr = PetscObjectGetClassId(obj,&cid); PCHKERRQ(obj,ierr);
ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
ierr = KSPSetInitialGuessNonzero(ksp, (PetscBool)iterative_mode);
PCHKERRQ(ksp, ierr);
SetOperator(A);
}
PetscLinearSolver::PetscLinearSolver(const HypreParMatrix &A, bool wrapin,
const std::string &prefix)
: PetscSolver(), Solver(), wrap(wrapin)
const std::string &prefix, bool iter_mode)
: PetscSolver(), Solver(0,iter_mode), wrap(wrapin)
{
KSP ksp;
ierr = KSPCreate(A.GetComm(),&ksp); CCHKERRQ(A.GetComm(),ierr);
obj = (PetscObject)ksp;
ierr = PetscObjectGetClassId(obj, &cid); PCHKERRQ(obj, ierr);
ierr = KSPSetOptionsPrefix(ksp, prefix.c_str()); PCHKERRQ(ksp, ierr);
ierr = KSPSetInitialGuessNonzero(ksp, (PetscBool)iterative_mode);
PCHKERRQ(ksp, ierr);
SetOperator(A);
}
@@ -3089,12 +3100,12 @@ void PetscLinearSolver::MultKernel(const Vector &b, Vector &x, bool trans) const
}
}
B->PlaceMemory(b.GetMemory());
X->PlaceMemory(x.GetMemory(),iterative_mode);
Customize();
ierr = KSPSetInitialGuessNonzero(ksp, (PetscBool)iterative_mode);
PCHKERRQ(ksp, ierr);
PetscBool flg;
ierr = KSPGetInitialGuessNonzero(ksp, &flg);
X->PlaceMemory(x.GetMemory(),flg);
// Solve the system.
if (trans)
@@ -3129,8 +3140,9 @@ PetscLinearSolver::~PetscLinearSolver()
// PetscPCGSolver methods
PetscPCGSolver::PetscPCGSolver(MPI_Comm comm, const std::string &prefix)
: PetscLinearSolver(comm,prefix)
PetscPCGSolver::PetscPCGSolver(MPI_Comm comm, const std::string &prefix,
bool iter_mode)
: PetscLinearSolver(comm,prefix,iter_mode)
{
KSP ksp = (KSP)obj;
ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
@@ -3138,8 +3150,9 @@ PetscPCGSolver::PetscPCGSolver(MPI_Comm comm, const std::string &prefix)
ierr = KSPSetNormType(ksp,KSP_NORM_NATURAL); PCHKERRQ(ksp,ierr);
}
PetscPCGSolver::PetscPCGSolver(PetscParMatrix& A, const std::string &prefix)
: PetscLinearSolver(A,prefix)
PetscPCGSolver::PetscPCGSolver(PetscParMatrix& A, const std::string &prefix,
bool iter_mode)
: PetscLinearSolver(A,prefix,iter_mode)
{
KSP ksp = (KSP)obj;
ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
@@ -3148,8 +3161,8 @@ PetscPCGSolver::PetscPCGSolver(PetscParMatrix& A, const std::string &prefix)
}
PetscPCGSolver::PetscPCGSolver(HypreParMatrix& A, bool wrap,
const std::string &prefix)
: PetscLinearSolver(A,wrap,prefix)
const std::string &prefix, bool iter_mode)
: PetscLinearSolver(A,wrap,prefix,iter_mode)
{
KSP ksp = (KSP)obj;
ierr = KSPSetType(ksp,KSPCG); PCHKERRQ(ksp,ierr);
+9 -7
View File
@@ -744,16 +744,16 @@ private:
public:
PetscLinearSolver(MPI_Comm comm, const std::string &prefix = std::string(),
bool wrap = true);
bool wrap = true, bool iter_mode = false);
PetscLinearSolver(const PetscParMatrix &A,
const std::string &prefix = std::string());
const std::string &prefix = std::string(), bool iter_mode = false);
/// Constructs a solver using a HypreParMatrix.
/** If @a wrap is true, then the MatMult ops of HypreParMatrix are wrapped.
No preconditioner can be automatically constructed from PETSc. If
@a wrap is false, the HypreParMatrix is converted into a the AIJ
PETSc format, which is suitable for most preconditioning methods. */
PetscLinearSolver(const HypreParMatrix &A, bool wrap = true,
const std::string &prefix = std::string());
const std::string &prefix = std::string(), bool iter_mode = false);
virtual ~PetscLinearSolver();
/// Sets the operator to be used for mat-vec operations and
@@ -780,10 +780,12 @@ public:
class PetscPCGSolver : public PetscLinearSolver
{
public:
PetscPCGSolver(MPI_Comm comm, const std::string &prefix = std::string());
PetscPCGSolver(PetscParMatrix &A, const std::string &prefix = std::string());
PetscPCGSolver(HypreParMatrix &A,bool wrap=true,
const std::string &prefix = std::string());
PetscPCGSolver(MPI_Comm comm, const std::string &prefix = std::string(),
bool iter_mode = false);
PetscPCGSolver(PetscParMatrix &A, const std::string &prefix = std::string(),
bool iter_mode = false);
PetscPCGSolver(HypreParMatrix &A, bool wrap = true,
const std::string &prefix = std::string(), bool iter_mode = false);
};
+11 -7
View File
@@ -3034,7 +3034,7 @@ void BlockILU::Mult(const Vector &b, Vector &x) const
}
LUFactors A_ii_inv(&DB(0,0,i), &ipiv[i*block_size]);
// x_i = D_ii^{-1} x_i
A_ii_inv.Solve(block_size, 1, xi);
A_ii_inv.Solve(block_size, 1, xi.GetData());
}
}
@@ -3197,7 +3197,8 @@ void UMFPackSolver::Mult(const Vector &b, Vector &x) const
{
int status =
umfpack_di_solve(UMFPACK_At, mat->HostReadI(), mat->HostReadJ(),
mat->HostReadData(), x, b, Numeric, Control, Info);
mat->HostReadData(), x.HostWrite(), b.HostRead(),
Numeric, Control, Info);
umfpack_di_report_info(Control, Info);
if (status < 0)
{
@@ -3208,8 +3209,9 @@ void UMFPackSolver::Mult(const Vector &b, Vector &x) const
else
{
SuiteSparse_long status =
umfpack_dl_solve(UMFPACK_At, AI, AJ, mat->HostReadData(), x, b,
Numeric, Control, Info);
umfpack_dl_solve(UMFPACK_At, AI, AJ, mat->HostReadData(),
x.HostWrite(), b.HostRead(), Numeric, Control,
Info);
umfpack_dl_report_info(Control, Info);
if (status < 0)
{
@@ -3230,7 +3232,8 @@ void UMFPackSolver::MultTranspose(const Vector &b, Vector &x) const
{
int status =
umfpack_di_solve(UMFPACK_A, mat->HostReadI(), mat->HostReadJ(),
mat->HostReadData(), x, b, Numeric, Control, Info);
mat->HostReadData(), x.HostWrite(), b.HostRead(),
Numeric, Control, Info);
umfpack_di_report_info(Control, Info);
if (status < 0)
{
@@ -3242,8 +3245,9 @@ void UMFPackSolver::MultTranspose(const Vector &b, Vector &x) const
else
{
SuiteSparse_long status =
umfpack_dl_solve(UMFPACK_A, AI, AJ, mat->HostReadData(), x, b,
Numeric, Control, Info);
umfpack_dl_solve(UMFPACK_A, AI, AJ, mat->HostReadData(),
x.HostWrite(), b.HostRead(), Numeric, Control,
Info);
umfpack_dl_report_info(Control, Info);
if (status < 0)
{
+340
View File
@@ -899,6 +899,346 @@ public:
virtual void Mult(const Vector &xt, Vector &x) const;
};
/** Defines operators and constraints for the following nonlinear contact
* problem:
*
* Find x in R^n and lambda in R^m such that
* K(x) - \nabla g(x)^T lambda = f
* 0 <= g(x) \perp lambda >= 0
*
* Above, the perpendicularity ("\perp") equation is understood pointwise,
* i.e., g_i(x) lambda_i = 0, for all i=1,2,...,m.
*
* This is class is to be derived by concrete contact problems and will be
* called by the contact solver to evaluate the contact problem.
*/
class ContactProblem
{
protected:
// Problem sizes
const int m, n;
// Right-hand side of the contact problem
mutable Vector f;
public:
/// Constructor taking the problem sizes as parameters.
ContactProblem(int m, int n);
inline int GetNumConstraints() const { return m; }
inline int GetNumDOFs () { return n; }
// [TODO:] an alternative design would be via a pure virtual method `Eval()`
// a members+getters for the problem's rhs, K, gradK, g, and gradG. The
// downside is that for nonlinear IPMs, sometimes g and K are evaluated without
// needing to evaluate their derivatives, gradG and gradK.
/// Returns the rhs of the (first set of equations of the ) contact problem.
virtual void GetRhs(Vector &f_out) { f_out = f; }
/** This method evaluates the nonlinear function K from the first set of contact
* equations. The contact solver calls this function. Concrete contact
* problems need to implement this callback. The method should return false
* when the evaluation failed, otherwise should return true. */
virtual bool EvalK(const Vector &x, Vector &Katx) = 0;
/** This method evaluates the gradient of the function K at x. The contact
* solver calls this function. Concrete contact problems need to implement this
* callback. The method should return false when the evaluation failed, otherwise
* should return true. */
virtual bool EvalGradK(const Vector &x, Operator &gradKatx) = 0;
/** This method evaluates the contact gap function g at x.
* The contact solver calls this function and concrete contact problems will
* implement this callback. The method should return false when the
* evaluation failed, otherwise should return true. */
virtual bool Evalg(const Vector &x, Vector &g) = 0;
/** This method evaluates the gradient (nonlinear operator) of the gap
* function g at x. The contact solver calls this function. Concrete contact
* problems need to implement this callback. The method should return false
* when the evaluation failed, otherwise should return true. */
virtual bool EvalGradg(const Vector &x, Operator &gradG) = 0;
//TODO: Hessian of the Lagrangian
};
//forward declaration of the "contact" linear solver
class ContactLinearSolver;
/// Abstract solver for ContactProblems.
class ContactSolver : public IterativeSolver
{
protected:
ContactProblem *problem;
ContactLinearSolver* linear_solver;
public:
ContactSolver()
: IterativeSolver(), problem(nullptr), linear_solver(nullptr) { }
#ifdef MFEM_USE_MPI
ContactSolver(MPI_Comm comm_)
: IterativeSolver(comm_), problem(nullptr), linear_solver(nullptr) { }
#endif
virtual ~ContactSolver() { }
/** This method is virtual as solvers might need to perform some initial
* actions (e.g., validation) with the ContactProblem. */
virtual void SetContactProblem(ContactProblem &prob)
{ problem = &prob; }
virtual void SetLinearSolver(ContactLinearSolver &lsolver)
{ linear_solver = &lsolver; }
/** This method performs the numerical solve of the complementarity
* problem. Potential implementations of this purely virtual method
* will be available via derived classes, e.g. implementations of
* Uzawa (Augmented Lagrangian), interior-point method, etc.
*
* [TODO: work around the two input parameters to pass the initial
* point and return the solution. Are there multivector vectors in
* MFEM?] */
///[TODO: clarify the const `Mult`;
virtual void Mult(const Vector &xt, Vector &x) const = 0;
virtual void SetPreconditioner(Solver &pr)
{ MFEM_ABORT("Not meaningful for this solver."); }
virtual void SetOperator(const Operator &op)
{ MFEM_ABORT("Not meaningful for this solver."); }
};
#if 0
// illustration of the contact nonlinear (outer) loop and interplay with
// linear solver and contact problem
void ContactSolverIPM::Mult(const Vector &xin, Vector &xout) const
{
x_iter.SetToZero();
s_iter.SetToZero();
l_iter.SetToZero();
R.SetToZero();
mu = 1.0;
int num_iter = 0;
//solve loop
while(true) {
//evaluate contact problem at x_iter
problem->GetRhs(f);
problem->EvalK(x_iter, K);
problem->EvalGradK(x_iter, GradK);
problem->Evalg(x_iter, g);
problem->EvalGradG(x_iter, gradG);
//evaluate residuals of the contact problem (illustration for IPM)
// rx = f + gradG^T l_iter - K
// rs = s - g
// rc = mu*ones(m,1) - l_iter .* s_iter
this->ComputeResiduals(rx, rs, rc);
//check residual norms, max # of iterations, etc.
if(this->StoppingCriteriaMet(num_iter, rx, rs, rc)) {
break;
}
num_iter++;
//
//set up linear system and solve to obtain search
//direction/step dx, ds, dl
//
//right hand side for linear system for the
// predictor step rc_pred = - l_iter .* s_iter
this->ComputePredictorResidual(rc_pred)
linear_solver->SetHessian(K);
linear_solver->SetGradG(gradG)
linear_solver->SetRhs(rx, rs, rc_pred);
linear_solver->SetLambda(l_iter);
linear_solver->SetS(s_iter);
linear_solver->SetPrimalReg(R);
linear_solver->Mult(dx, ds, dl);
//probably more like
//linear_solver->Mult(rx, rs, rc_pred, dx, ds, dl);
//was the linear solve successful?
while(!lin_sol_ok) {
this->ComputeRegularization(R);
linear_solver->SetPrimalReg(R);
linear_solver->Mult(dx, ds, dl);
//check linear solve ok
}
//uses x_iter, s_iter, l_iter, dx, ds, dl
double alpha = this->LineSearchBlocking();
//uses x_iter, s_iter, l_iter, dx, ds, dl, alpha;
double sigma = this->ComputeCenteringParameter(alpha);
//right hand side for linear system for the
// corrector step rc_pred = mu*sigma*ones(m,1) + ds.*dl - l_iter .* s_iter
//also uses s_iter, l_iter, ds, dl,
this->ComputeCorrectorResidual(mu, sigma, rc_corr);
linear_solver->SetRhs(rx, rs, rc_corr);
linear_solver->Mult(dx, ds, dl);
//was the linear solve successful?
while(!lin_sol_ok) {
this->ComputeRegularization(R);
linear_solver->SetPrimalReg(R);
linear_solver->Mult(dx, ds, dl);
//check linear solve ok
}
//uses x_iter, s_iter, l_iter, dx, ds, dl
double alpha_corr = this->LineSearchCorrector();
//x = x+alpha*dx s=s+alpha*ds l=l+alpha*dl
this->UpdateIter(alpha_corr);
} //end of contact loop
//return x_iter, s_iter, l_iter as the solution
//[TODO:]
}
#endif
#if 0
//illustration of the "main" driver
int main()
{
//dream big
//
mfem::ContactProblem* problem = new mfem::apps::ContactProblemMortar(/*mesh_files*/);
//this is curently doable
//mfem::ContactProblem* problem = new mfem::apps::ContactLinearProblemFromFiles(/*matrix_files*/);
//linear solver based on options
mfem::ContactLinearSolver* lin_solver = nullptr;
if(that) {
lin_solver = new mfem::ContactLinearSolverCondensed();
} else {
//testing
lin_solver = new mfem::ContactLinearSolverCondensendDirect();
}
mfem::ContactSolver* solver = new mfem::ContactSolverIPM();
solver->SetContactProblem(*problem);
solver->SetLinearSolver(*lin_solver);
solver->Mult();
//error control = ?
//[TODO: what does the interface(s) need to accomdate solving a sequence of (related) problems
//clean up
delete lin_solver;
delete problem;
}
#endif
/** Abstract linear solver for internal use in ContactSolver. Implementations
* of this class will solve linearizations of the contact problem in the form
* shown below. The unknowns are vectors dx, ds, and dlambda
*
* (H+R)dx - gradG^T dlambda = r1
* gradG dx - ds = r2
* Lambda ds + S dlambda = r3
*
* Above, H is an nxn symm. psd matrix, for example can be
* H = gradK(x)-\sum \lambda_i \nabla^2 g_i(x),
* or
* H = gradK(x),
* depending on the contact solver. gradG is an mxn matrix and Lambda and
* S are diagonal matrices with nonnegative entries. The regularization R
* is also a diagonal matrix with nonnegative entries.
*
*/
class ContactLinearSolver : public Solver
{
public:
// [TODO: better names?]
void SetHessian(const Operator &gradK);
void SetRhs(const Vector &r1, const Vector &r2, const Vector &r3);
void SetGradG(const Operator& gradG);
void SetLambda(const Vector& Lambda);
void SetS(const Vector& S);
void SetPrimalReg(const Vector& R);
//to be continued...
virtual void Mult(const Vector &x_in, Vector &x_out) const = 0;
protected:
};
/** Implementation of the contact linear solve in the form of
*
* (H + R + gradG^T S^{-1} Lambda gradG) dx =
* r1 + gradG^T S^{-1} (Lambda r2 + r3)
* ds = gradG dx - r2
* dlambda = -S^{-1} Lambda ds + S^{-1}r3
*
* Essentially, the solve is a Gauss elimination of the linearization
* described in ContactLinearSolver. The matrix from the first set
* of equations is generally symm. positive definite. The solve
* done by this class can/is allowed to fail, in which case the
* subsequent linear solve will be done with a "more" p.d. R.
* [TODO: ask about error control]
*
* This applies to both interior-point and Uzawa linearizations. To
* use this class with Uzawa, one needs to set S to the identity
* matrix and Lambda to a diagonal matrix having entry (i,i) equal to
* one when the corresponding gap is active (i.e., g_i(x)=0) or to
* zero otherwise, for all i=1,2,...,m. [TODO: what about r3?]
*
* The solver uses AMG [TODO: update me].
*/
class ContactLinearSolverCondensed : public ContactLinearSolver
{
public:
virtual void Mult(const Vector &dx_in, Vector &dx_out) const
{
MFEM_ASSERT(false, "to be implemented");
}
protected:
};
/** Implementation of the contact linear solve in the form of the
* general symmetric indefinite linear system shown above in the
* ContactLinearSolver class using direct linear solvers. This is
* mostly for testing and debugging purposes.
*
* [TODO: update me] Using a symmetric direct linear solver such
* as MA57, Pardiso, WSMP, etc. would do it. LU solvers OK.
*/
class ContactLinearSolverDirect : public ContactLinearSolver
{
public:
virtual void Mult(const Vector &x_in, Vector &x_out) const
{
MFEM_ASSERT(false, "to be implemented");
}
protected:
};
/** Implementation of the contact linear solve in the form of the
* symmetric p.d. linear system shown above in the
* ContactLinearSolverCondensed class using direct linear solvers.
* This is mostly for testing and debugging purposes.
*
* [TODO: update me] Using a Cholesky direct linear solver such
* as Cholmod would do it. LU or symmetric indefinite direct
* solvers OK.
*
*/
class ContactLinearSolverCondensendDirect : public ContactLinearSolverCondensed
{
public:
virtual void Mult(const Vector &x_in, Vector &x_out) const
{
MFEM_ASSERT(false, "to be implemented");
}
protected:
};
/** Block ILU solver:
* Performs a block ILU(k) approximate factorization with specified block
* size. Currently only k=0 is supported. This is useful as a preconditioner
+101 -17
View File
@@ -15,6 +15,7 @@
#include "../general/forall.hpp"
#include "../general/table.hpp"
#include "../general/sort_pairs.hpp"
#include "../general/backends.hpp"
#include <iostream>
#include <iomanip>
@@ -462,25 +463,108 @@ void SparseMatrix::SortColumnIndices()
return;
}
const int * Ip=HostReadI();
HostReadWriteJ();
HostReadWriteData();
Array<Pair<int,double> > row;
for (int j = 0, i = 0; i < height; i++)
#ifdef MFEM_USE_CUDA_OR_HIP
if ( Device::Allows( Backend::CUDA_MASK ))
{
int end = Ip[i+1];
row.SetSize(end - j);
for (int k = 0; k < row.Size(); k++)
#if defined(MFEM_USE_CUDA)
size_t pBufferSizeInBytes = 0;
void *pBuffer = NULL;
const int n = Height();
const int m = Width();
const int nnzA = J.Capacity();
double * d_a_sorted = ReadWriteData();
const int * d_ia = ReadI();
int * d_ja_sorted = ReadWriteJ();
csru2csrInfo_t sortInfoA;
cusparseMatDescr_t matA_descr;
cusparseCreateMatDescr( &matA_descr );
cusparseSetMatIndexBase( matA_descr, CUSPARSE_INDEX_BASE_ZERO );
cusparseSetMatType( matA_descr, CUSPARSE_MATRIX_TYPE_GENERAL );
cusparseCreateCsru2csrInfo( &sortInfoA );
cusparseDcsru2csr_bufferSizeExt( handle, n, m, nnzA, d_a_sorted, d_ia,
d_ja_sorted, sortInfoA,
&pBufferSizeInBytes);
CuMemAlloc( &pBuffer, pBufferSizeInBytes );
cusparseDcsru2csr( handle, n, m, nnzA, matA_descr, d_a_sorted, d_ia,
d_ja_sorted, sortInfoA, pBuffer);
cusparseDestroyCsru2csrInfo( sortInfoA );
cusparseDestroyMatDescr( matA_descr );
CuMemFree( pBuffer );
#endif
}
else if ( Device::Allows( Backend::HIP_MASK ))
{
#if defined(MFEM_USE_HIP)
size_t pBufferSizeInBytes = 0;
void *pBuffer = NULL;
int *P = NULL;
const int n = Height();
const int m = Width();
const int nnzA = J.Capacity();
double * d_a_sorted = ReadWriteData();
const int * d_ia = ReadI();
int * d_ja_sorted = ReadWriteJ();
hipsparseMatDescr_t descrA;
hipsparseCreateMatDescr( &descrA );
// FIXME: There is not in-place version of csr sort in hipSPARSE currently, so we make
// a temporary copy of the data for gthr, sort that, and then copy the sorted values
// back to the array being returned. Where there is an in-place version available,
// we should use it.
Array< double > a_tmp( nnzA );
double *d_a_tmp = a_tmp.Write();
hipsparseXcsrsort_bufferSizeExt(handle, n, m, nnzA, d_ia, d_ja_sorted,
&pBufferSizeInBytes);
HipMemAlloc( &pBuffer, pBufferSizeInBytes );
HipMemAlloc( (void**)&P, nnzA * sizeof(int) );
hipsparseCreateIdentityPermutation(handle, nnzA, P);
hipsparseXcsrsort(handle, n, m, nnzA, descrA, d_ia, d_ja_sorted, P, pBuffer);
hipsparseDgthr(handle, nnzA, d_a_sorted, d_a_tmp, P,
HIPSPARSE_INDEX_BASE_ZERO);
A.CopyFrom( a_tmp.GetMemory(), nnzA );
hipsparseDestroyMatDescr( descrA );
HipMemFree( pBuffer );
HipMemFree( P );
#endif
}
else
#endif // MFEM_USE_CUDA_OR_HIP
{
const int * Ip=HostReadI();
HostReadWriteJ();
HostReadWriteData();
Array<Pair<int,double> > row;
for (int j = 0, i = 0; i < height; i++)
{
row[k].one = J[j+k];
row[k].two = A[j+k];
}
row.Sort();
for (int k = 0; k < row.Size(); k++, j++)
{
J[j] = row[k].one;
A[j] = row[k].two;
int end = Ip[i+1];
row.SetSize(end - j);
for (int k = 0; k < row.Size(); k++)
{
row[k].one = J[j+k];
row[k].two = A[j+k];
}
row.Sort();
for (int k = 0; k < row.Size(); k++, j++)
{
J[j] = row[k].one;
A[j] = row[k].two;
}
}
}
isSorted = true;
+4
View File
@@ -23,7 +23,11 @@
#include "densemat.hpp"
#if defined(MFEM_USE_HIP)
#if (HIP_VERSION_MAJOR * 100 + HIP_VERSION_MINOR) < 502
#include <hipsparse.h>
#else
#include <hipsparse/hipsparse.h>
#endif
#endif
+8 -2
View File
@@ -56,7 +56,9 @@ STRUMPACKRowLocMatrix::STRUMPACKRowLocMatrix(const HypreParMatrix & hypParMat)
// Create the CSRMatrixMPI A_ by borrowing the internal data from a
// hypre_CSRMatrix.
hypParMat.HostRead();
hypre_CSRMatrix * csr_op = hypre_MergeDiagAndOffd(parcsr_op);
hypParMat.HypreRead();
hypre_CSRMatrixSetDataOwner(csr_op,0);
#if MFEM_HYPRE_VERSION >= 21600
// For now, this method assumes that HYPRE_Int is int. Also, csr_op->num_cols
@@ -201,8 +203,8 @@ void STRUMPACKSolver::Mult( const Vector & x, Vector & y ) const
MFEM_ASSERT(y.Size() == Height(), "invalid y.Size() = " << y.Size()
<< ", expected size = " << Height());
double* yPtr = (double*)y;
double* xPtr = (double*)(const_cast<Vector&>(x));
double* yPtr = y.HostWrite();
const double* xPtr = x.HostRead();
solver_->options().set_verbose( factor_verbose_ );
ReturnCode ret = solver_->factor();
@@ -219,6 +221,10 @@ void STRUMPACKSolver::Mult( const Vector & x, Vector & y ) const
MFEM_ABORT("STRUMPACK: Matrix reordering failed!");
}
break;
default:
{
MFEM_ABORT("STRUMPACK: 'factor()' error code = " << ret);
}
}
solver_->options().set_verbose( solve_verbose_ );
solver_->solve(xPtr, yPtr);
+2
View File
@@ -149,7 +149,9 @@ SuperLURowLocMatrix::SuperLURowLocMatrix( const HypreParMatrix & hypParMat )
// Create the SuperMatrix A by borrowing the internal data from a
// hypre_CSRMatrix.
hypParMat.HostRead();
hypre_CSRMatrix * csr_op = hypre_MergeDiagAndOffd(parcsr_op);
hypParMat.HypreRead();
hypre_CSRMatrixSetDataOwner(csr_op,0);
#if MFEM_HYPRE_VERSION >= 21600
// For now, this method assumes that HYPRE_BigInt is int. Also, csr_op->num_cols
+4 -13
View File
@@ -786,16 +786,13 @@ void Vector::Randomize(int seed)
{
const double max = (double)(RAND_MAX) + 1.;
if (!global_seed_set)
if (seed == 0)
{
if (seed == 0)
{
seed = (int)time(0);
}
srand((unsigned)seed);
seed = (int)time(0);
}
srand((unsigned)seed);
HostWrite();
for (int i = 0; i < size; i++)
{
@@ -803,12 +800,6 @@ void Vector::Randomize(int seed)
}
}
void Vector::SetGlobalSeed(int gseed)
{
srand((unsigned)gseed);
global_seed_set = true;
}
double Vector::Norml2() const
{
// Scale entries of Vector on the fly, using algorithms from
+33 -17
View File
@@ -63,7 +63,6 @@ protected:
Memory<double> data;
int size;
bool global_seed_set = false;
public:
@@ -209,15 +208,11 @@ public:
inline double *GetData() const
{ return const_cast<double*>((const double*)data); }
/// Conversion to `double *`.
/** @note This conversion function makes it possible to use [] for indexing
in addition to the overloaded operator()(int). */
inline operator double *() { return data; }
/// Conversion to `double *`. Deprecated.
MFEM_DEPRECATED inline operator double *() { return data; }
/// Conversion to `const double *`.
/** @note This conversion function makes it possible to use [] for indexing
in addition to the overloaded operator()(int). */
inline operator const double *() const { return data; }
/// Conversion to `const double *`. Deprecated.
MFEM_DEPRECATED inline operator const double *() const { return data; }
/// STL-like begin.
inline double *begin() { return data; }
@@ -269,6 +264,14 @@ public:
/** @note If MFEM_DEBUG is enabled, bounds checking is performed. */
inline const double &operator()(int i) const;
/// Access Vector entries using [] for 0-based indexing.
/** @note If MFEM_DEBUG is enabled, bounds checking is performed. */
inline double &operator[](int i) { return (*this)(i); }
/// Read only access to Vector entries using [] for 0-based indexing.
/** @note If MFEM_DEBUG is enabled, bounds checking is performed. */
inline const double &operator[](int i) const { return (*this)(i); }
/// Dot product with a `double *` array.
double operator*(const double *) const;
@@ -307,12 +310,6 @@ public:
Vector &operator+=(const Vector &v);
/// operator- is not supported. Use @ref subtract or @ref Add.
Vector &operator-(const Vector &v) = delete;
/// operator+ is not supported. Use @ref Add.
Vector &operator+(const Vector &v) = delete;
/// (*this) += a * Va
Vector &Add(const double a, const Vector &Va);
@@ -417,8 +414,6 @@ public:
/// Set random values in the vector.
void Randomize(int seed = 0);
/// Set global seed for random values in sequential calls to Randomize().
void SetGlobalSeed(int gseed);
/// Returns the l2 norm of the vector.
double Norml2() const;
/// Returns the l_infinity norm of the vector.
@@ -435,8 +430,12 @@ public:
double Sum() const;
/// Compute the square of the Euclidean distance to another vector.
inline double DistanceSquaredTo(const double *p) const;
/// Compute the square of the Euclidean distance to another vector.
inline double DistanceSquaredTo(const Vector &p) const;
/// Compute the Euclidean distance to another vector.
inline double DistanceTo(const double *p) const;
/// Compute the Euclidean distance to another vector.
inline double DistanceTo(const Vector &p) const;
/** @brief Count the number of entries in the Vector for which isfinite
is false, i.e. the entry is a NaN or +/-Inf. */
@@ -646,16 +645,33 @@ inline double Distance(const double *x, const double *y, const int n)
return std::sqrt(DistanceSquared(x, y, n));
}
inline double Distance(const Vector &x, const Vector &y)
{
return x.DistanceTo(y);
}
inline double Vector::DistanceSquaredTo(const double *p) const
{
return DistanceSquared(data, p, size);
}
inline double Vector::DistanceSquaredTo(const Vector &p) const
{
MFEM_ASSERT(p.Size() == Size(), "Incompatible vector sizes.");
return DistanceSquared(data, p.data, size);
}
inline double Vector::DistanceTo(const double *p) const
{
return Distance(data, p, size);
}
inline double Vector::DistanceTo(const Vector &p) const
{
MFEM_ASSERT(p.Size() == Size(), "Incompatible vector sizes.");
return Distance(data, p.data, size);
}
/// Returns the inner product of x and y
/** In parallel this computes the inner product of the local vectors,
producing different results on each MPI rank.
+4 -4
View File
@@ -10,7 +10,7 @@
# CONTRIBUTING.md for details.
# The current MFEM version as an integer, see also `CMakeLists.txt`.
MFEM_VERSION = 40500
MFEM_VERSION = 40501
MFEM_VERSION_STRING = $(shell printf "%06d" $(MFEM_VERSION) | \
sed -e 's/^0*\(.*.\)\(..\)\(..\)$$/\1.\2.\3/' -e 's/\.0/./g' -e 's/\.0$$//')
@@ -275,7 +275,7 @@ endif
# List of MFEM dependencies, that require the *_LIB variable to be non-empty
MFEM_REQ_LIB_DEPS = ENZYME SUPERLU MUMPS METIS FMS CONDUIT SIDRE LAPACK SUNDIALS\
MESQUITE SUITESPARSE STRUMPACK GINKGO GNUTLS NETCDF PETSC SLEPC MPFR PUMI HIOP\
SUITESPARSE STRUMPACK GINKGO GNUTLS NETCDF PETSC SLEPC MPFR PUMI HIOP\
GSLIB OCCA CEED RAJA UMPIRE MKL_CPARDISO AMGX CALIPER PARELAG BENCHMARK\
MOONOLITH ALGOIM
@@ -338,7 +338,7 @@ MFEM_DEFINES = MFEM_VERSION MFEM_VERSION_STRING MFEM_GIT_STRING MFEM_USE_MPI\
MFEM_USE_METIS MFEM_USE_METIS_5 MFEM_DEBUG MFEM_USE_EXCEPTIONS MFEM_USE_ZLIB\
MFEM_USE_LIBUNWIND MFEM_USE_LAPACK MFEM_THREAD_SAFE MFEM_USE_OPENMP\
MFEM_USE_LEGACY_OPENMP MFEM_USE_MEMALLOC MFEM_TIMER_TYPE MFEM_USE_SUNDIALS\
MFEM_USE_MESQUITE MFEM_USE_SUITESPARSE MFEM_USE_GINKGO MFEM_USE_SUPERLU\
MFEM_USE_SUITESPARSE MFEM_USE_GINKGO MFEM_USE_SUPERLU MFEM_USE_SUPERLU5\
MFEM_USE_STRUMPACK MFEM_USE_GNUTLS MFEM_USE_NETCDF MFEM_USE_PETSC\
MFEM_USE_SLEPC MFEM_USE_MPFR MFEM_USE_SIDRE MFEM_USE_FMS MFEM_USE_CONDUIT\
MFEM_USE_PUMI MFEM_USE_HIOP MFEM_USE_GSLIB MFEM_USE_CUDA MFEM_USE_HIP\
@@ -673,9 +673,9 @@ status info:
$(info MFEM_USE_MEMALLOC = $(MFEM_USE_MEMALLOC))
$(info MFEM_TIMER_TYPE = $(MFEM_TIMER_TYPE))
$(info MFEM_USE_SUNDIALS = $(MFEM_USE_SUNDIALS))
$(info MFEM_USE_MESQUITE = $(MFEM_USE_MESQUITE))
$(info MFEM_USE_SUITESPARSE = $(MFEM_USE_SUITESPARSE))
$(info MFEM_USE_SUPERLU = $(MFEM_USE_SUPERLU))
$(info MFEM_USE_SUPERLU5 = $(MFEM_USE_SUPERLU5))
$(info MFEM_USE_MUMPS = $(MFEM_USE_MUMPS))
$(info MFEM_USE_STRUMPACK = $(MFEM_USE_STRUMPACK))
$(info MFEM_USE_GINKGO = $(MFEM_USE_GINKGO))
-7
View File
@@ -72,13 +72,6 @@ if (MFEM_USE_MPI)
submesh/psubmesh.hpp)
endif()
if (MFEM_USE_MESQUITE)
list(APPEND SRCS mesquite.cpp)
# If this list (HDRS -> HEADERS) is used for install, we probably want the
# header added all the time.
list(APPEND HDRS mesquite.hpp)
endif()
if (MFEM_USE_PUMI)
list(APPEND SRCS
pumi.cpp)
+25 -3
View File
@@ -1627,6 +1627,13 @@ int Mesh::AddVertex(const double *coords)
return NumOfVertices++;
}
int Mesh::AddVertex(const Vector &coords)
{
MFEM_ASSERT(coords.Size() >= spaceDim,
"invalid 'coords' size: " << coords.Size());
return AddVertex(coords.GetData());
}
void Mesh::AddVertexParents(int i, int p1, int p2)
{
tmp_vertex_parents.Append(Triple<int, int, int>(i, p1, p2));
@@ -7025,6 +7032,11 @@ int *Mesh::CartesianPartitioning(int nxyz[])
return partitioning;
}
void FindPartitioningComponents(Table &elem_elem,
const Array<int> &partitioning,
Array<int> &component,
Array<int> &num_comp);
int *Mesh::GeneratePartitioning(int nparts, int part_method)
{
#ifdef MFEM_USE_METIS
@@ -7106,6 +7118,15 @@ int *Mesh::GeneratePartitioning(int nparts, int part_method)
#else
METIS_SetDefaultOptions(options);
options[METIS_OPTION_CONTIG] = 1; // set METIS_OPTION_CONTIG
// If the mesh is disconnected, disable METIS_OPTION_CONTIG.
{
Array<int> part(partitioning, NumOfElements);
part = 0; // single part for the whole mesh
Array<int> component; // size will be set to num. elem.
Array<int> num_comp; // size will be set to num. parts (1)
FindPartitioningComponents(*el_to_el, part, component, num_comp);
if (num_comp[0] > 1) { options[METIS_OPTION_CONTIG] = 0; }
}
#endif
// Sort the neighbor lists
@@ -10504,8 +10525,8 @@ void Mesh::PrintVTU(std::ostream &os, int ref, VTKFormat format,
};
int ne = bdr_elements ? GetNBE() : GetNE();
// count the points, cells, size
int np = 0, nc_ref = 0, size = 0;
// count the number of points and cells
int np = 0, nc_ref = 0;
for (int i = 0; i < ne; i++)
{
Geometry::Type geom = get_geom(i);
@@ -10513,7 +10534,6 @@ void Mesh::PrintVTU(std::ostream &os, int ref, VTKFormat format,
RefG = GlobGeometryRefiner.Refine(geom, ref, 1);
np += RefG->RefPts.GetNPoints();
nc_ref += RefG->RefGeoms.Size() / nv;
size += (RefG->RefGeoms.Size() / nv) * (nv + 1);
}
os << "<Piece NumberOfPoints=\"" << np << "\" NumberOfCells=\""
@@ -11636,6 +11656,7 @@ void Mesh::Transform(void (*f)(const Vector&, Vector&))
xnew.ProjectCoefficient(f_pert);
*Nodes = xnew;
}
NodesUpdated();
}
void Mesh::Transform(VectorCoefficient &deformation)
@@ -11660,6 +11681,7 @@ void Mesh::Transform(VectorCoefficient &deformation)
xnew.ProjectCoefficient(deformation);
*Nodes = xnew;
}
NodesUpdated();
}
void Mesh::RemoveUnusedVertices()
+59 -22
View File
@@ -272,8 +272,8 @@ public:
NURBSExtension *NURBSext; ///< Optional NURBS mesh extension.
NCMesh *ncmesh; ///< Optional nonconforming mesh extension.
Array<GeometricFactors*> geom_factors; ///< Optional geometric factors.
Array<FaceGeometricFactors*>
face_geom_factors; ///< Optional face geometric factors.
Array<FaceGeometricFactors*> face_geom_factors; /**< Optional face geometric
factors. */
// Global parameter that can be used to control the removal of unused
// vertices performed when reading a mesh in MFEM format. The default value
@@ -380,7 +380,14 @@ protected:
void InitRefinementTransforms();
int FindCoarseElement(int i);
/// Update the nodes of a curved mesh after refinement
/** @brief Update the nodes of a curved mesh after the topological part of a
Mesh::Operation, such as refinement, has been performed. */
/** If Nodes GridFunction is defined, i.e. not NULL, this method calls
NodesUpdated().
@note Unlike the similarly named public method NodesUpdated() this
method modifies the mesh nodes (if they exist) and calls NodesUpdated().
*/
void UpdateNodes();
/// Helper to set vertex coordinates given a high-order curvature function.
@@ -705,6 +712,7 @@ public:
int AddVertex(double x, double y = 0.0, double z = 0.0);
int AddVertex(const double *coords);
int AddVertex(const Vector &coords);
/// Mark vertex @a i as nonconforming, with parent vertices @a p1 and @a p2.
void AddVertexParents(int i, int p1, int p2);
@@ -964,10 +972,19 @@ public:
The IntegrationRule used with GetGeometricFactors needs to remain valid
until the internally stored GeometricFactors objects are destroyed (by
either calling Mesh::DeleteGeometricFactors or the Mesh destructor). If
the device MemoryType parameter @a d_mt is specified, then the returned
object will use that type unless it was previously allocated with a
different type. */
calling Mesh::DeleteGeometricFactors(), Mesh::NodesUpdated(), or the Mesh
destructor).
If the device MemoryType parameter @a d_mt is specified, then the
returned object will use that type unless it was previously allocated
with a different type.
The returned pointer points to an internal object that may be invalidated
by mesh operations such as refinement, vertex/node movement, etc. Since
not all such modifications can be tracked by the Mesh class (e.g. when
using the pointer returned by GetNodes() to change the nodes) one needs
to account for such changes by calling the method NodesUpdated() which,
in particular, will call DeleteGeometricFactors(). */
const GeometricFactors* GetGeometricFactors(
const IntegrationRule& ir,
const int flags,
@@ -978,22 +995,41 @@ public:
The IntegrationRule used with GetFaceGeometricFactors needs to remain
valid until the internally stored FaceGeometricFactors objects are
destroyed (by either calling Mesh::DeleteGeometricFactors or the Mesh
destructor). */
const FaceGeometricFactors* GetFaceGeometricFactors(const IntegrationRule& ir,
const int flags,
FaceType type,
MemoryType d_mt = MemoryType::DEFAULT);
destroyed (by either calling Mesh::DeleteGeometricFactors(),
Mesh::NodesUpdated(), or the Mesh destructor).
If the device MemoryType parameter @a d_mt is specified, then the
returned object will use that type unless it was previously allocated
with a different type.
The returned pointer points to an internal object that may be invalidated
by mesh operations such as refinement, vertex/node movement, etc. Since
not all such modifications can be tracked by the Mesh class (e.g. when
using the pointer returned by GetNodes() to change the nodes) one needs
to account for such changes by calling the method NodesUpdated() which,
in particular, will call DeleteGeometricFactors(). */
const FaceGeometricFactors* GetFaceGeometricFactors(
const IntegrationRule& ir,
const int flags,
FaceType type,
MemoryType d_mt = MemoryType::DEFAULT);
/// Destroy all GeometricFactors stored by the Mesh.
/** This method can be used to force recomputation of the GeometricFactors,
for example, after the mesh nodes are modified externally. */
for example, after the mesh nodes are modified externally.
@note In general, the preferred method for resetting the GeometricFactors
should be to call NodesUpdated(). */
void DeleteGeometricFactors();
/// @brief This function should be called after the mesh node coordinates
/// have changed, e.g. after the mesh has moved.
/** It updates internal quantities derived from the node coordinates, such
as the GeometricFactors. */
/** @brief This function should be called after the mesh node coordinates
have been updated externally, e.g. by modifying the internal nodal
GridFunction returned by GetNodes(). */
/** It deletes internal quantities derived from the node coordinates,
such as the (Face)GeometricFactors.
@note Unlike the similarly named protected method UpdateNodes() this
method does not modify the nodes. */
void NodesUpdated() { DeleteGeometricFactors(); }
/// Equals 1 + num_holes - num_loops
@@ -1535,6 +1571,7 @@ public:
// mesh is not curved (i.e. Nodes == NULL).
void MoveNodes(const Vector &displacements);
void GetNodes(Vector &node_coord) const;
/// Updates the vertex/node locations. Invokes NodesUpdated().
void SetNodes(const Vector &node_coord);
/// Return a pointer to the internal node GridFunction (may be NULL).
@@ -1545,9 +1582,11 @@ public:
/// Set the mesh nodes ownership flag.
void SetNodesOwner(bool nodes_owner) { own_nodes = nodes_owner; }
/// Replace the internal node GridFunction with the given GridFunction.
/** Invokes NodesUpdated(). */
void NewNodes(GridFunction &nodes, bool make_owner = false);
/** Swap the internal node GridFunction pointer and ownership flag members
with the given ones. */
/** @brief Swap the internal node GridFunction pointer and ownership flag
members with the given ones. */
/** Invokes NodesUpdated(). */
void SwapNodes(GridFunction *&nodes, int &own_nodes_);
/// Return the mesh nodes/vertices projected on the given GridFunction.
@@ -1783,8 +1822,6 @@ public:
PrintCharacteristics(NULL, NULL, os);
}
void MesquiteSmooth(const int mesquite_option = 0);
/** @brief Find the ids of the elements that contain the given points, and
their corresponding reference coordinates.
-4
View File
@@ -33,10 +33,6 @@
#include "wedge.hpp"
#include "pyramid.hpp"
#ifdef MFEM_USE_MESQUITE
#include "mesquite.hpp"
#endif
#ifdef MFEM_USE_MPI
#include "pncmesh.hpp"
#include "pmesh.hpp"
+9 -8
View File
@@ -2851,9 +2851,10 @@ void Mesh::ReadCubit(const char *filename, int &curved, int &read_gf)
int retval;
// dummy string
char str_dummy[256];
constexpr size_t buf_size = 256;
char str_dummy[buf_size];
char temp_str[256];
char temp_str[buf_size];
int temp_id;
// open the file.
@@ -2897,14 +2898,14 @@ void Mesh::ReadCubit(const char *filename, int &curved, int &read_gf)
int previous_num_node_per_el = 0;
for (int i = 0; i < (int) num_el_blk; i++)
{
sprintf(temp_str, "num_el_in_blk%d", i+1);
snprintf(temp_str, buf_size, "num_el_in_blk%d", i+1);
if ((retval = nc_inq_dimid(ncid, temp_str, &temp_id)) ||
(retval = nc_inq_dim(ncid, temp_id, str_dummy, &num_el_in_blk[i])))
{
MFEM_ABORT("Fatal NetCDF error: " << nc_strerror(retval));
}
sprintf(temp_str, "num_nod_per_el%d", i+1);
snprintf(temp_str, buf_size, "num_nod_per_el%d", i+1);
if ((retval = nc_inq_dimid(ncid, temp_str, &temp_id)) ||
(retval = nc_inq_dim(ncid, temp_id, str_dummy, &num_node_per_el)))
{
@@ -3051,7 +3052,7 @@ void Mesh::ReadCubit(const char *filename, int &curved, int &read_gf)
size_t *num_side_in_ss = new size_t[num_side_sets];
for (int i = 0; i < (int) num_side_sets; i++)
{
sprintf(temp_str, "num_side_ss%d", i+1);
snprintf(temp_str, buf_size, "num_side_ss%d", i+1);
if ((retval = nc_inq_dimid(ncid, temp_str, &temp_id)) ||
(retval = nc_inq_dim(ncid, temp_id, str_dummy, &num_side_in_ss[i])))
{
@@ -3086,7 +3087,7 @@ void Mesh::ReadCubit(const char *filename, int &curved, int &read_gf)
for (int i = 0; i < (int) num_el_blk; i++)
{
elem_blk[i] = new int[num_el_in_blk[i] * num_node_per_el];
sprintf(temp_str, "connect%d", i+1);
snprintf(temp_str, buf_size, "connect%d", i+1);
if ((retval = nc_inq_varid(ncid, temp_str, &temp_id)) ||
(retval = nc_get_var_int(ncid, temp_id, elem_blk[i])))
{
@@ -3110,14 +3111,14 @@ void Mesh::ReadCubit(const char *filename, int &curved, int &read_gf)
elem_ss[i] = new int[num_side_in_ss[i]];
side_ss[i] = new int[num_side_in_ss[i]];
sprintf(temp_str, "elem_ss%d", i+1);
snprintf(temp_str, buf_size, "elem_ss%d", i+1);
if ((retval = nc_inq_varid(ncid, temp_str, &temp_id)) ||
(retval = nc_get_var_int(ncid, temp_id, elem_ss[i])))
{
MFEM_ABORT("Fatal NetCDF error: " << nc_strerror(retval));
}
sprintf(temp_str,"side_ss%d",i+1);
snprintf(temp_str, buf_size,"side_ss%d",i+1);
if ((retval = nc_inq_varid(ncid, temp_str, &temp_id)) ||
(retval = nc_get_var_int(ncid, temp_id, side_ss[i])))
{
-1189
View File
File diff suppressed because it is too large Load Diff
-358
View File
@@ -1,358 +0,0 @@
// Copyright (c) 2010-2022, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifndef MFEM_MESQUITE
#define MFEM_MESQUITE
#include "../config/config.hpp"
#ifdef MFEM_USE_MESQUITE
#include "mesh.hpp"
#include "Mesquite_all_headers.hpp"
namespace mfem
{
using namespace Mesquite;
class MesquiteMesh : public Mesquite::Mesh
{
// tagging interface definition
private:
struct MfemTagDescription
{
std::string name; //!< Tag name
Mesh::TagType type; //!< Tag data type
size_t size; //!< Size of tag data (sizeof(type)*array_length)
inline MfemTagDescription( std::string n,
Mesh::TagType t,
size_t s)
: name(n), type(t), size(s) {}
inline MfemTagDescription( )
: type(Mesh::BYTE), size(0) {}
inline bool operator==(const MfemTagDescription& o) const
{ return name == o.name && type == o.type && size == o.size; }
inline bool operator!=(const MfemTagDescription& o) const
{ return name != o.name || type != o.type || size != o.size; }
};
/**\class MeshTags
*
* Store tags and tag data for MFEM's mesh representation.
* Stores for each tag: properties, element data, and vertex data.
* The tag element and vertex data sets are maps between some element
* or vertex index and a tag value.
*/
class MeshTags
{
public:
~MeshTags() { clear(); }
/** \class TagData
* Store data for a single tag
*/
struct TagData
{
//! tag meta data
const MfemTagDescription desc;
//! per-element data, or NULL if none has been set.
void* elementData;
//! number of entries in elementData
size_t elementCount;
//! per-vertex data, or NULL if none has been set.
void* vertexData;
//! number of entries in vertexData
size_t vertexCount;
//! Default value for tag
void* defaultValue;
/** \brief Construct tag
*\param name Tag name
*\param type Tag data type
*\param length Tag array length (1 for scalar/non-array)
*\param default_val Default value for tag
*/
inline TagData( const std::string& name,
Mesh::TagType type, unsigned length,
void* default_val = 0)
: desc(name, type, length*size_from_tag_type(type)),
elementData(0), elementCount(0),
vertexData(0), vertexCount(0),
defaultValue(default_val) {}
/** \brief Construct tag
*\param descr Tag description object
*/
inline TagData( const MfemTagDescription& descr )
: desc(descr), elementData(0), elementCount(0),
vertexData(0), vertexCount(0),
defaultValue(0) {}
~TagData();
};
/** \brief Get the size of the passed data type */
static size_t size_from_tag_type( Mesh::TagType type );
/** \brief Clear all data */
void clear();
/** \brief Get tag index from name */
size_t handle( const std::string& name, MsqError& err ) const;
/** \brief Get tag properties */
const MfemTagDescription& properties( size_t tag_handle, MsqError& err ) const;
/** \brief Create a new tag
*
* Create a new tag with the passed properties
*\param name Tag name (must be unique)
*\param type Tag data type
*\param length Number of values in tag (array length, 1 for scalar)
*\param defval Optional default value for tag
*/
size_t create( const std::string& name,
Mesh::TagType type,
unsigned length,
const void* defval,
MsqError& err );
/** \brief Create a new tag
*
* Create a new tag with the passed properties
*/
size_t create( const MfemTagDescription& desc,
const void* defval,
MsqError& err );
/**\brief Remove a tag */
void destroy( size_t tag_index, MsqError& err );
/**\brief Set tag data on elements */
void set_element_data( size_t tag_handle,
size_t num_indices,
const size_t* elem_indices,
const void* tag_data,
MsqError& err );
/**\brief Set tag data on vertices */
void set_vertex_data( size_t tag_handle,
size_t num_indices,
const size_t* elem_indices,
const void* tag_data,
MsqError& err );
/**\brief Get tag data on elements */
void get_element_data( size_t tag_handle,
size_t num_indices,
const size_t* elem_indices,
void* tag_data,
MsqError& err ) const;
/**\brief Get tag data on vertices */
void get_vertex_data( size_t tag_handle,
size_t num_indices,
const size_t* elem_indices,
void* tag_data,
MsqError& err ) const;
/**\class TagIterator
*
* Iterate over list of valid tag handles
*/
class TagIterator
{
public:
TagIterator() : tags(0), index(0) {}
TagIterator( MeshTags* d, size_t i ) : tags(d), index(i) {}
size_t operator*() const { return index+1; }
TagIterator operator++();
TagIterator operator--();
TagIterator operator++(int);
TagIterator operator--(int);
bool operator==(TagIterator other) const { return index == other.index; }
bool operator!=(TagIterator other) const { return index != other.index; }
private:
MeshTags* tags;
size_t index;
};
TagIterator tag_begin();
TagIterator tag_end() { return TagIterator(this,tagList.size()); }
/**\brief Check if any vertices have tag */
bool tag_has_vertex_data( size_t index, MsqError& err ) ;
/**\brief Check if any elements have tag */
bool tag_has_element_data( size_t index, MsqError& err ) ;
private:
friend class MeshTags::TagIterator;
std::vector<TagData*> tagList;
}; // class MeshTags
// data members
private:
int ndofs; // number of nodes (or vertices) in mesh
int nelems; // number of elements in mesh
mfem::Mesh *mesh; // pointer to mfem mesh object
mfem::Element *elem; // pointer to mfem element object
mfem::GridFunction *nodes; // pointer to mfem grid function object
// for nodes
mfem::FiniteElementSpace *fes; // pointer to mfem finite element
// space object
mfem::Table *dof_elem; // dof to element table
std::vector<char> mByte; // length = ndofs
std::vector<bool> mFixed; // length = ndofs
MeshTags* myTags;
public:
// The constructor
MesquiteMesh(mfem::Mesh *mfem_mesh);
// The mesh dimension
int get_geometric_dimension(MsqError &err);
// The handles are just pointers to the indexes of the nodes/elements
void get_all_elements(std::vector<ElementHandle>& elements,
MsqError& err );
void get_all_vertices(std::vector<VertexHandle>& vertices,
MsqError& err );
// Get/set vertex coordinates
void vertices_get_coordinates(const VertexHandle vert_array[],
MsqVertex* coordinates,
size_t num_vtx,
MsqError &err );
void vertex_set_coordinates(VertexHandle vertex,
const Vector3D &coordinates,
MsqError &err );
// These are internal markers for Mesquite that we should allocate for them
void vertex_set_byte(VertexHandle vertex,
unsigned char byte,
MsqError &err);
void vertices_set_byte(const VertexHandle *vert_array,
const unsigned char *byte_array,
size_t array_size,
MsqError &err );
void vertices_get_fixed_flag(const VertexHandle vert_array[],
std::vector<bool>& fixed_flag_array,
size_t num_vtx,
MsqError &err );
void vertices_set_fixed_flag(const VertexHandle vert_array[],
const std::vector< bool > &fixed_flag_array,
size_t num_vtx,
MsqError &err );
void vertex_get_byte( const VertexHandle vertex,
unsigned char *byte,
MsqError &err );
void vertices_get_byte( const VertexHandle *vertex,
unsigned char *byte_array,
size_t array_size,
MsqError &err );
// The dof_elem table
void vertices_get_attached_elements(const VertexHandle* vertex_array,
size_t num_vertex,
std::vector<ElementHandle>& elements,
std::vector<size_t>& offsets,
MsqError& err );
// The elem_dof table
void elements_get_attached_vertices(const ElementHandle *elem_handles,
size_t num_elems,
std::vector<VertexHandle>& vert_handles,
std::vector<size_t>& offsets,
MsqError &err);
// The topology of the elements: tri/tet/quad/hex...
void elements_get_topologies(const ElementHandle *element_handle_array,
EntityTopology *element_topologies,
size_t num_elements,
MsqError &err);
// The destructor
~MesquiteMesh();
// tag the attributes on the elements from the underlying mfem mesh
void tag_attributes();
// Clean these up .....
void vertices_get_slaved_flag( const VertexHandle vert_array[],
std::vector<bool>& slaved_flag_array,
size_t num_vtx,
MsqError &err ) {};
TagHandle tag_create( const std::string& tag_name,
TagType type, unsigned length,
const void* default_value,
MsqError &err);
void tag_delete( TagHandle handle, MsqError& err );
TagHandle tag_get( const std::string& name,
MsqError& err );
void tag_properties( TagHandle handle,
std::string& name_out,
TagType& type_out,
unsigned& length_out,
MsqError& err );
void tag_set_element_data( TagHandle handle,
size_t num_elems,
const ElementHandle* elem_array,
const void* tag_data,
MsqError& err );
void tag_set_vertex_data ( TagHandle handle,
size_t num_elems,
const VertexHandle* node_array,
const void* tag_data,
MsqError& err );
void tag_get_element_data( TagHandle handle,
size_t num_elems,
const ElementHandle* elem_array,
void* tag_data,
MsqError& err );
void tag_get_vertex_data ( TagHandle handle,
size_t num_elems,
const VertexHandle* node_array,
void* tag_data,
MsqError& err );
void release_entity_handles(const EntityHandle *handle_array,
size_t num_handles,
MsqError &err) {};
void release() {};
};
}
#endif
#endif
+257 -49
View File
@@ -33,10 +33,11 @@ void NCMesh::GeomInfo::InitGeom(Geometry::Type geom)
{
case Geometry::CUBE: elem = new Hexahedron; break;
case Geometry::PRISM: elem = new Wedge; break;
case Geometry::SQUARE: elem = new Quadrilateral; break;
case Geometry::SEGMENT: elem = new Segment; break;
case Geometry::TRIANGLE: elem = new Triangle; break;
case Geometry::TETRAHEDRON: elem = new Tetrahedron; break;
case Geometry::PYRAMID: elem = new Pyramid; break;
case Geometry::SQUARE: elem = new Quadrilateral; break;
case Geometry::TRIANGLE: elem = new Triangle; break;
case Geometry::SEGMENT: elem = new Segment; break;
default: MFEM_ABORT("unsupported geometry " << geom);
}
@@ -62,7 +63,7 @@ void NCMesh::GeomInfo::InitGeom(Geometry::Type geom)
}
}
// in 1D & 2D we pretend to have faces too, so we can use NCMesh::Face::elem[2]
// in 1D/2D we pretend to have faces too, so we can use NCMesh::Face::elem[2]
if (!nf)
{
if (ne)
@@ -97,7 +98,7 @@ static void CheckSupportedGeom(Geometry::Type geom)
MFEM_VERIFY(geom == Geometry::SEGMENT ||
geom == Geometry::TRIANGLE || geom == Geometry::SQUARE ||
geom == Geometry::CUBE || geom == Geometry::PRISM ||
geom == Geometry::TETRAHEDRON,
geom == Geometry::PYRAMID || geom == Geometry::TETRAHEDRON,
"Element type " << geom << " is not supported by NCMesh.");
}
@@ -119,6 +120,12 @@ NCMesh::NCMesh(const Mesh *mesh)
CheckSupportedGeom(geom);
GI[geom].InitGeom(geom);
// if we have pyramids we will need tets after refinement
if (geom == Geometry::PYRAMID)
{
GI[Geometry::TETRAHEDRON].InitGeom(Geometry::TETRAHEDRON);
}
// create NCMesh::Element for this mfem::Element
int root_id = AddElement(Element(geom, elem->GetAttribute()));
MFEM_ASSERT(root_id == i, "");
@@ -454,9 +461,10 @@ NCMesh::Element::Element(Geometry::Type geom, int attr)
: geom(geom), ref_type(0), tet_type(0), flag(0), index(-1)
, rank(0), attribute(attr), parent(-1)
{
for (int i = 0; i < 8; i++) { node[i] = -1; }
for (int i = 0; i < MaxElemNodes; i++) { node[i] = -1; }
for (int i = 0; i < MaxElemChildren; i++) { child[i] = -1; }
// NOTE: in 2D the 8-element node/child arrays are not optimal, however,
// NOTE: in 2D the 8/10-element node/child arrays are not optimal, however,
// testing shows we would only save 17% of the total NCMesh memory if
// 4-element arrays were used (e.g. through templates); we thus prefer to
// keep the code as simple as possible.
@@ -476,7 +484,7 @@ int NCMesh::NewHexahedron(int n0, int n1, int n2, int n3,
el.node[4] = n4, el.node[5] = n5, el.node[6] = n6, el.node[7] = n7;
// get faces and assign face attributes
Face* f[6];
Face* f[MaxElemFaces];
const GeomInfo &gi_hex = GI[Geometry::CUBE];
for (int i = 0; i < gi_hex.nf; i++)
{
@@ -549,6 +557,35 @@ int NCMesh::NewTetrahedron(int n0, int n1, int n2, int n3, int attr,
return new_id;
}
int NCMesh::NewPyramid(int n0, int n1, int n2, int n3, int n4, int attr,
int fattr0, int fattr1, int fattr2, int fattr3,
int fattr4)
{
// create new element, initialize nodes
int new_id = AddElement(Element(Geometry::PYRAMID, attr));
Element &el = elements[new_id];
el.node[0] = n0, el.node[1] = n1, el.node[2] = n2, el.node[3] = n3;
el.node[4] = n4;
// get faces and assign face attributes
Face* f[5];
const GeomInfo &gi_pyr = GI[Geometry::PYRAMID];
for (int i = 0; i < gi_pyr.nf; i++)
{
const int* fv = gi_pyr.faces[i];
f[i] = faces.Get(el.node[fv[0]], el.node[fv[1]],
el.node[fv[2]], el.node[fv[3]]);
}
f[0]->attribute = fattr0;
f[1]->attribute = fattr1;
f[2]->attribute = fattr2;
f[3]->attribute = fattr3;
f[4]->attribute = fattr4;
return new_id;
}
int NCMesh::NewQuadrilateral(int n0, int n1, int n2, int n3,
int attr,
@@ -895,7 +932,7 @@ void NCMesh::RefineElement(int elem, char ref_type)
char remaining = ref_type & ~el.ref_type;
// do the remaining splits on the children
for (int i = 0; i < 8; i++)
for (int i = 0; i < MaxElemChildren; i++)
{
if (el.child[i] >= 0) { RefineElement(el.child[i], remaining); }
}
@@ -912,11 +949,11 @@ void NCMesh::RefineElement(int elem, char ref_type)
int* no = el.node;
int attr = el.attribute;
int child[8];
for (int i = 0; i < 8; i++) { child[i] = -1; }
int child[MaxElemChildren];
for (int i = 0; i < MaxElemChildren; i++) { child[i] = -1; }
// get parent's face attributes
int fa[6];
int fa[MaxElemFaces];
GeomInfo& gi = GI[el.Geom()];
for (int i = 0; i < gi.nf; i++)
{
@@ -1404,6 +1441,65 @@ void NCMesh::RefineElement(int elem, char ref_type)
-1, -1, fa[3], -1);
}
}
else if (el.Geom() == Geometry::PYRAMID)
{
// Pyramid vertex numbering:
//
// 4
// + \_ Faces: 0 bottom (3,2,1,0)
// |\\_ \_ 1 front (0, 1, 4)
// || \_ \__ 2 right (1, 2, 4)
// | \ \_ \__ 3 back (2, 3, 4)
// | +____\_ ____\ 4 left (3, 0, 4)
// | /3 \_ 2 Z Y
// |/ \ / | /
// +------------+ *--X
// 0 1
ref_type = Refinement::XYZ; // for consistence
int mid01 = GetMidEdgeNode(no[0], no[1]);
int mid12 = GetMidEdgeNode(no[1], no[2]);
int mid23 = GetMidEdgeNode(no[2], no[3]);
int mid03 = GetMidEdgeNode(no[0], no[3]);
int mid04 = GetMidEdgeNode(no[0], no[4]);
int mid14 = GetMidEdgeNode(no[1], no[4]);
int mid24 = GetMidEdgeNode(no[2], no[4]);
int mid34 = GetMidEdgeNode(no[3], no[4]);
int midf0 = GetMidFaceNode(mid23, mid12, mid01, mid03);
child[0] = NewPyramid(no[0], mid01, midf0, mid03, mid04,
attr, fa[0], fa[1], -1, -1, fa[4]);
child[1] = NewPyramid(mid01, no[1], mid12, midf0, mid14,
attr, fa[0], fa[1], fa[2], -1, -1);
child[2] = NewPyramid(midf0, mid12, no[2], mid23, mid24,
attr, fa[0], -1, fa[2], fa[3], -1);
child[3] = NewPyramid(mid03, midf0, mid23, no[3], mid34,
attr, fa[0], -1, -1, fa[3], fa[4]);
child[4] = NewPyramid(mid24, mid14, mid04, mid34, midf0,
attr, -1, -1, -1, -1, -1);
child[5] = NewPyramid(mid04, mid14, mid24, mid34, no[4],
attr, -1, fa[1], fa[2], fa[3], fa[4]);
child[6] = NewTetrahedron(mid01, midf0, mid04, mid14,
attr, -1, -1, -1, fa[1]);
child[7] = NewTetrahedron(midf0, mid14, mid12, mid24,
attr, -1, -1, fa[2], -1);
child[8] = NewTetrahedron(midf0, mid23, mid34, mid24,
attr, -1, -1, fa[3], -1);
child[9] = NewTetrahedron(mid03, mid04, midf0, mid34,
attr, -1, fa[4], -1, -1);
CheckIsoFace(no[3], no[2], no[1], no[0], mid23, mid12, mid01, mid03, midf0);
}
else if (el.Geom() == Geometry::SQUARE)
{
ref_type &= 0x3; // ignore Z bit
@@ -1486,20 +1582,20 @@ void NCMesh::RefineElement(int elem, char ref_type)
}
// start using the nodes of the children, create edges & faces
for (int i = 0; i < 8 && child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && child[i] >= 0; i++)
{
ReferenceElement(child[i]);
}
int buf[6];
Array<int> parentFaces(buf, 6);
int buf[MaxElemFaces];
Array<int> parentFaces(buf, MaxElemFaces);
parentFaces.SetSize(0);
// sign off of all nodes of the parent, clean up unused nodes, but keep faces
UnreferenceElement(elem, parentFaces);
// register the children in their faces
for (int i = 0; i < 8 && child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && child[i] >= 0; i++)
{
RegisterFaces(child[i]);
}
@@ -1508,7 +1604,7 @@ void NCMesh::RefineElement(int elem, char ref_type)
DeleteUnusedFaces(parentFaces);
// make the children inherit our rank; set the parent element
for (int i = 0; i < 8 && child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && child[i] >= 0; i++)
{
Element &ch = elements[child[i]];
ch.rank = el.rank;
@@ -1556,6 +1652,8 @@ void NCMesh::Refine(const Array<Refinement>& refinements)
#if defined(MFEM_DEBUG) && !defined(MFEM_USE_MPI)
mfem::out << "Refined " << refinements.Size() << " + " << nforced
<< " elements" << std::endl;
#else
MFEM_CONTRACT_VAR(nforced);
#endif
ref_stack.DeleteAll();
@@ -1586,6 +1684,12 @@ int NCMesh::RetrieveNode(const Element &el, int index)
ch = el.child[ch];
break;
case Geometry::PYRAMID:
ch = pyramid_deref_table[el.ref_type - 1][index];
MFEM_ASSERT(ch != -1, "");
ch = el.child[ch];
break;
case Geometry::SQUARE:
ch = el.child[quad_deref_table[el.ref_type - 1][index]];
break;
@@ -1608,11 +1712,11 @@ void NCMesh::DerefineElement(int elem)
Element &el = elements[elem];
if (!el.ref_type) { return; }
int child[8];
int child[MaxElemChildren];
std::memcpy(child, el.child, sizeof(child));
// first make sure that all children are leaves, derefine them if not
for (int i = 0; i < 8 && child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && child[i] >= 0; i++)
{
if (elements[child[i]].ref_type)
{
@@ -1620,10 +1724,10 @@ void NCMesh::DerefineElement(int elem)
}
}
int faces_attribute[6];
int faces_attribute[MaxElemFaces];
int ref_type_key = el.ref_type - 1;
for (int i = 0; i < 8; i++) { el.node[i] = -1; }
for (int i = 0; i < MaxElemNodes; i++) { el.node[i] = -1; }
// retrieve original corner nodes and face attributes from the children
if (el.Geom() == Geometry::CUBE)
@@ -1678,6 +1782,34 @@ void NCMesh::DerefineElement(int elem)
->attribute;
}
}
else if (el.Geom() == Geometry::PYRAMID)
{
MFEM_ASSERT(pyramid_deref_table[ref_type_key][0] != -1,
"invalid pyramid refinement");
constexpr int nb_pyramid_childs = 5;
for (int i = 0; i < nb_pyramid_childs; i++)
{
const int child_local_index = pyramid_deref_table[ref_type_key][i];
const int child_global_index = child[child_local_index];
Element &ch = elements[child_global_index];
el.node[i] = ch.node[i];
}
el.node[5] = el.node[6] = el.node[7] = -1;
constexpr int nb_pyramid_faces = 5;
for (int i = 0; i < nb_pyramid_faces; i++)
{
const int child_local_index = pyramid_deref_table[ref_type_key]
[i + nb_pyramid_childs];
const int child_global_index = child[child_local_index];
Element &ch = elements[child_global_index];
const int* fv = GI[el.Geom()].faces[i];
faces_attribute[i] = faces.Find(ch.node[fv[0]], ch.node[fv[1]],
ch.node[fv[2]], ch.node[fv[3]])
->attribute;
}
}
else if (el.Geom() == Geometry::TETRAHEDRON)
{
for (int i = 0; i < 4; i++)
@@ -1745,13 +1877,13 @@ void NCMesh::DerefineElement(int elem)
// sign in to all nodes
ReferenceElement(elem);
int buf[8*6];
Array<int> childFaces(buf, 8*6);
int buf[MaxElemChildren*MaxElemFaces];
Array<int> childFaces(buf, MaxElemChildren*MaxElemFaces);
childFaces.SetSize(0);
// delete children, determine rank
el.rank = std::numeric_limits<int>::max();
for (int i = 0; i < 8 && child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && child[i] >= 0; i++)
{
el.rank = std::min(el.rank, elements[child[i]].rank);
UnreferenceElement(child[i], childFaces);
@@ -1775,7 +1907,7 @@ void NCMesh::CollectDerefinements(int elem, Array<Connection> &list)
if (!el.ref_type) { return; }
int total = 0, ref = 0, ghost = 0;
for (int i = 0; i < 8 && el.child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && el.child[i] >= 0; i++)
{
total++;
Element &ch = elements[el.child[i]];
@@ -1787,7 +1919,7 @@ void NCMesh::CollectDerefinements(int elem, Array<Connection> &list)
{
// can be derefined, add to list
int next_row = list.Size() ? (list.Last().from + 1) : 0;
for (int i = 0; i < 8 && el.child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && el.child[i] >= 0; i++)
{
Element &ch = elements[el.child[i]];
list.Append(Connection(next_row, ch.index));
@@ -1795,7 +1927,7 @@ void NCMesh::CollectDerefinements(int elem, Array<Connection> &list)
}
else
{
for (int i = 0; i < 8 && el.child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && el.child[i] >= 0; i++)
{
CollectDerefinements(el.child[i], list);
}
@@ -1905,7 +2037,7 @@ void NCMesh::SetDerefMatrixCodes(int parent, Array<int> &fine_coarse)
{
// encode the ref_type and child number for GetDerefinementTransforms()
Element &prn = elements[parent];
for (int i = 0; i < 8 && prn.child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && prn.child[i] >= 0; i++)
{
Element &ch = elements[prn.child[i]];
if (ch.index >= 0)
@@ -1977,7 +2109,7 @@ void NCMesh::CollectLeafElements(int elem, int state, Array<int> &ghosts,
}
else // no space filling curve tables yet for remaining cases
{
for (int i = 0; i < 8; i++)
for (int i = 0; i < MaxElemChildren; i++)
{
if (el.child[i] >= 0)
{
@@ -2231,7 +2363,8 @@ void NCMesh::InitRootState(int root_count)
if (v_in < 0) { v_in = 0; }
// determine which nodes are shared with the next element
bool shared[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
bool shared[MaxElemNodes];
for (int ni = 0; ni < MaxElemNodes; ++ni) { shared[ni] = 0; }
if (i+1 < root_count)
{
Element &next = elements[i+1];
@@ -2265,6 +2398,7 @@ mfem::Element* NCMesh::NewMeshElement(int geom) const
{
case Geometry::CUBE: return new mfem::Hexahedron;
case Geometry::PRISM: return new mfem::Wedge;
case Geometry::PYRAMID: return new mfem::Pyramid;
case Geometry::TETRAHEDRON: return new mfem::Tetrahedron;
case Geometry::SQUARE: return new mfem::Quadrilateral;
case Geometry::TRIANGLE: return new mfem::Triangle;
@@ -2347,7 +2481,8 @@ void NCMesh::GetMeshComponents(Mesh &mesh) const
if (face->Boundary())
{
if ((nc_elem.geom == Geometry::CUBE) ||
(nc_elem.geom == Geometry::PRISM && nfv == 4))
((nc_elem.geom == Geometry::PRISM ||
nc_elem.geom == Geometry::PYRAMID) && nfv == 4))
{
auto* quad = (Quadrilateral*) mesh.NewElement(Geometry::SQUARE);
quad->SetAttribute(face->attribute);
@@ -2358,6 +2493,7 @@ void NCMesh::GetMeshComponents(Mesh &mesh) const
mesh.boundary.Append(quad);
}
else if (nc_elem.geom == Geometry::PRISM ||
nc_elem.geom == Geometry::PYRAMID ||
nc_elem.geom == Geometry::TETRAHEDRON)
{
MFEM_ASSERT(nfv == 3, "");
@@ -2603,7 +2739,7 @@ bool NCMesh::TriFaceSplit(int v1, int v2, int v3, int mid[3]) const
int NCMesh::find_node(const Element &el, int node)
{
for (int i = 0; i < 8; i++)
for (int i = 0; i < MaxElemNodes; i++)
{
if (el.node[i] == node) { return i; }
}
@@ -3625,7 +3761,7 @@ void NCMesh::FindNeighbors(int elem, Array<int> &neighbors,
}
else
{
for (int i = 0; i < 8 && el.child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && el.child[i] >= 0; i++)
{
stack.Append(el.child[i]);
}
@@ -3737,8 +3873,8 @@ int NCMesh::GetVertexRootCoord(int elem, RefCoord coord[3]) const
MFEM_ASSERT(pa.ref_type, "internal error");
int ch = 0;
while (ch < 8 && pa.child[ch] != elem) { ch++; }
MFEM_ASSERT(ch < 8, "internal error");
while (ch < MaxElemChildren && pa.child[ch] != elem) { ch++; }
MFEM_ASSERT(ch < MaxElemChildren, "internal error");
MFEM_ASSERT(geom_parent[el.Geom()], "unsupported geometry");
const RefTrf &tr = geom_parent[el.Geom()][(int) pa.ref_type][ch];
@@ -3768,6 +3904,11 @@ static bool RefPointInside(Geometry::Type geom, const RefCoord pt[3])
return (pt[0] >= 0) && (pt[1] >= 0) && (pt[0] + pt[1] <= T_ONE) &&
(pt[2] >= 0) && (pt[2] <= T_ONE);
case Geometry::PYRAMID:
return (pt[0] >= 0) && (pt[1] >= 0) && (pt[2] >= 0.0) &&
(pt[0] + pt[2] <= T_ONE) && (pt[1] + pt[2] <= T_ONE) &&
(pt[2] <= T_ONE);
default:
MFEM_ABORT("unsupported geometry");
return false;
@@ -3785,7 +3926,7 @@ void NCMesh::CollectIncidentElements(int elem, const RefCoord coord[3],
}
RefCoord tcoord[3];
for (int ch = 0; ch < 8 && el.child[ch] >= 0; ch++)
for (int ch = 0; ch < MaxElemChildren && el.child[ch] >= 0; ch++)
{
const RefTrf &tr = geom_child[el.Geom()][(int) el.ref_type][ch];
tr.Apply(coord, tcoord);
@@ -3856,6 +3997,10 @@ NCMesh::PointMatrix NCMesh::pm_prism_identity(
Point(0, 0, 0), Point(1, 0, 0), Point(0, 1, 0),
Point(0, 0, 1), Point(1, 0, 1), Point(0, 1, 1)
);
NCMesh::PointMatrix NCMesh::pm_pyramid_identity(
Point(0, 0, 0), Point(1, 0, 0), Point(1, 1, 0),
Point(0, 1, 0), Point(0, 0, 1)
);
NCMesh::PointMatrix NCMesh::pm_hex_identity(
Point(0, 0, 0), Point(1, 0, 0), Point(1, 1, 0), Point(0, 1, 0),
Point(0, 0, 1), Point(1, 0, 1), Point(1, 1, 1), Point(0, 1, 1)
@@ -3870,6 +4015,7 @@ const NCMesh::PointMatrix& NCMesh::GetGeomIdentity(Geometry::Type geom)
case Geometry::SQUARE: return pm_quad_identity;
case Geometry::TETRAHEDRON: return pm_tet_identity;
case Geometry::PRISM: return pm_prism_identity;
case Geometry::PYRAMID: return pm_pyramid_identity;
case Geometry::CUBE: return pm_hex_identity;
default:
MFEM_ABORT("unsupported geometry " << geom);
@@ -4174,6 +4320,55 @@ void NCMesh::GetPointMatrix(Geometry::Type geom, const char* ref_path,
}
}
}
else if (geom == Geometry::PYRAMID)
{
Point mid01(pm(0), pm(1)), mid23(pm(2), pm(3));
Point mid03(pm(0), pm(3)), mid12(pm(1), pm(2));
Point mid04(pm(0), pm(4)), mid14(pm(1), pm(4));
Point mid24(pm(2), pm(4)), mid34(pm(3), pm(4));
Point midf0(mid23, mid12, mid01, mid03);
if (child == 0) // Pyramid
{
pm = PointMatrix(pm(0), mid01, midf0, mid03, mid04);
}
else if (child == 1) // Pyramid
{
pm = PointMatrix(mid01, pm(1), mid12, midf0, mid14);
}
else if (child == 2) // Pyramid
{
pm = PointMatrix(midf0, mid12, pm(2), mid23, mid24);
}
else if (child == 3) // Pyramid
{
pm = PointMatrix(mid03, midf0, mid23, pm(3), mid34);
}
else if (child == 4) // Pyramid
{
pm = PointMatrix(mid24, mid14, mid04, mid34, midf0);
}
else if (child == 5) // Pyramid
{
pm = PointMatrix(mid04, mid14, mid24, mid34, pm(4));
}
else if (child == 6) // Tet
{
pm = PointMatrix(mid01, midf0, mid04, mid14);
}
else if (child == 7) // Tet
{
pm = PointMatrix(midf0, mid14, mid12, mid24);
}
else if (child == 8) // Tet
{
pm = PointMatrix(midf0, mid23, mid34, mid24);
}
else if (child == 9) // Tet
{
pm = PointMatrix(mid03, mid04, midf0, mid34);
}
}
else if (geom == Geometry::TETRAHEDRON)
{
Point mid01(pm(0), pm(1)), mid12(pm(1), pm(2)), mid02(pm(2), pm(0));
@@ -4333,7 +4528,7 @@ void NCMesh::TraverseRefinements(int elem, int coarse_index,
ref_path.push_back(el.ref_type);
ref_path.push_back(0);
for (int i = 0; i < 8; i++)
for (int i = 0; i < MaxElemChildren; i++)
{
if (el.child[i] >= 0)
{
@@ -5091,14 +5286,14 @@ void NCMesh::CountSplits(int elem, int splits[3]) const
const int* node = el.node;
GeomInfo& gi = GI[el.Geom()];
int elevel[12];
int elevel[MaxElemEdges];
for (int i = 0; i < gi.ne; i++)
{
const int* ev = gi.edges[i];
elevel[i] = EdgeSplitLevel(node[ev[0]], node[ev[1]]);
}
int flevel[6][2];
int flevel[MaxElemFaces][2];
if (Dim >= 3)
{
for (int i = 0; i < gi.nf; i++)
@@ -5142,6 +5337,18 @@ void NCMesh::CountSplits(int elem, int splits[3]) const
splits[2] = max6(flevel[2][1], flevel[3][1], flevel[4][1],
elevel[6], elevel[7], elevel[8]);
}
else if (el.Geom() == Geometry::PYRAMID)
{
splits[0] = std::max(
max6(flevel[0][0], flevel[1][0], 0,
flevel[2][0], flevel[3][0], flevel[4][0]),
max8(elevel[0], elevel[1], elevel[2],
elevel[3], elevel[4], elevel[5],
elevel[6], elevel[7]));
splits[1] = splits[0];
splits[2] = splits[0];
}
else if (el.Geom() == Geometry::TETRAHEDRON)
{
splits[0] = std::max(
@@ -5404,7 +5611,8 @@ void NCMesh::Print(std::ostream &os) const
"# SQUARE = 3\n"
"# TETRAHEDRON = 4\n"
"# CUBE = 5\n"
"# PRISM = 6\n";
"# PRISM = 6\n"
"# PYRAMID = 7\n";
os << "\ndimension\n" << Dim << "\n";
@@ -5425,7 +5633,7 @@ void NCMesh::Print(std::ostream &os) const
if (el.parent == -2) { os << "-1\n"; continue; } // unused element
os << int(el.geom) << " " << int(el.ref_type);
for (int j = 0; j < 8 && el.node[j] >= 0; j++)
for (int j = 0; j < MaxElemNodes && el.node[j] >= 0; j++)
{
os << " " << el.node[j];
}
@@ -5482,7 +5690,7 @@ void NCMesh::InitRootElements()
Element &el = elements[i];
if (el.ref_type)
{
for (int j = 0; j < 8 && el.child[j] >= 0; j++)
for (int j = 0; j < MaxElemChildren && el.child[j] >= 0; j++)
{
int child = el.child[j];
MFEM_VERIFY(child < elements.Size(), "invalid mesh file: "
@@ -5704,7 +5912,7 @@ void NCMesh::CopyElements(int elem,
Element &el = elements[elem];
if (el.ref_type)
{
for (int i = 0; i < 8 && el.child[i] >= 0; i++)
for (int i = 0; i < MaxElemChildren && el.child[i] >= 0; i++)
{
int old_id = el.child[i];
// here we know 'free_element_ids' is empty
@@ -5984,9 +6192,9 @@ void NCMesh::Trim()
// maybe also of 'nodes' and 'faces'.
}
std::size_t NCMesh::NCList::MemoryUsage() const
long NCMesh::NCList::MemoryUsage() const
{
std::size_t pm_size = 0;
int pm_size = 0;
for (int i = 0; i < Geometry::NumGeom; i++)
{
for (int j = 0; j < point_matrices[i].Size(); i++)
@@ -6002,9 +6210,9 @@ std::size_t NCMesh::NCList::MemoryUsage() const
pm_size;
}
std::size_t CoarseFineTransformations::MemoryUsage() const
long CoarseFineTransformations::MemoryUsage() const
{
std::size_t mem = embeddings.MemoryUsage();
long mem = embeddings.MemoryUsage();
for (int i = 0; i < Geometry::NumGeom; i++)
{
mem += point_matrices[i].MemoryUsage();
@@ -6012,7 +6220,7 @@ std::size_t CoarseFineTransformations::MemoryUsage() const
return mem;
}
std::size_t NCMesh::MemoryUsage() const
long NCMesh::MemoryUsage() const
{
return nodes.MemoryUsage() +
faces.MemoryUsage() +
@@ -6073,7 +6281,7 @@ void NCMesh::DebugLeafOrder(std::ostream &os) const
{
double sum = 0.0;
int count = 0;
for (int k = 0; k < 8; k++)
for (int k = 0; k < MaxElemNodes; k++)
{
if (elem->node[k] >= 0)
{
+33 -9
View File
@@ -84,7 +84,7 @@ struct CoarseFineTransformations
void Clear();
bool IsInitialized() const;
std::size_t MemoryUsage() const;
long MemoryUsage() const;
MFEM_DEPRECATED
void GetCoarseToFineMap(const Mesh &fine_mesh, Table &coarse_to_fine) const
@@ -240,7 +240,7 @@ public:
void Clear();
bool Empty() const { return !conforming.Size() && !masters.Size(); }
long TotalSize() const;
std::size_t MemoryUsage() const;
long MemoryUsage() const;
const MeshId& LookUp(int index, int *type = NULL) const;
@@ -390,7 +390,7 @@ public:
virtual void Trim();
/// Return total number of bytes allocated.
std::size_t MemoryUsage() const;
long MemoryUsage() const;
int PrintMemoryDetail() const;
@@ -421,6 +421,15 @@ protected: // implementation
int Geoms; ///< bit mask of element geometries present, see InitGeomFlags()
bool Legacy; ///< true if the mesh was loaded from the legacy v1.1 format
static const int MaxElemNodes =
8; ///< Number of nodes of an element can have
static const int MaxElemEdges =
12; ///< Number of edges of an element can have
static const int MaxElemFaces =
6; ///< Number of faces of an element can have
static const int MaxElemChildren =
10; ///< Number of children of an element can have
/** A Node can hold a vertex, an edge, or both. Elements directly point to
their corner nodes, but edge nodes also exist and can be accessed using
a hash-table given their two end-point node IDs. All nodes can be
@@ -482,8 +491,8 @@ protected: // implementation
int attribute;
union
{
int node[8]; ///< element corners (if ref_type == 0)
int child[8]; ///< 2-8 children (if ref_type != 0)
int node[MaxElemNodes]; ///< element corners (if ref_type == 0)
int child[MaxElemChildren]; ///< 2-10 children (if ref_type != 0)
};
int parent; ///< parent element, -1 if this is a root element, -2 if free'd
@@ -586,6 +595,9 @@ protected: // implementation
/// Return true if the mesh contains prism elements.
bool HavePrisms() const { return Geoms & (1 << Geometry::PRISM); }
/// Return true if the mesh contains pyramid elements.
bool HavePyramids() const { return Geoms & (1 << Geometry::PYRAMID); }
/// Return true if the mesh contains tetrahedral elements.
bool HaveTets() const { return Geoms & (1 << Geometry::TETRAHEDRON); }
@@ -642,6 +654,10 @@ protected: // implementation
int NewTetrahedron(int n0, int n1, int n2, int n3, int attr,
int fattr0, int fattr1, int fattr2, int fattr3);
int NewPyramid(int n0, int n1, int n2, int n3, int n4, int attr,
int fattr0, int fattr1, int fattr2, int fattr3,
int fattr4);
int NewQuadrilateral(int n0, int n1, int n2, int n3, int attr,
int eattr0, int eattr1, int eattr2, int eattr3);
@@ -845,7 +861,7 @@ protected: // implementation
struct PointMatrix
{
int np;
Point points[8];
Point points[MaxElemNodes];
PointMatrix() : np(0) {}
@@ -858,6 +874,13 @@ protected: // implementation
PointMatrix(const Point& p0, const Point& p1, const Point& p2, const Point& p3)
{ np = 4; points[0] = p0; points[1] = p1; points[2] = p2; points[3] = p3; }
PointMatrix(const Point& p0, const Point& p1, const Point& p2,
const Point& p3, const Point& p4)
{
np = 5;
points[0] = p0; points[1] = p1; points[2] = p2;
points[3] = p3; points[4] = p4;
}
PointMatrix(const Point& p0, const Point& p1, const Point& p2,
const Point& p3, const Point& p4, const Point& p5)
{
@@ -887,6 +910,7 @@ protected: // implementation
static PointMatrix pm_quad_identity;
static PointMatrix pm_tet_identity;
static PointMatrix pm_prism_identity;
static PointMatrix pm_pyramid_identity;
static PointMatrix pm_hex_identity;
static const PointMatrix& GetGeomIdentity(Geometry::Type geom);
@@ -976,9 +1000,9 @@ protected: // implementation
struct GeomInfo
{
int nv, ne, nf; // number of: vertices, edges, faces
int edges[12][2]; // edge vertices (up to 12 edges)
int faces[6][4]; // face vertices (up to 6 faces)
int nfv[6]; // number of face vertices
int edges[MaxElemEdges][2]; // edge vertices (up to 12 edges)
int faces[MaxElemFaces][4]; // face vertices (up to 6 faces)
int nfv[MaxElemFaces]; // number of face vertices
bool initialized;
GeomInfo() : initialized(false) {}
+26 -2
View File
@@ -19,6 +19,10 @@ const int ref_type_num_children[8] = { 0, 2, 2, 4, 2, 4, 4, 8 };
// derefinement tables
// The first n numbers in each line are the refined elements that contain
// the vertices of the parent element. The next m numbers in each line
// are the refined elements that contain the faces attributes of the parent
// element.
const int quad_deref_table[3][4 + 4] =
{
@@ -49,6 +53,16 @@ const int prism_deref_table[7][6 + 5] =
{ 0, 1, 2, 4, 5, 6, /**/ 0, 5, 0, 5, 0 } // 7 - iso
};
const int pyramid_deref_table[7][5 + 5] =
{
{-1,-1,-1,-1,-1, /**/ -1,-1,-1,-1,-1 }, // 1
{-1,-1,-1,-1,-1, /**/ -1,-1,-1,-1,-1 }, // 2
{-1,-1,-1,-1,-1, /**/ -1,-1,-1,-1,-1 }, // 3
{-1,-1,-1,-1,-1, /**/ -1,-1,-1,-1,-1 }, // 4
{-1,-1,-1,-1,-1, /**/ -1,-1,-1,-1,-1 }, // 5
{-1,-1,-1,-1,-1, /**/ -1,-1,-1,-1,-1 }, // 6
{ 0, 1, 2, 3, 5, /**/ 0, 5, 5, 5, 5 } // 7 - iso
};
// child ordering tables
@@ -140,8 +154,17 @@ const RefCoord prism_corners[6][3] =
{ 0, T_ONE, T_ONE}
};
const RefCoord pyramid_corners[5][3] =
{
{ 0, 0, 0},
{T_ONE, 0, 0},
{T_ONE, T_ONE, 0},
{ 0, T_ONE, 0},
{ 0, 0, T_ONE}
};
typedef RefCoord RefPoint[3];
const RefPoint* geom_corners[7] =
const RefPoint* geom_corners[8] =
{
NULL, // point
NULL, // segment
@@ -149,7 +172,8 @@ const RefPoint* geom_corners[7] =
quad_corners,
NULL, // tetrahedron
hex_corners,
prism_corners
prism_corners,
pyramid_corners
};
// reference domain transform: 3 scales, 3 translations
+4 -2
View File
@@ -6099,8 +6099,10 @@ void ParMesh::GetBoundingBox(Vector &gp_min, Vector &gp_max, int ref)
gp_min.SetSize(sdim);
gp_max.SetSize(sdim);
MPI_Allreduce(p_min.GetData(), gp_min, sdim, MPI_DOUBLE, MPI_MIN, MyComm);
MPI_Allreduce(p_max.GetData(), gp_max, sdim, MPI_DOUBLE, MPI_MAX, MyComm);
MPI_Allreduce(p_min.GetData(), gp_min.GetData(), sdim, MPI_DOUBLE,
MPI_MIN, MyComm);
MPI_Allreduce(p_max.GetData(), gp_max.GetData(), sdim, MPI_DOUBLE,
MPI_MAX, MyComm);
}
void ParMesh::GetCharacteristics(double &gh_min, double &gh_max,
-8
View File
@@ -2798,14 +2798,6 @@ static std::size_t arrays_memory_usage(const Array<Type> (&arrays)[Size])
std::size_t ParNCMesh::MemoryUsage(bool with_base) const
{
std::size_t total_groups_owners = 0;
for (int i = 0; i < 3; i++)
{
total_groups_owners += entity_owner[i].MemoryUsage() +
entity_pmat_group[i].MemoryUsage() +
entity_index_rank[i].MemoryUsage();
}
return (with_base ? NCMesh::MemoryUsage() : 0) +
GroupsMemoryUsage() +
arrays_memory_usage(entity_owner) +
+6 -3
View File
@@ -248,8 +248,11 @@ ParSubMesh::ParSubMesh(const ParMesh &parent, SubMesh::From from,
Transfer(*pn, *n);
}
el_to_edge = new Table;
NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
if (Dim > 1)
{
el_to_edge = new Table;
NumOfEdges = GetElementToEdgeTable(*el_to_edge, be_to_edge);
}
SetAttributes();
Finalize();
@@ -811,4 +814,4 @@ ParTransferMap ParSubMesh::CreateTransferMap(const ParGridFunction &src,
} // namespace mfem
#endif // MFEM_USE_MPI
#endif // MFEM_USE_MPI
+2 -2
View File
@@ -183,7 +183,7 @@ void ParTransferMap::CommunicateSharedVdofs(Vector &f) const
}
// TODO: do the reduce only on dofs of interest
root_gc_->Reduce<double>(f, GroupCommunicator::Sum);
root_gc_->Reduce<double>(f.HostReadWrite(), GroupCommunicator::Sum);
// Indices that were set from this rank or other ranks have been summed up
// and therefore need to be "averaged". Note that this results in the exact
@@ -211,7 +211,7 @@ void ParTransferMap::CommunicateSharedVdofs(Vector &f) const
}
}
root_gc_->Bcast<double>(f);
root_gc_->Bcast<double>(f.HostReadWrite());
}
ParTransferMap::~ParTransferMap()
+11 -3
View File
@@ -95,6 +95,8 @@ void BuildVdofToVdofMap(const FiniteElementSpace& subfes,
auto *m = subfes.GetMesh();
vdof_to_vdof_map.SetSize(subfes.GetVSize());
const int vdim = parentfes.GetVDim();
IntegrationPointTransformation Tr;
DenseMatrix T;
Array<int> z1;
@@ -137,14 +139,20 @@ void BuildVdofToVdofMap(const FiniteElementSpace& subfes,
parentfes.GetElementVDofs(parent_volel_id, z1);
parent_vdofs.SetSize(parentfes.GetVDim() * T.Height());
parent_vdofs.SetSize(vdim * T.Height());
for (int j = 0; j < T.Height(); j++)
{
for (int k = 0; k < parentfes.GetVDim() * T.Width(); k++)
for (int k = 0; k < T.Width(); k++)
{
if (T(j, k) != 0.0)
{
parent_vdofs[j] = z1[static_cast<int>(k)];
for (int vd=0; vd<vdim; vd++)
{
int sub_vdof = j + T.Height() * vd;
int parent_vdof = k + T.Width() * vd;
parent_vdofs[sub_vdof] =
z1[static_cast<int>(parent_vdof)];
}
}
}
}
+2 -4
View File
@@ -58,7 +58,7 @@ RT_FESpace::~RT_FESpace()
void VisualizeMesh(socketstream &sock, const char *vishost, int visport,
Mesh &mesh, const char *title,
int x, int y, int w, int h, const char * keys, bool vec)
int x, int y, int w, int h, const char * keys)
{
bool newly_opened = false;
int connection_failed;
@@ -71,7 +71,7 @@ void VisualizeMesh(socketstream &sock, const char *vishost, int visport,
sock.precision(8);
newly_opened = true;
}
sock << "solution\n";
sock << "mesh\n";
mesh.Print(sock);
@@ -81,8 +81,6 @@ void VisualizeMesh(socketstream &sock, const char *vishost, int visport,
<< "window_geometry "
<< x << " " << y << " " << w << " " << h << "\n";
if ( keys ) { sock << "keys " << keys << "\n"; }
else { sock << "keys maaAc\n"; }
if ( vec ) { sock << "vvv"; }
sock << endl;
}

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