Compare commits

...
668 Commits
Author SHA1 Message Date
Dylan Copeland c6198593fb Creating example for testing. 2025-02-05 10:14:50 -08:00
Tzanio Kolev c9db272586 Merge pull request #4557 from david-kamensky/david/integ-base
Integrator base class unifying logic for selecting IntegrationRule
2025-02-03 11:03:53 -08:00
David Kamensky ae117fa580 Merge branch 'master' into david/integ-base 2025-02-03 10:35:40 -08:00
David Kamensky ee0e35c94b Updating CHANGELOG with note about Integrator base class. 2025-02-03 11:18:24 -07:00
Veselin Dobrev a0c3bdc93e Merge pull request #4652 from mfem/spiral-dev
😵‍💫 New toy miniapp: Spiral
2025-01-30 11:13:19 -08:00
Veselin Dobrev 2a1dd3d9c2 Merge pull request #4610 from lindsayad/netcdf-name-support
Allow reading exodus block/boundary names into corresponding attribute sets
2025-01-30 11:11:03 -08:00
Tzanio Kolev 2277c3729f Merge pull request #4637 from mfem/mesh-explorer-elem-fix
Fix element visualization in Mesh Explorer
2025-01-30 07:49:17 -08:00
Tzanio Kolev afb7aaa2a5 Merge pull request #4630 from mfem/mark-external-faces-dev
Experimental solution to BC selection issue in ex1 and ex1p [mark-external-faces-dev]
2025-01-30 07:48:38 -08:00
Tzanio Kolev 34cb75622a Merge pull request #4484 from mfem/hughcars/gmsh-reader-periodic-bugfix
Do not remove internal boundaries when loading a gmsh periodic mesh
2025-01-30 07:47:40 -08:00
Stowell, Mark L. 5dc85da306 Updating CHANGELOG with notices of the new methods 2025-01-28 11:46:56 -08:00
Tzanio Kolev 3f810f3591 Merge pull request #4649 from mfem/face-geom-jacobians
Compute derivatives in FaceQuadratureInterpolator, compute Jacobian matrices in FaceGeometricFactors
2025-01-28 11:35:26 -08:00
Mark L. StowellandVeselin Dobrev b60df76e98 Update mesh/mesh.cpp
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2025-01-28 10:21:33 -08:00
Tzanio Kolev 21537ec6c6 Separate array for element partitioning in Mesh Explorer 2025-01-27 18:05:16 -08:00
David Kamensky 5ba722dd2f Adding a link to Integrator::SetIntRule in the documentation for Integrator::SetIntegrationRule. 2025-01-27 16:56:25 -07:00
David Kamensky 4a9a6e3ba3 Avoiding assignment in conditional to fix debug build. 2025-01-24 09:34:56 -07:00
David Kamensky c4e672c71a Keep IntRule and patchRules mutually exclusive through setter methods and update documentation. 2025-01-24 09:15:36 -07:00
Stowell, Mark L. 7bb9027c82 Changes suggested by v-dobrev 2025-01-23 15:46:20 -08:00
Tzanio Kolev 7150b9e9bd Merge pull request #4668 from dect-cf/master
Fix bug in KnotVector initialization to enable nonopen knot vectors
2025-01-22 17:40:00 -08:00
Tzanio Kolev 2105441b2c Merge pull request #4598 from mfem/fes-move-dim-fns-dev
Move VectorDim, CurlDim to FiniteElementSpace (Redo)
2025-01-22 17:39:32 -08:00
David KamenskyandJustin Laughlin 55dc0f4b97 Fix typo in Doxygen comment.
Co-authored-by: Justin Laughlin <justinglaughlin@gmail.com>
2025-01-22 16:16:44 -08:00
Stowell, Mark L. 4de1e1bad3 Altering examples code comments as per Tzanio's suggestion 2025-01-22 09:49:29 -08:00
Mark L. Stowell dfec0c0281 Merge branch 'master' into mark-external-faces-dev 2025-01-22 09:40:33 -08:00
Stowell, Mark L. 61d4d6bbc2 Renaming "Remove" -> "Unmark" 2025-01-21 20:26:41 -08:00
Stowell, Mark L. e2ed642f5b Correcting the comments in the examples 2025-01-21 20:26:17 -08:00
Stowell, Mark L. 0656bc02cf Merge branches 'mark-external-faces-dev' and 'mark-external-faces-dev' of github.com:mfem/mfem into mark-external-faces-dev 2025-01-21 16:36:04 -08:00
Stowell, Mark L. 5b002f9452 Using the new MarkExternalBoundary methods in ex1, ex1p, and ex11p 2025-01-21 15:47:31 -08:00
Stowell, Mark L. f65afa6f7b Modifying behavior of MarkExternalBoundaries and adding named set versions (un)mark methods 2025-01-21 15:46:47 -08:00
Stowell, Mark L. 72dc6dd9df Adding "const" versions of select attribute set methods 2025-01-21 15:45:49 -08:00
Hugh Carson d4b8071871 Merge remote-tracking branch 'origin/master' into hughcars/gmsh-reader-periodic-bugfix 2025-01-21 15:02:44 -05:00
Will Pazner 006e348182 Merge remote-tracking branch 'origin/master' into face-geom-jacobians 2025-01-21 11:51:36 -08:00
Will Pazner f280d43ac9 Remove unneeded check in FaceQuadratureInterpolator
Derivatives are now supported. Also, the check was buggy, it should have been
!(eval_flags & DERIVATIVES)
2025-01-21 11:51:27 -08:00
Will Pazner abe37e5ed7 Remove unneeded check if non-null
FiniteElementSpace::GetTypicalFE always returns non-null pointer
2025-01-21 11:11:21 -08:00
David Kamensky d9fef7f574 Avoiding unnecessary dynamic cast in Integrator::GetIntegrationRule; minor adjacent formatting changes. 2025-01-21 08:59:12 -07:00
Tzanio Kolev 65585868a7 Merge pull request #4572 from mfem/bugfix-4570
Bug in VectorDiffusionIntegrator::AssembleElementVector.
2025-01-21 07:14:12 -08:00
Tzanio Kolev 0e0b81d87f Merge pull request #4657 from mfem/device_info
added helper functions for querying various device properties
2025-01-21 07:13:15 -08:00
David Kamensky 56bc30fa75 Changing const pointer arguments to Integrator::Get(Default)IntegrationRule to const references. 2025-01-17 13:23:40 -07:00
Mark L. Stowell 0d306df7ec Merge branch 'master' into mark-external-faces-dev 2025-01-17 09:48:45 -08:00
dect-cf 60aea56a1d Merge branch 'master' into master 2025-01-17 09:34:44 -07:00
David Kamensky f13d975c21 Adding @brief to short Doxygen comments in integrator.hpp. 2025-01-17 09:17:32 -07:00
Tzanio Kolev a496df4734 Merge pull request #4522 from mfem/TMOP_AD_ms
AD implementation for selected TMOP metrics
2025-01-17 07:56:12 -08:00
Derek Thomas 5b1171aae9 Fix bug in alternate KnotVector initialization to enable nonopen knot vectors 2025-01-17 05:54:52 +00:00
Philipp Dumitrescu 8ce411f481 Restore GetTypicalFE changes; tweak comments 2025-01-16 16:21:13 -08:00
Stowell, Mark L. bd3d1b6dcc ex1p showing four proposed solutions 2025-01-16 15:54:11 -08:00
Stowell, Mark L. 7d7ec1fa6a Bug fixes 2025-01-16 15:52:18 -08:00
Stowell, Mark L. c42fd1ccd5 Adding remove_interior option to suggested (Par)FiniteElementSpace methods 2025-01-16 14:49:29 -08:00
Stowell, Mark L. 7e1884ca65 Merge remote-tracking branch 'origin/master' into mark-external-faces-dev
# Conflicts:
#	mesh/mesh.cpp
2025-01-16 11:04:22 -08:00
Stowell, Mark L. 3ac922ac32 Using new functions in ex1 and ex1p 2025-01-15 17:18:45 -08:00
Stowell, Mark L. e09decae30 Adding suggested functions to ParMesh class 2025-01-15 16:55:58 -08:00
Stowell, Mark L. 2e326c97bf Adding recommended functions to Mesh class 2025-01-15 16:37:05 -08:00
Philipp Dumitrescu c0ad0924cd Merge branch 'master' into fes-move-dim-fns-dev 2025-01-15 16:35:18 -08:00
Tzanio Kolev 109b2f3eb3 Merge pull request #4513 from mfem/najlkin/impro-hyperbolic
Improvements of general hyperbolic framework
2025-01-15 07:10:03 -08:00
Tzanio Kolev 2dddad5381 Merge pull request #4574 from lindsayad/petsc-container-ctx-update
PetscContainerSetUserDestroy -> PetscContainerSetCtxDestroy
2025-01-15 07:08:14 -08:00
Tzanio Kolev 2fdac5753b Merge pull request #4621 from mfem/cmake-petsc-config-fix
CMake: fix an issue when finding PETSc
2025-01-15 07:07:45 -08:00
Andrew HoandVeselin Dobrev 5c53d66dc4 Update general/device.hpp
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2025-01-13 08:32:50 -08:00
Andrew HoandVeselin Dobrev dfb72d01f6 Update general/device.hpp
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2025-01-13 08:32:37 -08:00
Alex Lindsay dd8c1241a5 Add netcdf read capability for boundary ids-name pairs 2025-01-09 17:38:09 -07:00
Andrew Ho db323179f1 Merge branch 'master' into device_info 2025-01-09 14:41:57 -08:00
Andrew Ho 4983d81eb9 removed cuda < 10 since MFEM doesn't support this anyways 2025-01-09 14:40:08 -08:00
Andrew Ho 13b9e14526 Moved implementations to cpp file
removed host/device since this could lead to some ODR violations
2025-01-09 14:28:15 -08:00
Tzanio Kolev 7324c70027 Merge branch 'master' into najlkin/impro-hyperbolic 2025-01-09 02:20:52 -08:00
Vladimir Z Tomov 3bb7b0bcfe Merge branch 'master' into TMOP_AD_ms 2025-01-08 18:14:21 -08:00
Vladimir Z Tomov 6932e2038f changelog, changed a sample run. 2025-01-08 18:13:44 -08:00
Vladimir Z Tomov dbbb7b6b5d minor 2025-01-08 15:15:39 -08:00
Veselin Dobrev e7cf9fb5ac Merge pull request #4650 from mfem/actions-concurrency
Use 'concurrency' in GitHub CI instead of external action
2025-01-08 14:28:35 -08:00
Vladimir Z Tomov 15accf0271 minor 2025-01-08 12:47:35 -08:00
Vladimir Z Tomov 47afa5868b Merge branch 'actions-concurrency' into TMOP_AD_ms 2025-01-08 12:04:46 -08:00
Ketan Mittal 7fe2ba5e92 Merge branch 'master' into TMOP_AD_ms 2025-01-08 10:34:31 -08:00
Mittal, Ketan ae033ff089 minor 2025-01-08 10:32:19 -08:00
Mittal, Ketan 2f09f46776 add 3D VOS metric mu_342 2025-01-08 10:25:38 -08:00
Tzanio Kolev 09d9b0b1de Merge pull request #4619 from mfem/tmop-bg-bug
TMOP correction for background grids
2025-01-07 17:14:15 -08:00
Tzanio Kolev 99958b1c67 Merge pull request #4260 from mfem/pa-empty-partitions
Better support for PA with empty mesh partitions
2025-01-07 17:13:41 -08:00
Tzanio Kolev 7c78f98552 Merge pull request #4647 from mfem/getenv-wrapper
Rename getenv wrapper to GetEnv
2025-01-07 17:13:00 -08:00
Jan Nikl 6c2f6a9e7f Fixed typo. 2025-01-07 14:33:59 -08:00
Andrew Ho 96a0320f2c typo 2025-01-07 10:47:41 -08:00
Andrew Ho 04b09171dc documentation 2025-01-07 10:44:14 -08:00
Will Pazner 97bbd21b16 Fix YAML error in build analysis workflow 2025-01-07 09:31:45 -08:00
Will Pazner 810eb3dc09 Explicitly specify Ubuntu and clang version in sanitizer action
Also remove temporary workaround that is not needed on the newer Ubuntu runner.
2025-01-07 09:19:22 -08:00
Andrew Ho 6e1101f058 added helper functions for querying various device properties 2025-01-06 18:33:23 -08:00
Mittal, Ketan 9b4086319a minor 2025-01-06 14:45:43 -08:00
Mittal, Ketan e3e0eccc86 remove fd-based sample runs 2025-01-06 14:39:56 -08:00
Mittal, Ketan caa7ff4a95 minor 2025-01-06 13:18:17 -08:00
Mittal, Ketan e1c1fcc3fa simplify logic to remove duplication in metric definition for AD 2025-01-06 11:38:59 -08:00
David Kamensky c4e853a8ee Favoring GetIntRule over zero-argument GetIntegrationRule as direct accessor for IntRule. 2025-01-06 11:06:42 -07:00
David Kamensky 07db30222c Minor cosmetic changes: consistent const style, GetIntRule calls GetIntegrationRule, removing excess blank lines. 2025-01-06 09:06:49 -07:00
Tzanio Kolev b521859413 Uninitialized variables 2025-01-03 20:08:47 -08:00
Tzanio Kolev 88ae946755 Spiral: Added a note about mfem/data 2025-01-03 19:35:45 -08:00
Tzanio Kolev d9758bd216 New toy miniapp: Spiral 2025-01-03 19:32:24 -08:00
David Kamensky 3e0c373ee2 Formatting; replacing some overloads with default parameters; documentation updates. 2025-01-03 17:35:21 -07:00
Vladimir Z Tomov c6bbe85b21 Moved the implementations to EvalWMatrixForm()
since all new metrics are evaluated through their matrix forms.
2025-01-03 16:12:29 -08:00
Jan Nikl 837333b88a Renamed Godunov flux to upwinded flux. 2025-01-03 13:03:53 -08:00
David Kamensky b249a4de62 Wrapping some existing GetRule methods of Integrator subclasses with overrides of Integrator::GetDefaultIntegrationRule. 2025-01-03 13:30:58 -07:00
Jan Nikl 72de1e5d50 Elaborated dox of RusanovFlux. 2025-01-03 11:55:19 -08:00
David Kamensky 5bcba26e08 Additional minor changes requested during review. 2025-01-03 12:49:25 -07:00
Will Pazner 6ddea3ff47 Merge remote-tracking branch 'origin/master' into pa-empty-partitions 2025-01-03 09:36:06 -08:00
Ketan Mittal e97ff1222e Merge branch 'master' into tmop-bg-bug 2025-01-03 09:35:11 -08:00
Will Pazner 697c21aa7e Add more tests directories to 'make style' 2025-01-03 09:34:29 -08:00
Will Pazner 78e593bea1 Ensure meshgen is set on empty ranks 2025-01-03 09:32:23 -08:00
Will Pazner d85c8fb65a Revert unnecessary changes in kdtree.cpp 2025-01-03 09:31:56 -08:00
Ketan Mittal 178a4db5c8 Merge branch 'master' into TMOP_AD_ms 2025-01-03 09:12:36 -08:00
Mittal, Ketan dc241f8298 reviewer comments 2025-01-02 15:49:26 -08:00
Veselin Dobrev 701d3875c5 Merge pull request #4643 from mfem/array-move-ctor-fix
Array move constructor fix
2025-01-02 12:00:34 -08:00
Will Pazner 3bdbfb51f9 Don't explicitly specify clang version in sanitizer CI 2025-01-01 08:40:25 -08:00
Will Pazner 8d254f488e Use 'concurrency' in GitHub CI instead of external action
This is a built-in way to limit the CI to one job per workflow (canceling
previous runs).
2025-01-01 08:24:33 -08:00
Alex Lindsay 92e927ccf8 Add .vscode dir to .gitignore 2024-12-31 16:00:00 -07:00
Alex Lindsay b8a120ec3e Add unit test 2024-12-31 16:00:00 -07:00
Vladimir Z Tomov d10c9f7952 Merge branch 'master' into tmop-bg-bug 2024-12-31 14:54:09 -08:00
Alex Lindsay 50f5fcc42e Apply style 2024-12-31 12:33:42 -07:00
Alex Lindsay 4d5054c197 Change assert message 2024-12-31 12:33:42 -07:00
Alex Lindsay 845ff55e3f Exodus at least only ever writes NC_CHAR 2024-12-31 12:33:42 -07:00
Alex Lindsay ecfee97b37 Apparently working implementation for var_type == NC_CHAR 2024-12-31 12:33:42 -07:00
Alex Lindsay 8eaae0ff87 Read block names in NetCDF and add to attribute sets
Refs #4602
2024-12-31 12:33:42 -07:00
Will Pazner 0345861c6f Compute derivatives in FaceQuadratureInterpolator, compute Jacobian matrices in FaceGeometricFactors
Also add "Face geometric factor Jacobians" unit test
2024-12-31 09:32:12 -08:00
Vladimir Z Tomov 01d57ee7f8 minor 2024-12-28 20:57:02 -08:00
Vladimir Z Tomov 900385e06d minor 2024-12-28 20:45:52 -08:00
Vladimir Z Tomov 678d44a01e Merge branch 'master' into TMOP_AD_ms 2024-12-28 20:19:36 -08:00
Vladimir Z Tomov bf312430a7 style 2024-12-28 20:18:56 -08:00
Vladimir Z Tomov f35689d7bc Added all new metrics to tmop-check-metric. 2024-12-28 19:26:09 -08:00
Tzanio Kolev c45b3ef3ee Merge pull request #4578 from mfem/positive-lp-err-dev
Returning positive errors from GridFunction::ComputeLpError etc...
2024-12-27 22:00:49 -08:00
Tzanio Kolev 598413e2fc Merge pull request #4635 from mfem/bug-fix-par-green-ref-2d
Bug-Fix: Parallel Green Refinement in 2D
2024-12-27 21:59:37 -08:00
Tzanio Kolev 81cf9ed9a1 Merge pull request #4603 from adam-sim-dev/operator_equal
operator= for (Par)ComplexLinearForm
2024-12-27 21:59:05 -08:00
Will Pazner 33efde9e81 Add Doxygen comment for GetEnv 2024-12-26 21:33:27 -08:00
Will Pazner 19a1750527 Rename getenv wrapper to GetEnv
Also use getenv wrapper in KernelReporter
2024-12-26 16:55:45 -08:00
Will Pazner d08c019d4c Avoid initializing data twice in Array constructors 2024-12-24 18:19:37 -08:00
Will Pazner 1deaa1cb57 Add Memory constructor given host MemoryType 2024-12-24 18:19:37 -08:00
Will Pazner e69ad849ff Ensure *this is initialized in Array move constructor 2024-12-24 18:19:37 -08:00
Alex Lindsay 49450e3db7 Switch to PETSC_VERSION_LT 2024-12-23 16:56:35 -07:00
David Kamensky 14255ad4f4 Shortening some lines. 2024-12-23 08:49:22 -07:00
Tzanio Kolev d9850f4baa minor 2024-12-22 10:38:53 -08:00
Tzanio Kolev 4219887355 Added helpful information for GLVis visualization of mesh elements in Mesh Explorer 2024-12-22 10:36:07 -08:00
Tzanio Kolev f51d715503 Fix element visualization in Mesh Explorer 2024-12-21 19:48:21 -08:00
Stowell, Mark L. 3d35c66864 Removing unused doxygen anchor 2024-12-21 16:40:59 -08:00
Stowell, Mark L. b626908505 Expanding explanation of Coefficient array arguments 2024-12-21 16:40:39 -08:00
Stowell, Mark L. 8b95b3353b Expanding explanation of integration rule argument 2024-12-21 16:40:04 -08:00
Stowell, Mark L. bc2b87e891 Adding the negative quadrature note in a few places where it was missed 2024-12-21 16:36:42 -08:00
Stowell, Mark L. e01407f82b Applying doxygen reference fix in other locations 2024-12-20 18:26:42 -08:00
Stowell, Mark L. 88a10cb42b Attempting to fix doxygen reference error 2024-12-20 18:22:12 -08:00
Stowell, Mark L. 17cd445e8b Fixing shadowed variable error 2024-12-20 17:36:56 -08:00
Stowell, Mark L. 20fce49843 Attempting to fix deprecation error 2024-12-20 17:29:21 -08:00
Stowell, Mark L. c53f1c9188 Attempting to fix Doxygen error 2024-12-20 17:29:07 -08:00
Stowell, Mark L. 085f779379 Trying another way to bypass a deprecation error 2024-12-20 17:24:52 -08:00
Stowell, Mark L. 48ce125336 Moving implementation involving newly deprecated function to avoid compiler errors 2024-12-20 17:00:52 -08:00
Stowell, Mark L. 2bbdafa9f4 Adding CHANGELOG entry 2024-12-20 17:00:05 -08:00
Stowell, Mark L. 76fd3575d1 Adding documentation to parallel Compute*Error methods 2024-12-20 16:47:35 -08:00
adam-sim-dev b22b2158bf Merge branch 'master' into operator_equal 2024-12-21 08:03:29 +08:00
Stowell, Mark L. a1c279ee79 Cleaning up LaTeX and link errors 2024-12-20 15:02:37 -08:00
Mark L. Stowell a1429e80e2 Merge branch 'positive-lp-err-dev' of github.com:mfem/mfem into positive-lp-err-dev 2024-12-19 17:30:16 -08:00
Mark L. Stowell 8bfa001844 style adjustment 2024-12-19 17:28:22 -08:00
Mark L. Stowell 3230923742 Adding documentation for Sobolev norms 2024-12-19 17:27:54 -08:00
Mark L. Stowell 5038e96f34 Adding documentation for Max norms 2024-12-19 17:27:22 -08:00
Mark L. Stowell c421146f47 Documenting element-wise error functions 2024-12-19 13:24:18 -08:00
Mark L. Stowell 86336f1c51 Adding documentation for L1 and W11 error computations 2024-12-19 11:45:45 -08:00
Mark L. Stowell 699bb4d422 Fixing typos 2024-12-19 11:45:13 -08:00
Mark L. Stowell ce0bda7a35 Ensuring positive integrals in GridFunction::ComputeW11Error 2024-12-19 10:50:49 -08:00
Veselin Dobrev e2a20d381c Merge pull request #4624 from LeSnow-Ye/patch-1
CMake: fix `mpi.h` not being found when finding SLEPc.
2024-12-18 16:46:54 -08:00
adam-sim-dev 1f38748b11 Merge branch 'master' into operator_equal 2024-12-19 04:49:36 +08:00
Mark L. Stowell 42300d0fca Merge branch 'master' into bug-fix-par-green-ref-2d 2024-12-18 11:49:04 -08:00
Mark L. Stowell 7db0a9a8d3 Use spaceDim to ensure all necessary components of new vertices are computed 2024-12-18 11:03:10 -08:00
Tzanio Kolev 16a9b2be3c Merge pull request #4371 from mfem/ncmesh-spacing
General NCMesh spacing
2024-12-18 06:50:43 -08:00
Tzanio Kolev e731d2dd69 Merge pull request #4583 from lindsayad/install-miniapp-content
Install miniapp content
2024-12-18 06:20:39 -08:00
Tzanio Kolev 6afc7e6fe8 minor 2024-12-17 17:24:25 -08:00
Tzanio Kolev 2a4fd1121e Merge pull request #4467 from mfem/gslib-findpts-device-vol
FindPointsGSLIB on GPUs
2024-12-17 16:31:12 -08:00
Tzanio Kolev d5f029f016 Merge branch 'master' into ncmesh-spacing 2024-12-17 11:29:58 -08:00
Tzanio Kolev 06e7948445 Merge branch 'master' into positive-lp-err-dev 2024-12-17 11:29:53 -08:00
Veselin DobrevandAndrew Ho 1bd9ed53b3 Update CMakeLists.txt
Co-authored-by: Andrew Ho <ho37@llnl.gov>
2024-12-16 16:09:15 -08:00
Veselin Dobrev f72bfcce92 Additional tweaks based on PR reviews 2024-12-16 14:31:11 -08:00
Veselin DobrevandNuno Nobre 971864c3a1 Apply suggestions from code review
Co-authored-by: Nuno Nobre <nuno.nobre@stfc.ac.uk>
2024-12-16 13:06:16 -08:00
Veselin DobrevandNuno Nobre b11a4e2c6a Update CMakeLists.txt
Co-authored-by: Nuno Nobre <nuno.nobre@stfc.ac.uk>
2024-12-16 13:02:37 -08:00
Mark L. Stowell 2a109bd2ea Fixing return value comment 2024-12-16 11:36:27 -08:00
Alex Lindsay 9fce164b33 Veselin patch 2 2024-12-14 21:24:48 -07:00
adam-sim-dev faf6ea6ca6 Merge branch 'master' into operator_equal 2024-12-15 09:34:17 +08:00
Mark L. Stowell cbac9063ad Merge branch 'master' into mark-external-faces-dev 2024-12-13 14:26:30 -08:00
Mark L. Stowell 66c3474eb3 Adding support for AMR meshes 2024-12-13 14:03:22 -08:00
David Kamensky 61fd002be4 Updating documentation and formatting, and re-ordering attributes/methods of Integrator in header. 2024-12-13 13:07:47 -07:00
Jan Nikl 24da41f6bb Mentioned renaming of RiemannSolver in Changelog. 2024-12-13 10:03:34 -08:00
Jan Nikl 9943072dca Removed the switch for numerical fluxes from ex18(p). 2024-12-13 09:59:27 -08:00
Jan NiklandChris Vogl f8b638c569 Docs improvement in hyperbolic.hpp
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-12-13 09:13:49 -08:00
Mark L. Stowell 0c88591848 make style 2024-12-12 15:46:07 -08:00
Mark L. Stowell 1cdc2eb295 Testing the new method with change from PR #4484 2024-12-12 14:53:31 -08:00
Mark L. Stowell c8aa01fbe6 Using new methods to find essential BC DoFs in ex1 and ex1p 2024-12-12 14:52:48 -08:00
Mark L. Stowell 03c874a199 Adding GetExterior(VDofs|TrueDofs) functions to finite element space classes 2024-12-12 14:52:13 -08:00
Mark L. Stowell 3e69daedf7 Adding (Par)Mesh::GetExteriorFaceMarker to identify exterior faces of a mesh 2024-12-12 14:51:07 -08:00
Jan Nikl 1e4f2b5d2b Renamed GodunovFlux to ScalarGodunovFlux to make clear it is component-wise. 2024-12-12 12:08:51 -08:00
Jan Nikl e94e997790 Generalized gradient of RusanovFlux for systems. 2024-12-12 11:28:05 -08:00
Alex Lindsay 8b7b8bc4af Apply Veselin patch 2024-12-12 11:39:32 -07:00
Vladimir Z Tomov 8a63fe8a49 Merge branch 'master' into bugfix-4570 2024-12-12 09:23:44 -08:00
Vladimir Z Tomov 08d8058ce1 Edited the doxygen based on review comments. 2024-12-12 09:21:01 -08:00
David Kamensky ca48beb934 Adding integrator base class to unify quadrature rule selection. 2024-12-12 09:30:58 -07:00
Tzanio Kolev 9a9087e20b Merge pull request #4504 from helloworld922/master
Fix CUDA-enabled HYPRE finalization order issue
2024-12-12 07:26:37 -08:00
adam-sim-dev d7370c8518 Merge branch 'master' into operator_equal 2024-12-12 15:33:46 +08:00
Jan Nikl ef2636e4e9 Minor docs fix in hyperbolic.hpp. 2024-12-11 09:33:43 -08:00
Jan Nikl 0e1f45f060 Renamed rsolver to numFlux in HyperbolicFormIntegrator. 2024-12-11 09:30:17 -08:00
Jan Nikl 8cc9877716 Renamed Riemann solver to numerical flux in ex18(p). 2024-12-11 09:27:06 -08:00
Jan Nikl 0d389eed75 Fixed definitions of the characteristic speed. 2024-12-11 09:09:59 -08:00
Mark L. Stowell 029d0ee306 Adding improved documentation including parameter descriptions 2024-12-10 20:26:55 -08:00
Jan Nikl 46ab66d499 Moved warning about component-wise Godunov to its constructor. 2024-12-10 16:47:53 -08:00
Jan Nikl 144db3a53c Fixed maximal characteristic velocity definitions. 2024-12-10 15:39:12 -08:00
Jan Nikl 5895c08ff2 Minor doxygen change for RusanovFlux. 2024-12-10 15:33:52 -08:00
Dylan Copeland 74e93755fa Bug fix. 2024-12-10 13:36:56 -08:00
Mark L. Stowell acb91a69ab Merge branch 'positive-lp-err-dev' of github.com:mfem/mfem into positive-lp-err-dev 2024-12-10 13:26:48 -08:00
Mark L. Stowell 59b656a18c Improving documentation as suggested by @najlkin 2024-12-10 13:25:42 -08:00
Mark L. Stowell 4305f39092 Repalcing if/else blocks with fabs where appropriate 2024-12-10 10:59:17 -08:00
Mark L. StowellandJan Nikl 367266ee95 Update fem/gridfunc.cpp
Co-authored-by: Jan Nikl <nikl1@llnl.gov>
2024-12-10 10:51:05 -08:00
Jan Nikl afbaca05de Merge branch 'master' into najlkin/impro-hyperbolic 2024-12-10 10:33:48 -08:00
Jan Nikl 5780c2c21c Minor docs improvement. 2024-12-10 10:22:32 -08:00
Jan Nikl 16e0bad850 Renamed RiemannSolver to NumericalFlux with depracation of the old name. 2024-12-10 09:37:09 -08:00
Jan NiklandChris Vogl 5c0bd60944 Minor docs improvement.
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-12-10 09:35:14 -08:00
Jan NiklandChris Vogl 44438536af Minor docs improvement.
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-12-10 09:33:53 -08:00
Jan NiklandChris Vogl 3d488cd2fd Minor docs improvement.
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-12-10 09:33:18 -08:00
Jan NiklandChris Vogl 099c3493b2 Minor docs improvement.
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-12-10 09:32:46 -08:00
Jan NiklandChris Vogl 655623ca9b Minor docs improvement.
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-12-10 09:31:29 -08:00
Jan NiklandChris Vogl f91f3d12a6 Minor docs improvement.
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-12-10 09:30:37 -08:00
LeSnow Ye fc8312383f Fix mpi.h file not being found. 2024-12-10 13:43:30 +08:00
Vladimir Z Tomov 947bcc2b80 Removed leftover code from the previous approach. 2024-12-09 18:04:39 -08:00
Vladimir Z Tomov 4ff80fbb80 style 2024-12-09 17:48:20 -08:00
Vladimir Z Tomov 915fc1e910 fixed more warnings 2024-12-09 17:46:19 -08:00
Veselin Dobrev 6324806008 In CMake, fix an issue when finding PETSc with C compiler that is
not an MPI C wrapper.
2024-12-09 11:50:25 -08:00
Tzanio Kolev c3771b3352 Merge pull request #4613 from mfem/artv3/fix-ea-ho-lor-transfer-mem-leaks
Fix memory leaks in EA-HO-LOR transfer operators
2024-12-09 10:52:50 -08:00
Andrew Ho 51a75893f7 Changes from Veselin 2024-12-09 08:21:57 -08:00
Vladimir Z Tomov b164ad53a2 style 2024-12-08 18:18:22 -08:00
Vladimir Z Tomov aab51f6935 Fixed -Wall errors. 2024-12-08 18:15:57 -08:00
Vladimir Z Tomov 23afe83964 minor comment 2024-12-08 17:15:18 -08:00
Vladimir Z Tomov 7845bca7be doc error 2024-12-08 17:08:43 -08:00
Vladimir Z Tomov 98bbecd492 Simplification 2024-12-08 16:56:34 -08:00
Vladimir Z Tomov e079915f76 style 2024-12-08 16:49:48 -08:00
Vladimir Z Tomov ce253361c6 deprecated message 2024-12-08 16:46:33 -08:00
Vladimir Z Tomov 718a86594c Added ComputeAtGivenPositions. 2024-12-08 15:22:35 -08:00
Vladimir Z Tomov d24fd7d447 switched to the new function 2024-12-08 14:49:00 -08:00
Veselin Dobrev cac27438f5 In GitHub CI, use custom install dir for CMake on Ubuntu 2024-12-08 13:45:10 -08:00
Veselin Dobrev 7f2a2692dd In GNU make, during header installation, skip source directories that
do not have *.hpp files in them.
2024-12-08 13:08:50 -08:00
Veselin Dobrev 48c1a80fdc In the GitHub CI, add tests for the install targets 2024-12-08 13:01:27 -08:00
Vladimir Z Tomov 29a2501f8c Comments, renamed the space. 2024-12-08 12:48:48 -08:00
Vladimir Z Tomov ad7d173497 Added FESpace::GetNodePositions. 2024-12-08 09:51:53 -08:00
adam-sim-dev 9d2b6007ed Merge branch 'master' into operator_equal 2024-12-08 18:03:25 +08:00
Tzanio Kolev 35bbdc75c9 Merge pull request #4608 from Heinrich-BR/master
Conduit file path fix
2024-12-07 14:53:06 -08:00
Philipp Dumitrescu 88416db438 Fix style 2024-12-06 12:02:47 -08:00
Philipp Dumitrescu 00616cfccf Adjust docstrings for Vector/CurlDim 2024-12-06 11:58:34 -08:00
Vladimir Z Tomov b7c8d66a3d Only comments and renamed variables. 2024-12-06 10:20:17 -08:00
Vladimir Z Tomov c992bd681c minor 2024-12-05 23:13:44 -08:00
Andrew Ho 9bee2fcac8 Merge branch 'master' into master 2024-12-05 22:45:36 -08:00
Andrew Ho f1304374e0 Changed back to not use hypre's internal state tracker for calling init/finalize.
This will mean users can initialize hypre themself, and mfem won't
automatically finalize hypre for them in this situation.
2024-12-05 22:43:05 -08:00
Nuno Nobre d835203da0 Install miniapp content w/ GNU make 2024-12-05 15:42:01 -08:00
Alex Lindsay 49e4bd9d3d Install miniapp content 2024-12-05 15:41:55 -08:00
Alex Lindsay a3137917cd Ignore TAGS 2024-12-05 14:10:12 -08:00
Mittal, Ketan 965959e88c make sure fes_nodes are on device 2024-12-05 13:06:12 -08:00
Arturo Vargas 1136a2f283 remove unused destructor 2024-12-05 12:25:14 -08:00
Arturo Vargas baf6ba5d66 Merge branch 'artv3/fix-ea-ho-lor-transfer-mem-leaks' of github.com:mfem/mfem into artv3/fix-ea-ho-lor-transfer-mem-leaks 2024-12-05 12:23:19 -08:00
Arturo Vargas 3fb7697ffb use unique_ptr 2024-12-05 12:21:44 -08:00
Mittal, Ketan 6d288efd68 merge with master and resolve conflicts 2024-12-05 12:00:12 -08:00
Dylan Copeland 4b87236e73 Simplify interface for RefineElement function. 2024-12-05 11:40:57 -08:00
Dylan Copeland 8464088792 Merge branch 'master' of github.com:mfem/mfem into ncmesh-spacing 2024-12-05 10:44:59 -08:00
Dylan Copeland c03257233f New interface for RefineElement function. 2024-12-05 10:44:34 -08:00
adam-sim-dev 0f3df57632 Merge branch 'master' into operator_equal 2024-12-06 02:39:22 +08:00
Dylan Copeland 5c4d967f6c Indentation 2024-12-05 10:26:05 -08:00
Dylan CopelandandChris Vogl 436d1fa2ff Indentation
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-12-05 10:17:51 -08:00
Arturo Vargas 4f3bc873cc Merge branch 'master' into artv3/fix-ea-ho-lor-transfer-mem-leaks 2024-12-05 10:04:23 -08:00
Arturo Vargas cf90e56850 remove potential double free 2024-12-05 10:01:30 -08:00
Tzanio Kolev 7a6caccf99 Merge pull request #4600 from mfem/tmop-ae-space
Support in InterpolatorFP for mesh and gridfunction to have a different space
2024-12-05 08:33:50 -08:00
Tzanio Kolev f319ddef60 Merge pull request #4595 from adam-sim-dev/otmp
Ignore the .o.tmp temporary files generated by the Intel LLVM compiler
2024-12-05 08:33:22 -08:00
Arturo Vargas 8f4c1dbe79 make style 2024-12-04 10:57:18 -08:00
Arturo Vargas 1e838ff45e fix memory leaks 2024-12-04 10:30:57 -08:00
dylan-copeland 45c130f77b Revert another change for the distance miniapp. 2024-12-03 21:07:20 -08:00
dylan-copeland b805f2a48d Revert changes to distance miniapp. 2024-12-03 21:03:12 -08:00
dylan-copeland 6b87974c70 Merge branch 'master' of github.com:mfem/mfem into ncmesh-spacing 2024-12-03 20:52:40 -08:00
dylan-copeland 181030cc29 Minor fixes. 2024-12-03 20:39:47 -08:00
Mittal, Ketan 04c43fa7b9 Merge branch 'master' of https://github.com/mfem/mfem into gslib-findpts-device-vol 2024-12-03 11:40:25 -08:00
Mittal, Ketan 0dc0d1fcb9 fix comment for doxygen 2024-12-03 11:33:38 -08:00
Mittal, Ketan b96db37ab8 set discrete field order to 1 2024-12-03 11:29:23 -08:00
Andrew Ho 79834fa003 use hypre's internal state manager when possible, allow re-initialization 2024-12-03 09:50:07 -08:00
Andrew Ho 25a1f0b3c6 Merge branch 'master' into master 2024-12-03 09:18:14 -08:00
Mittal, Ketan aba31a53be guard MPI_Barrier and update sample runs 2024-12-02 16:30:03 -08:00
Mittal, Ketan 54982a700a merge with master and resolve conflicts 2024-12-02 13:03:51 -08:00
Mittal, Ketan d47622eed2 minor doxygen 2024-12-02 13:01:34 -08:00
“Henrique 6bcd940840 Conduit file path fix 2024-12-02 14:53:35 +00:00
Vladimir Z Tomov 93c07b5c1c bug 2024-11-29 15:12:02 -08:00
Vladimir Z Tomov 90e77b9ca1 minor 2024-11-29 14:40:10 -08:00
Vladimir Z Tomov 3bd439a3c4 Merge branch 'master' into tmop-ae-space 2024-11-29 14:39:24 -08:00
Vladimir Z Tomov 5b825515f7 fixed a warning. 2024-11-29 14:38:00 -08:00
Vladimir Z Tomov d4da37d89a FD assume mesh_order = field_order for discrete adaptivity. 2024-11-29 00:40:07 -08:00
Vladimir Z Tomov deb8bc7ed3 minor 2024-11-27 17:58:17 -08:00
Vladimir Z Tomov 982583068a Renamed some things, references instead of copies. 2024-11-27 17:49:19 -08:00
adam-sim-dev a6fdbe53b5 Use the operator= to init the (Par)ComplexLinearForm to zero 2024-11-28 09:13:46 +08:00
adam-sim-dev 21bf9c3c10 operator= for (Par)ComplexLinearForm 2024-11-27 17:12:40 +08:00
Tzanio Kolev 899a96b769 Merge pull request #4566 from david-kamensky/nurbs-constructors
Adding new constructors for NURBS patches
2024-11-26 15:51:38 -08:00
Ketan Mittal b4bd2f7e63 Merge branch 'master' into tmop-ae-space 2024-11-26 11:45:02 -08:00
David Kamensky 9837922654 Exceptions when calling serial prolongation/restriction setters for parallel FE space. 2024-11-26 11:05:24 -07:00
Veselin Dobrev 5ec2931690 Merge pull request #4564 from mfem/array-init-list
Use std::initializer_list for braced-list construction
2024-11-25 19:16:23 -08:00
Veselin Dobrev 911511ed1d Merge pull request #4550 from e-aranda/master
fix username std conflict
2024-11-25 19:14:48 -08:00
Mittal, Ketan d7e8d78ca4 Merge branch 'tmop-ae-space' of https://github.com/mfem/mfem into tmop-ae-space 2024-11-25 17:02:56 -08:00
Mittal, Ketan bbc37c5236 make style and test in mesh-optimizer as well 2024-11-25 17:02:39 -08:00
Ketan Mittal 4ca2e5cef2 Merge branch 'master' into tmop-ae-space 2024-11-25 17:00:03 -08:00
Mittal, Ketan c09c15c0b2 add check for adaptive limiting 2024-11-25 16:59:50 -08:00
Mittal, Ketan d6d3e30832 make style 2024-11-25 15:20:23 -08:00
Mittal, Ketan 9129e51b86 fix to make any vdim work 2024-11-25 15:20:02 -08:00
Tzanio Kolev 0797adb30a Merge pull request #4562 from adam-sim-dev/warning
Fix part of warnings for MSVC
2024-11-24 13:50:03 -08:00
Tzanio Kolev 3945247cf5 Merge pull request #4540 from mfem/get-serial-gf
Add version of ParGridFunction::GetSerialGridFunction using existing FiniteElementSpace
2024-11-24 13:49:37 -08:00
Mittal, Ketan de6ac02a8d minor 2024-11-22 17:24:53 -08:00
Mittal, Ketan 873a6aa84c fix advectorCG and interpolatorFP for fields of different order 2024-11-22 17:19:09 -08:00
Will Pazner 2ac825abe8 Merge remote-tracking branch 'origin/master' into pa-empty-partitions
# Conflicts:
#	fem/bilininteg.cpp
#	fem/quadinterpolator.cpp
2024-11-22 11:05:49 -08:00
adam-sim-dev 1262d17e8b Merge branch 'master' into warning 2024-11-22 11:18:32 +08:00
Philipp Dumitrescu 211baab557 Move VectorDim, CurlDim to FiniteElementSpace 2024-11-21 16:50:50 -08:00
adam-sim-dev d6e1063c5e Update globals.cpp 2024-11-22 08:40:09 +08:00
Tzanio Kolev fe9bd03f4b Merge pull request #4585 from mfem/tmop-conv-warning
Fix verbosity levels for NewtonSolver in TMOP miniapps
2024-11-21 16:05:35 -08:00
Will Pazner 7645bce2b5 Merge remote-tracking branch 'origin/master' into array-init-list
# Conflicts:
#	general/array.hpp
#	tests/unit/general/test_array.cpp
2024-11-21 13:27:02 -08:00
Mittal, Ketan 7cb81d5916 minor 2024-11-21 09:38:17 -08:00
Mittal, Ketan 128882200d add checks to ensure size consistency 2024-11-21 09:37:13 -08:00
adam-sim-dev 3f4dd4db7f Resolve the review comments by Veselin 2024-11-21 15:17:47 +08:00
adam-sim-dev 73dbd7446f Merge branch 'master' into warning 2024-11-21 11:16:21 +08:00
Tzanio Kolev 7c1a0eb5e3 Merge pull request #4576 from mfem/kernel-dispatch-ensure-init
Ensure kernel specializations are instantiated
2024-11-20 12:59:40 -08:00
Mittal, Ketan fc0a1eb8da update get obb 2024-11-19 16:10:01 -08:00
Mittal, Ketan e458e579e0 merge with master and resolve conflict 2024-11-19 15:27:57 -08:00
Mittal, Ketan f6dbf49709 Merge branch 'gslib-findpts-device-vol' of https://github.com/mfem/mfem into gslib-findpts-device-vol 2024-11-19 15:27:00 -08:00
Mittal, Ketan f4be9104f5 add method to get AABB and OBB info 2024-11-19 15:26:46 -08:00
Mittal, Ketan 3183af1b3c Merge branch 'tmop-conv-warning' of https://github.com/mfem/mfem into tmop-conv-warning 2024-11-19 14:39:32 -08:00
Mittal, Ketan ced884b231 update rtol for LBFGS run 2024-11-19 14:39:12 -08:00
Will Pazner afbd1a1ba5 Improve Doxygen and unit tests for ParGridFunction::GetSerialGridFunction 2024-11-19 10:49:38 -08:00
Mittal, Ketan 314ae7ed36 out -> outm 2024-11-19 09:46:10 -08:00
adam-sim-dev 72dc18cccb Ignore the .o.tmp temporary file generated by the Intel LLVM compiler 2024-11-19 17:12:49 +08:00
Mittal, Ketan 119d257bb1 clean up 2024-11-18 18:37:51 -08:00
Mittal, Ketan 4559bd4bea minor, and add nu_49 and 50 2024-11-18 18:19:36 -08:00
Justin Laughlin 8e3674396f Merge branch 'master' into nurbs-constructors 2024-11-18 11:49:58 -08:00
Ketan Mittal 4c0c3f822a Merge branch 'master' into get-serial-gf 2024-11-18 11:49:31 -08:00
adam-sim-dev cba0739740 Code style edit 2024-11-18 10:29:35 +08:00
adam-sim-dev 75f0ed1b67 static_cast size_t to int 2024-11-18 09:40:58 +08:00
adam-sim-dev 8853f574da static_cast _Ty (it's int) to int 2024-11-18 08:53:35 +08:00
adam-sim-dev 645b7ba0dc static_cast _Ty (it's int) to int 2024-11-18 08:52:07 +08:00
adam-sim-dev e90cff6413 static_cast _Ty (it's int) to int 2024-11-18 08:42:56 +08:00
Mittal, Ketan 0fc4ee363b add nu51 2024-11-17 12:43:42 -08:00
Ketan Mittal 449778485d Merge branch 'master' into tmop-conv-warning 2024-11-16 13:19:01 -08:00
Mittal, Ketan 59a033b3ea rel norm at the end of Newton and LBFGS 2024-11-16 13:18:20 -08:00
adam-sim-dev bf47bc9210 Update socketstream.cpp 2024-11-16 16:18:05 +08:00
adam-sim-dev 4eac35a79a Fix conversion of pointer differences __int64 to int. Suggested by najlkin 2024-11-16 16:08:20 +08:00
adam-sim-dev dffee6b764 Merge pull request #2 from adam-sim-dev/master
Merge master into warning
2024-11-16 15:29:40 +08:00
Tzanio Kolev 302be130d1 Merge pull request #4592 from mfem/stale-action-update
Update to stale.yml to enable cache, on-demand dispatch, and higher rate limit
2024-11-15 15:24:57 -08:00
Mittal, Ketan 9d7696d803 update to stale.yml 2024-11-15 13:36:10 -08:00
Tzanio Kolev 1e0bb496e8 Merge pull request #4476 from mfem/hughcars/ncsubmesh-dev
SubMesh support for nonconformal AMR
2024-11-15 13:01:18 -08:00
David Kamensky a954ed2046 Adding exception for NURBS mesh with no patches. 2024-11-15 10:35:16 -07:00
Ketan Mittal 064c5261a7 Merge branch 'master' into gslib-findpts-device-vol 2024-11-15 09:21:26 -08:00
David Kamensky 6e814df8cd Simplifying/clarifying KnotVector constructor and adding consistency checks. 2024-11-15 08:56:22 -07:00
adam-sim-dev fe3a6cba80 Merge pull request #1 from adam-sim-dev/_CRT_SECURE_NO_WARNINGS
Define a wrapper for getenv() to turn off CRT deprecation warnings
2024-11-15 09:40:31 +08:00
adam-sim-dev 8883f34f5d Define a wrapper for getenv() to turn off CRT deprecation warnings 2024-11-15 09:28:11 +08:00
737d9032d7 Adding new constructors for NURBS meshes.
This adds some convenience constructors for NURBS patches, and also includes a test exercising the new functionality.

Co-authored-by: Derek Thomas <derek@coreform.com>
Co-authored-by: Kevin Tew <kevin@coreform.com>
Co-authored-by: David Kamensky <david@coreform.com>
Co-authored-by: Justin Laughlin <laughlin6@llnl.gov>
2024-11-14 12:08:15 -07:00
Mittal, Ketan 4993d5e715 update some sample runs 2024-11-14 10:31:23 -08:00
Will Pazner 9148e14b6f Remove unneeded Doxygen comments in cpp file 2024-11-14 09:00:46 -08:00
David KamenskyandDerek Thomas e8c5dbd885 Methods to set prolongation and restriction operators.
Co-authored-by: Derek Thomas <derek@coreform.com>
Co-authored-by: David Kamensky <david@coreform.com>
2024-11-14 08:58:06 -07:00
Will Pazner e561db6d0a MFEM_EXPORT for static kernel dispatch members
For compatibility with Windows/MSVC
2024-11-13 22:41:29 -08:00
Will Pazner 40dbb933e7 Attempt workaround for MSVC segfault
Potential compiler bug with delegated constructors in MSVC
2024-11-13 19:55:17 -08:00
Mark L. Stowell 71a25ca7fa Adding documentation explaining this new behavior 2024-11-13 14:30:16 -08:00
Mark L. Stowell d06d5e2a5a Taking absolute value in each element to avoid cancellation between elements 2024-11-13 13:51:56 -08:00
Mittal, Ketan 026c5c9808 make style 2024-11-13 10:38:34 -08:00
Mittal, Ketan 7587dcad87 compile kernels for v1.0.9 or higher 2024-11-13 10:38:17 -08:00
Mittal, Ketan 3bcd024ca4 fix memory bug for nu11 2024-11-13 07:50:31 -08:00
Ernesto Aranda 701f109c1b Update convection-diffusion.cpp 2024-11-13 12:32:59 +01:00
Ernesto Aranda e250112b1b Update pconvection-diffusion.cpp 2024-11-13 12:32:04 +01:00
Ernesto Aranda 70af0843a6 Update convection-diffusion.cpp 2024-11-13 12:30:21 +01:00
Ernesto Aranda 9176c2b95f Merge branch 'mfem:master' into master 2024-11-13 09:14:35 +01:00
adam-sim-dev 79afc9f006 Merge branch 'master' into warning 2024-11-13 10:55:38 +08:00
Mittal, Ketan 57ebd5f0a1 minor 2024-11-12 17:58:51 -08:00
Mittal, Ketan df8989a28a Merge branch 'master' of https://github.com/mfem/mfem into TMOP_AD_ms 2024-11-12 17:26:11 -08:00
Mittal, Ketan 6377476998 Backwards compatibility for gslib v1.0.7 2024-11-12 17:18:40 -08:00
adam-sim-dev aeeadfe5d0 Revert "Remove #define _CRT_SECURE_NO_WARNINGS"
This reverts commit 941c6c2bac.
2024-11-13 09:10:34 +08:00
adam-sim-dev 29417aed77 Revert "define _CRT_SECURE_NO_WARNINGS for MSVC"
This reverts commit bee8df8b42.
2024-11-13 09:10:26 +08:00
adam-sim-dev 1f6abc2e0b Merge branch 'master' into warning 2024-11-13 05:21:58 +08:00
Will Pazner 293b5f78e8 Change kernel specialization instantiation to use local static variable in constructor
This is in order to avoid issues with the static member variable being optimized
away by the compiler.
2024-11-12 12:55:08 -08:00
Will Pazner 2ebe3efde8 Add unit test for kernel specializations
Adds const reference accessor for the kernel dispatch table
2024-11-12 12:06:14 -08:00
Mittal, Ketan 7399d8a8e0 fix for fitting miniapp 2024-11-11 18:45:30 -08:00
Mittal, Ketan 6ae591075c set verbosity level to always output warnings and errors 2024-11-11 18:15:33 -08:00
Mittal, Ketan 5f69535a0e AD for mu11 2024-11-11 13:16:44 -08:00
Mittal, Ketan df13f75834 use dmu/dW in gradient for mu(A,W) 2024-11-11 12:15:57 -08:00
adam-sim-dev e49747c49b Merge branch 'master' into warning 2024-11-11 08:41:10 +08:00
Tzanio Kolev 5a1d69837d Merge branch 'master' into hughcars/ncsubmesh-dev 2024-11-10 14:00:25 -08:00
Mittal, Ketan b0b726a2a9 merge and resolve conflicts 2024-11-09 16:09:15 -08:00
Mark L. Stowell 86b2599e50 Returning positive errors from GridFunction::ComputeLpError and related functions 2024-11-09 15:07:11 -08:00
Will Pazner 8007b5073f MFEM_EXPORT static member variables
Move QuadratureInterpolator::Kernels to static local variable
2024-11-09 07:31:08 -08:00
Veselin Dobrev 564e2ff58e Re-write a statement to work around an issue with gcc 8.3.1 2024-11-08 17:32:59 -08:00
Will Pazner 780eaeda5a Don't inline Kernels::EnsureInitialized()
Prevent the compiler from optimizing out the calls
2024-11-08 14:15:48 -08:00
Will Pazner 8a4bb61a2a Ensure kernel dispatch tables are initialized
The kernel dispatch tables are initialized in the constructor of a static member
variable.

If this variable is not odr-used, then it may be optimized away, and the
initialization code is never called. This commit ensures the initialization occurs
by adding a no-op EnsureInitialized member function to the Kernels class that can
be called from the integrator constructor.
2024-11-08 12:05:33 -08:00
Alex Lindsay dc1b1ce0ec PetscContainerSetUserDestroy -> PetscContainerSetCtxDestroy 2024-11-08 11:39:20 -08:00
Vladimir Z Tomov cd34967081 minor 2024-11-08 10:26:19 -08:00
Vladimir Z Tomov f2496c3599 minor 2024-11-08 10:22:39 -08:00
Vladimir Tomov 1ad507217d Merge pull request #4573 from hifabian/bugfix-4570
Correct scaling for VectorDiffusionIntegrator
2024-11-08 09:10:35 -08:00
hifabian 5ea5e37c9f Correct scaling for VectorDiffusionIntegrator
This corrects the scaling for VectorCoefficient and MatrixCoefficient in
the AssembleElementVector member function for VectorDiffusionIntegrator.
The integration was incorrect before due to the wrong scaling.

This resolves issue #4570
2024-11-08 12:40:47 +09:00
Vladimir Z Tomov 909272fc0d Unit test for VectorDiffusionIntegrator related to github issue 4570. 2024-11-07 11:38:04 -08:00
adam-sim-dev ff4544771b Merge branch 'master' into warning 2024-11-06 21:45:59 +08:00
adam-sim-dev 255c0c77e0 Merge branch 'master' into warning 2024-11-05 08:43:11 +08:00
Hugh Carson 1fcea2faf4 Merge branch 'master' into hughcars/gmsh-reader-periodic-bugfix 2024-11-04 11:41:39 -05:00
Hugh Carson 199f3616b6 Merge remote-tracking branch 'origin/master' into hughcars/ncsubmesh-dev 2024-11-04 10:28:45 -05:00
Hugh Carson 3b4825675b Updated CHANGELOG 2024-11-04 10:28:39 -05:00
adam-sim-dev 470698bb28 Merge branch 'master' into warning 2024-11-04 08:27:54 +08:00
Jan Nikl 8a4df331fe Replaced plain pointer by the std unique pointer. 2024-11-01 17:28:24 -07:00
Jan Nikl 6c07f873ef Merge branch 'master' into najlkin/impro-hyperbolic 2024-11-01 17:24:06 -07:00
Jan Nikl 7068d022f8 Added notes about usage of some methods. 2024-11-01 17:17:37 -07:00
Will Pazner c232029d84 Add unit test for convertible type Vector constructor
Also add include for type_traits header
2024-11-01 15:56:35 -07:00
Will Pazner c9cf2ec345 Add unit test for convertible type Array constructor 2024-11-01 14:45:51 -07:00
Will Pazner 7195af90b1 Compile-time check for Array convertible-type constructor 2024-11-01 14:43:39 -07:00
adam-sim-dev 325929278d Update communication.hpp 2024-11-01 08:33:52 +08:00
Vladimir Z Tomov 833ed331e1 style and minor formatting. 2024-10-31 14:46:18 -07:00
Will Pazner ea6ab76762 Change order of Vector constructor template parameters to match Array 2024-10-31 13:59:33 -07:00
Will Pazner b4efd401b8 Re-add C-style array constructor for Vector
Also small adjustments to the Vector and Array unit tests
2024-10-31 13:58:11 -07:00
Will Pazner c7bb0201c0 Re-add C-style array constructor for Array 2024-10-31 10:09:59 -07:00
Will Pazner 8a19254fc6 In Vector braced list constructor, use enable_if to select only types convertible to real_t 2024-10-31 10:00:41 -07:00
Will Pazner ff0b016126 Use std::initializer_list for braced-list construction
In the previous implementation, Array<T>({1}) would select the Array<T>(int)
constructor rather than the braced-list constructor.
2024-10-31 09:32:01 -07:00
adam-sim-dev 88f90717b1 Format the code style 2024-10-31 20:38:02 +08:00
adam-sim-dev 256995a053 Format the code style 2024-10-31 20:24:24 +08:00
adam-sim-dev 941c6c2bac Remove #define _CRT_SECURE_NO_WARNINGS 2024-10-31 20:14:22 +08:00
adam-sim-dev de235a0660 static_cast size_t to int 2024-10-31 18:11:24 +08:00
adam-sim-dev bee8df8b42 define _CRT_SECURE_NO_WARNINGS for MSVC 2024-10-31 18:08:23 +08:00
adam-sim-dev 4e17193a11 convert time_t to int 2024-10-31 18:08:00 +08:00
adam-sim-dev b4dfb8660d static_cast size_t to int 2024-10-31 18:07:45 +08:00
Dylan Copeland 95a5c503b1 Remove assert. 2024-10-30 11:53:45 -07:00
dylan-copeland e05a13bc98 Merge branch 'master' of github.com:mfem/mfem into ncmesh-spacing 2024-10-30 11:23:57 -07:00
dylan-copeland e5cfc35f87 Removed int type for refinements. 2024-10-30 11:23:41 -07:00
Hugh Carson 2cb4f5fd65 Merge remote-tracking branch 'origin/master' into hughcars/ncsubmesh-dev 2024-10-30 14:10:26 -04:00
Hugh Carson 9f708051da Address PR feedback
- Rename RemoveBoundaryElementToEdge to DeleteBoundaryElementToEdge
- Remove unneeded member variables `from` and `attributes` from NCSubMesh and ParNCSubMesh
2024-10-30 14:09:09 -04:00
Ernesto Aranda e1b98c30ec Update pconvection-diffusion.cpp (tab problem?) 2024-10-28 23:06:23 +01:00
Ernesto Aranda 33cbfac042 Merge branch 'master' of https://github.com/e-aranda/mfem 2024-10-28 19:32:18 +01:00
Ernesto Aranda 41d94a5528 correcting style 2024-10-28 19:27:31 +01:00
Tzanio Kolev a7382dd25e Update pconvection-diffusion.cpp 2024-10-28 11:24:42 -07:00
Tzanio Kolev c83264e825 Update pconvection-diffusion.cpp 2024-10-28 11:24:04 -07:00
Tzanio Kolev 70a4d67169 Update convection-diffusion.cpp 2024-10-28 11:23:27 -07:00
Ernesto Aranda 498d539f68 Update pconvection-diffusion.cpp fix typo 2024-10-28 18:21:28 +01:00
Ernesto Aranda a7cdb86334 Update convection-diffusion.cpp fixed typo 2024-10-28 18:20:35 +01:00
Ernesto Aranda 4259ecc48b Update pconvection-diffusion.cpp code style 2024-10-28 17:43:55 +01:00
Ernesto Aranda 1382f6c771 Update convection-diffusion.cpp code-style 2024-10-28 17:42:32 +01:00
Ernesto Aranda d0b1f760eb fix username std conflict 2024-10-28 16:55:20 +01:00
Tzanio Kolev 846c63d53e Merge branch 'master' into get-serial-gf 2024-10-27 15:50:53 -07:00
Dylan Copeland 91f14abe6e Disallow inconsistent refinement scalings on an edge. 2024-10-25 12:39:55 -07:00
Hugh Carson d7c3190a68 Restore public access of FindFaceNodes. Wrap another long method 2024-10-25 11:04:15 -04:00
Hugh Carson d98eb5b5a0 Fix long line not caught by ReWrap 2024-10-25 10:39:47 -04:00
Hugh Carson 14e5114039 Address PR feedback
- Fix doc typos: long line, extra spaces, apostrophes.
- Make FindFaceNodes protected again.
- Add doxygen descriptors to IntegerSet default constructors.
2024-10-25 10:36:23 -04:00
Hugh Carson 854b2c5ed8 Merge remote-tracking branch 'origin/master' into hughcars/ncsubmesh-dev 2024-10-22 12:03:40 -04:00
Hugh Carson de70ec68cf Add MFEM_DEPRECATED to some backwards compatible methods 2024-10-22 12:03:22 -04:00
Will Pazner acf8bdb43e Close stream before calling std::remove 2024-10-15 19:50:14 -07:00
Will Pazner c99c7581d8 Add version of ParGridFunction::GetSerialGridFunction using existing FiniteElementSpace
Also update the associated unit test
2024-10-15 16:15:40 -07:00
dylan-copeland 17d29a8390 Minor fix. 2024-10-15 12:05:09 -07:00
dylan-copeland e5de10c9d9 Restoring backwards compatibility. 2024-10-15 11:55:02 -07:00
Tzanio Kolev 33e507ccbc Merge branch 'master' into master 2024-10-14 17:23:45 -07:00
dylan-copeland db75ba5bed Merge branch 'master' of github.com:mfem/mfem into ncmesh-spacing 2024-10-11 21:00:04 -07:00
dylan-copeland a926841cf9 Improved interface for Refinement. 2024-10-11 20:08:05 -07:00
Hugh Carson bb1f48cc06 make style 2024-10-11 13:48:14 -04:00
Hugh Carson b42f27fe48 Move another debug only variables inside of assert 2024-10-11 13:25:40 -04:00
Hugh Carson ee59eb5cc0 Move debug only variable inside of assert 2024-10-11 11:31:38 -04:00
Hugh Carson 6672424982 Unused variable warnings 2024-10-11 11:06:33 -04:00
Hugh Carson 449ae5e8c3 Fix bug where ncmesh would not discover new boundary attribute group 2024-10-11 10:56:28 -04:00
Hugh Carson a130d17bc9 Merge remote-tracking branch 'origin/master' into hughcars/ncsubmesh-dev 2024-10-10 17:25:29 -04:00
Hugh Carson 445e41bb77 Tidy up and style fix 2024-10-10 17:24:51 -04:00
Hugh Carson 6c17447045 Fix triangle ambiguity by only labeling children after tree is finished. 2024-10-10 17:19:22 -04:00
Hugh Carson ada0e37801 Fix by only labeling non-ambiguous or central children 2024-10-09 17:00:52 -04:00
Hugh Carson 4cf617347f Handle the nodes in the case of center -> corner -> root. Non ambiguous paths now have the ability to reorganize all faces discovered. Not handling child reallocation correctly yet 2024-10-09 15:38:23 -04:00
Jan Nikl 976234b376 Fixed initialization of max char speed in HyperbolicFormIntegrator. 2024-10-08 14:42:40 -07:00
Jan Nikl 09b7d0a251 A fix for Windows CI. 2024-10-02 15:34:55 -07:00
Jan Nikl 607775421c Added a note about component-wise Godunov flux to example 18. 2024-10-02 15:23:48 -07:00
Jan Nikl 3d226227d8 Added tolerance for comparison of states. 2024-10-02 15:17:30 -07:00
Andrew Ho 48c1be8fb5 Changes suggested by Will
- fixed accidentally copying the singleton
- deleted copy/move constructors to prevent future accidental copying
2024-09-27 14:39:30 -07:00
Jan Nikl ab15daf765 Specified the maximal velocity in FluxFunction. 2024-09-26 12:31:11 -07:00
Jan Nikl a8ca317754 Added notes about treatment of systems in Rusanov and Godunov. 2024-09-26 10:22:01 -07:00
Jan Nikl 2a703daa56 Added a note about gradients for systems in Rusanov and Godunov. 2024-09-26 09:51:44 -07:00
Andrew Ho b3323ef6e4 Merge remote-tracking branch 'refs/remotes/origin/master' 2024-09-25 18:42:45 -07:00
Andrew Ho 345957aae2 Have Hypre track if it was initialized in addition to finalized.
Moved where HYPRE_Init gets called.
2024-09-25 18:27:10 -07:00
Mathias Rainer Schmidt e85a96e745 - documentation 2024-09-25 14:07:03 -07:00
Mathias Rainer Schmidt 7719196373 - added documentation 2024-09-25 14:01:28 -07:00
Mathias Rainer Schmidt 601ea3a147 Merge remote-tracking branch 'origin/master' into TMOP_AD_ms 2024-09-25 13:54:49 -07:00
Mathias Rainer Schmidt 8e85dcfbc8 - added AD computation of residual and hassian for selected tmop metrics 2024-09-25 13:39:35 -07:00
Jan Nikl f8e809903b Updated CHANGELOG. 2024-09-24 09:52:08 -07:00
Jan Nikl ae6a90e383 Revert "Added a note about average flux for systems."
This reverts commit cd20285435.
2024-09-24 09:40:06 -07:00
Jan Nikl cd20285435 Added a note about average flux for systems. 2024-09-23 17:36:04 -07:00
Jan Nikl e31e40b4fb Replaced latex by unicode for average fluxes. 2024-09-23 17:27:09 -07:00
Jan Nikl 3320cbda43 Make style. 2024-09-23 16:01:57 -07:00
Jan Nikl b269d1dc2f Clarified the definition of the average flux. 2024-09-23 16:00:30 -07:00
Jan Nikl 381abe9002 Fixed and updated the file dox. 2024-09-23 15:59:46 -07:00
Jan Nikl 2496d2af00 Fixed the definition of jump in hyperbolic. 2024-09-23 15:59:46 -07:00
Jan Nikl 8d077885a2 Fixed beggining -> beginning. 2024-09-23 15:31:14 -07:00
Jan NiklandChris Vogl d929df70c2 Fixed a typo in dox.
Co-authored-by: Chris Vogl <vogl2@llnl.gov>
2024-09-23 15:28:20 -07:00
Tzanio Kolev ecf167ca37 Merge branch 'master' into hughcars/ncsubmesh-dev 2024-09-21 16:22:15 -07:00
Ketan Mittal 343c4812a6 use required number of threads in kernels 2024-09-19 20:22:14 -07:00
Jan Nikl beae628d98 Removed Engquist-Osher flux as it conincides with Godunov. 2024-09-19 10:35:18 -07:00
Jan Nikl d9814767a2 Added the new Riemann solvers to ex18(p). 2024-09-19 09:17:14 -07:00
Jan Nikl b6c7920a3d Fixed zeros for real_t type. 2024-09-18 17:46:14 -07:00
Jan Nikl 00a1775659 Fixed shadowing in HyperbolicFormIntegrator::AssembleElementGrad(). 2024-09-18 17:32:16 -07:00
Jan Nikl 8c4f7851b3 Fixed dox of FluxFunction. 2024-09-18 17:27:23 -07:00
Jan Nikl ac0a593a6e Fixed shadowing in FluxFunction. 2024-09-18 17:24:04 -07:00
Jan Nikl b1c328aafb Minor fix of dox in hyperbolic. 2024-09-18 15:41:23 -07:00
Jan Nikl dd3fa25da7 Fixed @see usage in hyperbolic. 2024-09-18 15:41:23 -07:00
Jan Nikl f3814356d3 Added names to the flux functions. 2024-09-18 15:41:23 -07:00
Jan Nikl 7a708f4d64 Minor unification of dox in hyperbolic. 2024-09-18 15:41:23 -07:00
Jan Nikl 969077f526 Added face gradient to HyperbolicFormIntegrator. 2024-09-18 15:41:23 -07:00
Jan Nikl 825e8224a2 Added gradient to Riemann solvers. 2024-09-18 15:39:58 -07:00
Jan Nikl f645bae11a Minor dox improvement in hyperbolic. 2024-09-18 15:39:58 -07:00
Jan Nikl e05b0bcb44 Improved Engquist-Osher Jacobian of average flux to use the limit form. 2024-09-18 15:39:58 -07:00
Jan Nikl 52945319b2 Improved Godunov Jacobian of average flux to use the limit form. 2024-09-18 15:39:58 -07:00
Jan Nikl 13cd22c4b2 Added side=1 implementation of Jacobian to RusanovFlux. 2024-09-18 15:39:58 -07:00
Jan Nikl f920464b4d Added side=1 implementation of Jacobian to GodunovFlux. 2024-09-18 15:39:57 -07:00
Jan Nikl 48cfa24e8e Added side=1 implementation of Jacobian to EngquistOsherFlux. 2024-09-18 15:39:57 -07:00
Jan Nikl 8d2402e654 Minor dox improvement in hyperbolic. 2024-09-18 15:39:57 -07:00
Jan Nikl c0ac027e72 Added Engquist-Osher flux. 2024-09-18 15:39:57 -07:00
Jan Nikl 90ce12cb2f Minor doc fix for GodunovFlux. 2024-09-18 15:39:57 -07:00
Jan Nikl 97619c08f7 Changed non-decreasing to monotonous for Riemann solvers, which accounts for different signs. 2024-09-18 15:39:43 -07:00
Jan Nikl db38490daf Unified fluxes to use indexing parenthesis. 2024-09-18 15:39:43 -07:00
Jan Nikl ffaa345807 Added Godunov average and average Jacobian. 2024-09-18 15:39:43 -07:00
Jan Nikl 91f8956649 Minor dox fixup in hyperbolic. 2024-09-18 15:39:43 -07:00
Jan Nikl 03007510f3 Added Godunov flux. 2024-09-18 15:39:43 -07:00
Jan Nikl af1d533330 Minor fix of dox in hyperbolic. 2024-09-18 15:39:43 -07:00
Jan Nikl 51af7963da Added Rusanov flux Average(Grad)(). 2024-09-18 15:39:07 -07:00
Jan Nikl fa467ebf11 Added a note about monotonicity of F in Rusanov. 2024-09-18 15:39:07 -07:00
Jan Nikl 6d461e600d Minor dox fixes in hyperbolic.hpp. 2024-09-18 15:39:07 -07:00
Jan Nikl 4e52184594 Minor cleanup of RusanovFlux. 2024-09-18 15:39:07 -07:00
Jan Nikl 3dda022825 Added average fluxes to advection and Burgers FluxFunctions. 2024-09-18 15:39:07 -07:00
Jan Nikl be17af796b Added average gradient method to RiemannSolver. 2024-09-18 15:39:07 -07:00
Jan Nikl 130aa7072b Added normal fluxes to advection and Burgers FluxFunctions. 2024-09-18 15:39:07 -07:00
Jan Nikl c36623d665 Added average numerical flux to RiemannSolver. 2024-09-18 15:39:07 -07:00
Jan Nikl dad4e4cf2e Added average (normal) flux methods to FluxFunction. 2024-09-18 15:39:07 -07:00
Jan Nikl cb5470b63c Dimensions clarification in FluxFunction. 2024-09-18 15:39:07 -07:00
Jan Nikl 4aa52f4d61 Changed face/el information -> transformation. 2024-09-18 15:39:07 -07:00
Jan Nikl 39ee3831e7 Minor fix of dox for RiemannSolver::Eval(). 2024-09-18 15:39:07 -07:00
Jan Nikl 824ae129c5 Added Jacobians to AdvectionFlux. 2024-09-18 15:39:07 -07:00
Jan Nikl 7a824a4489 Optimized Burgers taking into account it has num_equations=1. 2024-09-18 15:39:07 -07:00
Jan Nikl f42b4d5789 Extended documentation in hyperbolic.hpp. 2024-09-18 15:39:07 -07:00
Jan Nikl 87638e3f26 Added JdotN to Burgers. 2024-09-18 15:39:07 -07:00
Jan Nikl 77095f5bc8 Moved the constructor of HyperbolicFormIntegrator to the top. 2024-09-18 15:32:47 -07:00
Jan Nikl c4d26dd313 Fixed dim of nor in HyperbolicFormIntegrator::AssembleFaceVector(). 2024-09-18 15:32:46 -07:00
Jan Nikl 093670e070 Fixed physical dshape dimension in HyperbolicFormIntegrator. 2024-09-18 15:32:46 -07:00
Jan Nikl 612e0777d8 Added gradient to HyperbolicFormIntegrator. 2024-09-18 15:32:46 -07:00
Jan Nikl e75359d87f Added optinal sign parameter to HyperbolicFormIntegrator. 2024-09-18 15:32:46 -07:00
Jan Nikl 78aea079ff Added Jacobian to BurgersFlux. 2024-09-18 15:32:46 -07:00
Jan Nikl 985b4c121e Added ComputeFluxJacobianDotN(). 2024-09-18 15:32:46 -07:00
Jan Nikl 07230f9d47 Improved documentation in hyperbolic.hpp. 2024-09-18 15:32:37 -07:00
Jan Nikl 3eacfe9d7e Changed allocation of flux in FluxFunction on-demand. 2024-09-18 14:12:42 -07:00
Ketan Mittal 98e0932f63 reviewer comments 2024-09-16 18:46:28 -07:00
Tzanio Kolev 7f6cbffd82 Merge branch 'master' into master 2024-09-16 08:53:05 -07:00
Andrew Ho f61629c5a5 Whitespace formatting from astyle 2024-09-13 18:02:16 -07:00
Andrew Ho b3fff9267a Moved Hypre::Finalize earlier in Device::~Device, only finalize HYPRE if it's been initialized.
Moving Hypre::Finalize earlier ensures that early return paths in
Device::~Device don't prevent Hypre::Finalize from executing.
2024-09-13 17:55:09 -07:00
Andrew Ho c253f00ddc Added ifdef guard for MFEM_USE_MPI
Hypre singleton doesn't exist otherwise
2024-09-13 12:16:54 -07:00
Andrew Ho cc43f03baa Merge branch 'mfem:master' into master 2024-09-13 11:57:52 -07:00
Andrew Ho cd5a72fabe Ensure that HYPRE is finalized inside the main function.
This fixes a bug where the Hypre singleton is currently cleaned up
after the main function returns, which causes errors with cleaning up
internal Cuda objects in HYPRE.
2024-09-13 11:52:06 -07:00
Hugh Carson 0432b1c47c Check for == -1 rather than < 0, rename variables 2024-09-13 10:25:30 -04:00
dylan-copeland f08544c863 Mac fix 2024-09-12 15:24:35 -07:00
Dylan Copeland 17929e4781 Scaled refinement in unit tests. 2024-09-12 14:10:50 -07:00
Dylan Copeland 37dd6b32d3 CHANGELOG 2024-09-12 13:00:40 -07:00
Hugh Carson 708a8d92f8 Fix Rewrap error + compile error from method definition 2024-09-12 15:17:42 -04:00
Dylan Copeland fd270b6c5f Merge branch 'master' of github.com:mfem/mfem into ncmesh-spacing 2024-09-12 12:16:56 -07:00
Dylan Copeland 910e840fda Documentation and minor fixes. 2024-09-12 12:15:06 -07:00
Hugh Carson f3add08ae3 Address MR feedback:
- Rewrapping to 80
- Forward some base methods to public access
- Restore some old implementation methods in terms of new versions
- Doyxgen and comment fixes
2024-09-12 14:14:07 -04:00
dylan-copeland 6194522f56 make clean 2024-09-11 12:28:52 -07:00
dylan-copeland 99cbad4040 Increase tolerance for single precision. 2024-09-11 12:05:37 -07:00
dylan-copeland fa7adc73eb Wshadow 2024-09-11 11:43:28 -07:00
dylan-copeland 7d3a46e95b Fix mac build. 2024-09-11 11:29:22 -07:00
Dylan Copeland 9bc55b81b4 Output of v1.1. Modified distance miniapp to do scaled AMR based on distance. 2024-09-11 11:11:43 -07:00
Dylan Copeland b541898594 Generalized for refinement of an element in more than 1 direction, with different spacings in each direction. 2024-09-10 13:15:40 -07:00
Tzanio Kolev cf530e9029 Merge branch 'master' into hughcars/ncsubmesh-dev 2024-09-10 12:23:40 -07:00
Hugh Carson 2f6871e449 CI Fixes:
- Unused variables
- Memory leak
- Initialization order
- Remove std::vector usage
- Fix char index into arrays
- Early exit if an empty ncsubmesh is constructed
- Array list initalizer was hardcoded to int
- Remove anonynmous namespace from ncmesh_tables.hpp, use static and
  constexpr instead
- Remove unneeded table includes in ncsubmesh.cpp and pncsubmesh.cpp
- Move trivial type assertion of Array to class body from constructor
- Fix warning about use of abs over std::abs in batched linalg
- Add parent hashtable accessors to bypass access controls in parent
  classes.
- Change loop condition to avoid need for ncmesh_tables.hpp include
- Change [ParSubMesh] to [SubMesh] for Catch2 category, the parallel
  is implicit in [Parallel] label
- Missing include in mesh_test_utils.cpp
- Fix bug for array access with empty ncmesh
2024-09-09 15:10:25 -04:00
Hugh Carson 8a2ef8aa36 Refactor volume ncsubmesh to use same code on serial and parallel paths. Also fix documentation issues 2024-09-09 15:10:25 -04:00
Hugh Carson f0bc536820 Revert back to master some unneeded changes 2024-09-09 15:10:25 -04:00
Hugh Carson f052af3d6b Make style 2024-09-09 15:10:25 -04:00
Hugh Carson a3be873907 Make serial unit test copies of the parallel versions 2024-09-09 15:10:25 -04:00
Hugh Carson d0c358ab48 Refactor serial to use the same code branches as parallel for surface 2024-09-09 15:10:25 -04:00
Hugh Carson 982f7a1729 Refactor the surface submesh into a templated utils method. 2024-09-09 15:10:24 -04:00
Hugh Carson 96ef25817c Convenience addElement method 2024-09-09 15:10:24 -04:00
Hugh Carson 7f0e9c8801 Delete alternative older implementation 2024-09-09 15:10:24 -04:00
Hugh Carson f96f8af545 Upgrade the internal face boundary attribute test for NC refinement of the volume submesh 2024-09-09 15:10:24 -04:00
Hugh Carson 4edd730ce7 ghost boundary attributes mean volume tests are passsing 2024-09-09 15:10:24 -04:00
Hugh Carson 06955c17d9 Fix the boundary attributes of subvolume issue without using an RT space 2024-09-09 15:10:24 -04:00
Hugh Carson 06a8b35570 Comment out a lot of printing, will need to delete properly. Fix up VolumeSubMesh test to be more succinct 2024-09-09 15:10:24 -04:00
Hugh Carson 92ff8c744f Reprotect some members of NCMesh, make exposed derived for testing, make hex nonconformal volume testing ok 2024-09-09 15:10:24 -04:00
Hugh Carson c269b1ea54 More bug fixes and testing
- Fix bug for higher order meshes
- Fix bug with missing fields in NCMesh copy ctor.
- Fix test_array double -> int casting.
- Add test for Hex volume submesh
2024-09-09 15:10:24 -04:00
Hugh Carson cc70734bc0 Add initializer_list constructor to Array, and fix some more edge cases from testing 2024-09-09 15:10:24 -04:00
Hugh Carson 013eace8a6 Fix issue where parent triangular faces discovered by child 3 might disagree with child 0,1,2. If an outer child rediscovers the face the parent face will be reordered. 2024-09-09 15:10:24 -04:00
Hugh Carson 8237b9212d Abandoning interior surfaces, the resulting spaces are too ambiguous and the results don't warrant the extra effort 2024-09-09 15:10:24 -04:00
Hugh Carson 009837f4c8 Collection of bug fixes:
- Fix to permute children if a grandchild discovers a different face node ordering. Running out of tests
- Fix bug for triangle faces where central face parent nodes were not being identified correctly.
- Fix bug in ParentFaceNodes where a central triangle face would discover parent nodes with a different orientation to the surrounding faces.
- Fix bug where check was on parent_nodes rather than face_nodes for a second node hit
2024-09-09 15:10:24 -04:00
Hugh Carson b991cb755e Rewrite of the parallel data structure, complete ncmesh is now built doing a leaf to root tree traversal. The ordering is inherited from the parent ncmesh, ensuring all ranks build the correct ncmesh structure. Can handle external nc boundaries, can't handle internal yet due to face instability. 2024-09-09 15:10:24 -04:00
Hugh Carson 5e3359a805 Preliminary work on developing NCSubMesh
Many small features and a lot of really quite dirty code, print statements etc. This comes from squashing a large number of commits together.
A few different strategies were tried and failed (partially building the NC structure, having ranks have different NC etc.) before arriving at
the final reverse tree traversal algorithm.
2024-09-09 15:10:24 -04:00
Mittal, Ketan 4a9f7f683d remove headers 2024-09-05 10:06:39 -07:00
Mittal, Ketan 9d89d1abef remove stopwatch timers 2024-09-05 10:05:59 -07:00
Mittal, Ketan 2ea08bacb4 make style 2024-09-04 09:24:48 -07:00
Hugh Carson b3ab618e6e Do not remove all internal boundaries if loading a periodic mesh 2024-09-04 10:48:38 -04:00
Ketan Mittal 66a2f5439d minor 2024-09-03 15:37:42 -07:00
Ketan Mittal 60326c575e minor fix, use edge/face mask only with thread 0, and remove bbox if block 2024-09-03 15:36:23 -07:00
Mittal, Ketan a9ae482df0 merge with master and resolve conflicts 2024-09-01 14:26:19 -07:00
Mittal, Ketan 04c7fa0f1c clean up code setting logic for points locally and on other ranks 2024-09-01 14:16:49 -07:00
Mittal, Ketan c65e6ad71c merge with master and resolve conflicts 2024-08-30 15:46:54 -07:00
Mittal, Ketan 8537c16f3d update miniapp to match original.. and add comments to kernel 2024-08-30 15:38:01 -07:00
Dylan Copeland 551c7a2a72 Fixed unit tests. 2024-08-29 20:04:20 -07:00
dylan-copeland 66981ac2fa Fix mac build. 2024-08-29 17:03:16 -07:00
Dylan Copeland 9b331b608d New NC mesh file format for scaling. 2024-08-29 16:40:24 -07:00
Dylan Copeland 11e2e7f039 Created a miniapp to demonstrate random 3:1 refinement in 2D and 3D. Reverted ex1. 2024-08-29 16:05:27 -07:00
Mittal, Ketan 9827a0f33e set gsl_mfem_elem 2024-08-27 08:56:32 -07:00
Mittal, Ketan eb6a485bc2 minor fix for L2 at element face 2024-08-26 17:38:43 -07:00
Mittal, Ketan 24532a295f automatically move data to host depending on field type 2024-08-26 14:10:51 -07:00
Mittal, Ketan 9ae249c2fc refactoring and renaming 2024-08-26 12:14:48 -07:00
Mittal, Ketan 312ed03ffd add way to randomize points in the mesh 2024-08-20 14:59:15 -07:00
Ketan Mittal 1b16534745 bug fix in new interpolation kernel and mapping in findpoints 2024-08-19 17:13:25 -07:00
Mittal, Ketan 81dcc8cdb1 dont need to map refpos for GPU version since it is done locally before communication during find now 2024-08-19 13:01:51 -07:00
Mittal, Ketan cfc96fa055 alternate kernel for interpolate using N^D threads 2024-08-19 09:52:09 -07:00
Mittal, Ketan 1c768998a4 rename functions and clean up 2024-08-14 14:18:55 -07:00
Mittal, Ketan a9f6fc53da get rid of some changes that were put in for surface meshes 2024-08-14 10:36:31 -07:00
Mittal, Ketan 3e967ff7b7 template interpolation kernel 2024-08-13 21:52:52 -07:00
Mittal, Ketan 1bd5b19ad4 fix shared memory array sizes 2024-08-13 13:45:51 -07:00
Mittal, Ketan b0971b1f80 rename and cosmetic changes 2024-08-13 11:27:17 -07:00
Mittal, Ketan 0284105a59 make style 2024-08-12 18:44:04 -07:00
Mittal, Ketan 5830a87b75 bring in changes from other branch 2024-08-12 18:43:53 -07:00
Dylan Copeland b062c59580 Debugged the 2D case and added 2D tests to ex1. 2024-07-17 18:30:30 -07:00
Dylan Copeland 1fce567e82 Fixed 3:1 refinement function by finding correct children in general. Added random test. 2024-07-16 23:23:57 -07:00
Dylan Copeland c06e6d6431 More bug fixes for special cases. 2024-07-16 14:47:55 -07:00
dylan-copeland 8fc7079174 Bug fix. 2024-07-16 11:14:24 -07:00
Dylan Copeland 5fe5e0068d Generalized spacing for forced refinements. 2024-07-15 21:24:42 -07:00
dylan-copeland 4e67781c2c Corrected node scaling with respect to orientation. 2024-07-06 12:29:11 -07:00
dylan-copeland 65daeaa533 Bug fix. 2024-07-05 21:13:24 -07:00
dylan-copeland 281c0182be Generalized to 3D. 2024-07-05 16:41:37 -07:00
Will Pazner f88486fda1 Use Mesh::meshgen directly in Mesh::GetTypicalElementGeometry 2024-06-26 13:20:58 -07:00
Will Pazner d8df6b8020 Add new overload of DGTraceIntegrator::GetRule
Also bring back old overload of DGDiffusionIntegrator::GetRule
2024-06-26 12:23:53 -07:00
dylan-copeland 061b6109a2 Added scale to mesh file format. Generalized TraverseEdge to use scale. 2024-06-25 16:03:48 -07:00
Will Pazner 1241960dc4 Merge remote-tracking branch 'origin/master' into pa-empty-partitions
# Conflicts:
#	fem/gridfunc.cpp
2024-06-24 10:16:56 -07:00
Dylan Copeland ee501168de Generalized NCMesh to use arbitrary relative spacing in refinement. 2024-06-21 19:37:19 -07:00
Will Pazner 4c96ebc652 Revert 'GetTypicalFE' changes in tmop-check-metric miniapp 2024-06-21 08:39:20 -07:00
Will Pazner 06f60e28d5 Revert 'GetTypicalFE' changes to KDTree 2024-06-21 08:37:12 -07:00
Mittal, Ketan 10705f397f [wip performace] minor + make style 2024-05-15 15:11:04 -07:00
Mittal, Ketan bbb78602a4 WIP analyze fpt kernel performance theoretical vs actual speed 2024-05-15 14:48:10 -07:00
Mittal, Ketan 040c5b2450 minor clean up and documentation 2024-05-08 15:30:39 -07:00
Mittal, Ketan 8e7428fbc3 Merge branch 'master' of https://github.com/mfem/mfem into gslib-findpts-device 2024-05-07 16:37:04 -07:00
Mittal, Ketan 5cda5516ff make style 2024-05-07 16:28:18 -07:00
Mittal, Ketan b0060c136d add leaner version of pfindpts 2024-05-07 11:55:55 -07:00
Mittal, Ketan 3d162b51a8 start miniapp for surface meshes 2024-05-02 12:03:28 -07:00
Mittal, Ketan 961882055b fix 2D bug for bounding box check 2024-05-01 21:15:37 -07:00
Will Pazner d86613219c Fix bug in SubMeshUtils::BuildVdofToVdofMap 2024-05-01 10:51:34 -07:00
Will Pazner 63f977d03f Use FiniteElementSpace::GetTypicalTraceElement throughout the PA code 2024-05-01 09:50:23 -07:00
Will Pazner ccccdf1736 Add FiniteElementSpace::GetTypicalTraceElement 2024-05-01 09:50:08 -07:00
Will Pazner 3b6c6ce6fb Variable order support in FiniteElementSpace::GetTraceElement 2024-05-01 09:49:55 -07:00
Will Pazner c768c5f579 Add FiniteElementCollection::GetTraceFE
This is a variable-order version of TraceFiniteElementForGeometry, analogous to
FiniteElementCollection::GetFE, which is a variable-order version of
FiniteElementForGeometry.
2024-05-01 09:49:34 -07:00
Mittal, Ketan 30091d6561 add sample run to getsubmesh 2024-04-24 14:45:21 -07:00
Mittal, Ketan c2722880b5 merge and resolve conflict 2024-04-24 14:44:28 -07:00
Mittal, Ketan 02def42421 add monitor for newton iterations and example to extract boundary meshes using submesh 2024-04-24 14:41:59 -07:00
Will Pazner 9aba2322fc Replace some instances of GetElementBaseGeometry(0) with m.GetTypicalElementGeometry 2024-04-23 14:45:30 -07:00
Will Pazner 4af8539ec3 Support empty partitions in FaceQuadratureSpace 2024-04-23 14:45:30 -07:00
Will Pazner a7eed94562 Replace many instances of GetFaceGeometry(0) with GetTypicalFaceGeometry() 2024-04-23 14:45:30 -07:00
Will Pazner ec535699d8 Change signature of DGDiffusionIntegrator::GetRule 2024-04-23 14:45:30 -07:00
Will Pazner 8184de5c57 Support Mesh::EnsureNodes with empty partitions and "legacy" nodal FEC 2024-04-23 14:45:30 -07:00
Will Pazner 54f6694c16 Add Mesh::GetTypicalFaceGeometry
Analogous to Mesh::GetTypicalElementGeometry
2024-04-23 14:45:30 -07:00
Will Pazner ef9043a122 Replace many instances of GetFE(0) with GetTypicalFE()
Also replace many instances of GetElementTransformation(0) with
GetTypicalElementTransformation() and instances of GetElementGeometry(0) with
GetTypicalElementGeometry().

Remove some "early returns" in PA code with empty partitions. The reasoning is
that the early returns create divergent code paths among different MPI ranks,
which can cause deadlocks if e.g. collectives are used in code paths on not all
ranks.
2024-04-23 14:45:30 -07:00
Will Pazner d3855adba0 Use "typical" mesh elements in mass and convection PA 2024-04-22 18:15:18 -07:00
Will Pazner a981a24dcc Add Mesh::GetTypicalElementTransformation 2024-04-22 18:14:39 -07:00
Will Pazner aab735263b Add Element::TypeFromGeometry 2024-04-22 18:14:24 -07:00
Veselin Dobrev 966143b0ce Some additions and tweaks to get ex14p to work with empty partitions 2024-04-22 17:35:14 -07:00
Ketan Mittal 01b3d0ae8b fix typo in get_edge 2024-03-26 17:11:40 -07:00
Mittal, Ketan ae862ca52d kernel with alternate implementation 2024-03-26 14:20:15 -07:00
Mittal, Ketan 051499f343 output bounding box mesh and add findpts kernel utilizing more threads 2024-03-26 13:37:51 -07:00
Ketan Mittal 98ee0c0047 use gsl_mesh for nodes 2024-03-19 12:01:27 -07:00
Mittal, Ketan d8a13d8da6 hash box test typo 2024-03-18 14:02:30 -07:00
Mittal, Ketan 87a9aa9f69 template kernel and minor refactoring 2024-03-18 13:12:42 -07:00
Ketan Mittal e315b66aeb minor - missing const specifier 2024-03-04 11:39:39 -08:00
Mittal, Ketan fb54c7c59a template 2D kernel and refactor loop over threads in 2D 2024-03-04 09:50:35 -08:00
Mittal, Ketan 72277751d7 copyright 2024-02-15 10:12:23 -08:00
Mittal, Ketan c5ae059755 minor 2024-02-15 10:10:41 -08:00
Ketan Mittal 56eded3dc3 fix bug in 2D 2024-02-13 15:02:22 -08:00
Mittal, Ketan 08a4ed8197 try2: restore max size for shared memory 2024-02-13 11:18:46 -08:00
Mittal, Ketan 7026c0eba2 restore max size for shared memory 2024-02-13 11:16:15 -08:00
Mittal, Ketan 650dec9528 minor refactor 2024-02-13 10:58:38 -08:00
Mittal, Ketan 1f2e93b391 Merge branch 'master' of https://github.com/mfem/mfem into gslib-findpts-device 2024-02-12 15:26:22 -08:00
Mittal, Ketan 9792e8dbdd working in 2D 2024-02-12 15:22:46 -08:00
Ketan Mittal 0bf89c6b62 working on lassen 2023-12-01 17:30:20 -08:00
Mittal, Ketan cd01ff94f5 minor 2023-11-29 13:02:29 -08:00
Ketan Mittal ab1c6c8652 working on lassen 2023-11-28 21:06:10 -08:00
Mittal, Ketan 13032f8ee9 interpolate local and make style 2023-11-20 14:56:36 -08:00
Ketan Mittal 393277c410 minor changes to make it work on lassen 2023-11-20 14:55:53 -08:00
Mittal, Ketan 75dbd8dd14 Merge branch 'master' of https://github.com/mfem/mfem into gslib-findpts-device 2023-11-20 13:39:36 -08:00
Mittal, Ketan 9047821947 add timers 2023-11-20 13:39:21 -08:00
Mittal, Ketan a6fac7c19b minor 2023-11-07 13:03:24 -08:00
Mittal, Ketan 128c3f7d73 interp local 2023-11-07 12:56:22 -08:00
Mittal, Ketan 0bc03e1128 make style 2023-10-30 17:37:53 -07:00
Mittal, Ketan 21fb6bc10f remove use of static variables 2023-10-30 17:30:04 -07:00
Mittal, Ketan ae4acc54d8 initial implementation for findpoints-local 2023-10-30 17:01:39 -07:00
237 changed files with 16230 additions and 2704 deletions
+21 -7
View File
@@ -29,6 +29,10 @@ on:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
HYPRE_ARCHIVE: v2.19.0.tar.gz
HYPRE_TOP_DIR: hypre-2.19.0
@@ -92,6 +96,7 @@ jobs:
build-system: cmake
hypre-target: int32
precision: fp64
config-opts: '-DCMAKE_INSTALL_PREFIX=../cmake-install'
# This option can be set to pass additional configuration options to
# the MFEM configuration command.
# config-opts: '-DCMAKE_VERBOSE_MAKEFILE=ON'
@@ -114,13 +119,6 @@ jobs:
runs-on: ${{ matrix.os }}
steps:
# This external action allows to interrupt a workflow already running on
# the same branch to save resources.
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.12.1
with:
access_token: ${{ github.token }}
# Fix 'No space left on device' errors for Ubuntu builds.
- name: Run Actions Cleaner
if: matrix.os == 'ubuntu-latest'
@@ -306,6 +304,22 @@ jobs:
ctest --rerun-failed --output-on-failure -C ${CTEST_CONFIG}
shell: bash
- name: make install
if: matrix.build-system == 'make'
run: |
cd ${{ env.MFEM_TOP_DIR }} && make install
- name: cmake install
if: matrix.build-system == 'cmake'
run: |
CONFIG="Release"
[[ ${{ matrix.target }} == 'dbg' ]] && CONFIG="Debug"
TARGET="install"
[[ ${{ matrix.os }} == 'windows-latest' ]] && TARGET="INSTALL"
cd ${{ env.MFEM_TOP_DIR }} && \
cmake --build build --target ${TARGET} --config ${CONFIG}
shell: bash
# Code coverage (process and upload reports)
- name: codecov
if: matrix.codecov == 'YES'
+4
View File
@@ -18,6 +18,10 @@ on:
# The branches below must be a subset of the branches above
branches: ["master"]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
analyze:
name: Analyze
+4 -5
View File
@@ -22,6 +22,10 @@ on:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
HYPRE_ARCHIVE: v2.19.0.tar.gz
HYPRE_TOP_DIR: hypre-2.19.0
@@ -34,11 +38,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.12.1
with:
access_token: ${{ github.token }}
- name: checkout MFEM
uses: actions/checkout@v4
with:
+6 -13
View File
@@ -22,22 +22,15 @@ on:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
Serial:
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
steps:
- name: Temporary workaround for sanitizer crashes
# See https://github.com/actions/runner-images/issues/9491
# The issue should be fixed in the next runner image for Ubuntu 22.04,
# see https://github.com/actions/runner-images/pull/9513
run: sudo sysctl vm.mmap_rnd_bits=28
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.12.1
with:
access_token: ${{ github.token }}
- name: MFEM Checkout
uses: actions/checkout@v4
with:
@@ -55,7 +48,7 @@ jobs:
build-system: make
library-only: false
config-options:
CXX="clang++-14"
CXX="clang++-18"
CXXFLAGS="-g -O1 -std=c++11
-fsanitize=address
-fno-omit-frame-pointer
+4 -5
View File
@@ -19,6 +19,10 @@ on:
pull_request:
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
# This workflow is run on pushes to any branch in the MFEM repo (with or without
# PRs), as well as on updates to PRs from forks. In particular, we do not
# duplicate work by running on both pushes and updates to local PRs. We do that
@@ -33,11 +37,6 @@ jobs:
(github.event_name == 'push' ||
github.event.pull_request.head.repo.full_name != github.repository)
steps:
- name: Cancel Previous Runs
uses: styfle/cancel-workflow-action@0.12.1
with:
access_token: ${{ github.token }}
- name: checkout mfem
uses: actions/checkout@v4
+4 -2
View File
@@ -3,6 +3,7 @@
name: Mark stale issues and pull requests
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
@@ -13,9 +14,10 @@ jobs:
permissions:
issues: write
pull-requests: write
actions: write
steps:
- uses: actions/stale@v5
- uses: actions/stale@v9
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
stale-issue-message: ':warning: This issue has been automatically marked as stale because it has not had any activity in the last month. *If no activity occurs in the next week, it will be automatically closed.* Thank you for your contributions.'
@@ -24,6 +26,6 @@ jobs:
days-before-close: 7
stale-issue-label: 'stale'
stale-pr-label: 'stale'
operations-per-run: 30
operations-per-run: 500
exempt-issue-labels: "bug,WIP,ready-for-review,in-review,in-next"
exempt-pr-labels: "bug,WIP,ready-for-review,in-review,in-next"
+11
View File
@@ -8,6 +8,7 @@
# Object and library files
*.o
*.o.tmp
/libmfem.*
/miniapps/common/libmfem-common.*
@@ -226,6 +227,7 @@ miniapps/meshing/extruder
miniapps/meshing/fit-node-position
miniapps/meshing/trimmer
miniapps/meshing/reflector
miniapps/meshing/ref321
miniapps/meshing/mesh-optimizer
miniapps/meshing/pmesh-optimizer
miniapps/meshing/pmesh-fitting
@@ -245,6 +247,8 @@ miniapps/meshing/shaper.mesh
miniapps/meshing/extruder.mesh
miniapps/meshing/trimmer.mesh
miniapps/meshing/reflected.mesh
miniapps/meshing/ref321.mesh
miniapps/meshing/sol.gf
miniapps/meshing/optimized*
miniapps/meshing/perturbed*
miniapps/meshing/polar-nc.mesh
@@ -339,6 +343,7 @@ miniapps/toys/rubik
miniapps/toys/snake
miniapps/toys/lissajous
miniapps/toys/mondrian
miniapps/toys/spiral
miniapps/toys/snake-init.mesh
miniapps/toys/snake-user.mesh
miniapps/toys/snake-joined.mesh
@@ -427,3 +432,9 @@ pkg.gitcommit
# Jupyter Notebook Checkpoints
.ipynb_checkpoints
# emacs tag file
TAGS
# vs code
.vscode
+54
View File
@@ -12,6 +12,8 @@ Version 4.7.1 (development)
===========================
- Refactored ALGOIM cut integration rules. The interface is unified with
the interface for moment based cut integration rules.
- Altered (Par)GridFunction::Compute*Error functions to ensure they return
non-negative values and therefore behave as "norms".
Discretization improvements
---------------------------
@@ -20,11 +22,28 @@ Discretization improvements
- Added support for boundary constraints to the hybridization class.
- Added support for external boundary submeshes with nonconformal mesh adaptation.
- Added assembly of Jacobians to `HyperbolicFormIntegrator`.
- Added average fluxes to `NumericalFlux` (formerly `RiemannSolver`)
and `FluxFunction`.
- Added component-wise upwinded flux (`ComponentwiseUpwindFlux`).
Meshing improvements
--------------------
- Added native AD support for numerous TMOP metrics that didn't have first or
second derivative implementations.
- The ExodusII reader now handles pyramid and wedge element types. Mixed meshes
are also supported.
- Added support for nonuniform anisotropic (nonconforming) mesh refinement with
arbitrary spacing in each direction, for quadrilateral (2D) and hexahedral
(3D) meshes. This enables in particular 3:1 refinement, as demonstrated in the
new meshing miniapp ref321.
New and updated examples and miniapps
-------------------------------------
- Added miniapps to demonstrate the H(div) and H(curl) NURBS elements.
@@ -32,6 +51,9 @@ New and updated examples and miniapps
- Added an MFEM example for the eikonal equation. This new solver is based on
the proximal Galerkin method introduced by Keith and Surowiec.
- Added a new toy miniapp that animates an interesting fidget spiral cone toy.
See miniapps/toys/spiral.cpp.
- Added a command line option to all miniapps (`-p` or `--send-port`) for
specifying the GLVis server socket port (19916 by default).
@@ -56,6 +78,9 @@ GPU computing
high-order transfer operators. New kernels can be offloaded as device
kernels. Example usage may be found in lor-transfer.cpp under miniapps/tools.
- Added support for GPU accelerated FindPointsGSLIB. Note that this will require
the users to switch from gslib v1.0.7 to v1.0.9.
Miscellaneous
-------------
- Added support for SUNDIALS v7. See the section "API changes" for some small
@@ -73,10 +98,39 @@ Miscellaneous
- Added support for custom interpolation procedure in FindPointsGSLIB.
- `FiniteElementSpace` has new methods to directly set prolongation and
restriction operators to arbitrary sparse matrices.
- There are new convenience constructors for NURBS patches and knot vectors.
- Added convenience methods for manipulating boundary attribute marker arrays;
`(Par)Mesh::MarkExternalBoundaries`, `(Par)Mesh::UnmarkInternalBoundaries`,
`(Par)Mesh::MarkNamedBoundaries`, and `(Par)Mesh::UnmarkNamedBoundaries`.
See examples `ex1.cpp`, `ex1p.cpp`, and `ex11p.cpp` for basic usage.
- Added `(Par)Mesh::GetExteriorFaceMarker` for identifying faces on the
exterior of the mesh irrespective of their presence in the list of "boundary
elements".
- Added methods to `(Par)FiniteElementSpace` to identify all degrees of freedom
located on the exterior of the domain without reference to the list of
"boundary elements"; `GetExteriorVDofs` and `GetExteriorTrueDofs`.
- `LinearFormIntegrator` and `NonlinearFormIntegrator` (including
`BilinearFormIntegrator`) now all inherit from a base class `Integrator`
that combines some logic related to selecting quadrature rules. This includes
a virtual method `Integrator::GetDefaultIntegrationRule`, which should be
favored over directly defining a default integration rule in the element-level
assembly routines (although the latter is still possible, by leaving the new
virtual method as its default base implementation of returning `NULL`).
API changes
-----------
- API change: in class GridFunction, 'fec' was renamed to 'fec_owned'.
- API change: `RiemannSolver` was renamed to `NumericalFlux` (the old name has
been been depracated through typedef)
- API change: support for SUNDIALS v7:
* the SUNDIALS types `realtype` and `booleantype` are no longer defined by v7
and therefore MFEM now uses the new type names `sunrealtype` and
+36 -19
View File
@@ -618,15 +618,37 @@ set(MASTER_HEADERS
${PROJECT_SOURCE_DIR}/mfem.hpp
${PROJECT_SOURCE_DIR}/mfem-performance.hpp)
set(_lib_path "${CMAKE_INSTALL_PREFIX}/lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON CACHE BOOL "")
set(CMAKE_INSTALL_RPATH "${_lib_path}" CACHE PATH "")
set(CMAKE_INSTALL_NAME_DIR "${_lib_path}" CACHE PATH "")
# Installation options (we use GNUInstallDirs but prefer lib by default)
set(MFEM_USE_GNUINSTALLDIRS OFF CACHE BOOL
"Use CMAKE_INSTALL_LIBDIR as defined by the GNUInstallDirs CMake module.")
if (NOT MFEM_USE_GNUINSTALLDIRS)
mfem_cache_path(CMAKE_INSTALL_LIBDIR "lib" "Object code libraries (lib)")
endif()
include(GNUInstallDirs)
mfem_cache_path(INSTALL_INCLUDE_DIR "${CMAKE_INSTALL_INCLUDEDIR}"
"Relative or absolute path for installing header files.")
mfem_cache_path(INSTALL_BIN_DIR "${CMAKE_INSTALL_BINDIR}"
"Relative or absolute path for installing the binaries.")
mfem_cache_path(INSTALL_LIB_DIR "${CMAKE_INSTALL_LIBDIR}"
"Relative or absolute path for installing the library.")
mfem_cache_path(INSTALL_SHARE_DIR "${CMAKE_INSTALL_DATAROOTDIR}"
"Relative or absolute path for installing shared data.")
# other options: "share/mfem/cmake", "lib/mfem/cmake"
mfem_cache_path(INSTALL_CMAKE_DIR "${INSTALL_LIB_DIR}/cmake/mfem"
"Relative or absolute path for installing cmake config files.")
set(MFEM_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH
"The MFEM source directory" FORCE)
set(MFEM_INSTALL_DIR ${CMAKE_INSTALL_PREFIX} CACHE PATH
"The MFEM install directory" FORCE)
mfem_path_to_fullpath("${INSTALL_LIB_DIR}" "${CMAKE_INSTALL_PREFIX}" _lib_path)
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON CACHE BOOL "")
if(NOT DEFINED CMAKE_INSTALL_RPATH)
set(CMAKE_INSTALL_RPATH "${_lib_path}")
endif()
if(NOT DEFINED CMAKE_INSTALL_NAME_DIR)
set(CMAKE_INSTALL_NAME_DIR "${_lib_path}")
endif()
# Variables used when generating _config.hpp, and config.mk
set(MFEM_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(MFEM_INSTALL_DIR ${CMAKE_INSTALL_PREFIX})
# Declaring the library
mfem_add_library(mfem ${SOURCES} ${HEADERS} ${MASTER_HEADERS})
@@ -745,7 +767,11 @@ endif()
# Create a target for all miniapps and, optionally, enable it.
set(MFEM_ALL_MINIAPPS_TARGET_NAME miniapps)
add_mfem_target(${MFEM_ALL_MINIAPPS_TARGET_NAME} ${MFEM_ENABLE_MINIAPPS})
add_subdirectory(miniapps EXCLUDE_FROM_ALL)
if (MFEM_ENABLE_MINIAPPS)
add_subdirectory(miniapps) #install miniapps if enabled
else()
add_subdirectory(miniapps EXCLUDE_FROM_ALL)
endif()
# Target to build all executables, i.e. everything.
add_custom_target(exec)
@@ -795,15 +821,6 @@ add_subdirectory(doc)
#-------------------------------------------------------------------------------
message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
set(INSTALL_INCLUDE_DIR include
CACHE PATH "Relative path for installing header files.")
set(INSTALL_BIN_DIR bin
CACHE PATH "Relative path for installing the binaries.")
set(INSTALL_LIB_DIR lib
CACHE PATH "Relative path for installing the library.")
# other options: "share/mfem/cmake", "lib/mfem/cmake"
set(INSTALL_CMAKE_DIR lib/cmake/mfem
CACHE PATH "Relative path for installing cmake config files.")
target_include_directories(mfem BEFORE
PUBLIC
@@ -828,7 +845,7 @@ foreach(Header mfem.hpp mfem-performance.hpp)
endforeach()
install(FILES ${MASTER_HEADERS} DESTINATION ${INSTALL_INCLUDE_DIR}/mfem)
# Install the headers; currently, the miniapps headers are excluded
# Install the headers (except common miniapp which is installed from its subdir)
install(DIRECTORY ${MFEM_SOURCE_DIRS}
DESTINATION ${INSTALL_INCLUDE_DIR}/mfem
FILES_MATCHING PATTERN "*.hpp")
+25 -11
View File
@@ -220,9 +220,10 @@ An optional installation of the library and the headers can be performed with
make install [PREFIX=<dir>]
The library will be installed in $(PREFIX)/lib, the headers in
$(PREFIX)/include, and the configuration makefile (config.mk) in
$(PREFIX)/share/mfem. The PREFIX option can also be set during configuration.
The library will be installed in ${PREFIX}/lib, the headers in
${PREFIX}/include, and the configuration and testing makefiles (config.mk and
test.mk) in ${PREFIX}/share/mfem. The PREFIX option can also be set during
configuration.
Information about the current build configuration can be viewed using
@@ -271,8 +272,9 @@ Build options:
Installation options:
PREFIX - Specify the installation directory. The library (libmfem.a) will be
installed in $(PREFIX)/lib, the headers in $(PREFIX)/include, and
the configuration makefile (config.mk) in $(PREFIX)/share/mfem.
installed in ${PREFIX}/lib, the headers in ${PREFIX}/include, and
the configuration and testing makefiles (config.mk and test.mk) in
${PREFIX}/share/mfem.
INSTALL - Specify the install program, default = /usr/bin/install
INSTALL_DEF_PERM - Specify the default install permissions. This affects
headers and configuration makefiles, default = 644
@@ -791,14 +793,14 @@ The specific libraries and their options are:
Versions: 1.9.3
- GSLIB (optional), used when MFEM_USE_GSLIB = YES. The gslib library must be
built prior to the MFEM build, as follows: download gslib-1.0.7, untar it at
the same level as MFEM and create a symbolic link: "ln -s gslib-1.0.7 gslib".
built prior to the MFEM build, as follows: download gslib-1.0.9, untar it at
the same level as MFEM and create a symbolic link: "ln -s gslib-1.0.9 gslib".
Build gslib in parallel or in serial based on the desired MFEM build: "make
clean; make CC=mpicc" or "make clean; make CC=gcc MPI=0". Build MFEM with
MFEM_USE_GSLIB=YES.
URL: https://github.com/gslib/gslib/archive/v1.0.7.tar.gz
URL: https://github.com/gslib/gslib/archive/v1.0.9.tar.gz
Options: GSLIB_OPT, GSLIB_LIB.
Versions: GSLIB >= 1.0.7.
Versions: GSLIB >= 1.0.9.
- ALGOIM (optional), used when MFEM_USE_ALGOIM=YES. The library provides only
headers so it just needs to be downloaded at the same level as MFEM. Download
@@ -980,8 +982,20 @@ or
cmake --build . --config Release --target install [Xcode]
cmake --build . --config Release --target INSTALL [Visual Studio]
The library will be installed in <PREFIX>/lib, the headers in <PREFIX>/include,
and the configuration CMake files in <PREFIX>/lib/cmake/mfem.
By default, the library will be installed in ${CMAKE_INSTALL_PREFIX}/lib, the
headers in ${CMAKE_INSTALL_PREFIX}/include, the configuration CMake files in
${CMAKE_INSTALL_PREFIX}/lib/cmake/mfem, and the configuration and testing GNU
make files in ${CMAKE_INSTALL_PREFIX}/share/mfem. For fine-tuning the
installation directories the following variables can be used:
INSTALL_INCLUDE_DIR, INSTALL_LIB_DIR, INSTALL_BIN_DIR (e.g. for dll files on
Windows), INSTALL_SHARE_DIR, and INSTALL_CMAKE_DIR; alternatively, with lower
precedence, the CMake GNUInstallDirs variables can also be used:
CMAKE_INSTALL_INCLUDEDIR, CMAKE_INSTALL_LIBDIR, CMAKE_INSTALL_BINDIR and
CMAKE_INSTALL_DATAROOTDIR. Note that the default for INSTALL_LIB_DIR and
CMAKE_INSTALL_LIBDIR is lib. This is in contrast to the default behavior for
GNUInstallDirs, which defines a platform-dependent default value for
CMAKE_INSTALL_LIBDIR (lib or lib64 or lib/<multiarch-tuple> on Debian). To
restore this behavior, the user can set MFEM_USE_GNUINSTALLDIRS=YES.
Configuration variables (CMake)
@@ -117,8 +117,8 @@ macro (MULTIPASS_SOURCE_RUNS includes libraries source runs language)
math (EXPR _tmp "${MULTIPASS_TEST_COUNT} + 1") # Why can't I add to a cache variable?
set (MULTIPASS_TEST_COUNT ${_tmp} CACHE INTERNAL "Unique test ID")
set (testname MULTIPASS_TEST_${MULTIPASS_TEST_COUNT}_${runs})
set (CMAKE_REQUIRED_INCLUDES ${includes})
set (CMAKE_REQUIRED_LIBRARIES ${libraries})
set (CMAKE_REQUIRED_INCLUDES ${includes} ${MPI_${language}_INCLUDE_PATH})
set (CMAKE_REQUIRED_LIBRARIES ${libraries} ${MPI_${language}_LIBRARIES})
if(${language} STREQUAL "C")
check_c_source_runs ("${source}" ${testname})
elseif(${language} STREQUAL "CXX")
+1 -1
View File
@@ -14,7 +14,7 @@
# - SLEPC_INCLUDE_DIRS
# - SLEPC_LIBRARIES
set(SLEPc_REQUIRED_PACKAGES "PETSC" CACHE STRING
set(SLEPc_REQUIRED_PACKAGES "PETSC" "MPI" CACHE STRING
"Additional packages required by SLEPc")
include(MfemCmakeUtilities)
+46 -5
View File
@@ -138,6 +138,8 @@ macro(add_mfem_miniapp MFEM_EXE_NAME)
# Actually add the executable
mfem_add_executable(${MFEM_EXE_NAME} ${MAIN_LIST}
${EXTRA_SOURCES_LIST} ${EXTRA_HEADERS_LIST})
install(TARGETS ${MFEM_EXE_NAME}
RUNTIME DESTINATION miniapps)
add_dependencies(${MFEM_ALL_MINIAPPS_TARGET_NAME} ${MFEM_EXE_NAME})
add_dependencies(${MFEM_EXE_NAME} ${MFEM_EXEC_PREREQUISITES_TARGET_NAME})
@@ -825,6 +827,20 @@ function(mfem_get_target_options Target CompileOptsVar LinkOptsVar)
endfunction(mfem_get_target_options)
#
# If ${Path} is not an absolute path, assign ${Prefix}/${Path} to the variable
# ${OutVar}. If ${Path} is an absolute path, assign ${Path} to the variable
# ${OutVar}.
#
function(mfem_path_to_fullpath Path Prefix OutVar)
if(IS_ABSOLUTE "${Path}")
set(${OutVar} "${Path}" PARENT_SCOPE)
else()
set(${OutVar} "${Prefix}/${Path}" PARENT_SCOPE)
endif()
endfunction()
#
# Function that creates 'config.mk' from 'config.mk.in' for the both the
# build- and the install-locations and define install rules for 'config.mk'
@@ -991,9 +1007,12 @@ function(mfem_export_mk_files)
"${PROJECT_BINARY_DIR}/config/test.mk" COPYONLY)
# Update variables for the install-tree version of 'config.mk'
set(MFEM_INC_DIR "${CMAKE_INSTALL_PREFIX}/include")
set(MFEM_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib")
set(MFEM_TEST_MK "${CMAKE_INSTALL_PREFIX}/share/mfem/test.mk")
mfem_path_to_fullpath(
"${INSTALL_INCLUDE_DIR}" "${CMAKE_INSTALL_PREFIX}" MFEM_INC_DIR)
mfem_path_to_fullpath(
"${INSTALL_LIB_DIR}" "${CMAKE_INSTALL_PREFIX}" MFEM_LIB_DIR)
mfem_path_to_fullpath(
"${INSTALL_SHARE_DIR}/mfem/test.mk" "${CMAKE_INSTALL_PREFIX}" MFEM_TEST_MK)
set(MFEM_CONFIG_EXTRA "")
# Create the install-tree version of 'config.mk'
@@ -1003,8 +1022,30 @@ function(mfem_export_mk_files)
# Install rules for 'config.mk' and 'test.mk'
install(FILES ${PROJECT_SOURCE_DIR}/config/test.mk
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mfem/)
DESTINATION ${INSTALL_SHARE_DIR}/mfem/)
install(FILES ${PROJECT_BINARY_DIR}/config/config-install.mk
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/mfem/ RENAME config.mk)
DESTINATION ${INSTALL_SHARE_DIR}/mfem/
RENAME config.mk)
endfunction()
#
# Function similar to the macro _GNUInstallDirs_cache_path from the module
# GNUInstallDirs. Used to process variables like INSTALL_LIB_DIR if they are
# set on the cmake command line without specifying type: -DINSTALL_LIB_DIR=lib.
# Without this special treatment, relative paths are expanded to full paths
# and we want to avoid that.
#
function(mfem_cache_path PathVar DefaultPath HelpStr)
if(NOT DEFINED ${PathVar})
set(${PathVar} "${DefaultPath}" CACHE PATH "${HelpStr}")
endif()
get_property(cache_type CACHE ${PathVar} PROPERTY TYPE)
if(cache_type STREQUAL "UNINITIALIZED")
file(TO_CMAKE_PATH "${${PathVar}}" cmakepath)
set_property(CACHE ${PathVar} PROPERTY TYPE PATH)
set_property(CACHE ${PathVar} PROPERTY VALUE "${cmakepath}")
set_property(CACHE ${PathVar} PROPERTY HELPSTRING "${HelpStr}")
endif()
endfunction()
+8 -3
View File
@@ -163,13 +163,18 @@ int main(int argc, char *argv[])
// 6. Determine the list of true (i.e. conforming) essential boundary dofs.
// In this example, the boundary conditions are defined by marking all
// the boundary attributes from the mesh as essential (Dirichlet) and
// converting them to a list of true dofs.
// the external boundary attributes from the mesh as essential (Dirichlet)
// and converting them to a list of true dofs.
Array<int> ess_tdof_list;
if (mesh.bdr_attributes.Size())
{
Array<int> ess_bdr(mesh.bdr_attributes.Max());
ess_bdr = 1;
ess_bdr = 0;
// Apply boundary conditions on all external boundaries:
mesh.MarkExternalBoundaries(ess_bdr);
// Boundary conditions can also be applied based on named attributes:
// mesh.MarkNamedBoundaries(set_name, ess_bdr)
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
+5 -1
View File
@@ -192,7 +192,11 @@ int main(int argc, char *argv[])
if (pmesh->bdr_attributes.Size())
{
ess_bdr.SetSize(pmesh->bdr_attributes.Max());
ess_bdr = 1;
ess_bdr = 0;
// Apply boundary conditions on all external boundaries:
pmesh->MarkExternalBoundaries(ess_bdr);
// Boundary conditions can also be applied based on named attributes:
// pmesh->MarkNamedBoundaries(set_name, ess_bdr)
}
ParBilinearForm *a = new ParBilinearForm(fespace);
+8 -3
View File
@@ -190,13 +190,18 @@ int main(int argc, char *argv[])
// 8. Determine the list of true (i.e. parallel conforming) essential
// boundary dofs. In this example, the boundary conditions are defined
// by marking all the boundary attributes from the mesh as essential
// (Dirichlet) and converting them to a list of true dofs.
// by marking all the external boundary attributes from the mesh as
// essential (Dirichlet) and converting them to a list of true dofs.
Array<int> ess_tdof_list;
if (pmesh.bdr_attributes.Size())
{
Array<int> ess_bdr(pmesh.bdr_attributes.Max());
ess_bdr = 1;
ess_bdr = 0;
// Apply boundary conditions on all external boundaries:
pmesh.MarkExternalBoundaries(ess_bdr);
// Boundary conditions can also be applied based on named attributes:
// pmesh.MarkNamedBoundaries(set_name, ess_bdr)
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
+1 -1
View File
@@ -206,7 +206,7 @@ int main(int argc, char *argv[])
// 7. Set up the linear form b(.) which corresponds to the right-hand side of
// the FEM linear system.
ComplexLinearForm b(fespace, conv);
b.Vector::operator=(0.0);
b = 0.0;
// 8. Define the solution vector u as a complex finite element grid function
// corresponding to fespace. Initialize u with initial guess of 1+0i or
+1 -1
View File
@@ -235,7 +235,7 @@ int main(int argc, char *argv[])
// 9. Set up the parallel linear form b(.) which corresponds to the
// right-hand side of the FEM linear system.
ParComplexLinearForm b(fespace, conv);
b.Vector::operator=(0.0);
b = 0.0;
// 10. Define the solution vector u as a parallel complex finite element grid
// function corresponding to fespace. Initialize u with initial guess of
+1 -1
View File
@@ -347,7 +347,7 @@ int main(int argc, char *argv[])
{
b.AddDomainIntegrator(NULL, new VectorFEDomainLFIntegrator(f));
}
b.Vector::operator=(0.0);
b = 0.0;
b.Assemble();
// 11. Define the solution vector x as a complex finite element grid function
+1 -1
View File
@@ -392,7 +392,7 @@ int main(int argc, char *argv[])
{
b.AddDomainIntegrator(NULL, new VectorFEDomainLFIntegrator(f));
}
b.Vector::operator=(0.0);
b = 0.0;
b.Assemble();
// 13. Define the solution vector x as a parallel complex finite element grid
+1 -1
View File
@@ -318,7 +318,7 @@ int main(int argc, char *argv[])
// 10. Set up the parallel linear form b(.) which corresponds to the
// right-hand side of the FEM linear system.
ParComplexLinearForm b(&fespace, conv);
b.Vector::operator=(0.0);
b = 0.0;
// 11a. Define the solution vector u as a parallel complex finite element
// grid function corresponding to fespace. Initialize u to equal zero.
+1 -1
View File
@@ -77,7 +77,7 @@ public:
DG_Solver(SparseMatrix &M_, SparseMatrix &K_, const FiniteElementSpace &fes)
: M(M_),
K(K_),
prec(fes.GetFE(0)->GetDof(),
prec(fes.GetTypicalFE()->GetDof(),
BlockILU::Reordering::MINIMUM_DISCARDED_FILL),
dt(-1.0)
{
+1 -1
View File
@@ -145,7 +145,7 @@ public:
linear_solver(M.GetComm()),
dt(-1.0)
{
int block_size = fes.GetFE(0)->GetDof();
int block_size = fes.GetTypicalFE()->GetDof();
if (prec_type == PrecType::ILU)
{
prec = new BlockILU(block_size,
+68
View File
@@ -0,0 +1,68 @@
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
int main(int argc, char *argv[])
{
// 1. Initialize MPI and HYPRE.
Mpi::Init();
int num_procs = Mpi::WorldSize();
int myid = Mpi::WorldRank();
Hypre::Init();
//Mesh mesh = Mesh::MakeCartesian3D(2, 2 ,2, Element::Type::HEXAHEDRON);
Mesh mesh = Mesh::MakeCartesian3D(2, 2, 2, Element::Type::TETRAHEDRON);
// Build faces and boundary
mesh.FinalizeTopology();
mesh.Finalize();
// Changing element and boundary attributes
for (int i=0; i<mesh.GetNE(); ++i)
{
mesh.SetAttribute(i, myid + 1);
}
for (int i=0; i<mesh.GetNBE(); ++i)
{
mesh.SetBdrAttribute(i, 100);
}
mesh.SetAttributes();
// Add internal boundary facets used for integrators
// TODO: what should be added here?
// Finalize connectivity and topology (is this even needed?)
mesh.FinalizeTopology();
mesh.Finalize(true);
// Make sure mesh is non-conforming
mesh.EnsureNCMesh(true);
// Make parallel mesh
ParMesh pmesh(MPI_COMM_WORLD, mesh);
mesh.Clear();
pmesh.EnsureNCMesh(true);
// Refinement
Array<Refinement> refinements;
refinements.Append(Refinement(0)); // Local element 0 on this rank
pmesh.GeneralRefinement(refinements);
pmesh.SetAttributes();
{
ostringstream mesh_name;
mesh_name << "mesh." << setfill('0') << setw(6) << myid;
ofstream mesh_ofs(mesh_name.str().c_str());
mesh_ofs.precision(8);
pmesh.Print(mesh_ofs);
}
return 0;
}
+1 -1
View File
@@ -76,7 +76,7 @@ public:
DG_Solver(SparseMatrix &M_, SparseMatrix &K_, const FiniteElementSpace &fes)
: M(M_),
K(K_),
prec(fes.GetFE(0)->GetDof(),
prec(fes.GetTypicalFE()->GetDof(),
BlockILU::Reordering::MINIMUM_DISCARDED_FILL),
dt(-1.0)
{
+1 -1
View File
@@ -143,7 +143,7 @@ public:
linear_solver(M.GetComm()),
dt(-1.0)
{
int block_size = fes.GetFE(0)->GetDof();
int block_size = fes.GetTypicalFE()->GetDof();
if (prec_type == PrecType::ILU)
{
prec = new BlockILU(block_size,
+6
View File
@@ -148,8 +148,13 @@ set(SRCS
tmop_tools.cpp
tmop_amr.cpp
gslib.cpp
gslib/findpts_local_2.cpp
gslib/findpts_local_3.cpp
gslib/interpolate_local_2.cpp
gslib/interpolate_local_3.cpp
transfer.cpp
hyperbolic.cpp
integrator.cpp
)
set(HDRS
@@ -248,6 +253,7 @@ set(HDRS
gslib.hpp
transfer.hpp
hyperbolic.hpp
integrator.hpp
)
if (MFEM_USE_SIDRE)
+1 -1
View File
@@ -1006,7 +1006,7 @@ void BilinearForm::ComputeElementMatrices()
}
int num_elements = fes->GetNE();
int num_dofs_per_el = fes->GetFE(0)->GetDof() * fes->GetVDim();
int num_dofs_per_el = fes->GetTypicalFE()->GetDof() * fes->GetVDim();
element_matrices = new DenseTensor(num_dofs_per_el, num_dofs_per_el,
num_elements);
+2 -4
View File
@@ -862,7 +862,7 @@ void EABilinearFormExtension::Assemble()
SetupRestrictionOperators(L2FaceValues::SingleValued);
ne = trial_fes->GetMesh()->GetNE();
elemDofs = trial_fes->GetFE(0)->GetDof();
elemDofs = trial_fes->GetTypicalFE()->GetDof();
ea_data.SetSize(ne*elemDofs*elemDofs, Device::GetMemoryType());
ea_data.UseDevice(true);
@@ -878,9 +878,7 @@ void EABilinearFormExtension::Assemble()
integrators[i]->AssembleEA(*a->FESpace(), ea_data, i);
}
faceDofs = trial_fes ->
GetTraceElement(0, trial_fes->GetMesh()->GetFaceGeometry(0)) ->
GetDof();
faceDofs = trial_fes->GetTypicalTraceElement()->GetDof();
MFEM_VERIFY(a->GetBBFI()->Size() == 0,
"Element assembly does not support AddBoundaryIntegrator yet.");
+106 -75
View File
@@ -508,7 +508,8 @@ void MixedScalarIntegrator::AssembleElementMatrix2(
elmat.SetSize(test_nd, trial_nd);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int ir_order = this->GetIntegrationOrder(trial_fe, test_fe, Trans);
@@ -599,7 +600,7 @@ void MixedVectorIntegrator::AssembleElementMatrix2(
elmat.SetSize(test_nd, trial_nd);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int ir_order = this->GetIntegrationOrder(trial_fe, test_fe, Trans);
@@ -755,7 +756,8 @@ void MixedScalarVectorIntegrator::AssembleElementMatrix2(
elmat.SetSize(test_nd, trial_nd);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int ir_order = this->GetIntegrationOrder(trial_fe, test_fe, Trans);
@@ -805,9 +807,8 @@ void GradientIntegrator::AssembleElementMatrix2(
shape.SetSize(test_dof);
elmat.SetSize(dim * test_dof, trial_dof);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(trial_fe, test_fe,
Trans);
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
elmat = 0.0;
elmat_comp.SetSize(test_dof, trial_dof);
@@ -848,13 +849,41 @@ void GradientIntegrator::AssembleElementMatrix2(
const IntegrationRule &GradientIntegrator::GetRule(const FiniteElement
&trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans)
const ElementTransformation &Trans)
{
int order = Trans.OrderGrad(&trial_fe) + test_fe.GetOrder() + Trans.OrderJ();
return IntRules.Get(trial_fe.GetGeomType(), order);
}
DiffusionIntegrator::DiffusionIntegrator(const IntegrationRule *ir)
: BilinearFormIntegrator(ir),
Q(nullptr), VQ(nullptr), MQ(nullptr), maps(nullptr), geom(nullptr)
{
static Kernels kernels;
}
DiffusionIntegrator::DiffusionIntegrator(Coefficient &q,
const IntegrationRule *ir)
: DiffusionIntegrator(ir)
{
Q = &q;
}
DiffusionIntegrator::DiffusionIntegrator(VectorCoefficient &q,
const IntegrationRule *ir)
: DiffusionIntegrator(ir)
{
VQ = &q;
}
DiffusionIntegrator::DiffusionIntegrator(MatrixCoefficient &q,
const IntegrationRule *ir)
: DiffusionIntegrator(ir)
{
MQ = &q;
}
void DiffusionIntegrator::AssembleElementMatrix
( const FiniteElement &el, ElementTransformation &Trans,
DenseMatrix &elmat )
@@ -892,21 +921,7 @@ void DiffusionIntegrator::AssembleElementMatrix
#endif
elmat.SetSize(nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el);
const NURBSFiniteElement *NURBSFE =
dynamic_cast<const NURBSFiniteElement *>(&el);
bool deleteRule = false;
if (NURBSFE && patchRules)
{
const int patch = NURBSFE->GetPatch();
const int* ijk = NURBSFE->GetIJK();
Array<const KnotVector*>& kv = NURBSFE->KnotVectors();
ir = &patchRules->GetElementRule(NURBSFE->GetElement(), patch, ijk, kv,
deleteRule);
}
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
@@ -941,11 +956,6 @@ void DiffusionIntegrator::AssembleElementMatrix
AddMult_a_AAt(w, dshapedxt, elmat);
}
}
if (deleteRule)
{
delete ir;
}
}
void DiffusionIntegrator::AssembleElementMatrix2(
@@ -991,8 +1001,7 @@ void DiffusionIntegrator::AssembleElementMatrix2(
#endif
elmat.SetSize(te_nd, tr_nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(trial_fe, test_fe);
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
@@ -1069,8 +1078,8 @@ void DiffusionIntegrator::AssembleElementVector(
elvect.SetSize(nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el);
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
elvect = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
@@ -1235,7 +1244,6 @@ real_t DiffusionIntegrator::ComputeFluxEnergy
int order = 2 * fluxelem.GetOrder(); // <--
const IntegrationRule *ir = &IntRules.Get(fluxelem.GetGeomType(), order);
real_t energy = 0.0;
if (d_energy) { *d_energy = 0.0; }
@@ -1310,6 +1318,17 @@ const IntegrationRule &DiffusionIntegrator::GetRule(
return IntRules.Get(trial_fe.GetGeomType(), order);
}
MassIntegrator::MassIntegrator(const IntegrationRule *ir)
: BilinearFormIntegrator(ir), Q(nullptr), maps(nullptr), geom(nullptr)
{
static Kernels kernels;
}
MassIntegrator::MassIntegrator(Coefficient &q, const IntegrationRule *ir)
: MassIntegrator(ir)
{
Q = &q;
}
void MassIntegrator::AssembleElementMatrix
( const FiniteElement &el, ElementTransformation &Trans,
@@ -1325,8 +1344,8 @@ void MassIntegrator::AssembleElementMatrix
elmat.SetSize(nd);
shape.SetSize(nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el, Trans);
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
@@ -1360,9 +1379,7 @@ void MassIntegrator::AssembleElementMatrix2(
shape.SetSize(tr_nd);
te_shape.SetSize(te_nd);
const IntegrationRule *ir = IntRule ? IntRule :
&GetRule(trial_fe, test_fe, Trans);
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
@@ -1385,7 +1402,7 @@ void MassIntegrator::AssembleElementMatrix2(
const IntegrationRule &MassIntegrator::GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans)
const ElementTransformation &Trans)
{
// int order = trial_fe.GetOrder() + test_fe.GetOrder();
const int order = trial_fe.GetOrder() + test_fe.GetOrder() + Trans.OrderW();
@@ -1461,7 +1478,8 @@ void ConvectionIntegrator::AssembleElementMatrix(
Vector vec1;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
int order = Trans.OrderGrad(&el) + Trans.Order() + el.GetOrder();
@@ -1502,7 +1520,7 @@ void GroupConvectionIntegrator::AssembleElementMatrix(
shape.SetSize(nd);
grad.SetSize(nd,dim);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
int order = Trans.OrderGrad(&el) + el.GetOrder();
@@ -1544,7 +1562,7 @@ void GroupConvectionIntegrator::AssembleElementMatrix(
const IntegrationRule &ConvectionIntegrator::GetRule(
const FiniteElement &trial_fe, const FiniteElement &test_fe,
ElementTransformation &Trans)
const ElementTransformation &Trans)
{
int order = Trans.OrderGrad(&trial_fe) + Trans.Order() + test_fe.GetOrder();
@@ -1552,7 +1570,7 @@ const IntegrationRule &ConvectionIntegrator::GetRule(
}
const IntegrationRule &ConvectionIntegrator::GetRule(
const FiniteElement &el, ElementTransformation &Trans)
const FiniteElement &el, const ElementTransformation &Trans)
{
return GetRule(el,el,Trans);
}
@@ -1581,7 +1599,8 @@ void VectorMassIntegrator::AssembleElementMatrix
mcoeff.SetSize(vdim);
}
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
int order = 2 * el.GetOrder() + Trans.OrderW() + Q_order;
@@ -1664,7 +1683,8 @@ void VectorMassIntegrator::AssembleElementMatrix2(
mcoeff.SetSize(vdim);
}
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int order = (trial_fe.GetOrder() + test_fe.GetOrder() +
@@ -1739,7 +1759,7 @@ void VectorFEDivergenceIntegrator::AssembleElementMatrix2(
elmat.SetSize(test_nd, trial_nd);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int order = trial_fe.GetOrder() + test_fe.GetOrder() - 1; // <--
@@ -1790,7 +1810,7 @@ void VectorFEWeakDivergenceIntegrator::AssembleElementMatrix2(
elmat.SetSize(test_nd, trial_nd);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
// The integrand on the reference element is:
@@ -1883,7 +1903,7 @@ void VectorFECurlIntegrator::AssembleElementMatrix2(
elmat.SetSize(test_nd, trial_nd);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int order = trial_fe.GetOrder() + test_fe.GetOrder() - 1; // <--
@@ -2047,7 +2067,7 @@ void DerivativeIntegrator::AssembleElementMatrix2 (
invdfdx.SetSize(dim, spaceDim);
shape.SetSize (test_nd);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int order;
@@ -2114,7 +2134,7 @@ void CurlCurlIntegrator::AssembleElementMatrix
if (MQ) { M.SetSize(dimc); }
if (DQ) { D.SetSize(dimc); }
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
int order;
@@ -2191,7 +2211,8 @@ void CurlCurlIntegrator::AssembleElementMatrix2(const FiniteElement &trial_fe,
if (MQ) { M.SetSize(dimc); }
if (DQ) { D.SetSize(dimc); }
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int order;
@@ -2383,7 +2404,8 @@ void VectorCurlCurlIntegrator::AssembleElementMatrix(
Jadj.SetSize(dim);
#endif
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
// use the same integration rule as diffusion
@@ -2431,7 +2453,8 @@ real_t VectorCurlCurlIntegrator::GetElementEnergy(
#endif
DenseMatrix elfun_mat(elfun.GetData(), dof, dim);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
// use the same integration rule as diffusion
@@ -2514,8 +2537,8 @@ void MixedCurlIntegrator::AssembleElementMatrix2(
real_t c;
Vector d_col;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int order = trial_fe.GetOrder() + test_fe.GetOrder() + Trans.OrderJ();
@@ -2583,7 +2606,7 @@ void VectorFEMassIntegrator::AssembleElementMatrix(
elmat.SetSize(dof);
elmat = 0.0;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
// int order = 2 * el.GetOrder();
@@ -2628,6 +2651,8 @@ void VectorFEMassIntegrator::AssembleElementMatrix2(
const FiniteElement &trial_fe, const FiniteElement &test_fe,
ElementTransformation &Trans, DenseMatrix &elmat)
{
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (test_fe.GetRangeType() == FiniteElement::SCALAR
&& trial_fe.GetRangeType() == FiniteElement::VECTOR)
{
@@ -2651,8 +2676,6 @@ void VectorFEMassIntegrator::AssembleElementMatrix2(
#endif
elmat.SetSize(vdim*test_dof, trial_dof);
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int order = (Trans.OrderW() + test_fe.GetOrder() + trial_fe.GetOrder());
@@ -2752,7 +2775,6 @@ void VectorFEMassIntegrator::AssembleElementMatrix2(
elmat.SetSize (test_dof, trial_dof);
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int order = (Trans.OrderW() + test_fe.GetOrder() + trial_fe.GetOrder());
@@ -2819,8 +2841,7 @@ void VectorDivergenceIntegrator::AssembleElementMatrix2(
elmat.SetSize (test_dof, dim*trial_dof);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(trial_fe, test_fe,
Trans);
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
elmat = 0.0;
@@ -2853,7 +2874,7 @@ void VectorDivergenceIntegrator::AssembleElementMatrix2(
const IntegrationRule &VectorDivergenceIntegrator::GetRule(
const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans)
const ElementTransformation &Trans)
{
int order = Trans.OrderGrad(&trial_fe) + test_fe.GetOrder() + Trans.OrderJ();
return IntRules.Get(trial_fe.GetGeomType(), order);
@@ -2875,7 +2896,7 @@ void DivDivIntegrator::AssembleElementMatrix(
#endif
elmat.SetSize(dof);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
int order = 2 * el.GetOrder() - 2; // <--- OK for RTk
@@ -2922,7 +2943,7 @@ void DivDivIntegrator::AssembleElementMatrix2(
#endif
elmat.SetSize(te_nd,tr_nd);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(trial_fe, test_fe, Trans);
if (ir == NULL)
{
int order = 2 * max(test_fe.GetOrder(),
@@ -2980,7 +3001,7 @@ void VectorDiffusionIntegrator::AssembleElementMatrix(
elmat.SetSize(vdim * dof);
pelmat.SetSize(dof);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
ir = &DiffusionIntegrator::GetRule(el,el);
@@ -3067,7 +3088,8 @@ void VectorDiffusionIntegrator::AssembleElementVector(
DenseMatrix mat_in(elfun.GetData(), dof, vdim);
DenseMatrix mat_out(elvect.GetData(), dof, vdim);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
ir = &DiffusionIntegrator::GetRule(el,el);
@@ -3090,10 +3112,9 @@ void VectorDiffusionIntegrator::AssembleElementVector(
VQ->Eval(vcoeff, Tr, ip);
for (int k = 0; k < vdim; ++k)
{
pelmat *= w*vcoeff(k);
const Vector vec_in(mat_in.GetColumn(k), dof);
Vector vec_out(mat_out.GetColumn(k), dof);
pelmat.AddMult(vec_in, vec_out);
pelmat.AddMult_a(w*vcoeff(k), vec_in, vec_out);
}
}
else if (MQ)
@@ -3104,9 +3125,8 @@ void VectorDiffusionIntegrator::AssembleElementVector(
Vector vec_out(mat_out.GetColumn(ii), dof);
for (int jj = 0; jj < vdim; ++jj)
{
pelmat *= w*mcoeff(ii,jj);
const Vector vec_in(mat_in.GetColumn(jj), dof);
pelmat.Mult(vec_in, vec_out);
pelmat.AddMult_a(w*mcoeff(ii,jj), vec_in, vec_out);
}
}
}
@@ -3152,7 +3172,7 @@ void ElasticityIntegrator::AssembleElementMatrix(
elmat.SetSize(dof * dim);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Trans);
if (ir == NULL)
{
int order = 2 * Trans.OrderGrad(&el); // correct order?
@@ -3161,7 +3181,7 @@ void ElasticityIntegrator::AssembleElementMatrix(
elmat = 0.0;
for (int i = 0; i < ir -> GetNPoints(); i++)
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
@@ -3320,7 +3340,8 @@ real_t ElasticityIntegrator::ComputeFluxEnergy(const FiniteElement &fluxelem,
// Use the same integration rule as in AssembleElementMatrix, replacing 'el'
// with 'fluxelem' when 'IntRule' is not set.
// Should we be using a different (more accurate) rule here?
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(fluxelem, Trans);
if (ir == NULL)
{
int order = 2 * Trans.OrderGrad(&fluxelem);
@@ -3381,7 +3402,6 @@ real_t ElasticityIntegrator::ComputeFluxEnergy(const FiniteElement &fluxelem,
energy += w * pt_e;
}
return energy;
}
@@ -3664,10 +3684,15 @@ void DGTraceIntegrator::AssembleFaceMatrix(const FiniteElement &trial_fe1,
}
const IntegrationRule &DGTraceIntegrator::GetRule(
Geometry::Type geom, int order, FaceElementTransformations &T)
Geometry::Type geom, int order, const ElementTransformation &T)
{
int int_order = T.Elem1->OrderW() + 2*order;
return IntRules.Get(geom, int_order);
return IntRules.Get(geom, T.OrderW() + 2*order);
}
const IntegrationRule &DGTraceIntegrator::GetRule(
Geometry::Type geom, int order, const FaceElementTransformations &T)
{
return GetRule(geom, order, *T.Elem1);
}
void DGDiffusionIntegrator::AssembleFaceMatrix(
@@ -3719,7 +3744,7 @@ void DGDiffusionIntegrator::AssembleFaceMatrix(
{
const int order = (ndof2) ? max(el1.GetOrder(),
el2.GetOrder()) : el1.GetOrder();
ir = &GetRule(order, Trans);
ir = &GetRule(order, Trans.GetGeometryType());
}
// assemble: < {(Q \nabla u).n},[v] > --> elmat
@@ -3898,11 +3923,17 @@ void DGDiffusionIntegrator::AssembleFaceMatrix(
}
const IntegrationRule &DGDiffusionIntegrator::GetRule(
int order, FaceElementTransformations &T)
int order, Geometry::Type geom)
{
// order is typically the maximum of the order of the left and right elements
// neighboring the given face.
return IntRules.Get(T.GetGeometryType(), 2*order);
return IntRules.Get(geom, 2*order);
}
const IntegrationRule &DGDiffusionIntegrator::GetRule(
int order, FaceElementTransformations &T)
{
return GetRule(order, T.GetGeometryType());
}
// static method
+68 -34
View File
@@ -2135,7 +2135,15 @@ public:
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
const ElementTransformation &Trans);
protected:
const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe,
const FiniteElement& test_fe,
const ElementTransformation& trans) const override
{
return &GetRule(trial_fe, test_fe, trans);
}
};
/** Class for integrating the bilinear form $a(u,v) := (Q \nabla u, \nabla v)$ where $Q$
@@ -2156,7 +2164,7 @@ public:
MFEM_REGISTER_KERNELS(ApplyPAKernels, ApplyKernelType, (int, int, int));
MFEM_REGISTER_KERNELS(DiagonalPAKernels, DiagonalKernelType, (int, int, int));
static struct Kernels { Kernels(); } kernels;
struct Kernels { Kernels(); };
protected:
Coefficient *Q;
@@ -2234,26 +2242,16 @@ private:
public:
/// Construct a diffusion integrator with coefficient Q = 1
DiffusionIntegrator(const IntegrationRule *ir = nullptr)
: BilinearFormIntegrator(ir),
Q(NULL), VQ(NULL), MQ(NULL), maps(NULL), geom(NULL) { }
DiffusionIntegrator(const IntegrationRule *ir = nullptr);
/// Construct a diffusion integrator with a scalar coefficient q
DiffusionIntegrator(Coefficient &q, const IntegrationRule *ir = nullptr)
: BilinearFormIntegrator(ir),
Q(&q), VQ(NULL), MQ(NULL), maps(NULL), geom(NULL) { }
DiffusionIntegrator(Coefficient &q, const IntegrationRule *ir = nullptr);
/// Construct a diffusion integrator with a vector coefficient q
DiffusionIntegrator(VectorCoefficient &q,
const IntegrationRule *ir = nullptr)
: BilinearFormIntegrator(ir),
Q(NULL), VQ(&q), MQ(NULL), maps(NULL), geom(NULL) { }
DiffusionIntegrator(VectorCoefficient &q, const IntegrationRule *ir = nullptr);
/// Construct a diffusion integrator with a matrix coefficient q
DiffusionIntegrator(MatrixCoefficient &q,
const IntegrationRule *ir = nullptr)
: BilinearFormIntegrator(ir),
Q(NULL), VQ(NULL), MQ(&q), maps(NULL), geom(NULL) { }
DiffusionIntegrator(MatrixCoefficient &q, const IntegrationRule *ir = nullptr);
/** Given a particular Finite Element computes the element stiffness matrix
elmat. */
@@ -2325,6 +2323,14 @@ public:
ApplyPAKernels::Specialization<DIM,D1D,Q1D>::Add();
DiagonalPAKernels::Specialization<DIM,D1D,Q1D>::Add();
}
protected:
const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe,
const FiniteElement& test_fe,
const ElementTransformation& trans) const override
{
return &GetRule(trial_fe, test_fe);
}
};
/** Class for local mass matrix assembling $a(u,v) := (Q u, v)$ */
@@ -2356,15 +2362,13 @@ public:
MFEM_REGISTER_KERNELS(ApplyPAKernels, ApplyKernelType, (int, int, int));
MFEM_REGISTER_KERNELS(DiagonalPAKernels, DiagonalKernelType, (int, int, int));
static struct Kernels { Kernels(); } kernels;
struct Kernels { Kernels(); };
public:
MassIntegrator(const IntegrationRule *ir = NULL)
: BilinearFormIntegrator(ir), Q(NULL), maps(NULL), geom(NULL) { }
MassIntegrator(const IntegrationRule *ir = nullptr);
/// Construct a mass integrator with coefficient q
MassIntegrator(Coefficient &q, const IntegrationRule *ir = NULL)
: BilinearFormIntegrator(ir), Q(&q), maps(NULL), geom(NULL) { }
MassIntegrator(Coefficient &q, const IntegrationRule *ir = NULL);
/** Given a particular Finite Element computes the element mass matrix
elmat. */
@@ -2398,7 +2402,7 @@ public:
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
const ElementTransformation &Trans);
bool SupportsCeed() const override { return DeviceCanUseCeed(); }
@@ -2410,6 +2414,15 @@ public:
ApplyPAKernels::Specialization<DIM,D1D,Q1D>::Add();
DiagonalPAKernels::Specialization<DIM,D1D,Q1D>::Add();
}
protected:
const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe,
const FiniteElement& test_fe,
const ElementTransformation& trans) const override
{
return &GetRule(trial_fe, test_fe, trans);
}
};
/** Mass integrator $(u, v)$ restricted to the boundary of a domain */
@@ -2470,13 +2483,22 @@ public:
void AddMultTransposePA(const Vector &x, Vector &y) const override;
static const IntegrationRule &GetRule(const FiniteElement &el,
ElementTransformation &Trans);
const ElementTransformation &Trans);
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
const ElementTransformation &Trans);
bool SupportsCeed() const override { return DeviceCanUseCeed(); }
protected:
const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe,
const FiniteElement& test_fe,
const ElementTransformation& trans) const override
{
return &GetRule(trial_fe, test_fe, trans);
}
};
// Alias for @ConvectionIntegrator.
@@ -2941,7 +2963,16 @@ public:
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
const ElementTransformation &Trans);
protected:
const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe,
const FiniteElement& test_fe,
const ElementTransformation& trans) const override
{
return &GetRule(trial_fe, test_fe, trans);
}
};
/// $(Q \nabla \cdot u, \nabla \cdot v)$ for Raviart-Thomas elements
@@ -2984,19 +3015,17 @@ public:
const Coefficient *GetCoefficient() const { return Q; }
};
/** Integrator for
$$
(Q \nabla u, \nabla v) = \sum_i (Q \nabla u_i, \nabla v_i) e_i e_i^{\mathrm{T}}
$$
for vector FE spaces, where $e_i$ is the unit vector in the $i$-th direction.
The resulting local element matrix is square, of size <tt> vdim*dof </tt>,
/** Class for integrating the bilinear form $a(u,v) := (Q \nabla u, \nabla v)$,
where $u=(u_1,\dots,u_n)$ and $v=(v_1,\dots,v_n)$, $u_i$ and $v_i$ are
defined by scalar FE through standard transformation.
See the constructors' documentation for all Coefficient options.
The computed local element matrix is square, of size <tt> vdim*dof </tt>,
where \c vdim is the vector dimension space and \c dof is the local degrees
of freedom. The integrator is not aware of the true vector dimension and
must use \c VectorCoefficient, \c MatrixCoefficient, or a caller-specified
value to determine the vector space. For a scalar coefficient, the caller
may manually specify the vector dimension or the vector dimension is assumed
to be the spatial dimension (i.e. 2-dimension or 3-dimension).
*/
to be the spatial dimension (i.e. 2-dimension or 3-dimension). */
class VectorDiffusionIntegrator : public BilinearFormIntegrator
{
protected:
@@ -3292,7 +3321,10 @@ public:
const bool add) override;
static const IntegrationRule &GetRule(Geometry::Type geom, int order,
FaceElementTransformations &T);
const FaceElementTransformations &T);
static const IntegrationRule &GetRule(Geometry::Type geom, int order,
const ElementTransformation &T);
private:
void SetupPA(const FiniteElementSpace &fes, FaceType type);
@@ -3381,6 +3413,8 @@ public:
const IntegrationRule &GetRule(int order, FaceElementTransformations &T);
const IntegrationRule &GetRule(int order, Geometry::Type geom);
private:
void SetupPA(const FiniteElementSpace &fes, FaceType type);
};
+1 -1
View File
@@ -135,7 +135,7 @@ void InitBasis(const FiniteElementSpace &fes,
const IntegrationRule &ir,
Ceed ceed, CeedBasis *basis)
{
const mfem::FiniteElement &fe = *fes.GetFE(0);
const mfem::FiniteElement &fe = *fes.GetTypicalFE();
InitBasisImpl(fes, fe, ir, ceed, basis);
}
+1 -1
View File
@@ -93,7 +93,7 @@ public:
const int first_index = indices[0];
const mfem::FiniteElement &el = *fes.GetFE(first_index);
auto &T = *fes.GetMesh()->GetElementTransformation(first_index);
MFEM_ASSERT(!integ.GetIntegrationRule(),
MFEM_ASSERT(!integ.GetIntRule(),
"Mixed mesh integrators should not have an"
" IntegrationRule.");
const IntegrationRule &ir = GetRule(integ, el, el, T);
+4 -4
View File
@@ -23,7 +23,7 @@ namespace ceed
static void InitNativeRestr(const mfem::FiniteElementSpace &fes,
Ceed ceed, CeedElemRestriction *restr)
{
const mfem::FiniteElement *fe = fes.GetFE(0);
const mfem::FiniteElement *fe = fes.GetTypicalFE();
const int P = fe->GetDof();
CeedInt compstride = fes.GetOrdering()==Ordering::byVDIM ? 1 : fes.GetNDofs();
const mfem::Table &el_dof = fes.GetElementToDofTable();
@@ -51,7 +51,7 @@ static void InitNativeRestr(const mfem::FiniteElementSpace &fes,
static void InitLexicoRestr(const mfem::FiniteElementSpace &fes,
Ceed ceed, CeedElemRestriction *restr)
{
const mfem::FiniteElement *fe = fes.GetFE(0);
const mfem::FiniteElement *fe = fes.GetTypicalFE();
const int P = fe->GetDof();
CeedInt compstride = fes.GetOrdering()==Ordering::byVDIM ? 1 : fes.GetNDofs();
const mfem::Table &el_dof = fes.GetElementToDofTable();
@@ -75,7 +75,7 @@ static void InitLexicoRestr(const mfem::FiniteElementSpace &fes,
static void InitRestrictionImpl(const mfem::FiniteElementSpace &fes,
Ceed ceed, CeedElemRestriction *restr)
{
const mfem::FiniteElement *fe = fes.GetFE(0);
const mfem::FiniteElement *fe = fes.GetTypicalFE();
const mfem::TensorBasisElement * tfe =
dynamic_cast<const mfem::TensorBasisElement *>(fe);
if ( tfe && tfe->GetDofMap().Size()>0 ) // Native ordering using dof_map
@@ -225,7 +225,7 @@ void InitRestriction(const FiniteElementSpace &fes,
CeedElemRestriction *restr)
{
// Check for FES -> basis, restriction in hash tables
const mfem::FiniteElement *fe = fes.GetFE(0);
const mfem::FiniteElement *fe = fes.GetTypicalFE();
const int P = fe->GetDof();
const int nelem = fes.GetNE();
const int ncomp = fes.GetVDim();
+8
View File
@@ -120,6 +120,10 @@ public:
virtual ~ComplexLinearForm();
/// Assign constant values to the ComplexLinearForm data.
ComplexLinearForm &operator=(const std::complex<real_t> & value)
{ *lfr = value.real(); *lfi = value.imag(); return *this; }
ComplexOperator::Convention GetConvention() const { return conv; }
void SetConvention(const ComplexOperator::Convention &
convention) { conv = convention; }
@@ -466,6 +470,10 @@ public:
virtual ~ParComplexLinearForm();
/// Assign constant values to the ParComplexLinearForm data.
ParComplexLinearForm &operator=(const std::complex<real_t> & value)
{ *plfr = value.real(); *plfi = value.imag(); return *this; }
ComplexOperator::Convention GetConvention() const { return conv; }
void SetConvention(const ComplexOperator::Convention &
convention) { conv = convention; }
+2 -3
View File
@@ -719,7 +719,7 @@ ConduitDataCollection::MeshToBlueprintMesh(Mesh *mesh,
// copy out. Some other cases (sidre) may actually have contig
// allocation but I am not sure how to detect this case from mfem
int num_ele = mesh->GetNE();
int geom = mesh->GetElementBaseGeometry(0);
int geom = mesh->GetTypicalElementGeometry();
int idxs_per_ele = Geometry::NumVerts[geom];
int num_conn_idxs = num_ele * idxs_per_ele;
@@ -997,8 +997,7 @@ std::string
ConduitDataCollection::MeshFilePattern(const std::string &relay_protocol)
{
std::ostringstream oss;
oss << prefix_path
<< name
oss << name
<< "_"
<< to_padded_string(cycle, pad_digits_cycle)
<< "/domain_%0"
+4 -2
View File
@@ -24,7 +24,7 @@ DGMassInverse::DGMassInverse(FiniteElementSpace &fes_orig, Coefficient *coeff,
fec(fes_orig.GetMaxElementOrder(),
fes_orig.GetMesh()->Dimension(),
btype,
fes_orig.GetFE(0)->GetMapType()),
fes_orig.GetTypicalFE()->GetMapType()),
fes(fes_orig.GetMesh(), &fec)
{
MFEM_VERIFY(fes.IsDGSpace(), "Space must be DG.");
@@ -42,7 +42,9 @@ DGMassInverse::DGMassInverse(FiniteElementSpace &fes_orig, Coefficient *coeff,
{
// original basis to solver basis
const auto mode = DofToQuad::TENSOR;
d2q = &fes_orig.GetFE(0)->GetDofToQuad(fes.GetFE(0)->GetNodes(), mode);
const FiniteElement &fe_orig = *fes_orig.GetTypicalFE();
const FiniteElement &fe = *fes.GetTypicalFE();
d2q = &fe_orig.GetDofToQuad(fe.GetNodes(), mode);
int n = d2q->ndof;
Array<real_t> B_inv = d2q->B; // deep copy
+2 -2
View File
@@ -41,8 +41,8 @@ void FillFaceMap(const int n_face_dofs_per_component,
const std::vector<int> &n_dofs_per_dim,
Array<int> &face_map)
{
const int n_components = offsets.size();
const int face_dim = strides.size() / n_components;
const int n_components = static_cast<int>(offsets.size());
const int face_dim = static_cast<int>(strides.size()) / n_components;
for (int comp = 0; comp < n_components; ++comp)
{
const int offset = offsets[comp];
+1 -1
View File
@@ -276,7 +276,7 @@ public:
UNKNOWN_MAP_TYPE = -1, /**< Used to distinguish an unset MapType variable
from the known values below. */
VALUE, /**< For scalar fields; preserves point values
$ u(x) = \hat u(\hat x) $ */
$ u(x) = \hat u(\hat x) $ @anchor map_type_value */
INTEGRAL, /**< For scalar fields; preserves volume integrals
$ u(x) = (1/w) \hat u(\hat x) $ */
H_DIV, /**< For vector fields; preserves surface integrals of the
+11
View File
@@ -195,6 +195,17 @@ public:
return var_orders[p]->FiniteElementForGeometry(geom);
}
/// Variable order version of TraceFiniteElementForGeometry().
/** The order parameter @a p represents the order of the highest-dimensional
FiniteElement%s the fixed-order collection we want to query. In general,
this order is different from the order of the returned FiniteElement. */
const FiniteElement *GetTraceFE(Geometry::Type geom, int p) const
{
if (p == base_p) { return TraceFiniteElementForGeometry(geom); }
if (p >= var_orders.Size() || !var_orders[p]) { InitVarOrder(p); }
return var_orders[p]->TraceFiniteElementForGeometry(geom);
}
/// Variable order version of DofForGeometry().
/** The order parameter @a p represents the order of the highest-dimensional
FiniteElement%s the fixed-order collection we want to query. In general,
+188 -3
View File
@@ -146,6 +146,43 @@ void FiniteElementSpace::CopyProlongationAndRestriction(
delete perm_mat_tr;
}
void FiniteElementSpace::SetProlongation(const SparseMatrix& p)
{
#ifdef MFEM_USE_MPI
MFEM_VERIFY(dynamic_cast<const ParFiniteElementSpace*>(this) == NULL,
"Attempting to set serial prolongation operator for "
"parallel finite element space.");
#endif
if (!cP)
{
cP = std::unique_ptr<SparseMatrix>(new SparseMatrix(p));
}
else
{
*cP = p;
}
cP_is_set = true;
}
void FiniteElementSpace::SetRestriction(const SparseMatrix& r)
{
#ifdef MFEM_USE_MPI
MFEM_VERIFY(dynamic_cast<const ParFiniteElementSpace*>(this) == NULL,
"Attempting to set serial restriction operator for "
"parallel finite element space.");
#endif
if (!cR)
{
cR = std::unique_ptr<SparseMatrix>(new SparseMatrix(r));
}
else
{
*cR = r;
}
}
void FiniteElementSpace::SetElementOrder(int i, int p)
{
MFEM_VERIFY(mesh_sequence == mesh->GetSequence(),
@@ -669,6 +706,78 @@ void FiniteElementSpace::GetBoundaryTrueDofs(Array<int> &boundary_dofs,
}
}
void FiniteElementSpace::GetExteriorVDofs(Array<int> &ext_vdofs,
int component) const
{
Array<int> dofs;
ext_vdofs.SetSize(GetVSize());
ext_vdofs = 0;
Array<int> ext_face_marker;
mesh->GetExteriorFaceMarker(ext_face_marker);
for (int i = 0; i < ext_face_marker.Size(); i++)
{
if (ext_face_marker[i])
{
if (component < 0)
{
// Mark all components.
GetFaceDofs(i, dofs);
DofsToVDofs(dofs);
}
else
{
GetFaceDofs(i, dofs);
for (auto &d : dofs) { d = DofToVDof(d, component); }
}
MarkDofs(dofs, ext_vdofs);
}
}
}
void FiniteElementSpace::GetExteriorTrueDofs(Array<int> &ext_tdof_list,
int component) const
{
Array<int> ext_vdofs, ext_tdofs;
GetExteriorVDofs(ext_vdofs, component);
const SparseMatrix *R = GetConformingRestriction();
if (!R)
{
ext_tdofs.MakeRef(ext_vdofs);
}
else
{
R->BooleanMult(ext_vdofs, ext_tdofs);
#ifdef MFEM_DEBUG
// Verify that in boolean arithmetic: P^T ext_dofs = R ext_dofs
Array<int> ext_tdofs2(ext_tdofs.Size());
GetConformingProlongation()->BooleanMultTranspose(ext_vdofs, ext_tdofs2);
int counter = 0;
std::string error_msg = "failed dof: ";
auto ext_tdofs_ = ext_tdofs.HostRead();
auto ext_tdofs2_ = ext_tdofs2.HostRead();
for (int i = 0; i < ext_tdofs2.Size(); ++i)
{
if (bool(ext_tdofs_[i]) != bool(ext_tdofs2_[i]))
{
error_msg += std::to_string(i) += "(R ";
error_msg += std::to_string(bool(ext_tdofs_[i])) += " P^T ";
error_msg += std::to_string(bool(ext_tdofs2_[i])) += ") ";
counter++;
}
}
MFEM_ASSERT(R->Height() == GetConformingProlongation()->Width(), "!");
MFEM_ASSERT(R->Width() == GetConformingProlongation()->Height(), "!");
MFEM_ASSERT(R->Width() == ext_vdofs.Size(), "!");
MFEM_VERIFY(counter == 0, "internal MFEM error: counter = " << counter
<< ' ' << error_msg);
#endif
}
MarkerToList(ext_tdofs, ext_tdof_list);
}
// static method
void FiniteElementSpace::MarkerToList(const Array<int> &marker,
Array<int> &list)
@@ -1358,6 +1467,26 @@ int FiniteElementSpace::GetNConformingDofs() const
return P ? (P->Width() / vdim) : ndofs;
}
int FiniteElementSpace::GetVectorDim() const
{
const FiniteElement *fe = GetTypicalFE();
if (fe->GetRangeType() == FiniteElement::SCALAR)
{
return GetVDim();
}
return GetVDim()*std::max(GetMesh()->SpaceDimension(), fe->GetRangeDim());
}
int FiniteElementSpace::GetCurlDim() const
{
const FiniteElement *fe = GetTypicalFE();
if (fe->GetRangeType() == FiniteElement::SCALAR)
{
return 2 * GetMesh()->SpaceDimension() - 3;
}
return GetVDim()*fe->GetCurlDim();
}
const ElementRestrictionOperator *FiniteElementSpace::GetElementRestriction(
ElementDofOrdering e_ordering) const
{
@@ -2657,7 +2786,7 @@ void FiniteElementSpace::Construct()
else
{
// the simple case: all faces are of the same geometry and order
uni_fdof = fec->GetNumDof(mesh->GetFaceGeometry(0), order);
uni_fdof = fec->GetNumDof(mesh->GetTypicalFaceGeometry(), order);
nfdofs = mesh->GetNFaces() * uni_fdof;
var_face_dofs.Clear(); // ensure any old var_face_dof table is dumped.
}
@@ -3337,7 +3466,7 @@ void FiniteElementSpace::GetFaceInteriorDofs(int i, Array<int> &dofs) const
}
else
{
auto geom = mesh->GetFaceGeometry(0);
auto geom = mesh->GetTypicalFaceGeometry();
nf = fec->GetNumDof(geom, fec->GetOrder());
base = i*nf;
}
@@ -3404,6 +3533,16 @@ const FiniteElement *FiniteElementSpace::GetFE(int i) const
return FE;
}
const FiniteElement *FiniteElementSpace::GetTypicalFE() const
{
if (mesh->GetNE() > 0) { return GetFE(0); }
Geometry::Type geom = mesh->GetTypicalElementGeometry();
const FiniteElement *fe = fec->FiniteElementForGeometry(geom);
MFEM_VERIFY(fe != nullptr, "Could not determine a typical FE!");
return fe;
}
const FiniteElement *FiniteElementSpace::GetBE(int i) const
{
int order = fec->GetOrder();
@@ -3479,7 +3618,12 @@ const FiniteElement *FiniteElementSpace::GetEdgeElement(int i,
const FiniteElement *FiniteElementSpace::GetTraceElement(
int i, Geometry::Type geom_type) const
{
return fec->TraceFiniteElementForGeometry(geom_type);
return fec->GetTraceFE(geom_type, GetElementOrder(i));
}
const FiniteElement *FiniteElementSpace::GetTypicalTraceElement() const
{
return fec->TraceFiniteElementForGeometry(mesh->GetTypicalFaceGeometry());
}
FiniteElementSpace::~FiniteElementSpace()
@@ -3797,6 +3941,47 @@ void FiniteElementSpace::UpdateMeshPointer(Mesh *new_mesh)
mesh = new_mesh;
}
void FiniteElementSpace::GetNodePositions(const Vector &mesh_nodes,
Vector &fes_node_pos,
int fes_nodes_ordering) const
{
Mesh *m = GetMesh();
const int NE = m->GetNE();
if (NE == 0) { fes_node_pos.SetSize(0); return; }
const int dim = m->Dimension();
Array<int> dofs;
Vector e_xyz;
fes_node_pos.SetSize(GetNDofs() * dim);
const FiniteElementSpace *mesh_fes = m->GetNodalFESpace();
FiniteElementSpace vector_fes(m, FEColl(), dim, fes_nodes_ordering);
for (int e = 0; e < NE; e++)
{
mesh_fes->GetElementVDofs(e, dofs);
const int mdof_cnt = dofs.Size() / dim;
mesh_nodes.GetSubVector(dofs, e_xyz); //e_xyz is ordered by nodes here
auto ir = GetFE(e)->GetNodes();
const int fdof_cnt = ir.GetNPoints();
Vector mesh_shape(mdof_cnt), gf_xyz(fdof_cnt * dim);
for (int q = 0; q < fdof_cnt; q++)
{
mesh_fes->GetFE(e)->CalcShape(ir.IntPoint(q), mesh_shape);
for (int d = 0; d < dim; d++)
{
Vector x(e_xyz.GetData() + d*mdof_cnt, mdof_cnt);
gf_xyz(d*fdof_cnt + q) = x * mesh_shape; // order by nodes
}
}
// reuse/resize dofs.
vector_fes.GetElementVDofs(e, dofs);
fes_node_pos.SetSubVector(dofs, gf_xyz);
}
}
void FiniteElementSpace::Save(std::ostream &os) const
{
int fes_format = 90; // the original format, v0.9
+71 -7
View File
@@ -203,7 +203,7 @@ class FaceQuadratureInterpolator;
@par
%Vector dofs do not represent a specific index space the way the three
previous types of dofs do. Rather they are related to modifications of
these other index spaces to accomodate multiple copies of the underlying
these other index spaces to accommodate multiple copies of the underlying
function spaces.
@par
When using @b vdofs, i.e. when @b vdim != 1, the FiniteElementSpace only
@@ -587,6 +587,14 @@ public:
bool Conforming() const { return mesh->Conforming() && cP == NULL; }
bool Nonconforming() const { return mesh->Nonconforming() || cP != NULL; }
/** Set the prolongation operator of the space to an arbitrary sparse matrix,
creating a copy of the argument. */
void SetProlongation(const SparseMatrix& p);
/** Set the restriction operator of the space to an arbitrary sparse matrix,
creating a copy of the argument. */
void SetRestriction(const SparseMatrix& r);
/// Sets the order of the i'th finite element.
/** By default, all elements are assumed to be of fec->GetOrder(). Once
SetElementOrder is called, the space becomes a variable order space. */
@@ -729,7 +737,9 @@ public:
/// Returns the polynomial degree of the i'th face finite element
int GetFaceOrder(int face, int variant = 0) const;
/// Returns vector dimension.
/// Returns the vector dimension of the finite element space.
/** Since the finite elements could be vector-valued, this may not be the
dimension of an actual vector in the space; see GetVectorDim(). */
inline int GetVDim() const { return vdim; }
/// @brief Returns number of degrees of freedom.
@@ -748,6 +758,22 @@ public:
int GetConformingVSize() const { return vdim * GetNConformingDofs(); }
/// Return the total dimension of a vector in the space
/** This accounts for the vectorization of elements and cases where the
elements themselves are vector-valued; see FiniteElement:GetRangeDim().
If the finite elements are FiniteElement::SCALAR, this equals GetVDim().
Note: For vector-valued elements, the results pads up the range dimension
to the spatial dimension. E.g., consider a stack of 5 vector-valued
elements each representing 2D vectors, living in a 3 dimensional space.
Then this fucntion would give 15, not 10.
*/
int GetVectorDim() const;
/// Return the dimension of the curl of a GridFunction defined on this space.
/** Note: This assumes a space dimension of 2 or 3 only. */
int GetCurlDim() const;
/// Return the ordering method.
inline Ordering::Type GetOrdering() const { return ordering; }
@@ -1198,6 +1224,13 @@ public:
an empty partition. */
virtual const FiniteElement *GetFE(int i) const;
/** @brief Return GetFE(0) if the local mesh is not empty; otherwise return a
typical FE based on the Geometry types in the global mesh.
This method can be used as a replacement for GetFE(0) that will be valid
even if the local mesh is empty. */
const FiniteElement *GetTypicalFE() const;
/** @brief Returns pointer to the FiniteElement in the FiniteElementCollection
associated with i'th boundary face in the mesh object. */
const FiniteElement *GetBE(int i) const;
@@ -1215,6 +1248,12 @@ public:
/// Return the trace element from element 'i' to the given 'geom_type'
const FiniteElement *GetTraceElement(int i, Geometry::Type geom_type) const;
/// @brief Return a "typical" trace element.
///
/// This can be used in situations where the local mesh partition may be
/// empty.
const FiniteElement *GetTypicalTraceElement() const;
/** @brief Mark degrees of freedom associated with boundary elements with
the specified boundary attributes (marked in 'bdr_attr_is_ess').
For spaces with 'vdim' > 1, the 'component' parameter can be used
@@ -1238,6 +1277,18 @@ public:
marked as essential. */
void GetBoundaryTrueDofs(Array<int> &boundary_dofs, int component = -1);
/** @brief Mark degrees of freedom associated with exterior faces of the
mesh. For spaces with 'vdim' > 1, the 'component' parameter can be used
to restricts the marked vDOFs to the specified component. */
virtual void GetExteriorVDofs(Array<int> &exterior_vdofs,
int component = -1) const;
/** @brief Get a list of all true dofs on the exterior of the mesh,
@a exterior_dofs. For spaces with 'vdim' > 1, the 'component' parameter
can be used to restricts the marked tDOFs to the specified component. */
virtual void GetExteriorTrueDofs(Array<int> &exterior_dofs,
int component = -1) const;
/// Convert a Boolean marker array to a list containing all marked indices.
static void MarkerToList(const Array<int> &marker, Array<int> &list);
@@ -1361,6 +1412,18 @@ public:
Update(false);
}
/** @brief Compute the space's node positions w.r.t. given mesh positions.
The function uses FiniteElement::GetNodes() to obtain the reference DOF
positions of each finite element.
@param[in] mesh_nodes Mesh positions. Assumes that it has the same
topology & ordering as the mesh of the FE space,
i.e, same size as this->GetMesh()->GetNodes().
@param[out] fes_node_pos Positions of the FE space's nodes.
@param[in] fes_nodes_ordering Ordering of fes_node_pos. */
void GetNodePositions(const Vector &mesh_nodes, Vector &fes_node_pos,
int fes_nodes_ordering = Ordering::byNODES) const;
/// Save finite element space to output stream @a out.
void Save(std::ostream &out) const;
@@ -1371,18 +1434,19 @@ public:
virtual ~FiniteElementSpace();
};
/// @brief Return true if the mesh contains only one topology and the elements are tensor elements.
/// @brief Return true if the mesh contains only one topology and the elements
/// are tensor elements.
inline bool UsesTensorBasis(const FiniteElementSpace& fes)
{
Mesh & mesh = *fes.GetMesh();
const bool mixed = mesh.GetNumGeometries(mesh.Dimension()) > 1;
// Potential issue: empty local mesh --> no element 0.
return !mixed &&
dynamic_cast<const mfem::TensorBasisElement *>(fes.GetFE(0))!=nullptr;
dynamic_cast<const mfem::TensorBasisElement *>(
fes.GetTypicalFE()) != nullptr;
}
/// @brief Return LEXICOGRAPHIC if mesh contains only one topology and the elements are tensor
/// elements, otherwise, return NATIVE.
/// @brief Return LEXICOGRAPHIC if mesh contains only one topology and the
/// elements are tensor elements, otherwise, return NATIVE.
ElementDofOrdering GetEVectorOrdering(const FiniteElementSpace& fes);
}
+62 -103
View File
@@ -324,45 +324,12 @@ void GridFunction::ComputeFlux(BilinearFormIntegrator &blfi,
int GridFunction::VectorDim() const
{
const FiniteElement *fe;
if (!fes->GetNE())
{
static const Geometry::Type geoms[3] =
{ Geometry::SEGMENT, Geometry::TRIANGLE, Geometry::TETRAHEDRON };
fe = fes->FEColl()->
FiniteElementForGeometry(geoms[fes->GetMesh()->Dimension()-1]);
}
else
{
fe = fes->GetFE(0);
}
if (!fe || fe->GetRangeType() == FiniteElement::SCALAR)
{
return fes->GetVDim();
}
return fes->GetVDim()*std::max(fes->GetMesh()->SpaceDimension(),
fe->GetRangeDim());
return fes->GetVectorDim();
}
int GridFunction::CurlDim() const
{
const FiniteElement *fe;
if (!fes->GetNE())
{
static const Geometry::Type geoms[3] =
{ Geometry::SEGMENT, Geometry::TRIANGLE, Geometry::TETRAHEDRON };
fe = fes->FEColl()->
FiniteElementForGeometry(geoms[fes->GetMesh()->Dimension()-1]);
}
else
{
fe = fes->GetFE(0);
}
if (!fe || fe->GetRangeType() == FiniteElement::SCALAR)
{
return 2 * fes->GetMesh()->SpaceDimension() - 3;
}
return fes->GetVDim()*fe->GetCurlDim();
return fes->GetCurlDim();
}
void GridFunction::GetTrueDofs(Vector &tv) const
@@ -1793,8 +1760,8 @@ void GridFunction::ProjectGridFunction(const GridFunction &src)
{
// Assuming that the projection matrix is the same for all elements
sameP = true;
fes->GetFE(0)->Project(*src.fes->GetFE(0),
*mesh->GetElementTransformation(0), P);
fes->GetTypicalFE()->Project(*src.fes->GetTypicalFE(),
*mesh->GetTypicalElementTransformation(), P);
}
const int vdim = fes->GetVDim();
MFEM_VERIFY(vdim == src.fes->GetVDim(), "incompatible vector dimensions!");
@@ -2456,7 +2423,6 @@ void GridFunction::ProjectCoefficient(VectorCoefficient &vcoeff)
{
if (fes->GetNURBSext() == NULL)
{
int i;
Array<int> vdofs;
Vector vals;
@@ -2474,9 +2440,7 @@ void GridFunction::ProjectCoefficient(VectorCoefficient &vcoeff)
}
SetSubVector(vdofs, vals);
}
}
else
{
// Define and assemble linear form
@@ -2825,6 +2789,7 @@ real_t GridFunction::ComputeL2Error(
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
fes->GetElementVDofs(i, vdofs);
real_t elem_error = 0.0;
for (j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
@@ -2843,12 +2808,14 @@ real_t GridFunction::ComputeL2Error(
a -= (*this)(-1-vdofs[fdof*d+k]) * shape(k);
}
a -= exsol[d]->Eval(*transf, ip);
error += ip.weight * transf->Weight() * a * a;
elem_error += ip.weight * transf->Weight() * a * a;
}
}
// negative quadrature weights may cause the error to be negative
error += fabs(elem_error);
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
return sqrt(error);
}
real_t GridFunction::ComputeL2Error(
@@ -2875,6 +2842,7 @@ real_t GridFunction::ComputeL2Error(
{
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
real_t elem_error = 0.0;
T = fes->GetElementTransformation(i);
GetVectorValues(*T, *ir, vals);
exsol.Eval(exact_vals, *T, *ir);
@@ -2885,11 +2853,12 @@ real_t GridFunction::ComputeL2Error(
{
const IntegrationPoint &ip = ir->IntPoint(j);
T->SetIntPoint(&ip);
error += ip.weight * T->Weight() * (loc_errs(j) * loc_errs(j));
elem_error += ip.weight * T->Weight() * (loc_errs(j) * loc_errs(j));
}
// negative quadrature weights may cause the error to be negative
error += fabs(elem_error);
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
return sqrt(error);
}
real_t GridFunction::ComputeElementGradError(int ielem,
@@ -2927,7 +2896,7 @@ real_t GridFunction::ComputeElementGradError(int ielem,
vec-=grad;
error += ip.weight * Tr->Weight() * (vec * vec);
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
return sqrt(fabs(error));
}
real_t GridFunction::ComputeGradError(VectorCoefficient *exgrad,
@@ -2957,6 +2926,7 @@ real_t GridFunction::ComputeGradError(VectorCoefficient *exgrad,
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
fes->GetElementDofs(i, dofs);
real_t elem_error = 0.0;
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
@@ -2964,10 +2934,12 @@ real_t GridFunction::ComputeGradError(VectorCoefficient *exgrad,
GetGradient(*Tr,grad);
exgrad->Eval(vec,*Tr,ip);
vec-=grad;
error += ip.weight * Tr->Weight() * (vec * vec);
elem_error += ip.weight * Tr->Weight() * (vec * vec);
}
// negative quadrature weights may cause the error to be negative
error += fabs(elem_error);
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
return sqrt(error);
}
real_t GridFunction::ComputeCurlError(VectorCoefficient *excurl,
@@ -2997,6 +2969,7 @@ real_t GridFunction::ComputeCurlError(VectorCoefficient *excurl,
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
fes->GetElementDofs(i, dofs);
real_t elem_error = 0.0;
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
@@ -3004,11 +2977,13 @@ real_t GridFunction::ComputeCurlError(VectorCoefficient *excurl,
GetCurl(*Tr,curl);
excurl->Eval(vec,*Tr,ip);
vec-=curl;
error += ip.weight * Tr->Weight() * ( vec * vec );
elem_error += ip.weight * Tr->Weight() * ( vec * vec );
}
// negative quadrature weights may cause the error to be negative
error += fabs(elem_error);
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
return sqrt(error);
}
real_t GridFunction::ComputeDivError(
@@ -3035,16 +3010,19 @@ real_t GridFunction::ComputeDivError(
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
fes->GetElementDofs(i, dofs);
real_t elem_error = 0.0;
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
Tr->SetIntPoint (&ip);
a = GetDivergence(*Tr) - exdiv->Eval(*Tr, ip);
error += ip.weight * Tr->Weight() * a * a;
elem_error += ip.weight * Tr->Weight() * a * a;
}
// negative quadrature weights may cause the error to be negative
error += fabs(elem_error);
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
return sqrt(error);
}
real_t GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
@@ -3145,6 +3123,7 @@ real_t GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
err_val(j) -= (exsol->Eval(*transf, eip) - (shape * el_dofs));
}
}
real_t face_error = 0.0;
face_elem_transf = mesh->GetFaceElementTransformations(i, 16);
transf = face_elem_transf;
for (int j = 0; j < ir->GetNPoints(); j++)
@@ -3152,13 +3131,15 @@ real_t GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
const IntegrationPoint &ip = ir->IntPoint(j);
transf->SetIntPoint(&ip);
real_t nu = jump_scaling.Eval(h, p);
error += (ip.weight * nu * ell_coeff_val(j) *
transf->Weight() *
err_val(j) * err_val(j));
face_error += (ip.weight * nu * ell_coeff_val(j) *
transf->Weight() *
err_val(j) * err_val(j));
}
// negative quadrature weights may cause the error to be negative
error += fabs(face_error);
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
return sqrt(error);
}
real_t GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
@@ -3309,6 +3290,7 @@ real_t GridFunction::ComputeW11Error(
{
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
real_t elem_error = 0.0;
fes->GetElementVDofs(i, vdofs);
for (k = 0; k < fdof; k++)
if (vdofs[k] >= 0)
@@ -3325,8 +3307,9 @@ real_t GridFunction::ComputeW11Error(
fe->CalcShape(ip, shape);
transf->SetIntPoint(&ip);
a = (el_dofs * shape) - (exsol->Eval(*transf, ip));
error += ip.weight * transf->Weight() * fabs(a);
elem_error += ip.weight * transf->Weight() * fabs(a);
}
error += fabs(elem_error);
}
if (norm_type & 2) // W^1_1 seminorm
@@ -3349,6 +3332,7 @@ real_t GridFunction::ComputeW11Error(
{
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
real_t elem_error = 0.0;
fes->GetElementVDofs(i, vdofs);
for (k = 0; k < fdof; k++)
if (vdofs[k] >= 0)
@@ -3369,8 +3353,9 @@ real_t GridFunction::ComputeW11Error(
Mult(dshape, Jinv, dshapet);
dshapet.MultTranspose(el_dofs, a_grad);
e_grad -= a_grad;
error += ip.weight * transf->Weight() * e_grad.Norml1();
elem_error += ip.weight * transf->Weight() * e_grad.Norml1();
}
error += fabs(elem_error);
}
return error;
@@ -3400,6 +3385,7 @@ real_t GridFunction::ComputeLpError(const real_t p, Coefficient &exsol,
int intorder = 2*fe->GetOrder() + 3; // <----------
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
real_t elem_error = 0.0;
GetValues(i, *ir, vals);
T = fes->GetElementTransformation(i);
for (int j = 0; j < ir->GetNPoints(); j++)
@@ -3414,7 +3400,7 @@ real_t GridFunction::ComputeLpError(const real_t p, Coefficient &exsol,
{
diff *= weight->Eval(*T, ip);
}
error += ip.weight * T->Weight() * diff;
elem_error += ip.weight * T->Weight() * diff;
}
else
{
@@ -3425,19 +3411,16 @@ real_t GridFunction::ComputeLpError(const real_t p, Coefficient &exsol,
error = std::max(error, diff);
}
}
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
error += fabs(elem_error);
}
}
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
if (error < 0.)
{
error = -pow(-error, 1./p);
}
else
{
error = pow(error, 1./p);
}
error = pow(error, 1./p);
}
return error;
@@ -3497,14 +3480,7 @@ void GridFunction::ComputeElementLpErrors(const real_t p, Coefficient &exsol,
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
if (error[i] < 0.)
{
error[i] = -pow(-error[i], 1./p);
}
else
{
error[i] = pow(error[i], 1./p);
}
error[i] = pow(fabs(error[i]), 1./p);
}
}
}
@@ -3533,6 +3509,7 @@ real_t GridFunction::ComputeLpError(const real_t p, VectorCoefficient &exsol,
int intorder = 2*fe->GetOrder() + 3; // <----------
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
real_t elem_error = 0.0;
T = fes->GetElementTransformation(i);
GetVectorValues(*T, *ir, vals);
exsol.Eval(exact_vals, *T, *ir);
@@ -3571,7 +3548,7 @@ real_t GridFunction::ComputeLpError(const real_t p, VectorCoefficient &exsol,
{
errj *= weight->Eval(*T, ip);
}
error += ip.weight * T->Weight() * errj;
elem_error += ip.weight * T->Weight() * errj;
}
else
{
@@ -3582,19 +3559,16 @@ real_t GridFunction::ComputeLpError(const real_t p, VectorCoefficient &exsol,
error = std::max(error, errj);
}
}
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
error += fabs(elem_error);
}
}
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
if (error < 0.)
{
error = -pow(-error, 1./p);
}
else
{
error = pow(error, 1./p);
}
error = pow(error, 1./p);
}
return error;
@@ -3681,14 +3655,7 @@ void GridFunction::ComputeElementLpErrors(const real_t p,
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
if (error[i] < 0.)
{
error[i] = -pow(-error[i], 1./p);
}
else
{
error[i] = pow(error[i], 1./p);
}
error[i] = pow(fabs(error[i]), 1./p);
}
}
}
@@ -4490,7 +4457,6 @@ real_t ComputeElementLpDistance(real_t p, int i,
int nip = ir->GetNPoints();
Vector val1, val2;
ElementTransformation *T = fes1->GetElementTransformation(i);
for (int j = 0; j < nip; j++)
{
@@ -4516,14 +4482,7 @@ real_t ComputeElementLpDistance(real_t p, int i,
if (p < infinity())
{
// Negative quadrature weights may cause the norm to be negative
if (norm < 0.)
{
norm = -pow(-norm, 1./p);
}
else
{
norm = pow(norm, 1./p);
}
norm = pow(fabs(norm), 1./p);
}
return norm;
+811 -32
View File
@@ -123,7 +123,10 @@ public:
FiniteElementCollection *OwnFEC() { return fec_owned; }
/// Shortcut for calling FiniteElementSpace::GetVectorDim() on the underlying #fes
int VectorDim() const;
/// Shortcut for calling FiniteElementSpace::GetCurlDim() on the underlying #fes
int CurlDim() const;
/// Read only access to the (optional) internal true-dof Vector.
@@ -500,49 +503,232 @@ public:
virtual void ProjectBdrCoefficientTangent(VectorCoefficient &vcoeff,
const Array<int> &bdr_attr);
/// @brief Returns ||exsol - u_h||_L2 for scalar or vector H1 or L2 elements
///
/// @param[in] exsol Pointer to an array of scalar Coefficient objects,
/// one for each component of the vector field. The
/// length of the array should be at least equal to
/// FiniteElementSpace::GetVDim().
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
/// @param[in] elems Optional pointer to a marker array, with a length
/// equal to the number of local elements, indicating
/// which elements to integrate over. Only those elements
/// corresponding to non-zero entries in @a elems will
/// contribute to the computed L2 error.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeL2Error(Coefficient *exsol[],
const IntegrationRule *irs[] = NULL,
const Array<int> *elems = NULL) const;
/// Returns ||grad u_ex - grad u_h||_L2 in element ielem for H1 or L2 elements
/// @brief Returns ||grad u_ex - grad u_h||_L2 in element ielem for
/// H1 or L2 elements
///
/// @param[in] ielem Index of the element in which to compute the L2 error.
/// @param[in] exgrad Pointer to a VectorCoefficient object reproducing the
/// expected gradient of the scalar field, grad u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeElementGradError(int ielem, VectorCoefficient *exgrad,
const IntegrationRule *irs[] = NULL) const;
/// Returns ||u_ex - u_h||_L2 for H1 or L2 elements
/* The @a elems input variable expects a list of markers:
an elem marker equal to 1 will compute the L2 error on that element
an elem marker equal to 0 will not compute the L2 error on that element */
/// @brief Returns ||u_ex - u_h||_L2 for H1 or L2 elements
///
/// @param[in] exsol Coefficient object reproducing the anticipated values
/// of the scalar field, u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
/// @param[in] elems Optional pointer to a marker array, with a length
/// equal to the number of local elements, indicating
/// which elements to integrate over. Only those elements
/// corresponding to non-zero entries in @a elems will
/// contribute to the computed L2 error.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeL2Error(Coefficient &exsol,
const IntegrationRule *irs[] = NULL,
const Array<int> *elems = NULL) const
{ return GridFunction::ComputeLpError(2.0, exsol, NULL, irs, elems); }
/// @brief Returns ||u_ex - u_h||_L2 for vector fields
///
/// @param[in] exsol VectorCoefficient object reproducing the anticipated
/// values of the vector field, u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
/// @param[in] elems Optional pointer to a marker array, with a length
/// equal to the number of local elements, indicating
/// which elements to integrate over. Only those elements
/// corresponding to non-zero entries in @a elems will
/// contribute to the computed L2 error.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeL2Error(VectorCoefficient &exsol,
const IntegrationRule *irs[] = NULL,
const Array<int> *elems = NULL) const;
/// Returns ||grad u_ex - grad u_h||_L2 for H1 or L2 elements
/// @brief Returns ||grad u_ex - grad u_h||_L2 for H1 or L2 elements
///
/// @param[in] exgrad Pointer to a VectorCoefficient object reproducing the
/// expected gradient of the scalar field, grad u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note This function only computes the error of the gradient in the
/// interior of the elements. In the context of discontinuous
/// Galerkin (DG) methods it may also be desirable to compute the
/// error in the jumps across element interfaces using
/// ComputeDGFaceJumpError().
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeGradError(VectorCoefficient *exgrad,
const IntegrationRule *irs[] = NULL) const;
/// Returns ||curl u_ex - curl u_h||_L2 for ND elements
/// @brief Returns ||curl u_ex - curl u_h||_L2 for ND elements
///
/// @param[in] excurl Pointer to a VectorCoefficient object reproducing the
/// expected curl of the vector field, curl u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeCurlError(VectorCoefficient *excurl,
const IntegrationRule *irs[] = NULL) const;
/// Returns ||div u_ex - div u_h||_L2 for RT elements
/// @brief Returns ||div u_ex - div u_h||_L2 for RT elements
///
/// @param[in] exdiv Pointer to a Coefficient object reproducing the
/// expected divergence of the vector field, div u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeDivError(Coefficient *exdiv,
const IntegrationRule *irs[] = NULL) const;
/// Returns the Face Jumps error for L2 elements. The error can be weighted
/// by a constant nu, by nu/h, or nu*p^2/h, depending on the value of
/// @a jump_scaling.
/// @brief Returns the Face Jumps error for L2 elements.
///
/// Computes:
/// $$\sqrt{\sum_{f\in faces}\int_f js(f) ell(f)
/// (2 u_{ex} - u_1 - u_2)^2}$$
///
/// Where js[f] is the jump_scaling evaluated on the face f and ell is the
/// average of ell_coef evaluated in the two elements sharing the face f.
///
/// @param[in] exsol Pointer to a Coefficient object reproducing the
/// anticipated values of the scalar field, u_ex.
/// @param[in] ell_coeff Pointer to a Coefficient object used to compute
/// the averaged value ell in the above integral.
/// @param[in] jump_scaling Can be configured to provide scaling by
/// nu, nu/h, or nu*p^2/h
/// @param[in] irs Optional pointer to an array of custom
/// integration rules e.g. higher order than the
/// default rules. If present the array will be
/// indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of faces.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
class JumpScaling jump_scaling,
const IntegrationRule *irs[] = NULL)
const;
/// Returns the Face Jumps error for L2 elements, with 1/h scaling.
/// @brief Returns the Face Jumps error for L2 elements, with 1/h scaling.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @deprecated See @ref ComputeDGFaceJumpError(Coefficient *exsol,
/// Coefficient *ell_coeff,
/// class JumpScaling jump_scaling,
/// const IntegrationRule *irs[]) const
/// for the preferred implementation.
MFEM_DEPRECATED
real_t ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
@@ -559,98 +745,589 @@ public:
Coefficient *ell_coef, real_t Nu,
int norm_type) const;
/// Returns the error measured in H1-norm for H1 elements or in "broken"
/// H1-norm for L2 elements
/// @brief Returns the error measured in H1-norm for H1 or L2 elements
///
/// Computes the norm using the $L^2$ norms of the function and its gradient
/// $$\sqrt{norm\_u^2 + norm\_du^2}$$
/// Where
/// $$norm\_u = \|u_{ex} - u_h\|_{L^2}$$
/// and
/// $$norm\_du = \|du_{ex} - \nabla u_h\|_{L^2}$$
///
/// @param[in] exsol Coefficient object reproducing the anticipated values
/// of the scalar field, u_ex.
/// @param[in] exgrad VectorCoefficient object reproducing the anticipated
/// values of the gradient of the scalar field, du_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @note For L2 elements this returns what could be called a "broken"
/// H1-norm.
virtual real_t ComputeH1Error(Coefficient *exsol, VectorCoefficient *exgrad,
const IntegrationRule *irs[] = NULL) const;
/// Returns the error measured in H(div)-norm for RT elements
/// @brief Returns the error measured in H(div)-norm for RT elements
///
/// Computes the norm using the $L^2$ norms of the function and its
/// divergence
/// $$\sqrt{norm\_u^2 + norm\_du^2}$$
/// Where
/// $$norm\_u = \|u_{ex} - u_h\|_{L^2}$$
/// and
/// $$norm\_du = \|du_{ex} - \nabla\cdot u_h\|_{L^2}$$
///
/// @param[in] exsol VectorCoefficient object reproducing the anticipated
/// values of the vector field, u_ex.
/// @param[in] exdiv VectorCoefficient object reproducing the anticipated
/// values of the divergence of the vector field, du_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeHDivError(VectorCoefficient *exsol,
Coefficient *exdiv,
const IntegrationRule *irs[] = NULL) const;
/// Returns the error measured in H(curl)-norm for ND elements
/// @brief Returns the error measured in H(curl)-norm for ND elements
///
/// Computes the norm using the $L^2$ norms of the function and its curl
/// $$\sqrt{norm\_u^2 + norm\_du^2}$$
/// Where
/// $$norm\_u = \|u_{ex} - u_h\|_{L^2}$$
/// and
/// $$norm\_du = \|du_{ex} - \nabla\times u_h\|_{L^2}$$
///
/// @param[in] exsol VectorCoefficient object reproducing the anticipated
/// values of the vector field, u_ex.
/// @param[in] excurl VectorCoefficient object reproducing the anticipated
/// values of the curl of the vector field, du_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeHCurlError(VectorCoefficient *exsol,
VectorCoefficient *excurl,
const IntegrationRule *irs[] = NULL) const;
/// @brief Returns Max|u_ex - u_h| error for H1 or L2 elements
///
/// Compute the $L^\infty$ error across the entire domain.
///
/// @param[in] exsol Coefficient object reproducing the anticipated
/// values of the scalar field, u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note Uses ComputeLpError internally. See the ComputeLpError
/// documentation for generalizations of this error computation.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
virtual real_t ComputeMaxError(Coefficient &exsol,
const IntegrationRule *irs[] = NULL) const
{
return ComputeLpError(infinity(), exsol, NULL, irs);
}
/// @brief Returns Max|u_ex - u_h| error for scalar or vector fields
///
/// Compute the $L^\infty$ error across the entire domain.
///
/// Computes:
/// $$max_{elems} (max_{elem} |scalar\_error|)$$
///
/// Where
/// $$scalar\_error = max_{d=0\ldots vdim}|u_{ex}[d] - u_h[d]|$$
///
/// @param[in] exsol Pointer to an array of scalar Coefficient objects,
/// one for each component of the vector field. The
/// length of the array should be at least equal to
/// FiniteElementSpace::GetVDim().
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note This implementation of the max error of a vector field computes
/// the max norm over vector components rather than the magnitude of
/// the vector.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
virtual real_t ComputeMaxError(Coefficient *exsol[],
const IntegrationRule *irs[] = NULL) const;
/// @brief Returns Max|u_ex - u_h| error for vector fields
///
/// Compute the $L^\infty$ error across the entire domain.
///
/// Computes:
/// $$max_{elems} (max_{elem} |scalar\_error|)$$
///
/// Where
/// $$scalar\_error = \sqrt{(u_{ex} - u_h) \cdot (u_{ex} - u_h)}$$
///
/// @param[in] exsol VectorCoefficient object reproducing the
/// anticipated values of the vector field, u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note Uses ComputeLpError internally. See the ComputeLpError
/// documentation for generalizations of this error computation.
///
/// @note Computes the maximum magnitude of the difference vector not the
/// component-wise maximum difference of the vector fields.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
virtual real_t ComputeMaxError(VectorCoefficient &exsol,
const IntegrationRule *irs[] = NULL) const
{
return ComputeLpError(infinity(), exsol, NULL, NULL, irs);
}
virtual real_t ComputeL1Error(Coefficient *exsol[],
const IntegrationRule *irs[] = NULL) const
{ return ComputeW11Error(*exsol, NULL, 1, NULL, irs); }
/// @brief Returns ||u_ex - u_h||_L1 for H1 or L2 elements
///
/// Computes:
/// $$\sum_{elems} \int_{elem} |u_{ex} - u_h|$$
///
/// @param[in] exsol Coefficient object reproducing the anticipated values
/// of the scalar field, u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @note Uses ComputeLpError internally. See the ComputeLpError
/// documentation for generalizations of this error computation.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
virtual real_t ComputeL1Error(Coefficient &exsol,
const IntegrationRule *irs[] = NULL) const
{ return ComputeLpError(1.0, exsol, NULL, irs); }
/// @brief Returns ||u_ex - u_h||_L1 for H1 or L2 elements
///
/// Computes:
/// $$\sum_{elems} \int_{elem} |u_{ex} - u_h|$$
///
/// @param[in] exsol Pointer to an array of Coefficient objects
/// reproducing the anticipated values of the scalar
/// field, u_ex. Only the first entry of this array will
/// be accessed.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @note Uses ComputeW11Error internally. See the ComputeW11Error
/// documentation for generalizations of this error computation.
///
/// @warning While this function is nominally equivalent to ComputeLpError,
/// with appropriate arguments, the returned errors may differ
/// noticeably because ComputeLpError uses a higher order
/// integration rule by default.
///
/// @deprecated See @ref ComputeL1Error(Coefficient &exsol,
/// const IntegrationRule *irs[]) const
/// for the preferred implementation.
MFEM_DEPRECATED
virtual real_t ComputeL1Error(Coefficient *exsol[],
const IntegrationRule *irs[] = NULL) const
{ return ComputeW11Error(*exsol, NULL, 1, NULL, irs); }
/// @brief Returns $W^1_1$ norm (or portions thereof) for H1 or L2 elements
///
/// Computes for norm_type == 1 the $L^1$ norm of $u$:
/// $$(\sum_{elems} \int_{elem} |u_{ex} - u_h|$$
///
/// Computes for norm_type == 2 the $L^1$ semi-norm of $\nabla u$:
/// $$(\sum_{elems} \int_{elem} |du_{ex} - \nabla u_h|$$
///
/// Computes for norm_type == 3 the $W^1_1$ norm of $u$:
/// $$(\sum_{elems} \int_{elem} |u_{ex} - u_h| + |du_{ex} - \nabla u_h|$$
///
/// @param[in] exsol Pointer to Coefficient object reproducing the
/// anticipated values of the scalar field, u_ex.
/// @param[in] exgrad Pointer to VectorCoefficient object reproducing the
/// anticipated values of the gradient of the scalar
/// field, du_ex.
/// @param[in] norm_type Integer value of 1, 2, or 3 indicating the type of
/// norm to compute (see above).
/// @param[in] elems Optional pointer to a marker array, with a length
/// equal to the number of local elements, indicating
/// which elements to integrate over. Only those
/// elements corresponding to non-zero entries in
/// @a elems will contribute to the computed $W^1_1$
/// error.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeW11Error(Coefficient *exsol, VectorCoefficient *exgrad,
int norm_type, const Array<int> *elems = NULL,
const IntegrationRule *irs[] = NULL) const;
/// @brief Returns ||u_ex - u_h||_L1 for vector fields
///
/// Computes:
/// $$\sum_{elems} \int_{elem} |scalar\_error|$$
///
/// Where
/// $$scalar\_error = \sqrt{(u_{ex} - u_h) \cdot (u_{ex} - u_h)}$$
///
/// @param[in] exsol VectorCoefficient object reproducing the anticipated
/// values of the vector field, u_ex.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @note Uses ComputeLpError internally. See the ComputeLpError
/// documentation for generalizations of this error computation.
virtual real_t ComputeL1Error(VectorCoefficient &exsol,
const IntegrationRule *irs[] = NULL) const
{ return ComputeLpError(1.0, exsol, NULL, NULL, irs); }
/* The @a elems input variable expects a list of markers:
an elem marker equal to 1 will compute the L2 error on that element
an elem marker equal to 0 will not compute the L2 error on that element */
/// @brief Returns ||u_ex - u_h||_Lp for H1 or L2 elements
///
/// Computes:
/// $$(\sum_{elems} \int_{elem} w \, |u_{ex} - u_h|^p)^{1/p}$$
///
/// @param[in] p Real value indicating the exponent of the $L^p$ norm.
/// To avoid domain errors p should have a positive value,
/// either finite or infinite.
/// @param[in] exsol Coefficient object reproducing the anticipated values
/// of the scalar field, u_ex.
/// @param[in] weight Optional pointer to a Coefficient object reproducing
/// a weighting function, w.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
/// @param[in] elems Optional pointer to a marker array, with a length
/// equal to the number of local elements, indicating
/// which elements to integrate over. Only those elements
/// corresponding to non-zero entries in @a elems will
/// contribute to the computed L2 error.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeLpError(const real_t p, Coefficient &exsol,
Coefficient *weight = NULL,
const IntegrationRule *irs[] = NULL,
const Array<int> *elems = NULL) const;
/** Compute the Lp error in each element of the mesh and store the results in
the Vector @a error. The result should be of length number of elements,
for example an L2 GridFunction of order zero using map type VALUE. */
/// @brief Returns ||u_ex - u_h||_Lp elementwise for H1 or L2 elements
///
/// Compute the Lp error in each element of the mesh and store the results in
/// the Vector @a error. The result should be of length number of elements,
/// for example an L2 GridFunction of order zero using map type @ref
/// map_type_value "VALUE".
///
/// Computes:
/// $$(\int_{elem} w \, |u_{ex} - u_h|^p)^{1/p}$$
///
/// @param[in] p Real value indicating the exponent of the $L^p$
/// norm. To avoid domain errors p should have a
/// positive value, either finite or infinite.
/// @param[in] exsol Coefficient object reproducing the anticipated
/// values of the scalar field, u_ex.
/// @param[in,out] error Vector to contain the element-wise $L^p$ errors
/// @param[in] weight Optional pointer to a Coefficient object
/// reproducing a weighting function, w.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual void ComputeElementLpErrors(const real_t p, Coefficient &exsol,
Vector &error,
Coefficient *weight = NULL,
const IntegrationRule *irs[] = NULL
) const;
/// @brief Returns ||u_ex - u_h||_L1 elementwise for H1 or L2 elements
///
/// Compute the $L^1$ error in each element of the mesh and store the
/// results in the Vector @a error. The result should be of length number of
/// elements, for example an L2 GridFunction of order zero using map type
/// @ref map_type_value "VALUE".
///
/// @param[in] exsol Coefficient object reproducing the anticipated
/// values of the scalar field, u_ex.
/// @param[in,out] error Vector to contain the element-wise $L^1$ errors
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @note Uses ComputeElementLpError internally. See the
/// ComputeElementLpError documentation for generalizations of this
/// error computation.
virtual void ComputeElementL1Errors(Coefficient &exsol,
Vector &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(1.0, exsol, error, NULL, irs); }
/// @brief Returns ||u_ex - u_h||_L2 elementwise for H1 or L2 elements
///
/// Compute the $L^2$ error in each element of the mesh and store the results
/// in the Vector @a error. The result should be of length number of
/// elements, for example an L2 GridFunction of order zero using map type
/// @ref map_type_value "VALUE".
///
/// Computes:
/// $$(\int_{elem} |u_{ex} - u_h|^2)^{1/2}$$
///
/// @param[in] exsol Coefficient object reproducing the anticipated
/// values of the scalar field, u_ex.
/// @param[in,out] error Vector to contain the element-wise $L^2$ errors
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @note Uses ComputeElementLpError internally. See the
/// ComputeElementLpError documentation for generalizations of this
/// error computation.
virtual void ComputeElementL2Errors(Coefficient &exsol,
Vector &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(2.0, exsol, error, NULL, irs); }
/// @brief Returns Max|u_ex - u_h| elementwise for H1 or L2 elements
///
/// Compute the $L^\infty$ error in each element of the mesh and store the
/// results in the Vector @a error. The result should be of length number of
/// elements, for example an L2 GridFunction of order zero using map type
/// @ref map_type_value "VALUE".
///
/// @param[in] exsol Coefficient object reproducing the anticipated
/// values of the scalar field, u_ex.
/// @param[in,out] error Vector to contain the element-wise $L^\infty$
/// errors
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Uses ComputeElementLpError internally. See the
/// ComputeElementLpError documentation for generalizations of this
/// error computation.
virtual void ComputeElementMaxErrors(Coefficient &exsol,
Vector &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(infinity(), exsol, error, NULL, irs); }
/** When given a vector weight, compute the pointwise (scalar) error as the
dot product of the vector error with the vector weight. Otherwise, the
scalar error is the l_2 norm of the vector error. */
/// @brief Returns ||u_ex - u_h||_Lp for vector fields
///
/// When given a vector weight, compute the pointwise (scalar) error as the
/// dot product of the vector error with the vector weight. Otherwise, the
/// scalar error is the l_2 norm of the vector error.
///
/// Computes:
/// $$(\sum_{elems} \int_{elem} w \, |scalar\_error|^p)^{1/p}$$
///
/// Where
/// $$scalar\_error = |v\_weight \cdot (u_{ex} - u_h)|$$
/// or
/// $$scalar\_error = \sqrt{(u_{ex} - u_h) \cdot (u_{ex} - u_h)}$$
///
/// @param[in] p Real value indicating the exponent of the $L^p$
/// norm. To avoid domain errors p should have a
/// positive value, either finite or infinite.
/// @param[in] exsol VectorCoefficient object reproducing the anticipated
/// values of the vector field, u_ex.
/// @param[in] weight Optional pointer to a Coefficient object reproducing
/// a weighting function, w.
/// @param[in] v_weight Optional pointer to a VectorCoefficient object
/// reproducing a weighting vector as shown above.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual real_t ComputeLpError(const real_t p, VectorCoefficient &exsol,
Coefficient *weight = NULL,
VectorCoefficient *v_weight = NULL,
const IntegrationRule *irs[] = NULL) const;
/** Compute the Lp error in each element of the mesh and store the results in
the Vector @ error. The result should be of length number of elements,
for example an L2 GridFunction of order zero using map type VALUE. */
/// @brief Returns ||u_ex - u_h||_Lp elementwise for vector fields
///
/// Compute the $L^p$ error in each element of the mesh and store the results
/// in the Vector @a error. The result should be of length number of
/// elements, for example an L2 GridFunction of order zero using map type
/// @ref map_type_value "VALUE".
///
/// Computes:
/// $$(\int_{elem} w \, |scalar\_error|^p)^{1/p}$$
///
/// Where
/// $$scalar\_error = |v\_weight \cdot (u_{ex} - u_h)|$$
/// or
/// $$scalar\_error = \sqrt{(u_{ex} - u_h) \cdot (u_{ex} - u_h)}$$
///
/// @param[in] p Real value indicating the exponent of the $L^p$
/// norm. To avoid domain errors p should have a
/// positive value, either finite or infinite.
/// @param[in] exsol VectorCoefficient object reproducing the
/// anticipated values of the vector field, u_ex.
/// @param[in,out] error Vector to contain the element-wise $L^p$ errors
/// @param[in] weight Optional pointer to a Coefficient object
/// reproducing a weighting function, w.
/// @param[in] v_weight Optional pointer to a VectorCoefficient object
/// reproducing a weighting vector as shown above.
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
virtual void ComputeElementLpErrors(const real_t p, VectorCoefficient &exsol,
Vector &error,
Coefficient *weight = NULL,
@@ -658,18 +1335,120 @@ public:
const IntegrationRule *irs[] = NULL
) const;
/// @brief Returns ||u_ex - u_h||_L1 elementwise for vector fields
///
/// Compute the $L^1$ error in each element of the mesh and store the
/// results in the Vector @a error. The result should be of length number of
/// elements, for example an L2 GridFunction of order zero using map type
/// @ref map_type_value "VALUE".
///
/// Computes:
/// $$\int_{elem} |scalar\_error|$$
///
/// Where
/// $$scalar\_error = \sqrt{(u_{ex} - u_h) \cdot (u_{ex} - u_h)}$$
///
/// @param[in] exsol VectorCoefficient object reproducing the
/// anticipated values of the vector field, u_ex.
/// @param[in,out] error Vector to contain the element-wise $L^1$ errors
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @note Uses ComputeElementLpError internally. See the
/// ComputeElementLpError documentation for generalizations of this
/// error computation.
virtual void ComputeElementL1Errors(VectorCoefficient &exsol,
Vector &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(1.0, exsol, error, NULL, NULL, irs); }
/// @brief Returns ||u_ex - u_h||_L2 elementwise for vector fields
///
/// Compute the $L^2$ error in each element of the mesh and store the
/// results in the Vector @a error. The result should be of length number of
/// elements, for example an L2 GridFunction of order zero using map type
/// @ref map_type_value "VALUE".
///
/// Computes:
/// $$(\int_{elem} |scalar\_error|^2)^{1/2}$$
///
/// Where
/// $$scalar\_error = \sqrt{(u_{ex} - u_h) \cdot (u_{ex} - u_h)}$$
///
/// @param[in] exsol VectorCoefficient object reproducing the
/// anticipated values of the vector field, u_ex.
/// @param[in,out] error Vector to contain the element-wise $L^2$ errors
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Quadratures with negative weights (as in some simplex integration
/// rules in MFEM) can produce negative integrals even with
/// non-negative integrands. To avoid returning negative errors this
/// function uses the absolute values of the element-wise integrals.
/// This may lead to results which are not entirely consistent with
/// such integration rules.
///
/// @note Uses ComputeElementLpError internally. See the
/// ComputeElementLpError documentation for generalizations of this
/// error computation.
virtual void ComputeElementL2Errors(VectorCoefficient &exsol,
Vector &error,
const IntegrationRule *irs[] = NULL
) const
{ ComputeElementLpErrors(2.0, exsol, error, NULL, NULL, irs); }
/// @brief Returns Max|u_ex - u_h| elementwise for vector fields
///
/// Compute the $L^\infty$ error in each element of the mesh and store the
/// results in the Vector @a error. The result should be of length number of
/// elements, for example an L2 GridFunction of order zero using map type
/// @ref map_type_value "VALUE".
///
/// Computes:
/// $$max_{elem} |scalar\_error|$$
///
/// Where
/// $$scalar\_error = \sqrt{(u_{ex} - u_h) \cdot (u_{ex} - u_h)}$$
///
/// @param[in] exsol VectorCoefficient object reproducing the
/// anticipated values of the vector field, u_ex.
/// @param[in,out] error Vector to contain the element-wise $L^\infty$
/// errors
/// @param[in] irs Optional pointer to an array of custom integration
/// rules e.g. higher order than the default rules. If
/// present the array will be indexed by
/// Geometry::Type.
///
/// @note If an array of integration rules is provided through @a irs, be
/// sure to include valid rules for each element type that may occur
/// in the list of elements.
///
/// @note Uses ComputeElementLpError internally. See the
/// ComputeElementLpError documentation for generalizations of this
/// error computation.
///
/// @note Computes the maximum magnitude of the difference vector not the
/// component-wise maximum difference of the vector fields.
virtual void ComputeElementMaxErrors(VectorCoefficient &exsol,
Vector &error,
const IntegrationRule *irs[] = NULL
+1138 -50
View File
File diff suppressed because it is too large Load Diff
+106 -12
View File
@@ -20,9 +20,9 @@
namespace gslib
{
struct comm;
struct findpts_data_2;
struct findpts_data_3;
struct crystal;
struct hash_data_3;
struct hash_data_2;
struct gs_data;
}
@@ -71,18 +71,16 @@ public:
protected:
Mesh *mesh;
Array<Mesh *> mesh_split; // Meshes used to split simplices.
// IntegrationRules for simplex->Quad/Hex and to project to highest polynomial
// order in-case of p-refinement.
// IntegrationRules for simplex->Quad/Hex and to project to p_max in-case of
// p-refinement.
Array<IntegrationRule *> ir_split;
Array<FiniteElementSpace *>
fes_rst_map; // FESpaces to map info Quad/Hex->Simplex
Array<GridFunction *> gf_rst_map; // GridFunctions to map info Quad/Hex->Simplex
Array<FiniteElementSpace *> fes_rst_map; //FESpaces to map Quad/Hex->Simplex
Array<GridFunction *> gf_rst_map; // GridFunctions to map Quad/Hex->Simplex
FiniteElementCollection *fec_map_lin;
struct gslib::findpts_data_2 *fdata2D; // gslib's internal data
struct gslib::findpts_data_3 *fdata3D; // gslib's internal data
void *fdataD;
struct gslib::crystal *cr; // gslib's internal data
struct gslib::comm *gsl_comm; // gslib's internal data
int dim, points_cnt;
int dim, points_cnt; // mesh dimension and number of points
Array<unsigned int> gsl_code, gsl_proc, gsl_elem, gsl_mfem_elem;
Vector gsl_mesh, gsl_ref, gsl_dist, gsl_mfem_ref;
Array<unsigned int> recv_proc, recv_index; // data for custom interpolation
@@ -91,9 +89,28 @@ protected:
AvgType avgtype; // average type used for L2 functions
Array<int> split_element_map;
Array<int> split_element_index;
int NE_split_total;
// Tolerance to ignore points just outside elements at the boundary.
int NE_split_total; // total number of elements after mesh splitting
int mesh_points_cnt; // number of mesh nodes
// Tolerance to ignore points found beyond the mesh boundary.
// i.e. if ||x*-x(r)||_2^2 > bdr_tol, we mark point as not found.
double bdr_tol;
// Use CPU functions for mesh/gridfunction on device for gslib1.0.7
bool gpu_to_cpu_fallback = false;
// Device specific data used for FindPoints
struct
{
bool setup_device = false;
bool find_device = false;
int local_hash_size, dof1d, dof1d_sol, h_o_size, h_nx;
double newt_tol; // Tolerance specified during setup for Newton solve
struct gslib::crystal *cr;
struct gslib::hash_data_3 *hash3;
struct gslib::hash_data_2 *hash2;
mutable Vector bb, wtend, gll1d, lagcoeff, gll1d_sol, lagcoeff_sol;
mutable Array<unsigned int> loc_hash_offset;
mutable Vector loc_hash_min, loc_hash_fac;
} DEV;
/// Use GSLIB for communication and interpolation
virtual void InterpolateH1(const GridFunction &field_in, Vector &field_out);
@@ -120,6 +137,63 @@ protected:
/// during the setup phase.
virtual void MapRefPosAndElemIndices();
// Device functions
// FindPoints locally on device for 3D.
void FindPointsLocal3(const Vector &point_pos,
int point_pos_ordering,
Array<unsigned int> &gsl_code_dev_l,
Array<unsigned int> &gsl_elem_dev_l,
Vector &gsl_ref_l,
Vector &gsl_dist_l,
int npt);
// FindPoints locally on device for 2D.
void FindPointsLocal2(const Vector &point_pos,
int point_pos_ordering,
Array<unsigned int> &gsl_code_dev_l,
Array<unsigned int> &gsl_elem_dev_l,
Vector &gsl_ref_l,
Vector &gsl_dist_l,
int npt);
// Interpolate on device for 3D.
void InterpolateLocal3(const Vector &field_in,
Array<int> &gsl_elem_dev_l,
Vector &gsl_ref_l,
Vector &field_out,
int npt, int ncomp,
int nel, int dof1dsol);
// Interpolate on device for 2D.
void InterpolateLocal2(const Vector &field_in,
Array<int> &gsl_elem_dev_l,
Vector &gsl_ref_l,
Vector &field_out,
int npt, int ncomp,
int nel, int dof1dsol);
// Prepare data for device functions.
void SetupDevice();
/** Searches positions given in physical space by @a point_pos.
These positions can be ordered byNodes: (XXX...,YYY...,ZZZ) or
byVDim: (XYZ,XYZ,....XYZ) specified by @a point_pos_ordering. */
void FindPointsOnDevice(const Vector &point_pos,
int point_pos_ordering = Ordering::byNODES);
/** Interpolation of field values at prescribed reference space positions.
@param[in] field_in_evec E-vector of gridfunction to be interpolated.
Assumed ordering is NDOFSxVDIMxNEL
@param[in] nel Number of elements in the mesh.
@param[in] ncomp Number of components in the field.
@param[in] dof1dsol Number of degrees of freedom in each reference
space direction.
@param[in] ordering Ordering of the out field values: byNodes/byVDIM
@param[out] field_out Interpolated values. For points that are not found
the value is set to #default_interp_value. */
void InterpolateOnDevice(const Vector &field_in_evec, Vector &field_out,
const int nel, const int ncomp,
const int dof1dsol, const int ordering);
public:
FindPointsGSLIB();
@@ -213,6 +287,10 @@ public:
bdr_tol = bdr_tol_;
}
/// Enable/Disable use of CPU functions for GPU data if the gslib version
/// is older.
virtual void SetGPUtoCPUFallback(bool mode) { gpu_to_cpu_fallback = mode; }
/** Cleans up memory allocated internally by gslib.
Note that in parallel, this must be called before MPI_Finalize(), as it
calls MPI_Comm_free() for internal gslib communicators. */
@@ -272,6 +350,22 @@ public:
const int ordering,
Vector &field_out) const;
///@}
/// Return the axis-aligned bounding boxes (AABB) computed during \ref Setup.
/// The size of the returned vector is (nel x nverts x dim), where nel is the
/// number of elements (after splitting for simplcies), nverts is number of
/// vertices (4 in 2D, 8 in 3D), and dim is the spatial dimension.
void GetAxisAlignedBoundingBoxes(Vector &aabb);
/// Return the oriented bounding boxes (OBB) computed during \ref Setup.
/// Each OBB is represented using the inverse transformation (A^{-1}) and
/// its center (x_c), such that a point x is inside the OBB if:
/// -1 <= A^{-1}(x-x_c) <= 1.
/// The inverse transformation is returned in \p obbA, a DenseTensor of
/// size (dim x dim x nel), and the OBB centers are returned in \p obbC,
/// a vector of size (nel x dim). The vertices of the OBBs are returned in
/// \p obbV, a vector of size (nel x nverts x dim) .
void GetOrientedBoundingBoxes(DenseTensor &obbA, Vector &obbC, Vector &obbV);
};
/** \brief OversetFindPointsGSLIB enables use of findpts for arbitrary number of
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+167
View File
@@ -0,0 +1,167 @@
// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "../gslib.hpp"
#include "../../general/forall.hpp"
#ifdef MFEM_USE_GSLIB
#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#include "gslib.h"
#ifndef GSLIB_RELEASE_VERSION //gslib v1.0.7
#define GSLIB_RELEASE_VERSION 10007
#endif
#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
#pragma GCC diagnostic pop
#endif
namespace mfem
{
#if GSLIB_RELEASE_VERSION >= 10009
#define CODE_INTERNAL 0
#define CODE_BORDER 1
#define CODE_NOT_FOUND 2
static MFEM_HOST_DEVICE void lagrange_eval(double *p0, double x,
int i, int p_Nq,
double *z, double *lagrangeCoeff)
{
double p_i = (1 << (p_Nq - 1));
for (int j = 0; j < p_Nq; ++j)
{
double d_j = x - z[j];
p_i *= j == i ? 1 : d_j;
}
p0[i] = lagrangeCoeff[i] * p_i;
}
template<int T_D1D = 0>
static void InterpolateLocal2DKernel(const double *const gf_in,
int *const el,
double *const r,
double *const int_out,
const int npt,
const int ncomp,
const int nel,
const int gf_offset,
double *gll1D,
double *lagcoeff,
const int pN = 0)
{
const int Nfields = ncomp;
const int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
const int D1D = T_D1D ? T_D1D : pN;
const int p_Np = D1D*D1D;
MFEM_VERIFY(MD1 <= DofQuadLimits::MAX_D1D,
"Increase Max allowable polynomial order.");
MFEM_VERIFY(D1D != 0, "Polynomial order not specified.");
mfem::forall_2D(npt, D1D, D1D, [=] MFEM_HOST_DEVICE (int i)
{
MFEM_SHARED double wtr[2*MD1];
MFEM_SHARED double sums[MD1*MD1];
// Evaluate basis functions at the reference space coordinates
MFEM_FOREACH_THREAD(j,x,D1D)
{
MFEM_FOREACH_THREAD(k,y,2)
{
lagrange_eval(wtr + k*D1D, r[2*i+k], j, D1D, gll1D, lagcoeff);
}
}
MFEM_SYNC_THREAD;
for (int fld = 0; fld < Nfields; ++fld)
{
// If using GetNodalValues, ordering is NDOFSxNELxVDIM
// const int elemOffset = el[i] * p_Np + fld * gf_offset;
//if using R->Mult for L -> E-Vec use below: NDOFSxVDIMxNEL
const int elemOffset = el[i] * p_Np * Nfields + fld * p_Np;
MFEM_FOREACH_THREAD(j,x,D1D)
{
MFEM_FOREACH_THREAD(k,y,D1D)
{
sums[j + k*D1D] = gf_in[elemOffset + j + k * D1D] *
wtr[D1D+k] *
wtr[j];
}
}
MFEM_SYNC_THREAD;
// MFEM_FOREACH_THREAD(j,x,D1D)
MFEM_FOREACH_THREAD(j,x,1)
{
MFEM_FOREACH_THREAD(k,y,1)
{
double sumv = 0.0;
for (int jj = 0; jj < D1D*D1D; ++jj)
{
sumv += sums[jj];
}
int_out[i + fld * npt] = sumv;
}
}
MFEM_SYNC_THREAD;
}
});
}
void FindPointsGSLIB::InterpolateLocal2(const Vector &field_in,
Array<int> &gsl_elem_dev_l,
Vector &gsl_ref_l,
Vector &field_out,
int npt, int ncomp,
int nel, int dof1Dsol)
{
if (npt == 0) { return; }
const int gf_offset = field_in.Size()/ncomp;
auto pfin = field_in.Read();
auto pgsl = gsl_elem_dev_l.ReadWrite();
auto pgslr = gsl_ref_l.ReadWrite();
auto pfout = field_out.Write();
auto pgll = DEV.gll1d_sol.ReadWrite();
auto plcf = DEV.lagcoeff_sol.ReadWrite();
switch (dof1Dsol)
{
case 2: return InterpolateLocal2DKernel<2>(pfin, pgsl, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf);
case 3: return InterpolateLocal2DKernel<3>(pfin, pgsl, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf);
case 4: return InterpolateLocal2DKernel<4>(pfin, pgsl, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf);
case 5: return InterpolateLocal2DKernel<5>(pfin, pgsl, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf);
default: return InterpolateLocal2DKernel(pfin, pgsl, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf, dof1Dsol);
}
}
#undef CODE_INTERNAL
#undef CODE_BORDER
#undef CODE_NOT_FOUND
#else
void FindPointsGSLIB::InterpolateLocal2(const Vector &field_in,
Array<int> &gsl_elem_dev_l,
Vector &gsl_ref_l,
Vector &field_out,
int npt, int ncomp,
int nel, int dof1Dsol) {};
#endif
} // namespace mfem
#endif //ifdef MFEM_USE_GSLIB
+172
View File
@@ -0,0 +1,172 @@
// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "../gslib.hpp"
#include "../../general/forall.hpp"
#ifdef MFEM_USE_GSLIB
#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif
#include "gslib.h"
#ifndef GSLIB_RELEASE_VERSION //gslib v1.0.7
#define GSLIB_RELEASE_VERSION 10007
#endif
#ifdef MFEM_HAVE_GCC_PRAGMA_DIAGNOSTIC
#pragma GCC diagnostic pop
#endif
namespace mfem
{
#if GSLIB_RELEASE_VERSION >= 10009
#define CODE_INTERNAL 0
#define CODE_BORDER 1
#define CODE_NOT_FOUND 2
static MFEM_HOST_DEVICE void lagrange_eval(double *p0, double x,
int i, int p_Nq,
double *z, double *lagrangeCoeff)
{
double p_i = (1 << (p_Nq - 1));
for (int j = 0; j < p_Nq; ++j)
{
double d_j = x - z[j];
p_i *= j == i ? 1 : d_j;
}
p0[i] = lagrangeCoeff[i] * p_i;
}
template<int T_D1D = 0>
static void InterpolateLocal3DKernel(const double *const gf_in,
int *const el,
double *const r,
double *const int_out,
const int npt,
const int ncomp,
const int nel,
const int gf_offset,
double *gll1D,
double *lagcoeff,
const int pN = 0)
{
const int Nfields = ncomp;
const int MD1 = T_D1D ? T_D1D : DofQuadLimits::MAX_D1D;
const int D1D = T_D1D ? T_D1D : pN;
const int p_Np = D1D*D1D*D1D;
MFEM_VERIFY(MD1 <= DofQuadLimits::MAX_D1D,
"Increase Max allowable polynomial order.");
MFEM_VERIFY(D1D != 0, "Polynomial order not specified.");
#define MAXC(a, b) (((a) > (b)) ? (a) : (b))
const int nThreadsy = MAXC(D1D, 3);
mfem::forall_2D(npt, D1D, nThreadsy, [=] MFEM_HOST_DEVICE (int i)
{
MFEM_SHARED double wtr[3*MD1];
MFEM_SHARED double sums[MD1*MD1];
// Evaluate basis functions at the reference space coordinates
MFEM_FOREACH_THREAD(j,x,D1D)
{
MFEM_FOREACH_THREAD(k,y,3)
{
lagrange_eval(wtr + k*D1D, r[3*i+k], j, D1D, gll1D, lagcoeff);
}
}
MFEM_SYNC_THREAD;
for (int fld = 0; fld < Nfields; ++fld)
{
// If using GetNodalValues, ordering is NDOFSxNELxVDIM
// const int elemOffset = el[i] * p_Np + fld * gf_offset;
//if using R->Mult for L -> E-Vec use below.
const int elemOffset = el[i] * p_Np * Nfields + fld * p_Np;
MFEM_FOREACH_THREAD(j,x,D1D)
{
MFEM_FOREACH_THREAD(k,y,D1D)
{
sums[j + k*D1D] = 0.0;
for (int l = 0; l < D1D; ++l)
{
sums[j + k*D1D] += gf_in[elemOffset + j + k*D1D + l*D1D*D1D] *
wtr[2*D1D+l];
}
sums[j+k*D1D] *= wtr[D1D+k]*wtr[j];
}
}
MFEM_SYNC_THREAD;
MFEM_FOREACH_THREAD(j,x,1)
{
MFEM_FOREACH_THREAD(k,y,1)
{
double sumv = 0.0;
for (int jj = 0; jj < D1D*D1D; ++jj)
{
sumv += sums[jj];
}
int_out[i + fld * npt] = sumv;
}
}
MFEM_SYNC_THREAD;
}
});
}
void FindPointsGSLIB::InterpolateLocal3(const Vector &field_in,
Array<int> &gsl_elem_dev_l,
Vector &gsl_ref_l,
Vector &field_out,
int npt, int ncomp,
int nel, int dof1Dsol)
{
if (npt == 0) { return; }
const int gf_offset = field_in.Size()/ncomp;
auto pfin = field_in.Read();
auto pgsle = gsl_elem_dev_l.ReadWrite();
auto pgslr = gsl_ref_l.ReadWrite();
auto pfout = field_out.Write();
auto pgll = DEV.gll1d_sol.ReadWrite();
auto plcf = DEV.lagcoeff_sol.ReadWrite();
switch (dof1Dsol)
{
case 2: return InterpolateLocal3DKernel<2>(pfin, pgsle, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf);
case 3: return InterpolateLocal3DKernel<3>(pfin, pgsle, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf);
case 4: return InterpolateLocal3DKernel<4>(pfin, pgsle, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf);
case 5: return InterpolateLocal3DKernel<5>(pfin, pgsle, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf);
default: return InterpolateLocal3DKernel(pfin, pgsle, pgslr, pfout,
npt, ncomp, nel, gf_offset,
pgll, plcf, dof1Dsol);
}
}
#undef CODE_INTERNAL
#undef CODE_BORDER
#undef CODE_NOT_FOUND
#else
void FindPointsGSLIB::InterpolateLocal3(const Vector &field_in,
Array<int> &gsl_elem_dev_l,
Vector &gsl_ref_l,
Vector &field_out,
int npt, int ncomp,
int nel, int dof1Dsol) {};
#endif
} // namespace mfem
#endif //ifdef MFEM_USE_GSLIB
+691 -27
View File
@@ -18,6 +18,29 @@
namespace mfem
{
HyperbolicFormIntegrator::HyperbolicFormIntegrator(
const NumericalFlux &numFlux,
const int IntOrderOffset,
real_t sign)
: NonlinearFormIntegrator(),
numFlux(numFlux),
fluxFunction(numFlux.GetFluxFunction()),
IntOrderOffset(IntOrderOffset),
sign(sign),
num_equations(fluxFunction.num_equations)
{
#ifndef MFEM_THREAD_SAFE
state.SetSize(num_equations);
flux.SetSize(num_equations, fluxFunction.dim);
state1.SetSize(num_equations);
state2.SetSize(num_equations);
fluxN.SetSize(num_equations);
JDotN.SetSize(num_equations);
nor.SetSize(fluxFunction.dim);
#endif
ResetMaxCharSpeed();
}
void HyperbolicFormIntegrator::AssembleElementVector(const FiniteElement &el,
ElementTransformation &Tr,
const Vector &elfun,
@@ -33,7 +56,7 @@ void HyperbolicFormIntegrator::AssembleElementVector(const FiniteElement &el,
// shape function value at an integration point
Vector shape(dof);
// derivative of shape function at an integration point
DenseMatrix dshape(dof, el.GetDim());
DenseMatrix dshape(dof, Tr.GetSpaceDim());
// state value at an integration point
Vector state(num_equations);
// flux value at an integration point
@@ -41,7 +64,7 @@ void HyperbolicFormIntegrator::AssembleElementVector(const FiniteElement &el,
#else
// resize shape and gradient shape storage
shape.SetSize(dof);
dshape.SetSize(dof, el.GetDim());
dshape.SetSize(dof, Tr.GetSpaceDim());
#endif
// setDegree-up output vector
@@ -77,7 +100,77 @@ void HyperbolicFormIntegrator::AssembleElementVector(const FiniteElement &el,
// update maximum characteristic speed
max_char_speed = std::max(mcs, max_char_speed);
// integrate (F(u,x), grad v)
AddMult_a_ABt(ip.weight * Tr.Weight(), dshape, flux, elvect_mat);
AddMult_a_ABt(ip.weight * Tr.Weight() * sign, dshape, flux, elvect_mat);
}
}
void HyperbolicFormIntegrator::AssembleElementGrad(
const FiniteElement &el, ElementTransformation &Tr, const Vector &elfun,
DenseMatrix &grad)
{
// current element's the number of degrees of freedom
// does not consider the number of equations
const int dof = el.GetDof();
#ifdef MFEM_THREAD_SAFE
// Local storage for element integration
// shape function value at an integration point
Vector shape(dof);
// derivative of shape function at an integration point
DenseMatrix dshape(dof, Tr.GetSpaceDim());
// state value at an integration point
Vector state(num_equations);
// Jacobian value at an integration point
DenseTensor J(num_equations, num_equations, fluxFunction.dim);
#else
// resize shape, gradient shape and Jacobian storage
shape.SetSize(dof);
dshape.SetSize(dof, Tr.GetSpaceDim());
J.SetSize(num_equations, num_equations, fluxFunction.dim);
#endif
// setup output gradient matrix
grad.SetSize(dof * num_equations);
grad = 0.0;
// make state variable and output dual vector matrix form.
const DenseMatrix elfun_mat(elfun.GetData(), dof, num_equations);
//DenseMatrix elvect_mat(elvect.GetData(), dof, num_equations);
// obtain integration rule. If integration is rule is given, then use it.
// Otherwise, get (2*p + IntOrderOffset) order integration rule
const IntegrationRule *ir = IntRule;
if (!ir)
{
const int order = el.GetOrder()*2 + IntOrderOffset;
ir = &IntRules.Get(Tr.GetGeometryType(), order);
}
// loop over integration points
for (int q = 0; q < ir->GetNPoints(); q++)
{
const IntegrationPoint &ip = ir->IntPoint(q);
Tr.SetIntPoint(&ip);
el.CalcShape(ip, shape);
el.CalcPhysDShape(Tr, dshape);
// compute current state value with given shape function values
elfun_mat.MultTranspose(shape, state);
// compute J(u,x)
fluxFunction.ComputeFluxJacobian(state, Tr, J);
// integrate (J(u,x), grad v)
const real_t w = ip.weight * Tr.Weight() * sign;
for (int di = 0; di < num_equations; di++)
for (int dj = 0; dj < num_equations; dj++)
for (int i = 0; i < dof; i++)
for (int j = 0; j < dof; j++)
for (int d = 0; d < fluxFunction.dim; d++)
{
grad(di*dof+i, dj*dof+j) += w * dshape(i,d) * shape(j) * J(di,dj,d);
}
}
}
@@ -98,7 +191,7 @@ void HyperbolicFormIntegrator::AssembleFaceVector(
// shape function value at an integration point - second elem
Vector shape2(dof2);
// normal vector (usually not a unit vector)
Vector nor(el1.GetDim());
Vector nor(Tr.GetSpaceDim());
// state value at an integration point - first elem
Vector state1(num_equations);
// state value at an integration point - second elem
@@ -157,34 +250,144 @@ void HyperbolicFormIntegrator::AssembleFaceVector(
}
// Compute F(u+, x) and F(u-, x) with maximum characteristic speed
// Compute hat(F) using evaluated quantities
const real_t speed = rsolver.Eval(state1, state2, nor, Tr, fluxN);
const real_t speed = numFlux.Eval(state1, state2, nor, Tr, fluxN);
// Update the global max char speed
max_char_speed = std::max(speed, max_char_speed);
// pre-multiply integration weight to flux
AddMult_a_VWt(-ip.weight, shape1, fluxN, elvect1_mat);
AddMult_a_VWt(+ip.weight, shape2, fluxN, elvect2_mat);
AddMult_a_VWt(-ip.weight*sign, shape1, fluxN, elvect1_mat);
AddMult_a_VWt(+ip.weight*sign, shape2, fluxN, elvect2_mat);
}
}
HyperbolicFormIntegrator::HyperbolicFormIntegrator(
const RiemannSolver &rsolver,
const int IntOrderOffset)
: NonlinearFormIntegrator(),
rsolver(rsolver),
fluxFunction(rsolver.GetFluxFunction()),
IntOrderOffset(IntOrderOffset),
num_equations(fluxFunction.num_equations)
void HyperbolicFormIntegrator::AssembleFaceGrad(
const FiniteElement &el1, const FiniteElement &el2,
FaceElementTransformations &Tr, const Vector &elfun, DenseMatrix &elmat)
{
#ifndef MFEM_THREAD_SAFE
state.SetSize(num_equations);
flux.SetSize(num_equations, fluxFunction.dim);
state1.SetSize(num_equations);
state2.SetSize(num_equations);
fluxN.SetSize(num_equations);
nor.SetSize(fluxFunction.dim);
// current elements' the number of degrees of freedom
// does not consider the number of equations
const int dof1 = el1.GetDof();
const int dof2 = el2.GetDof();
#ifdef MFEM_THREAD_SAFE
// Local storage for element integration
// shape function value at an integration point - first elem
Vector shape1(dof1);
// shape function value at an integration point - second elem
Vector shape2(dof2);
// normal vector (usually not a unit vector)
Vector nor(Tr.GetSpaceDim());
// state value at an integration point - first elem
Vector state1(num_equations);
// state value at an integration point - second elem
Vector state2(num_equations);
// hat(J)(u,x)
DenseMatrix JDotN(num_equations);
#else
shape1.SetSize(dof1);
shape2.SetSize(dof2);
#endif
elmat.SetSize((dof1 + dof2) * num_equations);
elmat = 0.0;
const DenseMatrix elfun1_mat(elfun.GetData(), dof1, num_equations);
const DenseMatrix elfun2_mat(elfun.GetData() + dof1 * num_equations, dof2,
num_equations);
// Obtain integration rule. If integration is rule is given, then use it.
// Otherwise, get (2*p + IntOrderOffset) order integration rule
const IntegrationRule *ir = IntRule;
if (!ir)
{
const int order = 2*std::max(el1.GetOrder(), el2.GetOrder()) + IntOrderOffset;
ir = &IntRules.Get(Tr.GetGeometryType(), order);
}
// loop over integration points
for (int q = 0; q < ir->GetNPoints(); q++)
{
const IntegrationPoint &ip = ir->IntPoint(q);
Tr.SetAllIntPoints(&ip); // set face and element int. points
// Calculate basis functions on both elements at the face
el1.CalcShape(Tr.GetElement1IntPoint(), shape1);
el2.CalcShape(Tr.GetElement2IntPoint(), shape2);
// Interpolate elfun at the point
elfun1_mat.MultTranspose(shape1, state1);
elfun2_mat.MultTranspose(shape2, state2);
// Get the normal vector and the flux on the face
if (nor.Size() == 1) // if 1D, use 1 or -1.
{
// This assume the 1D integration point is in (0,1). This may not work
// if this changes.
nor(0) = (Tr.GetElement1IntPoint().x - 0.5) * 2.0;
}
else
{
CalcOrtho(Tr.Jacobian(), nor);
}
// Trial side 1
// Compute hat(J) using evaluated quantities
numFlux.Grad(1, state1, state2, nor, Tr, JDotN);
const int ioff = fluxFunction.num_equations * dof1;
for (int di = 0; di < fluxFunction.num_equations; di++)
for (int dj = 0; dj < fluxFunction.num_equations; dj++)
{
// pre-multiply integration weight to Jacobian
const real_t w = -ip.weight * sign * JDotN(di,dj);
for (int j = 0; j < dof1; j++)
{
// Test side 1
for (int i = 0; i < dof1; i++)
{
elmat(i+dof1*di, j+dof1*dj) += w * shape1(i) * shape1(j);
}
// Test side 2
for (int i = 0; i < dof2; i++)
{
elmat(ioff+i+dof2*di, j+dof1*dj) -= w * shape2(i) * shape1(j);
}
}
}
// Trial side 2
// Compute hat(J) using evaluated quantities
numFlux.Grad(2, state1, state2, nor, Tr, JDotN);
const int joff = ioff;
for (int di = 0; di < fluxFunction.num_equations; di++)
for (int dj = 0; dj < fluxFunction.num_equations; dj++)
{
// pre-multiply integration weight to Jacobian
const real_t w = +ip.weight * sign * JDotN(di,dj);
for (int j = 0; j < dof2; j++)
{
// Test side 1
for (int i = 0; i < dof1; i++)
{
elmat(i+dof1*di, joff+j+dof2*dj) += w * shape1(i) * shape2(j);
}
// Test side 2
for (int i = 0; i < dof2; i++)
{
elmat(ioff+i+dof2*di, joff+j+dof2*dj) -= w * shape2(i) * shape2(j);
}
}
}
}
}
real_t FluxFunction::ComputeFluxDotN(const Vector &U,
@@ -194,12 +397,55 @@ real_t FluxFunction::ComputeFluxDotN(const Vector &U,
{
#ifdef MFEM_THREAD_SAFE
DenseMatrix flux(num_equations, dim);
#else
flux.SetSize(num_equations, dim);
#endif
real_t val = ComputeFlux(U, Tr, flux);
flux.Mult(normal, FUdotN);
return val;
}
real_t FluxFunction::ComputeAvgFluxDotN(const Vector &U1, const Vector &U2,
const Vector &normal,
FaceElementTransformations &Tr,
Vector &fluxDotN) const
{
#ifdef MFEM_THREAD_SAFE
DenseMatrix flux(num_equations, dim);
#else
flux.SetSize(num_equations, dim);
#endif
real_t val = ComputeAvgFlux(U1, U2, Tr, flux);
flux.Mult(normal, fluxDotN);
return val;
}
void FluxFunction::ComputeFluxJacobianDotN(const Vector &U,
const Vector &normal,
ElementTransformation &Tr,
DenseMatrix &JDotN) const
{
#ifdef MFEM_THREAD_SAFE
DenseTensor J(num_equations, num_equations, dim);
#else
J.SetSize(num_equations, num_equations, dim);
#endif
ComputeFluxJacobian(U, Tr, J);
JDotN.Set(normal(0), J(0));
for (int d = 1; d < dim; d++)
{
JDotN.AddMatrix(normal(d), J(d), 0, 0);
}
}
RusanovFlux::RusanovFlux(const FluxFunction &fluxFunction)
: NumericalFlux(fluxFunction)
{
#ifndef MFEM_THREAD_SAFE
fluxN1.SetSize(fluxFunction.num_equations);
fluxN2.SetSize(fluxFunction.num_equations);
#endif
}
real_t RusanovFlux::Eval(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
@@ -212,15 +458,321 @@ real_t RusanovFlux::Eval(const Vector &state1, const Vector &state2,
const real_t speed2 = fluxFunction.ComputeFluxDotN(state2, nor, Tr, fluxN2);
// NOTE: nor in general is not a unit normal
const real_t maxE = std::max(speed1, speed2);
// here, std::sqrt(nor*nor) is multiplied to match the scale with fluxN
const real_t scaledMaxE = maxE*std::sqrt(nor*nor);
for (int i=0; i<state1.Size(); i++)
// here, nor.Norml2() is multiplied to match the scale with fluxN
const real_t scaledMaxE = maxE * nor.Norml2();
for (int i = 0; i < fluxFunction.num_equations; i++)
{
flux[i] = 0.5*(scaledMaxE*(state1[i] - state2[i]) + (fluxN1[i] + fluxN2[i]));
flux(i) = 0.5*(scaledMaxE*(state1(i) - state2(i)) + (fluxN1(i) + fluxN2(i)));
}
return maxE;
}
void RusanovFlux::Grad(int side, const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const
{
#ifdef MFEM_THREAD_SAFE
Vector fluxN1(fluxFunction.num_equations), fluxN2(fluxFunction.num_equations);
#endif
const real_t speed1 = fluxFunction.ComputeFluxDotN(state1, nor, Tr, fluxN1);
const real_t speed2 = fluxFunction.ComputeFluxDotN(state2, nor, Tr, fluxN2);
// NOTE: nor in general is not a unit normal
const real_t maxE = std::max(speed1, speed2);
// here, nor.Norml2() is multiplied to match the scale with fluxN
const real_t scaledMaxE = maxE * nor.Norml2();
if (side == 1)
{
fluxFunction.ComputeFluxJacobianDotN(state1, nor, Tr, grad);
for (int i = 0; i < fluxFunction.num_equations; i++)
{
grad(i,i) += 0.5 * scaledMaxE;
}
}
else
{
fluxFunction.ComputeFluxJacobianDotN(state2, nor, Tr, grad);
for (int i = 0; i < fluxFunction.num_equations; i++)
{
grad(i,i) -= 0.5 * scaledMaxE;
}
}
}
real_t RusanovFlux::Average(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const
{
#ifdef MFEM_THREAD_SAFE
Vector fluxN1(fluxFunction.num_equations), fluxN2(fluxFunction.num_equations);
#endif
const real_t speed1 = fluxFunction.ComputeFluxDotN(state1, nor, Tr, fluxN1);
const real_t speed2 = fluxFunction.ComputeAvgFluxDotN(state1, state2, nor, Tr,
fluxN2);
// NOTE: nor in general is not a unit normal
const real_t maxE = std::max(speed1, speed2);
// here, nor.Norml2() is multiplied to match the scale with fluxN
const real_t scaledMaxE = maxE * nor.Norml2() * 0.5;
for (int i = 0; i < fluxFunction.num_equations; i++)
{
flux(i) = 0.5*(scaledMaxE*(state1(i) - state2(i)) + (fluxN1(i) + fluxN2(i)));
}
return maxE;
}
void RusanovFlux::AverageGrad(int side, const Vector &state1,
const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const
{
#ifdef MFEM_THREAD_SAFE
Vector fluxN1(fluxFunction.num_equations), fluxN2(fluxFunction.num_equations);
#endif
#if defined(MFEM_USE_DOUBLE)
constexpr real_t tol = 1e-12;
#elif defined(MFEM_USE_SINGLE)
constexpr real_t tol = 4e-6;
#else
#error "Only single and double precision are supported!"
constexpr real_t tol = 1.;
#endif
auto equal_check = [=](real_t a, real_t b) -> bool { return std::abs(a - b) <= tol * std::abs(a + b); };
if (side == 1)
{
#ifdef MFEM_THREAD_SAFE
DenseMatrix JDotN(fluxFunction.num_equations);
#else
JDotN.SetSize(fluxFunction.num_equations);
#endif
const real_t speed1 = fluxFunction.ComputeFluxDotN(state1, nor, Tr, fluxN1);
const real_t speed2 = fluxFunction.ComputeAvgFluxDotN(state1, state2, nor, Tr,
fluxN2);
fluxFunction.ComputeFluxJacobianDotN(state1, nor, Tr, JDotN);
// NOTE: nor in general is not a unit normal
const real_t maxE = std::max(speed1, speed2);
// here, nor.Norml2() is multiplied to match the scale with fluxN
const real_t scaledMaxE = maxE * nor.Norml2() * 0.5;
grad = 0.;
for (int i = 0; i < fluxFunction.num_equations; i++)
{
// Only diagonal terms of J are considered
// lim_{u → u⁻} (F̄(u⁻,u)n - F(u⁻)n) / (u - u⁻) = ½λ
if (equal_check(state1(i), state2(i))) { continue; }
grad(i,i) = 0.5 * ((fluxN2(i) - fluxN1(i)) / (state2(i) - state1(i))
- JDotN(i,i) + scaledMaxE);
}
}
else
{
const real_t speed1 = fluxFunction.ComputeAvgFluxDotN(state1, state2, nor, Tr,
fluxN1);
const real_t speed2 = fluxFunction.ComputeFluxDotN(state2, nor, Tr, fluxN2);
// NOTE: nor in general is not a unit normal
const real_t maxE = std::max(speed1, speed2);
// here, nor.Norml2() is multiplied to match the scale with fluxN
const real_t scaledMaxE = maxE * nor.Norml2() * 0.5;
grad = 0.;
for (int i = 0; i < fluxFunction.num_equations; i++)
{
// lim_{u → u⁻} (F(u)n - F̄(u⁻,u)n) / (u - u⁻) = ½λ
if (equal_check(state1(i), state2(i))) { continue; }
grad(i,i) = 0.5 * ((fluxN2(i) - fluxN1(i)) / (state2(i) - state1(i))
- scaledMaxE);
}
}
}
ComponentwiseUpwindFlux::ComponentwiseUpwindFlux(
const FluxFunction &fluxFunction)
: NumericalFlux(fluxFunction)
{
#ifndef MFEM_THREAD_SAFE
fluxN1.SetSize(fluxFunction.num_equations);
fluxN2.SetSize(fluxFunction.num_equations);
#endif
if (fluxFunction.dim > 1)
MFEM_WARNING("Upwinded flux is implemented only component-wise.")
}
real_t ComponentwiseUpwindFlux::Eval(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const
{
#ifdef MFEM_THREAD_SAFE
Vector fluxN1(fluxFunction.num_equations), fluxN2(fluxFunction.num_equations);
#endif
const real_t speed1 = fluxFunction.ComputeFluxDotN(state1, nor, Tr, fluxN1);
const real_t speed2 = fluxFunction.ComputeFluxDotN(state2, nor, Tr, fluxN2);
for (int i = 0; i < fluxFunction.num_equations; i++)
{
if (state1(i) <= state2(i))
{
flux(i) = std::min(fluxN1(i), fluxN2(i));
}
else
{
flux(i) = std::max(fluxN1(i), fluxN2(i));
}
}
return std::max(speed1, speed2);
}
void ComponentwiseUpwindFlux::Grad(int side, const Vector &state1,
const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const
{
#ifdef MFEM_THREAD_SAFE
DenseMatrix JDotN(fluxFunction.num_equations);
#else
JDotN.SetSize(fluxFunction.num_equations);
#endif
grad = 0.;
if (side == 1)
{
fluxFunction.ComputeFluxJacobianDotN(state1, nor, Tr, JDotN);
for (int i = 0; i < fluxFunction.num_equations; i++)
{
// Only diagonal terms of J are considered
grad(i,i) = std::max(JDotN(i,i), 0_r);
}
}
else
{
fluxFunction.ComputeFluxJacobianDotN(state2, nor, Tr, JDotN);
for (int i = 0; i < fluxFunction.num_equations; i++)
{
// Only diagonal terms of J are considered
grad(i,i) = std::min(JDotN(i,i), 0_r);
}
}
}
real_t ComponentwiseUpwindFlux::Average(const Vector &state1,
const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const
{
#ifdef MFEM_THREAD_SAFE
Vector fluxN1(fluxFunction.num_equations), fluxN2(fluxFunction.num_equations);
#endif
const real_t speed1 = fluxFunction.ComputeFluxDotN(state1, nor, Tr, fluxN1);
const real_t speed2 = fluxFunction.ComputeAvgFluxDotN(state1, state2, nor, Tr,
fluxN2);
for (int i = 0; i < fluxFunction.num_equations; i++)
{
if (state1(i) <= state2(i))
{
flux(i) = std::min(fluxN1(i), fluxN2(i));
}
else
{
flux(i) = std::max(fluxN1(i), fluxN2(i));
}
}
return std::max(speed1, speed2);
}
void ComponentwiseUpwindFlux::AverageGrad(int side, const Vector &state1,
const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const
{
#ifdef MFEM_THREAD_SAFE
Vector fluxN1(fluxFunction.num_equations), fluxN2(fluxFunction.num_equations);
#endif
#if defined(MFEM_USE_DOUBLE)
constexpr real_t tol = 1e-12;
#elif defined(MFEM_USE_SINGLE)
constexpr real_t tol = 4e-6;
#else
#error "Only single and double precision are supported!"
constexpr real_t tol = 1.;
#endif
auto equal_check = [=](real_t a, real_t b) -> bool { return std::abs(a - b) <= tol * std::abs(a + b); };
if (side == 1)
{
#ifdef MFEM_THREAD_SAFE
DenseMatrix JDotN(fluxFunction.num_equations);
#else
JDotN.SetSize(fluxFunction.num_equations);
#endif
fluxFunction.ComputeFluxDotN(state1, nor, Tr, fluxN1);
fluxFunction.ComputeAvgFluxDotN(state1, state2, nor, Tr, fluxN2);
fluxFunction.ComputeFluxJacobianDotN(state1, nor, Tr, JDotN);
grad = 0.;
for (int i = 0; i < fluxFunction.num_equations; i++)
{
// Only diagonal terms of J are considered
// lim_{u → u⁻} (F̄(u⁻,u)n - F(u⁻)n) / (u - u⁻) = ½J(u⁻)n
const real_t gr12 = (!equal_check(state1(i), state2(i)))?
(fluxN2(i) - fluxN1(i)) / (state2(i) - state1(i))
:(0.5 * JDotN(i,i));
grad(i,i) = (gr12 >= 0.)?(JDotN(i,i)):(gr12);
}
}
else
{
#ifdef MFEM_THREAD_SAFE
DenseMatrix JDotN;
#endif
fluxFunction.ComputeAvgFluxDotN(state1, state2, nor, Tr, fluxN1);
fluxFunction.ComputeFluxDotN(state2, nor, Tr, fluxN2);
// Jacobian is not needed except the limit case when u⁺=u⁻
bool J_needed = false;
for (int i = 0; i < fluxFunction.num_equations; i++)
if (equal_check(state1(i), state2(i)))
{
J_needed = true;
break;
}
if (J_needed)
{
JDotN.SetSize(fluxFunction.num_equations);
fluxFunction.ComputeFluxJacobianDotN(state1, nor, Tr, JDotN);
}
grad = 0.;
for (int i = 0; i < fluxFunction.num_equations; i++)
{
// Only diagonal terms of J are considered
// lim_{u → u⁻} (F(u)n - F̄(u⁻,u)n) / (u - u⁻) = ½J(u⁻)n
const real_t gr12 = (!equal_check(state1(i), state2(i)))?
(fluxN2(i) - fluxN1(i)) / (state2(i) - state1(i))
:(0.5 * JDotN(i,i));
grad(i,i) = std::min(gr12, 0_r);
}
}
}
real_t AdvectionFlux::ComputeFlux(const Vector &U,
ElementTransformation &Tr,
@@ -234,15 +786,127 @@ real_t AdvectionFlux::ComputeFlux(const Vector &U,
return bval.Norml2();
}
real_t AdvectionFlux::ComputeFluxDotN(const Vector &U,
const Vector &normal,
FaceElementTransformations &Tr,
Vector &FDotN) const
{
#ifdef MFEM_THREAD_SAFE
Vector bval(b.GetVDim());
#endif
b.Eval(bval, Tr, Tr.GetIntPoint());
FDotN(0) = U(0) * (bval * normal);
return bval.Norml2();
}
real_t AdvectionFlux::ComputeAvgFlux(const Vector &U1, const Vector &U2,
ElementTransformation &Tr,
DenseMatrix &FU) const
{
#ifdef MFEM_THREAD_SAFE
Vector bval(b.GetVDim());
#endif
b.Eval(bval, Tr, Tr.GetIntPoint());
Vector Uavg(1);
Uavg(0) = (U1(0) + U2(0)) * 0.5;
MultVWt(Uavg, bval, FU);
return bval.Norml2();
}
real_t AdvectionFlux::ComputeAvgFluxDotN(const Vector &U1, const Vector &U2,
const Vector &normal,
FaceElementTransformations &Tr,
Vector &FDotN) const
{
#ifdef MFEM_THREAD_SAFE
Vector bval(b.GetVDim());
#endif
b.Eval(bval, Tr, Tr.GetIntPoint());
FDotN(0) = (U1(0) + U2(0)) * 0.5 * (bval * normal);
return bval.Norml2();
}
void AdvectionFlux::ComputeFluxJacobian(const Vector &state,
ElementTransformation &Tr,
DenseTensor &J) const
{
#ifdef MFEM_THREAD_SAFE
Vector bval(b.GetVDim());
#endif
b.Eval(bval, Tr, Tr.GetIntPoint());
J = 0.;
for (int d = 0; d < dim; d++)
{
J(0,0,d) = bval(d);
}
}
void AdvectionFlux::ComputeFluxJacobianDotN(const Vector &state,
const Vector &normal,
ElementTransformation &Tr,
DenseMatrix &JDotN) const
{
#ifdef MFEM_THREAD_SAFE
Vector bval(b.GetVDim());
#endif
b.Eval(bval, Tr, Tr.GetIntPoint());
JDotN(0,0) = bval * normal;
}
real_t BurgersFlux::ComputeFlux(const Vector &U,
ElementTransformation &Tr,
DenseMatrix &FU) const
{
FU = U * U * 0.5;
FU = U(0) * U(0) * 0.5;
return std::fabs(U(0));
}
real_t BurgersFlux::ComputeFluxDotN(const Vector &U,
const Vector &normal,
FaceElementTransformations &Tr,
Vector &FDotN) const
{
FDotN(0) = U(0) * U(0) * 0.5 * normal.Sum();
return std::fabs(U(0));
}
real_t BurgersFlux::ComputeAvgFlux(const Vector &U1,
const Vector &U2,
ElementTransformation &Tr,
DenseMatrix &FU) const
{
FU = (U1(0)*U1(0) + U1(0)*U2(0) + U2(0)*U2(0)) / 6.;
return std::max(std::fabs(U1(0)), std::fabs(U2(0)));
}
real_t BurgersFlux::ComputeAvgFluxDotN(const Vector &U1,
const Vector &U2,
const Vector &normal,
FaceElementTransformations &Tr,
Vector &FDotN) const
{
FDotN(0) = (U1(0)*U1(0) + U1(0)*U2(0) + U2(0)*U2(0)) / 6. * normal.Sum();
return std::max(std::fabs(U1(0)), std::fabs(U2(0)));
}
void BurgersFlux::ComputeFluxJacobian(const Vector &U,
ElementTransformation &Tr,
DenseTensor &J) const
{
J = 0.;
for (int d = 0; d < dim; d++)
{
J(0,0,d) = U(0);
}
}
void BurgersFlux::ComputeFluxJacobianDotN(const Vector &U,
const Vector &normal,
ElementTransformation &Tr,
DenseMatrix &JDotN) const
{
JDotN(0,0) = U(0) * normal.Sum();
}
real_t ShallowWaterFlux::ComputeFlux(const Vector &U,
ElementTransformation &Tr,
+570 -79
View File
@@ -19,17 +19,17 @@ namespace mfem
{
// This file contains general hyperbolic conservation element/face form
// integrators. HyperbolicFormIntegrator and RiemannSolver are defined.
// integrators. HyperbolicFormIntegrator and NumericalFlux are defined.
//
// HyperbolicFormIntegrator is a NonlinearFormIntegrator that implements
// element weak divergence and interface flux
//
// ∫_T F(u):∇v, -∫_e F̂(u)⋅[[v]]
// ∫_K F(u):∇v, -∫_f F̂(u)⋅n[v]
//
// Here, T is an element, e is an edge, and [[⋅]] is jump. This form integrator
// is coupled with RiemannSolver that implements the numerical flux F̂. For
// RiemannSolver, the Rusanov flux, also known as local Lax-Friedrichs flux, is
// provided.
// Here, K is an element, f is a face, n normal and [] is jump. This form
// integrator is coupled with NumericalFlux that implements the numerical flux
// F̂. For NumericalFlux, the Rusanov flux, also known as local Lax-Friedrichs
// flux, or component-wise upwinded flux are provided.
//
// To implement a specific hyperbolic conservation laws, users can create
// derived classes from FluxFunction with overloaded ComputeFlux. One can
@@ -61,58 +61,126 @@ public:
const int dim;
FluxFunction(const int num_equations, const int dim)
: num_equations(num_equations), dim(dim)
{
#ifndef MFEM_THREAD_SAFE
flux.SetSize(num_equations, dim);
#endif
}
: num_equations(num_equations), dim(dim) { }
virtual ~FluxFunction() {}
/**
* @brief Compute flux F(u, x) for given state u and physical point x
* @brief Compute flux F(u, x). Must be implemented in a derived class.
*
* @param[in] state value of state at the current integration point
* @param[in] Tr element information
* @param[out] flux F(u, x)
* @return real_t maximum characteristic speed
* Used in HyperbolicFormIntegrator::AssembleElementVector() for evaluation
* of (F(u), v) and in the default implementation of ComputeFluxDotN()
* for evaluation of F(u)n.
* @param[in] state state at the current integration point (num_equations)
* @param[in] Tr element transformation
* @param[out] flux flux from the given element at the current
* integration point (num_equations, dim)
* @return real_t maximum characteristic speed |dF(u,x)/du|
*
* @note One can put assertion in here to detect non-physical solution
*/
virtual real_t ComputeFlux(const Vector &state, ElementTransformation &Tr,
DenseMatrix &flux) const = 0;
/**
* @brief Compute normal flux. Optionally overloaded in the
* derived class to avoid creating full dense matrix for flux.
* @brief Compute normal flux F(u, x)n. Optionally overloaded in a derived
* class to avoid creating a full dense matrix for flux.
*
* @param[in] state state at the current integration point
* @param[in] normal normal vector, @see CalcOrtho
* @param[in] Tr face information
* Used in NumericalFlux for evaluation of the normal flux on a face.
* @param[in] state state at the current integration point (num_equations)
* @param[in] normal normal vector, see mfem::CalcOrtho() (dim)
* @param[in] Tr face transformation
* @param[out] fluxDotN normal flux from the given element at the current
* integration point
* @return real_t maximum (normal) characteristic velocity
* integration point (num_equations)
* @return real_t maximum (normal) characteristic speed |dF(u,x)/dun|
*/
virtual real_t ComputeFluxDotN(const Vector &state, const Vector &normal,
FaceElementTransformations &Tr,
Vector &fluxDotN) const;
/**
* @brief Compute flux Jacobian. Optionally overloaded in the derived class
* when Jacobian is necessary (e.g. Newton iteration, flux limiter)
* @brief Compute average flux over the given interval of states.
* Optionally overloaded in a derived class.
*
* @param state state at the current integration point
* @param Tr element information
* @param J flux Jacobian, J(i,j,d) = dF_{id} / u_j
* The average flux is defined as (u1,u2) = F(u) du / (u2 - u1) for
* u [u1,u2], where u1 is the first state (@a state1) and the u2 the
* second state (@a state2), while F(u) is the flux as defined in
* ComputeFlux().
*
* Used in the default implementation of ComputeAvgFluxDotN().
* @param[in] state1 state of the beginning of the interval (num_equations)
* @param[in] state2 state of the end of the interval (num_equations)
* @param[in] Tr element transformation
* @param[out] flux_ average flux from the given element at the current
* integration point (num_equations, dim)
* @return real_t maximum characteristic speed |dF(u,x)/du| over
* the interval [u1,u2]
*/
virtual real_t ComputeAvgFlux(const Vector &state1, const Vector &state2,
ElementTransformation &Tr,
DenseMatrix &flux_) const
{ MFEM_ABORT("Not Implemented."); }
/**
* @brief Compute average normal flux over the given interval of states.
* Optionally overloaded in a derived class.
*
* The average normal flux is defined as (u1,u2)n = F(u)n du / (u2 - u1)
* for u [u1,u2], where u1 is the first state (@a state1) and the u2 the
* second state (@a state2), while n is the normal and F(u) is the flux as
* defined in ComputeFlux().
*
* Used in NumericalFlux::Average() and NumericalFlux::AverageGrad() for
* evaluation of the average normal flux on a face.
* @param[in] state1 state of the beginning of the interval (num_equations)
* @param[in] state2 state of the end of the interval (num_equations)
* @param[in] normal normal vector, see mfem::CalcOrtho() (dim)
* @param[in] Tr face transformation
* @param[out] fluxDotN average normal flux from the given element at the
* current integration point (num_equations)
* @return real_t maximum (normal) characteristic speed |dF(u,x)/dun|
* over the interval [u1,u2]
*/
virtual real_t ComputeAvgFluxDotN(const Vector &state1, const Vector &state2,
const Vector &normal,
FaceElementTransformations &Tr,
Vector &fluxDotN) const;
/**
* @brief Compute flux Jacobian J(u, x). Optionally overloaded in a derived
* class when Jacobian is necessary (e.g. Newton iteration, flux limiter)
*
* Used in HyperbolicFormIntegrator::AssembleElementGrad() for evaluation of
* Jacobian of the flux in an element and in the default implementation of
* ComputeFluxJacobianDotN().
* @param[in] state state at the current integration point (num_equations)
* @param[in] Tr element transformation
* @param[out] J_ flux Jacobian, $ J(i,j,d) = dF_{id} / du_j $
*/
virtual void ComputeFluxJacobian(const Vector &state,
ElementTransformation &Tr,
DenseTensor &J) const
{
MFEM_ABORT("Not Implemented.");
}
DenseTensor &J_) const
{ MFEM_ABORT("Not Implemented."); }
/**
* @brief Compute normal flux Jacobian J(u, x)n. Optionally overloaded in
* a derived class to avoid creating a full dense tensor for Jacobian.
*
* Used in NumericalFlux for evaluation of Jacobian of the normal flux on
* a face.
* @param[in] state state at the current integration point (num_equations)
* @param[in] normal normal vector, see mfem::CalcOrtho() (dim)
* @param[in] Tr element transformation
* @param[out] JDotN normal flux Jacobian, $ JDotN(i,j) = d(F_{id} n_d) / du_j $
*/
virtual void ComputeFluxJacobianDotN(const Vector &state,
const Vector &normal,
ElementTransformation &Tr,
DenseMatrix &JDotN) const;
private:
#ifndef MFEM_THREAD_SAFE
mutable DenseMatrix flux;
mutable DenseTensor J;
#endif
};
@@ -122,29 +190,99 @@ private:
* conservation laws on a face with states, fluxes and characteristic speed
*
*/
class RiemannSolver
class NumericalFlux
{
public:
RiemannSolver(const FluxFunction &fluxFunction)
/**
* @brief Constructor for a flux function
* @param fluxFunction flux function F(u,x)
*/
NumericalFlux(const FluxFunction &fluxFunction)
: fluxFunction(fluxFunction) { }
/**
* @brief Evaluates numerical flux for given states and fluxes. Must be
* overloaded in a derived class
* @brief Evaluates normal numerical flux for the given states and normal.
* Must be implemented in a derived class.
*
* Used in HyperbolicFormIntegrator::AssembleFaceVector() for evaluation of
* <(u,u,x) n, [v]> term at the face.
* @param[in] state1 state value at a point from the first element
* (num_equations)
* @param[in] state2 state value at a point from the second element
* (num_equations)
* @param[in] nor scaled normal vector, see mfem::CalcOrtho() (dim)
* @param[in] Tr face information
* @param[in] Tr face transformation
* @param[out] flux numerical flux (num_equations)
* @return real_t maximum characteristic speed |dF(u,x)/dun|
*/
virtual real_t Eval(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const = 0;
virtual ~RiemannSolver() = default;
/**
* @brief Evaluates Jacobian of the normal numerical flux for the given
* states and normal. Optionally overloaded in a derived class.
*
* Used in HyperbolicFormIntegrator::AssembleFaceGrad() for Jacobian
* of the term <(u,u,x) n, [v]> at the face.
* @param[in] side indicates gradient w.r.t. the first (side = 1)
* or second (side = 2) state
* @param[in] state1 state value of the beginning of the interval
* (num_equations)
* @param[in] state2 state value of the end of the interval
* (num_equations)
* @param[in] nor scaled normal vector, see mfem::CalcOrtho() (dim)
* @param[in] Tr face transformation
* @param[out] grad Jacobian of normal numerical flux (num_equations, dim)
*/
virtual void Grad(int side, const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const
{ MFEM_ABORT("Not implemented."); }
/**
* @brief Evaluates average normal numerical flux over the interval between
* the given end states in the second argument and for the given normal.
* Optionally overloaded in a derived class.
*
* Presently, not used. Reserved for future use.
* @param[in] state1 state value of the beginning of the interval
* (num_equations)
* @param[in] state2 state value of the end of the interval
* (num_equations)
* @param[in] nor scaled normal vector, see mfem::CalcOrtho() (dim)
* @param[in] Tr face transformation
* @param[out] flux numerical flux (num_equations)
* @return real_t maximum characteristic speed |dF(u,x)/dun|
*/
virtual real_t Average(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const
{ MFEM_ABORT("Not implemented."); }
/**
* @brief Evaluates Jacobian of the average normal numerical flux over the
* interval between the given end states in the second argument and for the
* given normal. Optionally overloaded in a derived class.
*
* Presently, not used. Reserved for future use.
* @param[in] side indicates gradient w.r.t. the first (side = 1)
* or second (side = 2) state
* @param[in] state1 state value of the beginning of the interval
* (num_equations)
* @param[in] state2 state value of the end of the interval
* (num_equations)
* @param[in] nor scaled normal vector, see mfem::CalcOrtho() (dim)
* @param[in] Tr face transformation
* @param[out] grad Jacobian of the average normal numerical flux
* (num_equations, dim)
*/
virtual void AverageGrad(int side, const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const
{ MFEM_ABORT("Not implemented."); }
virtual ~NumericalFlux() = default;
/// @brief Get flux function F
/// @return constant reference to the flux function.
@@ -154,31 +292,41 @@ protected:
const FluxFunction &fluxFunction;
};
/// @deprecated Use NumericalFlux instead.
MFEM_DEPRECATED typedef NumericalFlux RiemannSolver;
/**
* @brief Abstract hyperbolic form integrator, (F(u, x), v) and ((u±, x, n))
* @brief Abstract hyperbolic form integrator, assembling (F(u, x), v) and
* <(u,u,x) n, [v]> terms for scalar finite elements.
*
* This form integrator is coupled with a NumericalFlux that implements the
* numerical flux at the faces. The flux F is obtained from the FluxFunction
* assigned to the aforementioned NumericalFlux.
*/
class HyperbolicFormIntegrator : public NonlinearFormIntegrator
{
private:
// The maximum characteristic speed, updated during element/face vector assembly
real_t max_char_speed;
const RiemannSolver &rsolver; // Numerical flux that maps F(u±,x) to hat(F)
const NumericalFlux &numFlux; // Numerical flux that maps F(u±,x) to
const FluxFunction &fluxFunction;
const int IntOrderOffset; // integration order offset, 2*p + IntOrderOffset.
const real_t sign;
#ifndef MFEM_THREAD_SAFE
// Local storage for element integration
Vector shape; // shape function value at an integration point
Vector state; // state value at an integration point
DenseMatrix flux; // flux value at an integration point
DenseTensor J; // Jacobian matrix at an integration point
DenseMatrix dshape; // derivative of shape function at an integration point
Vector shape1; // shape function value at an integration point - first elem
Vector shape2; // shape function value at an integration point - second elem
Vector state1; // state value at an integration point - first elem
Vector state2; // state value at an integration point - second elem
Vector nor; // normal vector, @see CalcOrtho
Vector fluxN; // hat(F)(u,x)
Vector nor; // normal vector, see mfem::CalcOrtho()
Vector fluxN; // (u±,x) n
DenseMatrix JDotN; // Ĵ(u±,x) n
#endif
public:
@@ -186,12 +334,14 @@ public:
/**
* @brief Construct a new Hyperbolic Form Integrator object
*
* @param[in] rsolver numerical flux
* @param[in] numFlux numerical flux
* @param[in] IntOrderOffset integration order offset
* @param[in] sign sign of the convection term
*/
HyperbolicFormIntegrator(
const RiemannSolver &rsolver,
const int IntOrderOffset=0);
const NumericalFlux &numFlux,
const int IntOrderOffset = 0,
const real_t sign = 1.);
/**
* @brief Reset the Max Char Speed 0
@@ -210,7 +360,8 @@ public:
const FluxFunction &GetFluxFunction() { return fluxFunction; }
/**
* @brief implement (F(u), grad v) with abstract F computed by ComputeFlux
* @brief Implements (F(u), v) with abstract F computed by
* FluxFunction::ComputeFlux()
*
* @param[in] el local finite element
* @param[in] Tr element transformation
@@ -222,62 +373,270 @@ public:
const Vector &elfun, Vector &elvect) override;
/**
* @brief implement <-hat(F)(u,x) n, [[v]]> with abstract hat(F) computed by
* ComputeFluxDotN and numerical flux object
* @brief Implements (J(u), v) with abstract J computed by
* FluxFunction::ComputeFluxJacobian()
*
* @param[in] el local finite element
* @param[in] Tr element transformation
* @param[in] elfun local coefficient of basis
* @param[out] grad evaluated Jacobian
*/
void AssembleElementGrad(const FiniteElement &el,
ElementTransformation &Tr,
const Vector &elfun, DenseMatrix &grad) override;
/**
* @brief Implements <-(u,u,x) n, [v]> with abstract computed by
* NumericalFlux::Eval() of the numerical flux object
*
* @param[in] el1 finite element of the first element
* @param[in] el2 finite element of the second element
* @param[in] Tr face element transformations
* @param[in] elfun local coefficient of basis from both elements
* @param[out] elvect evaluated dual vector <-hat(F)(u,x) n, [[v]]>
* @param[out] elvect evaluated dual vector <-(u,u,x) n, [v]>
*/
void AssembleFaceVector(const FiniteElement &el1,
const FiniteElement &el2,
FaceElementTransformations &Tr,
const Vector &elfun, Vector &elvect) override;
/**
* @brief Implements <-(u,u,x) n, [v]> with abstract computed by
* NumericalFlux::Grad() of the numerical flux object
*
* @param[in] el1 finite element of the first element
* @param[in] el2 finite element of the second element
* @param[in] Tr face element transformations
* @param[in] elfun local coefficient of basis from both elements
* @param[out] elmat evaluated Jacobian matrix <-(u,u,x) n, [v]>
*/
void AssembleFaceGrad(const FiniteElement &el1,
const FiniteElement &el2,
FaceElementTransformations &Tr,
const Vector &elfun, DenseMatrix &elmat) override;
};
/**
* @brief Rusanov flux, also known as local Lax-Friedrichs,
* n = ½(F(u,x)n + F(u,x)n) - ½λ(u - u)
* where λ is the maximum characteristic velocity
*
* where λ is the maximum characteristic speed.
* @note The implementation assumes monotonous |dF(u,x)/dun| in u, so the
* maximum characteristic speed λ for any interval [u, u] is given by
* max(|dF(u,x)/dun|, |dF(u,x)/dun|).
*/
class RusanovFlux : public RiemannSolver
class RusanovFlux : public NumericalFlux
{
public:
RusanovFlux(const FluxFunction &fluxFunction)
: RiemannSolver(fluxFunction)
{
#ifndef MFEM_THREAD_SAFE
fluxN1.SetSize(fluxFunction.num_equations);
fluxN2.SetSize(fluxFunction.num_equations);
#endif
}
/**
* @brief Constructor for a flux function
* @param fluxFunction flux function F(u,x)
*/
RusanovFlux(const FluxFunction &fluxFunction);
/**
* @brief hat(F)n = ½(F(u,x)n + F(u,x)n) - ½λ(u - u)
* @brief Normal numerical flux (u,u,x) n
* @note Systems of equations are treated component-wise
*
* @param[in] state1 state value at a point from the first element
* @param[in] state1 state value (u) at a point from the first element
* (num_equations)
* @param[in] state2 state value at a point from the second element
* @param[in] state2 state value (u) at a point from the second element
* (num_equations)
* @param[in] nor normal vector (not a unit vector) (dim)
* @param[in] Tr face element transformation
* @param[out] flux ½(F(u,x)n + F(u,x)n) - ½λ(u - u)
* @param[out] flux n = ½(F(u,x)n + F(u,x)n) - ½λ(u - u)
* @return max(|dF(u,x)/dun|, |dF(u,x)/dun|)
*/
real_t Eval(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const override;
/**
* @brief Jacobian of normal numerical flux (u,u,x) n
* @note The Jacobian of flux J n is required to be implemented in
* FluxFunction::ComputeFluxJacobianDotN()
*
* @param[in] side gradient w.r.t the first (u) or second argument (u)
* @param[in] state1 state value (u) of the beginning of the interval
* (num_equations)
* @param[in] state2 state value (u) of the end of the interval
* (num_equations)
* @param[in] nor normal vector (not a unit vector) (dim)
* @param[in] Tr face element transformation
* @param[out] grad Jacobian of F(u,u,x) n
* side = 1:
* ½J(u,x)n + ½λ
* side = 2:
* ½J(u,x)n - ½λ
*/
void Grad(int side, const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const override;
/**
* @brief Average normal numerical flux over the interval [u, u] in the
* second argument of the flux (u,u,x) n
* @note The average normal flux n is required to be implemented in
* FluxFunction::ComputeAvgFluxDotN()
* @note Systems of equations are treated component-wise
*
* @param[in] state1 state value (u) of the beginning of the interval
* (num_equations)
* @param[in] state2 state value (u) of the end of the interval
* (num_equations)
* @param[in] nor normal vector (not a unit vector) (dim)
* @param[in] Tr face element transformation
* @param[out] flux ½((u,u,x)n + F(u,x)n) - ¼λ(u - u)
* @return max(|dF(u,x)/dun|, |dF(u,x)/dun|)
*/
real_t Average(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const override;
/**
* @brief Jacobian of average normal numerical flux over the interval
* [u, u] in the second argument of the flux (u,u,x) n
* @note The average normal flux n is required to be implemented in
* FluxFunction::ComputeAvgFluxDotN() and the Jacobian of flux J n in
* FluxFunction::ComputeFluxJacobianDotN()
* @note Only the diagonal terms of the J n are considered, i.e., systems
* are treated as a set of independent equations
*
* @param[in] side gradient w.r.t the first (u) or second argument (u)
* @param[in] state1 state value (u) of the beginning of the interval
* (num_equations)
* @param[in] state2 state value (u) of the end of the interval
* (num_equations)
* @param[in] nor normal vector (not a unit vector) (dim)
* @param[in] Tr face element transformation
* @param[out] grad Jacobian of (u,u,x) n
* side = 1:
* ½((u,u,x)n - F(u,x)n) / (u - u) - ½J(u,x)n + ¼λ
* side = 2:
* ½(F(u,x)n - (u,u,x)n) / (u - u) - ¼λ
*/
void AverageGrad(int side, const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const override;
protected:
#ifndef MFEM_THREAD_SAFE
mutable Vector fluxN1, fluxN2;
mutable DenseMatrix JDotN;
#endif
};
/**
* @brief Component-wise upwinded flux
*
* Upwinded flux for scalar equations, a special case of Godunov or
* Engquist-Osher flux, is defined as follows:
* n = F(u)n for dF(u)/du < 0 on [u,u]
* n = F(u)n for dF(u)/du > 0 on [u,u]
* @note This construction assumes monotonous F(u,x) in u
* @note Systems of equations are treated component-wise
*/
class ComponentwiseUpwindFlux : public NumericalFlux
{
public:
/**
* @brief Constructor for a flux function
* @param fluxFunction flux function F(u,x)
*/
ComponentwiseUpwindFlux(const FluxFunction &fluxFunction);
/**
* @brief Normal numerical flux (u,u,x) n
*
* @param[in] state1 state value (u) at a point from the first element
* (num_equations)
* @param[in] state2 state value (u) at a point from the second element
* (num_equations)
* @param[in] nor normal vector (not a unit vector) (dim)
* @param[in] Tr face element transformation
* @param[out] flux n = min(F(u,x)n, F(u,x)n) for u u
* or n = max(F(u,x)n, F(u,x)n) for u > u
* @return max(|dF(u,x)/dun|, |dF(u,x)/dun|)
*/
real_t Eval(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const override;
/**
* @brief Jacobian of normal numerical flux (u,u,x) n
* @note The Jacobian of flux J n is required to be implemented in
* FluxFunction::ComputeFluxJacobianDotN()
*
* @param[in] side gradient w.r.t the first (u) or second argument (u)
* @param[in] state1 state value (u) of the beginning of the interval
* (num_equations)
* @param[in] state2 state value (u) of the end of the interval
* (num_equations)
* @param[in] nor normal vector (not a unit vector) (dim)
* @param[in] Tr face element transformation
* @param[out] grad Jacobian of F(u,u,x) n
* side = 1:
* max(J(u,x)n, 0)
* side = 2:
* min(J(u,x)n, 0)
*/
void Grad(int side, const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const override;
/**
* @brief Average normal numerical flux over the interval [u, u] in the
* second argument of the flux (u,u,x) n
* @note The average normal flux n is required to be implemented in
* FluxFunction::ComputeAvgFluxDotN()
*
* @param[in] state1 state value (u) of the beginning of the interval
* (num_equations)
* @param[in] state2 state value (u) of the end of the interval
* (num_equations)
* @param[in] nor normal vector (not a unit vector) (dim)
* @param[in] Tr face element transformation
* @param[out] flux n = min(F(u)n, (u,x)n) for u u
* or n = max(F(u)n, (u,x)n) for u > u
* @return max(|dF(u,x)/dun|, |dF(u,x)/dun|)
*/
real_t Average(const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
Vector &flux) const override;
/**
* @brief Jacobian of average normal numerical flux over the interval
* [u, u] in the second argument of the flux (u,u,x) n
* @note The average normal flux n is required to be implemented in
* FluxFunction::ComputeAvgFluxDotN() and the Jacobian of flux J n in
* FluxFunction::ComputeFluxJacobianDotN()
*
* @param[in] side gradient w.r.t the first (u) or second argument (u)
* @param[in] state1 state value (u) of the beginning of the interval
* (num_equations)
* @param[in] state2 state value (u) of the end of the interval
* (num_equations)
* @param[in] nor normal vector (not a unit vector) (dim)
* @param[in] Tr face element transformation
* @param[out] grad Jacobian of (u,u,x) n
* side = 1:
* (F(u) - (u,u))n / (u - u) when negative
* J(u,x) n otherwise
* side = 2:
* min((F(u) - (u,u))n / (u - u), 0)
*/
void AverageGrad(int side, const Vector &state1, const Vector &state2,
const Vector &nor, FaceElementTransformations &Tr,
DenseMatrix &grad) const override;
protected:
#ifndef MFEM_THREAD_SAFE
mutable Vector fluxN1, fluxN2;
mutable DenseMatrix JDotN;
#endif
};
/// Advection flux
class AdvectionFlux : public FluxFunction
{
private:
@@ -289,8 +648,7 @@ private:
public:
/**
* @brief Construct a new Advection Flux Function with given
* spatial dimension
* @brief Construct AdvectionFlux FluxFunction with given velocity
*
* @param b velocity coefficient, possibly depends on space
*/
@@ -306,20 +664,83 @@ public:
* @brief Compute F(u)
*
* @param state state (u) at current integration point
* @param Tr current element transformation with integration point
* @param Tr current element transformation with the integration point
* @param flux F(u) = ubᵀ
* @return real_t maximum characteristic speed, |b|
*/
real_t ComputeFlux(const Vector &state, ElementTransformation &Tr,
DenseMatrix &flux) const override;
/**
* @brief Compute F(u) n
*
* @param state state (u) at current integration point
* @param normal normal vector, usually not a unit vector
* @param Tr current element transformation with the integration point
* @param fluxDotN F(u) n = u (bᵀn)
* @return real_t maximum characteristic speed, |b|
*/
real_t ComputeFluxDotN(const Vector &state,
const Vector &normal, FaceElementTransformations &Tr,
Vector &fluxDotN) const override;
/**
* @brief Compute average flux (u)
*
* @param state1 state value (u) of the beginning of the interval
* @param state2 state value (u) of the end of the interval
* @param Tr current element transformation with the integration point
* @param flux (u) = (u+u)/2*bᵀ
* @return real_t maximum characteristic speed, |b|
*/
real_t ComputeAvgFlux(const Vector &state1, const Vector &state2,
ElementTransformation &Tr, DenseMatrix &flux) const override;
/**
* @brief Compute average flux (u) n
*
* @param state1 state value (u) of the beginning of the interval
* @param state2 state value (u) of the end of the interval
* @param normal normal vector, usually not a unit vector
* @param Tr current element transformation with the integration point
* @param fluxDotN (u) n = (u+u)/2*(bᵀn)
* @return real_t maximum characteristic speed, |b|
*/
real_t ComputeAvgFluxDotN(const Vector &state1, const Vector &state2,
const Vector &normal, FaceElementTransformations &Tr,
Vector &fluxDotN) const override;
/**
* @brief Compute J(u)
*
* @param state state (u) at current integration point
* @param Tr current element transformation with the integration point
* @param J J(u) = diag(b)
*/
void ComputeFluxJacobian(const Vector &state,
ElementTransformation &Tr,
DenseTensor &J) const override;
/**
* @brief Compute J(u) n
*
* @param state state (u) at current integration point
* @param normal normal vector, usually not a unit vector
* @param Tr current element transformation with the integration point
* @param JDotN J(u) n = bᵀn
*/
void ComputeFluxJacobianDotN(const Vector &state,
const Vector &normal,
ElementTransformation &Tr,
DenseMatrix &JDotN) const override;
};
/// Burgers flux
class BurgersFlux : public FluxFunction
{
public:
/**
* @brief Construct a new Burgers Flux Function with given
* spatial dimension
* @brief Construct BurgersFlux FluxFunction with given spatial dimension
*
* @param dim spatial dimension
*/
@@ -330,14 +751,83 @@ public:
* @brief Compute F(u)
*
* @param state state (u) at current integration point
* @param Tr current element transformation with integration point
* @param Tr current element transformation with the integration point
* @param flux F(u) = ½u²*1 where 1 is (dim) vector
* @return real_t maximum characteristic speed, |u|
*/
real_t ComputeFlux(const Vector &state, ElementTransformation &Tr,
DenseMatrix &flux) const override;
/**
* @brief Compute F(u) n
*
* @param state state (u) at current integration point
* @param normal normal vector, usually not a unit vector
* @param Tr current element transformation with the integration point
* @param fluxDotN F(u) n = ½u²*(1n) where 1 is (dim) vector
* @return real_t maximum characteristic speed, |u|
*/
real_t ComputeFluxDotN(const Vector &state,
const Vector &normal,
FaceElementTransformations &Tr,
Vector &fluxDotN) const override;
/**
* @brief Compute average flux (u)
*
* @param state1 state value (u) of the beginning of the interval
* @param state2 state value (u) of the end of the interval
* @param Tr current element transformation with the integration point
* @param flux (u) = (u²+u*u+u²)/6*1 where 1 is (dim) vector
* @return real_t maximum characteristic speed, |u|
*/
real_t ComputeAvgFlux(const Vector &state1,
const Vector &state2,
ElementTransformation &Tr,
DenseMatrix &flux) const override;
/**
* @brief Compute average flux (u) n
*
* @param state1 state value (u) of the beginning of the interval
* @param state2 state value (u) of the end of the interval
* @param normal normal vector, usually not a unit vector
* @param Tr current element transformation with the integration point
* @param fluxDotN (u) n = (u²+u*u+u²)/6*(1n) where 1 is (dim) vector
* @return real_t maximum characteristic speed, |u|
*/
real_t ComputeAvgFluxDotN(const Vector &state1,
const Vector &state2,
const Vector &normal,
FaceElementTransformations &Tr,
Vector &fluxDotN) const override;
/**
* @brief Compute J(u)
*
* @param state state (u) at current integration point
* @param Tr current element transformation with the integration point
* @param J J(u) = diag(u*1) where 1 is (dim) vector
*/
void ComputeFluxJacobian(const Vector &state,
ElementTransformation &Tr,
DenseTensor &J) const override;
/**
* @brief Compute J(u) n
*
* @param state state (u) at current integration point
* @param normal normal vector, usually not a unit vector
* @param Tr current element transformation with the integration point
* @param JDotN J(u) n = u*(1n) where 1 is (dim) vector
*/
void ComputeFluxJacobianDotN(const Vector &state,
const Vector &normal,
ElementTransformation &Tr,
DenseMatrix &JDotN) const override;
};
/// Shallow water flux
class ShallowWaterFlux : public FluxFunction
{
private:
@@ -345,8 +835,8 @@ private:
public:
/**
* @brief Construct a new Shallow Water Flux Function with
* given spatial dimension
* @brief Construct a new ShallowWaterFlux FluxFunction with given spatial
* dimension and gravity constant
*
* @param dim spatial dimension
* @param g gravity constant
@@ -358,7 +848,7 @@ public:
* @brief Compute F(h, hu)
*
* @param state state (h, hu) at current integration point
* @param Tr current element transformation with integration point
* @param Tr current element transformation with the integration point
* @param flux F(h, hu) = [huᵀ; huuᵀ + ½gh²I]
* @return real_t maximum characteristic speed, |u| + (gh)
*/
@@ -370,7 +860,7 @@ public:
*
* @param state state (h, hu) at current integration point
* @param normal normal vector, usually not a unit vector
* @param Tr current element transformation with integration point
* @param Tr current element transformation with the integration point
* @param fluxN F(ρ, ρu, E)n = [ρun; ρu(un) + pn; (un)(E + p)]
* @return real_t maximum characteristic speed, |u| + (γp/ρ)
*/
@@ -379,6 +869,7 @@ public:
Vector &fluxN) const override;
};
/// Euler flux
class EulerFlux : public FluxFunction
{
private:
@@ -387,8 +878,8 @@ private:
public:
/**
* @brief Construct a new Euler Flux Function with given
* spatial dimension
* @brief Construct a new EulerFlux FluxFunction with given spatial
* dimension and specific heat ratio
*
* @param dim spatial dimension
* @param specific_heat_ratio specific heat ratio, γ
@@ -401,7 +892,7 @@ public:
* @brief Compute F(ρ, ρu, E)
*
* @param state state (ρ, ρu, E) at current integration point
* @param Tr current element transformation with integration point
* @param Tr current element transformation with the integration point
* @param flux F(ρ, ρu, E) = [ρuᵀ; ρuuᵀ + pI; uᵀ(E + p)]
* @return real_t maximum characteristic speed, |u| + (γp/ρ)
*/
@@ -413,7 +904,7 @@ public:
*
* @param x x (ρ, ρu, E) at current integration point
* @param normal normal vector, usually not a unit vector
* @param Tr current element transformation with integration point
* @param Tr current element transformation with the integration point
* @param fluxN F(ρ, ρu, E)n = [ρun; ρu(un) + pn; (un)(E + p)]
* @return real_t maximum characteristic speed, |u| + (γp/ρ)
*/
+2 -2
View File
@@ -21,8 +21,8 @@ void ConvectionIntegrator::AssembleMF(const FiniteElementSpace &fes)
// Assuming the same element type
Mesh *mesh = fes.GetMesh();
if (mesh->GetNE() == 0) { return; }
const FiniteElement &el = *fes.GetFE(0);
ElementTransformation &Trans = *fes.GetElementTransformation(0);
const FiniteElement &el = *fes.GetTypicalFE();
ElementTransformation &Trans = *mesh->GetTypicalElementTransformation();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, Trans);
if (DeviceCanUseCeed())
{
+2 -2
View File
@@ -138,8 +138,8 @@ void ConvectionIntegrator::AssemblePA(const FiniteElementSpace &fes)
Device::GetDeviceMemoryType() : pa_mt;
// Assumes tensor-product elements
Mesh *mesh = fes.GetMesh();
const FiniteElement &el = *fes.GetFE(0);
ElementTransformation &Trans = *fes.GetElementTransformation(0);
const FiniteElement &el = *fes.GetTypicalFE();
ElementTransformation &Trans = *mesh->GetTypicalElementTransformation();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, Trans);
if (DeviceCanUseCeed())
{
+2 -2
View File
@@ -19,7 +19,7 @@ void CurlCurlIntegrator::AssemblePA(const FiniteElementSpace &fes)
{
// Assumes tensor-product elements
Mesh *mesh = fes.GetMesh();
const FiniteElement *fel = fes.GetFE(0);
const FiniteElement *fel = fes.GetTypicalFE();
const VectorTensorFiniteElement *el =
dynamic_cast<const VectorTensorFiniteElement*>(fel);
@@ -27,7 +27,7 @@ void CurlCurlIntegrator::AssemblePA(const FiniteElementSpace &fes)
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(*el, *el,
*mesh->GetElementTransformation(0));
*mesh->GetTypicalElementTransformation());
const int dims = el->GetDim();
MFEM_VERIFY(dims == 2 || dims == 3, "");
+5 -7
View File
@@ -456,18 +456,16 @@ void DGDiffusionIntegrator::SetupPA(const FiniteElementSpace &fes,
// Assumes tensor-product elements
Mesh &mesh = *fes.GetMesh();
const FiniteElement &el =
*fes.GetTraceElement(0, mesh.GetFaceGeometry(0));
FaceElementTransformations &T0 =
*fes.GetMesh()->GetFaceElementTransformations(0);
const Geometry::Type face_geom_type = mesh.GetTypicalFaceGeometry();
const FiniteElement &el = *fes.GetTypicalTraceElement();
const int ir_order = IntRule ? IntRule->GetOrder()
: GetRule(el.GetOrder(), T0).GetOrder();
const IntegrationRule &ir = irs.Get(T0.GetGeometryType(), ir_order);
: GetRule(el.GetOrder(), face_geom_type).GetOrder();
const IntegrationRule &ir = irs.Get(face_geom_type, ir_order);
dim = mesh.Dimension();
const int q1d = (ir.GetOrder() + 3)/2;
MFEM_ASSERT(q1d == pow(real_t(ir.Size()), 1.0/(dim - 1)), "");
const auto vol_ir = irs.Get(mesh.GetElementGeometry(0), ir_order);
const auto vol_ir = irs.Get(mesh.GetTypicalElementGeometry(), ir_order);
const auto geom_flags = GeometricFactors::JACOBIANS |
GeometricFactors::DETERMINANTS;
const auto el_geom = mesh.GetGeometricFactors(vol_ir, geom_flags, mt);
+3 -5
View File
@@ -143,13 +143,11 @@ void DGTraceIntegrator::SetupPA(const FiniteElementSpace &fes, FaceType type)
if (nf==0) { return; }
// Assumes tensor-product elements
Mesh *mesh = fes.GetMesh();
const FiniteElement &el =
*fes.GetTraceElement(0, fes.GetMesh()->GetFaceGeometry(0));
FaceElementTransformations &T0 =
*fes.GetMesh()->GetFaceElementTransformations(0);
const FiniteElement &el = *fes.GetTypicalTraceElement();
const IntegrationRule *ir = IntRule?
IntRule:
&GetRule(el.GetGeomType(), el.GetOrder(), T0);
&GetRule(el.GetGeomType(), el.GetOrder(),
*mesh->GetTypicalElementTransformation());
const int symmDims = 4;
nq = ir->GetNPoints();
dim = mesh->Dimension();
@@ -16,7 +16,6 @@ namespace mfem
// PA Diffusion Integrator
DiffusionIntegrator::Kernels DiffusionIntegrator::kernels;
DiffusionIntegrator::Kernels::Kernels()
{
// 2D
+1 -2
View File
@@ -21,8 +21,7 @@ void DiffusionIntegrator::AssembleMF(const FiniteElementSpace &fes)
// Assuming the same element type
fespace = &fes;
Mesh *mesh = fes.GetMesh();
if (mesh->GetNE() == 0) { return; }
const FiniteElement &el = *fes.GetFE(0);
const FiniteElement &el = *fes.GetTypicalFE();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el);
if (DeviceCanUseCeed())
{
+1 -2
View File
@@ -93,8 +93,7 @@ void DiffusionIntegrator::AssemblePA(const FiniteElementSpace &fes)
// Assuming the same element type
fespace = &fes;
Mesh *mesh = fes.GetMesh();
if (mesh->GetNE() == 0) { return; }
const FiniteElement &el = *fes.GetFE(0);
const FiniteElement &el = *fes.GetTypicalFE();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el);
if (DeviceCanUseCeed())
{
+5 -5
View File
@@ -1039,7 +1039,7 @@ void DiffusionIntegrator::AssemblePatchMatrix_reducedQuadrature(
for (int zquad = 0; zquad<2; ++zquad)
{
// Reduced quadrature in z
const int nwz = rid(zquad,2,patch)[jdz].size();
const int nwz = static_cast<int>(rid(zquad,2,patch)[jdz].size());
for (int irz=0; irz < nwz; ++irz)
{
const int qz = rid(zquad,2,patch)[jdz][irz] + minD[2][jdz];
@@ -1062,7 +1062,7 @@ void DiffusionIntegrator::AssemblePatchMatrix_reducedQuadrature(
for (int yquad = 0; yquad<2; ++yquad)
{
// Reduced quadrature in y
const int nwy = rid(yquad,1,patch)[jdy].size();
const int nwy = static_cast<int>(rid(yquad,1,patch)[jdy].size());
for (int iry=0; iry < nwy; ++iry)
{
const int qy = rid(yquad,1,patch)[jdy][iry] + minD[1][jdy];
@@ -1082,7 +1082,7 @@ void DiffusionIntegrator::AssemblePatchMatrix_reducedQuadrature(
// Reduced quadrature in x
for (int xquad=0; xquad<2; ++xquad)
{
const int nwx = rid(xquad,0,patch)[jdx].size();
const int nwx = static_cast<int>(rid(xquad,0,patch)[jdx].size());
for (int irx=0; irx < nwx; ++irx)
{
const int qx = rid(xquad,0,patch)[jdx][irx] + minD[0][jdx];
@@ -1117,7 +1117,7 @@ void DiffusionIntegrator::AssemblePatchMatrix_reducedQuadrature(
}
// 00 terms
const int nw = rid(0,0,patch)[jdx].size();
const int nw = static_cast<int>(rid(0,0,patch)[jdx].size());
for (int irx=0; irx < nw; ++irx)
{
const int qx = rid(0,0,patch)[jdx][irx] + minD[0][jdx];
@@ -1140,7 +1140,7 @@ void DiffusionIntegrator::AssemblePatchMatrix_reducedQuadrature(
}
// 11 terms
const int nw11 = rid(1,0,patch)[jdx].size();
const int nw11 = static_cast<int>(rid(1,0,patch)[jdx].size());
for (int irx=0; irx < nw11; ++irx)
{
+2 -2
View File
@@ -21,14 +21,14 @@ void DivDivIntegrator::AssemblePA(const FiniteElementSpace &fes)
{
// Assumes tensor-product elements
Mesh *mesh = fes.GetMesh();
const FiniteElement *fel = fes.GetFE(0);
const FiniteElement *fel = fes.GetTypicalFE();
const VectorTensorFiniteElement *el =
dynamic_cast<const VectorTensorFiniteElement*>(fel);
MFEM_VERIFY(el != NULL, "Only VectorTensorFiniteElement is supported!");
const IntegrationRule *ir = IntRule ? IntRule : &MassIntegrator::GetRule
(*el, *el, *mesh->GetElementTransformation(0));
(*el, *el, *mesh->GetTypicalElementTransformation());
const int dims = el->GetDim();
MFEM_VERIFY(dims == 2 || dims == 3, "");
+5 -5
View File
@@ -23,8 +23,8 @@ void ElasticityIntegrator::SetUpQuadratureSpaceAndCoefficients(
if (IntRule == nullptr)
{
// This is where it's assumed that all elements are the same.
const auto &T = *fes.GetElementTransformation(0);
int quad_order = 2 * T.OrderGrad(fes.GetFE(0));
const auto &T = *fes.GetMesh()->GetTypicalElementTransformation();
int quad_order = 2 * T.OrderGrad(fes.GetTypicalFE());
IntRule = &IntRules.Get(T.GetGeometryType(), quad_order);
}
@@ -46,14 +46,14 @@ void ElasticityIntegrator::AssemblePA(const FiniteElementSpace &fes)
Mesh &mesh = *fespace->GetMesh();
MFEM_VERIFY(fespace->GetVDim() == mesh.Dimension(), "");
vdim = fespace->GetVDim();
ndofs = fespace->GetFE(0)->GetDof();
ndofs = fespace->GetTypicalFE()->GetDof();
SetUpQuadratureSpaceAndCoefficients(fes);
auto ordering = GetEVectorOrdering(*fespace);
auto mode = ordering == ElementDofOrdering::NATIVE ? DofToQuad::FULL :
DofToQuad::LEXICOGRAPHIC_FULL;
maps = &fespace->GetFE(0)->GetDofToQuad(*IntRule, mode);
maps = &fespace->GetTypicalFE()->GetDofToQuad(*IntRule, mode);
geom = mesh.GetGeometricFactors(*IntRule, GeometricFactors::JACOBIANS);
}
@@ -95,7 +95,7 @@ void ElasticityComponentIntegrator::AssemblePA(const FiniteElementSpace &fes)
DofToQuad::LEXICOGRAPHIC_FULL;
geom = fes.GetMesh()->GetGeometricFactors(*IntRule,
GeometricFactors::JACOBIANS);
maps = &fespace->GetFE(0)->GetDofToQuad(*IntRule, mode);
maps = &fespace->GetTypicalFE()->GetDofToQuad(*IntRule, mode);
}
void ElasticityComponentIntegrator::AddMultPA(const Vector &x, Vector &y) const
+3 -3
View File
@@ -202,9 +202,9 @@ void GradientIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
"PA Only supports Ordering::byNODES!");
// Assuming the same element type
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement &trial_fe = *trial_fes.GetFE(0); // H1
const FiniteElement &test_fe = *test_fes.GetFE(0); // H1^d or L2^d
ElementTransformation *trans = mesh->GetElementTransformation(0);
const FiniteElement &trial_fe = *trial_fes.GetTypicalFE(); // H1
const FiniteElement &test_fe = *test_fes.GetTypicalFE(); // H1^d or L2^d
ElementTransformation *trans = mesh->GetTypicalElementTransformation();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(trial_fe, test_fe,
*trans);
const int dims = trial_fe.GetDim();
+4 -4
View File
@@ -1033,8 +1033,8 @@ void GradientInterpolator::AssemblePA(const FiniteElementSpace &trial_fes,
{
// Assumes tensor-product elements, with a vector test space and H^1 trial space.
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *trial_fel = trial_fes.GetFE(0);
const FiniteElement *test_fel = test_fes.GetFE(0);
const FiniteElement *trial_fel = trial_fes.GetTypicalFE();
const FiniteElement *test_fel = test_fes.GetTypicalFE();
const NodalTensorFiniteElement *trial_el =
dynamic_cast<const NodalTensorFiniteElement*>(trial_fel);
@@ -1800,8 +1800,8 @@ void IdentityInterpolator::AssemblePA(const FiniteElementSpace &trial_fes,
{
// Assumes tensor-product elements, with a vector test space and H^1 trial space.
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *trial_fel = trial_fes.GetFE(0);
const FiniteElement *test_fel = test_fes.GetFE(0);
const FiniteElement *trial_fel = trial_fes.GetTypicalFE();
const FiniteElement *test_fel = test_fes.GetTypicalFE();
const NodalTensorFiniteElement *trial_el =
dynamic_cast<const NodalTensorFiniteElement*>(trial_fel);
-1
View File
@@ -14,7 +14,6 @@
namespace mfem
{
MassIntegrator::Kernels MassIntegrator::kernels;
MassIntegrator::Kernels::Kernels()
{
// 2D
+2 -3
View File
@@ -21,9 +21,8 @@ void MassIntegrator::AssembleMF(const FiniteElementSpace &fes)
// Assuming the same element type
fespace = &fes;
Mesh *mesh = fes.GetMesh();
if (mesh->GetNE() == 0) { return; }
const FiniteElement &el = *fes.GetFE(0);
ElementTransformation *T = mesh->GetElementTransformation(0);
const FiniteElement &el = *fes.GetTypicalFE();
ElementTransformation *T = mesh->GetTypicalElementTransformation();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el, *T);
if (DeviceCanUseCeed())
{
+2 -3
View File
@@ -29,9 +29,8 @@ void MassIntegrator::AssemblePA(const FiniteElementSpace &fes)
// Assuming the same element type
fespace = &fes;
Mesh *mesh = fes.GetMesh();
if (mesh->GetNE() == 0) { return; }
const FiniteElement &el = *fes.GetFE(0);
ElementTransformation *T0 = mesh->GetElementTransformation(0);
const FiniteElement &el = *fes.GetTypicalFE();
ElementTransformation *T0 = mesh->GetTypicalElementTransformation();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el, *T0);
if (DeviceCanUseCeed())
{
+9 -9
View File
@@ -23,8 +23,8 @@ void MixedScalarCurlIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
{
// Assumes tensor-product elements
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *fel = trial_fes.GetFE(0); // In H(curl)
const FiniteElement *eltest = test_fes.GetFE(0); // In scalar space
const FiniteElement *fel = trial_fes.GetTypicalFE(); // In H(curl)
const FiniteElement *eltest = test_fes.GetTypicalFE(); // In scalar space
const VectorTensorFiniteElement *el =
dynamic_cast<const VectorTensorFiniteElement*>(fel);
@@ -37,7 +37,7 @@ void MixedScalarCurlIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(*eltest, *eltest,
*mesh->GetElementTransformation(0));
*mesh->GetTypicalElementTransformation());
const int dims = el->GetDim();
MFEM_VERIFY(dims == 2, "");
@@ -112,8 +112,8 @@ void MixedVectorCurlIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
{
// Assumes tensor-product elements, with vector test and trial spaces.
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *trial_fel = trial_fes.GetFE(0);
const FiniteElement *test_fel = test_fes.GetFE(0);
const FiniteElement *trial_fel = trial_fes.GetTypicalFE();
const FiniteElement *test_fel = test_fes.GetTypicalFE();
const VectorTensorFiniteElement *trial_el =
dynamic_cast<const VectorTensorFiniteElement*>(trial_fel);
@@ -125,7 +125,7 @@ void MixedVectorCurlIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(*trial_el, *trial_el,
*mesh->GetElementTransformation(0));
*mesh->GetTypicalElementTransformation());
const int dims = trial_el->GetDim();
MFEM_VERIFY(dims == 3, "");
@@ -271,8 +271,8 @@ void MixedVectorWeakCurlIntegrator::AssemblePA(const FiniteElementSpace
{
// Assumes tensor-product elements, with vector test and trial spaces.
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *trial_fel = trial_fes.GetFE(0);
const FiniteElement *test_fel = test_fes.GetFE(0);
const FiniteElement *trial_fel = trial_fes.GetTypicalFE();
const FiniteElement *test_fel = test_fes.GetTypicalFE();
const VectorTensorFiniteElement *trial_el =
dynamic_cast<const VectorTensorFiniteElement*>(trial_fel);
@@ -284,7 +284,7 @@ void MixedVectorWeakCurlIntegrator::AssemblePA(const FiniteElementSpace
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(*trial_el, *trial_el,
*mesh->GetElementTransformation(0));
*mesh->GetTypicalElementTransformation());
const int dims = trial_el->GetDim();
MFEM_VERIFY(dims == 3, "");
+3 -3
View File
@@ -666,8 +666,8 @@ void MixedVectorGradientIntegrator::AssemblePA(const FiniteElementSpace
{
// Assumes tensor-product elements, with a vector test space and H^1 trial space.
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *trial_fel = trial_fes.GetFE(0);
const FiniteElement *test_fel = test_fes.GetFE(0);
const FiniteElement *trial_fel = trial_fes.GetTypicalFE();
const FiniteElement *test_fel = test_fes.GetTypicalFE();
const NodalTensorFiniteElement *trial_el =
dynamic_cast<const NodalTensorFiniteElement*>(trial_fel);
@@ -679,7 +679,7 @@ void MixedVectorGradientIntegrator::AssemblePA(const FiniteElementSpace
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(*trial_el, *trial_el,
*mesh->GetElementTransformation(0));
*mesh->GetTypicalElementTransformation());
const int dims = trial_el->GetDim();
MFEM_VERIFY(dims == 2 || dims == 3, "");
+6 -12
View File
@@ -23,8 +23,7 @@ void TransposeIntegrator::AssembleEA(const FiniteElementSpace &fes,
Vector ea_data_tmp(ea_data.Size());
bfi->AssembleEA(fes, ea_data_tmp, false);
const int ne = fes.GetNE();
if (ne == 0) { return; }
const int dofs = fes.GetFE(0)->GetDof();
const int dofs = fes.GetTypicalFE()->GetDof();
auto A = Reshape(ea_data_tmp.Read(), dofs, dofs, ne);
auto AT = Reshape(ea_data.ReadWrite(), dofs, dofs, ne);
mfem::forall(ne, [=] MFEM_HOST_DEVICE (int e)
@@ -43,8 +42,7 @@ void TransposeIntegrator::AssembleEA(const FiniteElementSpace &fes,
{
bfi->AssembleEA(fes, ea_data, false);
const int ne = fes.GetNE();
if (ne == 0) { return; }
const int dofs = fes.GetFE(0)->GetDof();
const int dofs = fes.GetTypicalFE()->GetDof();
auto A = Reshape(ea_data.ReadWrite(), dofs, dofs, ne);
mfem::forall(ne, [=] MFEM_HOST_DEVICE (int e)
{
@@ -74,8 +72,7 @@ void TransposeIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace& fes,
Vector ea_data_int_tmp(ea_data_int.Size());
Vector ea_data_ext_tmp(ea_data_ext.Size());
bfi->AssembleEAInteriorFaces(fes, ea_data_int_tmp, ea_data_ext_tmp, false);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceGeometry(0))->GetDof();
const int faceDofs = fes.GetTypicalTraceElement()->GetDof();
auto A_int = Reshape(ea_data_int_tmp.Read(), faceDofs, faceDofs, 2, nf);
auto A_ext = Reshape(ea_data_ext_tmp.Read(), faceDofs, faceDofs, 2, nf);
auto AT_int = Reshape(ea_data_int.ReadWrite(), faceDofs, faceDofs, 2, nf);
@@ -101,8 +98,7 @@ void TransposeIntegrator::AssembleEAInteriorFaces(const FiniteElementSpace& fes,
else
{
bfi->AssembleEAInteriorFaces(fes, ea_data_int, ea_data_ext, false);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceGeometry(0))->GetDof();
const int faceDofs = fes.GetTypicalTraceElement()->GetDof();
auto A_int = Reshape(ea_data_int.ReadWrite(), faceDofs, faceDofs, 2, nf);
auto A_ext = Reshape(ea_data_ext.ReadWrite(), faceDofs, faceDofs, 2, nf);
mfem::forall(nf, [=] MFEM_HOST_DEVICE (int f)
@@ -145,8 +141,7 @@ void TransposeIntegrator::AssembleEABoundaryFaces(const FiniteElementSpace& fes,
{
Vector ea_data_bdr_tmp(ea_data_bdr.Size());
bfi->AssembleEABoundaryFaces(fes, ea_data_bdr_tmp, false);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceGeometry(0))->GetDof();
const int faceDofs = fes.GetTypicalTraceElement()->GetDof();
auto A_bdr = Reshape(ea_data_bdr_tmp.Read(), faceDofs, faceDofs, nf);
auto AT_bdr = Reshape(ea_data_bdr.ReadWrite(), faceDofs, faceDofs, nf);
mfem::forall(nf, [=] MFEM_HOST_DEVICE (int f)
@@ -164,8 +159,7 @@ void TransposeIntegrator::AssembleEABoundaryFaces(const FiniteElementSpace& fes,
else
{
bfi->AssembleEABoundaryFaces(fes, ea_data_bdr, false);
const int faceDofs = fes.GetTraceElement(0,
fes.GetMesh()->GetFaceGeometry(0))->GetDof();
const int faceDofs = fes.GetTypicalTraceElement()->GetDof();
auto A_bdr = Reshape(ea_data_bdr.ReadWrite(), faceDofs, faceDofs, nf);
mfem::forall(nf, [=] MFEM_HOST_DEVICE (int f)
{
+1 -2
View File
@@ -20,8 +20,7 @@ void VectorDiffusionIntegrator::AssembleMF(const FiniteElementSpace &fes)
{
// Assumes tensor-product elements
Mesh *mesh = fes.GetMesh();
if (mesh->GetNE() == 0) { return; }
const FiniteElement &el = *fes.GetFE(0);
const FiniteElement &el = *fes.GetTypicalFE();
const IntegrationRule *ir
= IntRule ? IntRule : &DiffusionIntegrator::GetRule(el, el);
if (DeviceCanUseCeed())
+1 -1
View File
@@ -140,7 +140,7 @@ void VectorDiffusionIntegrator::AssemblePA(const FiniteElementSpace &fes)
{
// Assumes tensor-product elements
Mesh *mesh = fes.GetMesh();
const FiniteElement &el = *fes.GetFE(0);
const FiniteElement &el = *fes.GetTypicalFE();
const IntegrationRule *ir
= IntRule ? IntRule : &DiffusionIntegrator::GetRule(el, el);
if (DeviceCanUseCeed())
+3 -3
View File
@@ -124,9 +124,9 @@ void VectorDivergenceIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
MFEM_ASSERT(trial_fes.GetOrdering() == Ordering::byNODES,
"PA Only supports Ordering::byNODES!");
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement &trial_fe = *trial_fes.GetFE(0);
const FiniteElement &test_fe = *test_fes.GetFE(0);
ElementTransformation *trans = mesh->GetElementTransformation(0);
const FiniteElement &trial_fe = *trial_fes.GetTypicalFE();
const FiniteElement &test_fe = *test_fes.GetTypicalFE();
ElementTransformation *trans = mesh->GetTypicalElementTransformation();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(trial_fe, test_fe,
*trans);
const int dims = trial_fe.GetDim();
+2 -3
View File
@@ -20,9 +20,8 @@ void VectorMassIntegrator::AssembleMF(const FiniteElementSpace &fes)
{
// Assuming the same element type
Mesh *mesh = fes.GetMesh();
if (mesh->GetNE() == 0) { return; }
const FiniteElement &el = *fes.GetFE(0);
ElementTransformation *T = mesh->GetElementTransformation(0);
const FiniteElement &el = *fes.GetTypicalFE();
ElementTransformation *T = mesh->GetTypicalElementTransformation();
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(el, el, *T);
if (DeviceCanUseCeed())
+2 -3
View File
@@ -21,9 +21,8 @@ void VectorMassIntegrator::AssemblePA(const FiniteElementSpace &fes)
{
// Assuming the same element type
Mesh *mesh = fes.GetMesh();
if (mesh->GetNE() == 0) { return; }
const FiniteElement &el = *fes.GetFE(0);
ElementTransformation *T = mesh->GetElementTransformation(0);
const FiniteElement &el = *fes.GetTypicalFE();
ElementTransformation *T = mesh->GetTypicalElementTransformation();
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(el, el, *T);
if (DeviceCanUseCeed())
+3 -3
View File
@@ -24,8 +24,8 @@ VectorFEDivergenceIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
// Assumes tensor-product elements, with a vector test space and
// scalar trial space.
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *trial_fel = trial_fes.GetFE(0);
const FiniteElement *test_fel = test_fes.GetFE(0);
const FiniteElement *trial_fel = trial_fes.GetTypicalFE();
const FiniteElement *test_fel = test_fes.GetTypicalFE();
const VectorTensorFiniteElement *trial_el =
dynamic_cast<const VectorTensorFiniteElement*>(trial_fel);
@@ -37,7 +37,7 @@ VectorFEDivergenceIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
const IntegrationRule *ir = IntRule ? IntRule : &MassIntegrator::GetRule(
*trial_el, *trial_el,
*mesh->GetElementTransformation(0));
*mesh->GetTypicalElementTransformation());
const int dims = trial_el->GetDim();
MFEM_VERIFY(dims == 2 || dims == 3, "");
+3 -3
View File
@@ -31,19 +31,19 @@ void VectorFEMassIntegrator::AssemblePA(const FiniteElementSpace &trial_fes,
// Assumes tensor-product elements
Mesh *mesh = trial_fes.GetMesh();
const FiniteElement *trial_fel = trial_fes.GetFE(0);
const FiniteElement *trial_fel = trial_fes.GetTypicalFE();
const VectorTensorFiniteElement *trial_el =
dynamic_cast<const VectorTensorFiniteElement*>(trial_fel);
MFEM_VERIFY(trial_el != NULL, "Only VectorTensorFiniteElement is supported!");
const FiniteElement *test_fel = test_fes.GetFE(0);
const FiniteElement *test_fel = test_fes.GetTypicalFE();
const VectorTensorFiniteElement *test_el =
dynamic_cast<const VectorTensorFiniteElement*>(test_fel);
MFEM_VERIFY(test_el != NULL, "Only VectorTensorFiniteElement is supported!");
const IntegrationRule *ir
= IntRule ? IntRule : &MassIntegrator::GetRule(*trial_el, *trial_el,
*mesh->GetElementTransformation(0));
*mesh->GetTypicalElementTransformation());
const int dims = trial_el->GetDim();
MFEM_VERIFY(dims == 2 || dims == 3, "");
+4 -4
View File
@@ -190,13 +190,13 @@ static void DLFEvalAssemble(const FiniteElementSpace &fes,
{
Mesh *mesh = fes.GetMesh();
const int dim = mesh->Dimension();
const FiniteElement &el = *fes.GetFE(0);
const FiniteElement &el = *fes.GetTypicalFE();
const MemoryType mt = Device::GetDeviceMemoryType();
const DofToQuad &maps = el.GetDofToQuad(*ir, DofToQuad::TENSOR);
const int d = maps.ndof, q = maps.nqpt;
constexpr int flags = GeometricFactors::DETERMINANTS;
const GeometricFactors *geom = mesh->GetGeometricFactors(*ir, flags, mt);
const int map_type = fes.GetFE(0)->GetMapType();
const int map_type = fes.GetTypicalFE()->GetMapType();
decltype(&DLFEvalAssemble2D<>) ker =
dim == 2 ? DLFEvalAssemble2D<> : DLFEvalAssemble3D<>;
@@ -242,7 +242,7 @@ void DomainLFIntegrator::AssembleDevice(const FiniteElementSpace &fes,
const Array<int> &markers,
Vector &b)
{
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const int qorder = oa * fe.GetOrder() + ob;
const Geometry::Type gtype = fe.GetGeomType();
const IntegrationRule *ir = IntRule ? IntRule : &IntRules.Get(gtype, qorder);
@@ -256,7 +256,7 @@ void VectorDomainLFIntegrator::AssembleDevice(const FiniteElementSpace &fes,
const Array<int> &markers,
Vector &b)
{
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const int qorder = 2 * fe.GetOrder();
const Geometry::Type gtype = fe.GetGeomType();
const IntegrationRule *ir = IntRule ? IntRule : &IntRules.Get(gtype, qorder);
+3 -3
View File
@@ -267,7 +267,7 @@ static void DLFGradAssemble(const FiniteElementSpace &fes,
{
Mesh *mesh = fes.GetMesh();
const int dim = mesh->Dimension();
const FiniteElement &el = *fes.GetFE(0);
const FiniteElement &el = *fes.GetTypicalFE();
const MemoryType mt = Device::GetDeviceMemoryType();
const DofToQuad &maps = el.GetDofToQuad(*ir, DofToQuad::TENSOR);
const int d = maps.ndof, q = maps.nqpt;
@@ -320,7 +320,7 @@ void DomainLFGradIntegrator::AssembleDevice(const FiniteElementSpace &fes,
Vector &b)
{
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const int qorder = 2 * fe.GetOrder();
const Geometry::Type gtype = fe.GetGeomType();
const IntegrationRule *ir = IntRule ? IntRule : &IntRules.Get(gtype, qorder);
@@ -334,7 +334,7 @@ void VectorDomainLFGradIntegrator::AssembleDevice(const FiniteElementSpace &fes,
const Array<int> &markers,
Vector &b)
{
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const int qorder = 2 * fe.GetOrder();
const Geometry::Type gtype = fe.GetGeomType();
const IntegrationRule *ir = IntRule ? IntRule : &IntRules.Get(gtype, qorder);
+2 -2
View File
@@ -278,7 +278,7 @@ static void HdivDLFAssemble(const FiniteElementSpace &fes,
{
Mesh &mesh = *fes.GetMesh();
const int dim = mesh.Dimension();
const FiniteElement *el = fes.GetFE(0);
const FiniteElement *el = fes.GetTypicalFE();
const auto *vel = dynamic_cast<const VectorTensorFiniteElement *>(el);
MFEM_VERIFY(vel != nullptr, "Must be VectorTensorFiniteElement");
const MemoryType mt = Device::GetDeviceMemoryType();
@@ -329,7 +329,7 @@ void VectorFEDomainLFIntegrator::AssembleDevice(const FiniteElementSpace &fes,
const Array<int> &markers,
Vector &b)
{
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const int qorder = 2 * fe.GetOrder();
const Geometry::Type gtype = fe.GetGeomType();
const IntegrationRule *ir = IntRule ? IntRule : &IntRules.Get(gtype, qorder);
+2 -2
View File
@@ -20,8 +20,8 @@ void VectorConvectionNLFIntegrator::AssembleMF(const FiniteElementSpace &fes)
MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES,
"PA Only supports Ordering::byNODES!");
Mesh *mesh = fes.GetMesh();
const FiniteElement &el = *fes.GetFE(0);
ElementTransformation &T = *mesh->GetElementTransformation(0);
const FiniteElement &el = *fes.GetTypicalFE();
ElementTransformation &T = *mesh->GetTypicalElementTransformation();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, T);
if (DeviceCanUseCeed())
{
+2 -2
View File
@@ -21,8 +21,8 @@ void VectorConvectionNLFIntegrator::AssemblePA(const FiniteElementSpace &fes)
MFEM_ASSERT(fes.GetOrdering() == Ordering::byNODES,
"PA Only supports Ordering::byNODES!");
Mesh *mesh = fes.GetMesh();
const FiniteElement &el = *fes.GetFE(0);
ElementTransformation &T = *mesh->GetElementTransformation(0);
const FiniteElement &el = *fes.GetTypicalFE();
ElementTransformation &T = *mesh->GetTypicalElementTransformation();
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, T);
if (DeviceCanUseCeed())
{
+50
View File
@@ -0,0 +1,50 @@
// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#include "integrator.hpp"
#include "fem.hpp"
#include "intrules.hpp"
namespace mfem
{
const IntegrationRule* Integrator::GetIntegrationRule(
const FiniteElement& trial_fe, const FiniteElement& test_fe,
const ElementTransformation& trans) const
{
const IntegrationRule* result;
const NURBSFiniteElement *NURBSFE;
if (patchRules &&
(NURBSFE = dynamic_cast<const NURBSFiniteElement *>(&test_fe)))
{
const int patch = NURBSFE->GetPatch();
const int* ijk = NURBSFE->GetIJK();
Array<const KnotVector*>& kv = NURBSFE->KnotVectors();
result = &patchRules->GetElementRule(NURBSFE->GetElement(), patch, ijk,
kv);
}
else if (IntRule)
{
result = IntRule;
}
else
{
result = GetDefaultIntegrationRule(trial_fe, test_fe, trans);
}
return result;
}
const IntegrationRule* Integrator::GetIntegrationRule(
const FiniteElement& el,
const ElementTransformation& trans) const
{
return GetIntegrationRule(el, el, trans);
}
}
+118
View File
@@ -0,0 +1,118 @@
// Copyright (c) 2010-2024, 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_INTEGRATOR
#define MFEM_INTEGRATOR
#include "../config/config.hpp"
#include "fe.hpp"
namespace mfem
{
/** @brief This base class implements some shared functionality between
linear and nonlinear form integrators. */
class Integrator
{
public:
/** @brief Create a new Integrator, optionally providing a prescribed
quadrature rule to use in assembly. */
Integrator(const IntegrationRule *ir = NULL) : IntRule(ir) {}
/** @brief Prescribe a fixed IntegrationRule to use, or set to null to let
the integrator choose an appropriate rule.
@details This method allows setting a custom integration rule to use
on each element during assembly, overriding the default
choice if it is non-null. Passing a non-null value will
set the Integrator's NURBS patch integration rule to null
to avoid ambiguity in GetIntegrationRule.
*/
virtual void SetIntRule(const IntegrationRule *ir)
{ IntRule = ir; if (ir) { patchRules = nullptr; } }
/** @brief Prescribe a fixed IntegrationRule to use. Sets the NURBS patch
integration rule to null.
@see SetIntRule(const IntegrationRule*)
*/
void SetIntegrationRule(const IntegrationRule &ir) { SetIntRule(&ir); }
/** @brief Sets an integration rule for use on NURBS patches.
@details For patchwise integration, SetNURBSPatchIntRule
must be called. Passing a non-null value will set the
Integrator's standard element IntegrationRule to null
to avoid ambiguity in GetIntegrationRule.
*/
void SetNURBSPatchIntRule(NURBSMeshRules *pr)
{ patchRules = pr; if (pr) { IntRule = nullptr; } }
/** @brief Check if a NURBS patch integration rule has been set. */
bool HasNURBSPatchIntRule() const { return patchRules != nullptr; }
/** @brief Directly return the IntRule pointer (possibly null) without
checking for NURBS patch rules or falling back on a default. */
const IntegrationRule *GetIntRule() const { return IntRule; }
/** @brief Equivalent to GetIntRule, but retained for backward
compatibility with applications. */
const IntegrationRule *GetIntegrationRule() const { return GetIntRule(); }
protected:
const IntegrationRule *IntRule;
NURBSMeshRules *patchRules = nullptr;
/** @brief Returns an integration rule based on the the arguments and
internal state of the Integrator object.
@details This method returns an integration rule in a way that depends
on the integrator's attributes. Attributes can specify an
existing IntegrationRule, and/or a NURBSMeshRules object.
This method will pick the NURBSMeshRules' restriction to the
element if given and applicable, and IntRule otherwise,
prioritizing the NURBS rule if available. If neither is
valid, the integrator will fall back on the virtual method
GetDefaultIntegrationRule to choose a default integration
rule, where subclasses can override this in a problem-specific
way.
*/
const IntegrationRule* GetIntegrationRule(
const FiniteElement& trial_fe, const FiniteElement& test_fe,
const ElementTransformation& trans) const;
/** @brief Returns an integration rule based on the arguments and
internal state. (Version for identical trial_fe and test_fe)
@see GetIntegrationRule(const FiniteElement*, const FiniteElement*,
const ElementTransformation*)
*/
const IntegrationRule* GetIntegrationRule(
const FiniteElement& el,
const ElementTransformation& trans) const;
/** @brief Subclasses should override to choose a default integration rule.
@details This method is intended to be overriden by subclasses to
choose an appropriate integration rule based on the finite
element spaces and/or element transformation. The trial_fe
and test_fe should be equal for linear forms. The default
base-class implementation returns null, which assumes that
an appropriate rule is provided by another means, or that null
integration rules are handled appropriately by the caller.
*/
virtual const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe, const FiniteElement& test_fe,
const ElementTransformation& trans) const
{ return NULL; }
};
}
#endif
+20 -15
View File
@@ -1864,11 +1864,8 @@ IntegrationRule *IntegrationRules::CubeIntegrationRule(int Order)
IntegrationRule& NURBSMeshRules::GetElementRule(const int elem,
const int patch, const int *ijk,
Array<const KnotVector*> const& kv,
bool & deleteRule) const
Array<const KnotVector*> const& kv) const
{
deleteRule = false;
// First check whether a rule has been assigned to element index elem.
auto search = elementToRule.find(elem);
if (search != elementToRule.end())
@@ -1876,6 +1873,11 @@ IntegrationRule& NURBSMeshRules::GetElementRule(const int elem,
return *elementRule[search->second];
}
#ifndef MFEM_THREAD_SAFE
// If no prescribed rule is given for the current element, a temporary one is
// formed by restricting a tensor-product of 1D rules to the element. The
// ownership model for this temporary rule is not thread-safe.
MFEM_VERIFY(patchRules1D.NumRows(),
"Undefined rule in NURBSMeshRules::GetElementRule");
@@ -1908,14 +1910,13 @@ IntegrationRule& NURBSMeshRules::GetElementRule(const int elem,
}
}
npd[d] = el[d].size() / 2;
npd[d] = static_cast<int>(el[d].size() / 2);
np *= npd[d];
}
IntegrationRule *irp = new IntegrationRule(np);
deleteRule = true;
temporaryElementRule.SetSize(np);
// Set (*irp)[i + j*npd[0] + k*npd[0]*npd[1]] =
// Set temporaryElementRule[i + j*npd[0] + k*npd[0]*npd[1]] =
// (el[0][2*i], el[1][2*j], el[2][2*k])
MFEM_VERIFY(npd[0] > 0 && npd[1] > 0, "Assuming 2D or 3D");
@@ -1927,22 +1928,26 @@ IntegrationRule& NURBSMeshRules::GetElementRule(const int elem,
for (int k = 0; k < std::max(npd[2], 1); ++k)
{
const int id = i + j*npd[0] + k*npd[0]*npd[1];
(*irp)[id].x = el[0][2*i];
(*irp)[id].y = el[1][2*j];
temporaryElementRule[id].x = el[0][2*i];
temporaryElementRule[id].y = el[1][2*j];
(*irp)[id].weight = el[0][(2*i)+1];
(*irp)[id].weight *= el[1][(2*j)+1];
temporaryElementRule[id].weight = el[0][(2*i)+1];
temporaryElementRule[id].weight *= el[1][(2*j)+1];
if (npd[2] > 0)
{
(*irp)[id].z = el[2][2*k];
(*irp)[id].weight *= el[2][(2*k)+1];
temporaryElementRule[id].z = el[2][2*k];
temporaryElementRule[id].weight *= el[2][(2*k)+1];
}
}
}
}
return *irp;
return temporaryElementRule;
#else
MFEM_ABORT("Temporary integration rules on NURBS elements "
"are not thread-safe.");
#endif
}
void NURBSMeshRules::GetIntegrationPointFrom1D(const int patch, int i, int j,
+8 -2
View File
@@ -286,8 +286,7 @@ public:
/// Returns a rule for the element.
IntegrationRule &GetElementRule(const int elem, const int patch,
const int *ijk,
Array<const KnotVector*> const& kv,
bool & deleteRule) const;
Array<const KnotVector*> const& kv) const;
/// Add a rule to be used for individual elements. Returns the rule index.
std::size_t AddElementRule(IntegrationRule *ir_element)
@@ -361,6 +360,13 @@ private:
std::vector<Array3D<int>> pointToElem;
std::vector<std::vector<Array<int>>> patchRules1D_KnotSpan;
#ifndef MFEM_THREAD_SAFE
// This is a temporary quadrature rule for integrating over the
// current element in an assembly loop. It may be modified when
// moving to a new element, and is therefore not thread-safe.
mutable IntegrationRule temporaryElementRule;
#endif
const int npatches;
const int dim;
};
+2 -2
View File
@@ -109,8 +109,8 @@ public:
}
// intialize the bounding box
const FiniteElement* el=space->GetFE(0);
trans = space->GetElementTransformation(0);
const FiniteElement* el = space->GetTypicalFE();
trans = mesh->GetTypicalElementTransformation();
ir=&(el->GetNodes());
space->GetElementVDofs(0,vdofs);
elco.SetSize(dim,ir->GetNPoints());
+12 -6
View File
@@ -78,9 +78,9 @@ namespace mfem
const char *kernel_name = MFEM_KERNEL_NAME(KernelName); \
using KernelSignature = KernelType; \
template <MFEM_PARAM_LIST P3> \
static KernelSignature Kernel(); \
static KernelSignature Fallback(MFEM_PARAM_LIST P1); \
static KernelName &Get() \
static MFEM_EXPORT KernelSignature Kernel(); \
static MFEM_EXPORT KernelSignature Fallback(MFEM_PARAM_LIST P1); \
static MFEM_EXPORT KernelName &Get() \
{ static KernelName table; return table;} \
}
@@ -126,9 +126,9 @@ class KernelDispatchTable<Kernels,
internal::KernelTypeList<Params...>,
internal::KernelTypeList<OptParams...>>
{
std::unordered_map<std::tuple<Params...>,
Signature,
KernelDispatchKeyHash<Params...>> table;
using TableType = std::unordered_map<std::tuple<Params...>,
Signature, KernelDispatchKeyHash<Params...>>;
TableType table;
public:
/// @brief Run the kernel with the given dispatch parameters and arguments.
@@ -176,6 +176,12 @@ public:
}
};
};
/// Return the dispatch map table
static const TableType &GetDispatchTable()
{
return Kernels::Get().table;
}
};
}
+1 -1
View File
@@ -64,7 +64,7 @@ class KernelReporter
std::set<std::string> reported_fallbacks;
KernelReporter()
{
const char *env = getenv("MFEM_REPORT_KERNELS");
const char *env = GetEnv("MFEM_REPORT_KERNELS");
if (env)
{
if (std::string(env) != "NO") { enabled = true; }
+9 -8
View File
@@ -11,10 +11,10 @@
#include "fem.hpp"
#include <cmath>
#include "intrules.hpp"
namespace mfem
{
void LinearFormIntegrator::AssembleDevice(const FiniteElementSpace &fes,
const Array<int> &markers,
Vector &b)
@@ -45,7 +45,8 @@ void DomainLFIntegrator::AssembleRHSElementVect(const FiniteElement &el,
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
// ir = &IntRules.Get(el.GetGeomType(),
@@ -86,7 +87,7 @@ void DomainLFGradIntegrator::AssembleRHSElementVect(
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
int intorder = 2 * el.GetOrder();
@@ -278,7 +279,7 @@ void VectorDomainLFIntegrator::AssembleRHSElementVect(
elvect.SetSize(dof * vdim);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
int intorder = 2*el.GetOrder();
@@ -337,7 +338,7 @@ void VectorDomainLFGradIntegrator::AssembleRHSElementVect(
elvect.SetSize(dof*(vdim/sdim));
elvect = 0.0;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
int intorder = 2 * el.GetOrder();
@@ -463,7 +464,7 @@ void VectorFEDomainLFIntegrator::AssembleRHSElementVect(
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
// int intorder = 2*el.GetOrder() - 1; // ok for O(h^{k+1}) conv. in L2
@@ -512,7 +513,7 @@ void VectorFEDomainLFCurlIntegrator::AssembleRHSElementVect(
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
int intorder = 2*el.GetOrder();
@@ -558,7 +559,7 @@ void VectorFEDomainLFDivIntegrator::AssembleRHSElementVect(
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Tr);
if (ir == NULL)
{
int intorder = 2 * el.GetOrder();
+4 -7
View File
@@ -16,17 +16,17 @@
#include "coefficient.hpp"
#include "bilininteg.hpp"
#include <random>
#include "integrator.hpp"
namespace mfem
{
/// Abstract base class LinearFormIntegrator
class LinearFormIntegrator
class LinearFormIntegrator : public Integrator
{
protected:
const IntegrationRule *IntRule;
LinearFormIntegrator(const IntegrationRule *ir = NULL) { IntRule = ir; }
LinearFormIntegrator(const IntegrationRule *ir = NULL) : Integrator(ir) {}
public:
@@ -51,9 +51,6 @@ public:
FaceElementTransformations &Tr,
Vector &elvect);
virtual void SetIntRule(const IntegrationRule *ir) { IntRule = ir; }
const IntegrationRule* GetIntRule() { return IntRule; }
virtual ~LinearFormIntegrator() { }
};
@@ -676,7 +673,7 @@ public:
int myid;
MPI_Comm_rank(comm, &myid);
int seed = (seed_ > 0) ? seed_ + myid : time(0) + myid;
int seed = (seed_ > 0) ? seed_ + myid : (int)time(0) + myid;
SetSeed(seed);
}
#else
+2 -2
View File
@@ -29,7 +29,7 @@ void LORBase::AddIntegrators(BilinearForm &a_from,
{
BilinearFormIntegrator *integrator = (*integrators)[i];
(a_to.*add_integrator)(integrator);
ir_map[integrator] = integrator->GetIntegrationRule();
ir_map[integrator] = integrator->GetIntRule();
if (ir) { integrator->SetIntegrationRule(*ir); }
}
}
@@ -56,7 +56,7 @@ void LORBase::AddIntegratorsAndMarkers(BilinearForm &a_from,
{
(a_to.*add_integrator)(integrator);
}
ir_map[integrator] = integrator->GetIntegrationRule();
ir_map[integrator] = integrator->GetIntRule();
if (ir) { integrator->SetIntegrationRule(*ir); }
}
}
+3 -3
View File
@@ -140,7 +140,7 @@ int BatchedLORAssembly::FillI(SparseMatrix &A) const
const int nvdof = fes_ho.GetVSize();
const int ndof_per_el = fes_ho.GetFE(0)->GetDof();
const int ndof_per_el = fes_ho.GetTypicalFE()->GetDof();
const int nel_ho = fes_ho.GetNE();
const int nnz_per_row = sparse_mapping.Size()/ndof_per_el;
@@ -230,7 +230,7 @@ int BatchedLORAssembly::FillI(SparseMatrix &A) const
void BatchedLORAssembly::FillJAndData(SparseMatrix &A) const
{
const int nvdof = fes_ho.GetVSize();
const int ndof_per_el = fes_ho.GetFE(0)->GetDof();
const int ndof_per_el = fes_ho.GetTypicalFE()->GetDof();
const int nel_ho = fes_ho.GetNE();
const int nnz_per_row = sparse_mapping.Size()/ndof_per_el;
@@ -500,7 +500,7 @@ BatchedLORAssembly::BatchedLORAssembly(FiniteElementSpace &fes_ho_)
IntegrationRule GetCollocatedIntRule(FiniteElementSpace &fes)
{
IntegrationRules irs(0, Quadrature1D::GaussLobatto);
const Geometry::Type geom = fes.GetMesh()->GetElementGeometry(0);
const Geometry::Type geom = fes.GetMesh()->GetTypicalElementGeometry();
const int nd1d = fes.GetMaxElementOrder() + 1;
return irs.Get(geom, 2*nd1d - 3);
}
+14 -12
View File
@@ -383,6 +383,12 @@ void NeoHookeanModel::AssembleH(const DenseMatrix &J, const DenseMatrix &DS,
}
}
const IntegrationRule* HyperelasticNLFIntegrator::GetDefaultIntegrationRule(
const FiniteElement& trial_fe, const FiniteElement& test_fe,
const ElementTransformation& trans) const
{
return &(IntRules.Get(test_fe.GetGeomType(), 2*test_fe.GetOrder() + 3));
}
real_t HyperelasticNLFIntegrator::GetElementEnergy(const FiniteElement &el,
ElementTransformation &Ttr,
@@ -397,11 +403,7 @@ real_t HyperelasticNLFIntegrator::GetElementEnergy(const FiniteElement &el,
Jpt.SetSize(dim);
PMatI.UseExternalData(elfun.GetData(), dof, dim);
const IntegrationRule *ir = IntRule;
if (!ir)
{
ir = &(IntRules.Get(el.GetGeomType(), 2*el.GetOrder() + 3)); // <---
}
const IntegrationRule *ir = GetIntegrationRule(el, Ttr);
energy = 0.0;
model->SetTransformation(Ttr);
@@ -436,7 +438,7 @@ void HyperelasticNLFIntegrator::AssembleElementVector(
elvect.SetSize(dof*dim);
PMatO.UseExternalData(elvect.GetData(), dof, dim);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Ttr);
if (!ir)
{
ir = &(IntRules.Get(el.GetGeomType(), 2*el.GetOrder() + 3)); // <---
@@ -475,7 +477,7 @@ void HyperelasticNLFIntegrator::AssembleElementGrad(const FiniteElement &el,
PMatI.UseExternalData(elfun.GetData(), dof, dim);
elmat.SetSize(dof*dim);
const IntegrationRule *ir = IntRule;
const IntegrationRule *ir = GetIntegrationRule(el, Ttr);
if (!ir)
{
ir = &(IntRules.Get(el.GetGeomType(), 2*el.GetOrder() + 3)); // <---
@@ -733,7 +735,7 @@ void IncompressibleNeoHookeanIntegrator::AssembleElementGrad(
const IntegrationRule&
VectorConvectionNLFIntegrator::GetRule(const FiniteElement &fe,
ElementTransformation &T)
const ElementTransformation &T)
{
const int order = 2 * fe.GetOrder() + T.OrderGrad(&fe);
return IntRules.Get(fe.GetGeomType(), order);
@@ -757,7 +759,7 @@ void VectorConvectionNLFIntegrator::AssembleElementVector(
ELV.UseExternalData(elvect.GetData(), nd, dim);
Vector vec1(dim), vec2(dim);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, T);
const IntegrationRule *ir = GetIntegrationRule(el, T);
ELV = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
@@ -797,7 +799,7 @@ void VectorConvectionNLFIntegrator::AssembleElementGrad(
real_t w;
Vector vec1(dim), vec2(dim), vec3(nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, trans);
const IntegrationRule *ir = GetIntegrationRule(el, trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
@@ -868,7 +870,7 @@ void ConvectiveVectorConvectionNLFIntegrator::AssembleElementGrad(
Vector vec1(dim), vec2(dim), vec3(nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, trans);
const IntegrationRule *ir = GetIntegrationRule(el, trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
@@ -919,7 +921,7 @@ void SkewSymmetricVectorConvectionNLFIntegrator::AssembleElementGrad(
Vector vec1(dim), vec2(dim), vec3(nd), vec4(dim), vec5(nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, trans);
const IntegrationRule *ir = GetIntegrationRule(el, trans);
elmat = 0.0;
elmat_comp_T = 0.0;
+19 -19
View File
@@ -17,6 +17,7 @@
#include "coefficient.hpp"
#include "fespace.hpp"
#include "ceed/interface/operator.hpp"
#include "integrator.hpp"
namespace mfem
{
@@ -24,7 +25,7 @@ namespace mfem
/** @brief This class is used to express the local action of a general nonlinear
finite element operator. In addition it may provide the capability to
assemble the local gradient operator and to compute the local energy. */
class NonlinearFormIntegrator
class NonlinearFormIntegrator : public Integrator
{
public:
enum Mode
@@ -36,43 +37,27 @@ public:
};
protected:
const IntegrationRule *IntRule;
Mode integrationMode = Mode::ELEMENTWISE;
// Prescribed integration rules (not reduced approximate rules).
NURBSMeshRules *patchRules = nullptr;
// CEED extension
ceed::Operator* ceedOp;
MemoryType pa_mt = MemoryType::DEFAULT;
NonlinearFormIntegrator(const IntegrationRule *ir = NULL)
: IntRule(ir), ceedOp(NULL) { }
: Integrator(ir), ceedOp(NULL) { }
public:
/** @brief Prescribe a fixed IntegrationRule to use (when @a ir != NULL) or
let the integrator choose (when @a ir == NULL). */
virtual void SetIntRule(const IntegrationRule *ir) { IntRule = ir; }
void SetIntegrationMode(Mode m) { integrationMode = m; }
/// For patchwise integration, SetNURBSPatchIntRule must be called.
void SetNURBSPatchIntRule(NURBSMeshRules *pr) { patchRules = pr; }
bool HasNURBSPatchIntRule() const { return patchRules != nullptr; }
bool Patchwise() const { return integrationMode != Mode::ELEMENTWISE; }
/// Prescribe a fixed IntegrationRule to use.
void SetIntegrationRule(const IntegrationRule &ir) { SetIntRule(&ir); }
/// Set the memory type used for GeometricFactors and other large allocations
/// in PA extensions.
void SetPAMemoryType(MemoryType mt) { pa_mt = mt; }
/// Get the integration rule of the integrator (possibly NULL).
const IntegrationRule *GetIntegrationRule() const { return IntRule; }
/// Perform the local action of the NonlinearFormIntegrator
virtual void AssembleElementVector(const FiniteElement &el,
@@ -353,6 +338,11 @@ public:
void AssembleElementGrad(const FiniteElement &el,
ElementTransformation &Ttr,
const Vector &elfun, DenseMatrix &elmat) override;
protected:
const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe,
const FiniteElement& test_fe,
const ElementTransformation& trans) const override;
};
/** Hyperelastic incompressible Neo-Hookean integrator with the PK1 stress
@@ -405,7 +395,7 @@ public:
VectorConvectionNLFIntegrator() = default;
static const IntegrationRule &GetRule(const FiniteElement &fe,
ElementTransformation &T);
const ElementTransformation &T);
void AssembleElementVector(const FiniteElement &el,
ElementTransformation &trans,
@@ -426,6 +416,16 @@ public:
void AddMultPA(const Vector &x, Vector &y) const override;
void AddMultMF(const Vector &x, Vector &y) const override;
protected:
const IntegrationRule* GetDefaultIntegrationRule(
const FiniteElement& trial_fe,
const FiniteElement& test_fe,
const ElementTransformation& trans) const override
{
return &GetRule(test_fe, trans);
}
};
+5 -5
View File
@@ -107,7 +107,7 @@ L2NormalDerivativeFaceRestriction::L2NormalDerivativeFaceRestriction(
Mesh &mesh = *fes.GetMesh();
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const int d = fe.GetDofToQuad(fe.GetNodes(), DofToQuad::TENSOR).ndof;
if (dim == 2)
@@ -323,7 +323,7 @@ void L2NormalDerivativeFaceRestriction::Mult2D(const Vector &x, Vector &y) const
const bool t = fes.GetOrdering() == Ordering::byVDIM;
const int num_elem = ne;
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const DofToQuad &maps = fe.GetDofToQuad(fe.GetNodes(), DofToQuad::TENSOR);
const int q = maps.nqpt;
@@ -435,7 +435,7 @@ void L2NormalDerivativeFaceRestriction::Mult3D(const Vector &x, Vector &y) const
const bool t = fes.GetOrdering() == Ordering::byVDIM;
const int num_elem = ne;
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const DofToQuad &maps = fe.GetDofToQuad(fe.GetNodes(), DofToQuad::TENSOR);
const int q = maps.nqpt;
@@ -560,7 +560,7 @@ void L2NormalDerivativeFaceRestriction::AddMultTranspose2D(
const int vd = fes.GetVDim();
const bool t = fes.GetOrdering() == Ordering::byVDIM;
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const DofToQuad &maps = fe.GetDofToQuad(fe.GetNodes(), DofToQuad::TENSOR);
const int q = maps.nqpt;
@@ -682,7 +682,7 @@ void L2NormalDerivativeFaceRestriction::AddMultTranspose3D(
MFEM_VERIFY(vd == 1, "vdim > 1 not supported.");
const FiniteElement &fe = *fes.GetFE(0);
const FiniteElement &fe = *fes.GetTypicalFE();
const DofToQuad &maps = fe.GetDofToQuad(fe.GetNodes(), DofToQuad::TENSOR);
const int q = maps.nqpt;
+56 -8
View File
@@ -1068,6 +1068,54 @@ void ParFiniteElementSpace::GetEssentialTrueDofs(const Array<int>
MarkerToList(true_ess_dofs, ess_tdof_list);
}
void ParFiniteElementSpace::GetExteriorVDofs(Array<int> &ext_dofs,
int component) const
{
FiniteElementSpace::GetExteriorVDofs(ext_dofs, component);
// Make sure that processors without boundary elements mark
// their boundary dofs (if they have any).
Synchronize(ext_dofs);
}
void ParFiniteElementSpace::GetExteriorTrueDofs(Array<int> &ext_tdof_list,
int component) const
{
Array<int> ext_dofs, true_ext_dofs;
GetExteriorVDofs(ext_dofs, component);
GetRestrictionMatrix()->BooleanMult(ext_dofs, true_ext_dofs);
#ifdef MFEM_DEBUG
// Verify that in boolean arithmetic: P^T ext_dofs = R ext_dofs.
Array<int> true_ext_dofs2(true_ext_dofs.Size());
auto Pt = std::unique_ptr<HypreParMatrix>(Dof_TrueDof_Matrix()->Transpose());
const int *ext_dofs_data = ext_dofs.HostRead();
Pt->BooleanMult(1, ext_dofs_data, 0, true_ext_dofs2);
int counter = 0;
const int *ted = true_ext_dofs.HostRead();
std::string error_msg = "failed dof: ";
for (int i = 0; i < true_ext_dofs.Size(); i++)
{
if (bool(ted[i]) != bool(true_ext_dofs2[i]))
{
error_msg += std::to_string(i) += "(R ";
error_msg += std::to_string(bool(ted[i])) += " P^T ";
error_msg += std::to_string(bool(true_ext_dofs2[i])) += ") ";
++counter;
}
}
MFEM_ASSERT(R->Height() == P->Width(), "!");
MFEM_ASSERT(R->Width() == P->Height(), "!");
MFEM_ASSERT(R->Width() == ext_dofs.Size(), "!");
MFEM_VERIFY(counter == 0, "internal MFEM error: counter = " << counter
<< ", rank = " << MyRank << ", " << error_msg);
#endif
MarkerToList(true_ext_dofs, ext_tdof_list);
}
int ParFiniteElementSpace::GetLocalTDofNumber(int ldof) const
{
if (Nonconforming())
@@ -1880,7 +1928,7 @@ void ParFiniteElementSpace::UnpackDof(int dof,
{
if (uni_fdof >= 0) // uniform faces
{
int nf = fec->DofForGeometry(pncmesh->GetFaceGeometry(0));
int nf = fec->DofForGeometry(pmesh->GetTypicalFaceGeometry());
index = dof / nf, edof = dof % nf;
}
else // mixed faces or var-order space
@@ -1984,7 +2032,7 @@ struct PMatrixRow
void write(std::ostream &os, real_t sign) const
{
bin_io::write<int>(os, elems.size());
bin_io::write<int>(os, static_cast<int>(elems.size()));
for (unsigned i = 0; i < elems.size(); i++)
{
const PMatrixElement &e = elems[i];
@@ -2074,7 +2122,7 @@ void NeighborRowMessage::Encode(int rank)
}
Array<GroupId> all_group_ids;
all_group_ids.Reserve(rows.size());
all_group_ids.Reserve(static_cast<int>(rows.size()));
for (int i = 0; i < 3; i++)
{
all_group_ids.Append(group_ids[i]);
@@ -2833,7 +2881,7 @@ HypreParMatrix* ParFiniteElementSpace
}
// create offd column mapping
HYPRE_BigInt *cmap = Memory<HYPRE_BigInt>(col_map.size());
HYPRE_BigInt *cmap = Memory<HYPRE_BigInt>(static_cast<int>(col_map.size()));
int offd_col = 0;
for (auto it = col_map.begin(); it != col_map.end(); ++it)
{
@@ -2893,7 +2941,7 @@ HypreParMatrix* ParFiniteElementSpace
row_starts.GetData(), col_starts.GetData(),
I_diag, J_diag, A_diag,
I_offd, J_offd, A_offd,
col_map.size(), cmap);
static_cast<HYPRE_Int>(col_map.size()), cmap);
}
template <typename int_type>
@@ -3119,7 +3167,7 @@ ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
msg.dofs[i] = old_offset + dofs[i];
}
MPI_Isend(&msg.dofs[0], msg.dofs.size(), HYPRE_MPI_BIG_INT,
MPI_Isend(&msg.dofs[0], static_cast<int>(msg.dofs.size()), HYPRE_MPI_BIG_INT,
coarse_rank, 291, MyComm, &msg.request);
}
else if (coarse_rank == MyRank && fine_rank != MyRank)
@@ -3240,7 +3288,7 @@ ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
{
if (row[j] == 0.0) { continue; } // NOTE: lR thresholded
int &lcol = col_map[remote_dofs[j]];
if (!lcol) { lcol = col_map.size(); }
if (!lcol) { lcol = static_cast<int>(col_map.size()); }
offd->_Set_(m, lcol-1, row[j]);
}
mark[m] = 1;
@@ -3252,7 +3300,7 @@ ParFiniteElementSpace::ParallelDerefinementMatrix(int old_ndofs,
messages.clear();
offd->Finalize(0);
offd->SetWidth(col_map.size());
offd->SetWidth(static_cast<int>(col_map.size()));
// create offd column mapping for use by hypre
HYPRE_BigInt *cmap = Memory<HYPRE_BigInt>(offd->Width());
+9
View File
@@ -367,6 +367,15 @@ public:
Array<int> &ess_tdof_list,
int component = -1) const override;
/// Determine the external degrees of freedom
void GetExteriorVDofs(Array<int> &ext_dofs,
int component = -1) const override;
/** Get a list of external true dofs, ext_tdof_list, corresponding to the
face on the exterior of the mesh. */
void GetExteriorTrueDofs(Array<int> &ext_tdof_list,
int component = -1) const override;
/** If the given ldof is owned by the current processor, return its local
tdof number, otherwise return -1 */
int GetLocalTDofNumber(int ldof) const;
+61 -67
View File
@@ -914,19 +914,22 @@ real_t ParGridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
err_val(j) -= (exsol->Eval(*transf, eip) - (shape * el_dofs));
}
}
real_t face_error = 0.0;
transf = face_elem_transf;
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
transf->SetIntPoint(&ip);
real_t nu = jump_scaling.Eval(h, p);
error += shared_face_factor*(ip.weight * nu * ell_coeff_val(j) *
transf->Weight() *
err_val(j) * err_val(j));
face_error += shared_face_factor*(ip.weight * nu * ell_coeff_val(j) *
transf->Weight() *
err_val(j) * err_val(j));
}
// negative quadrature weights may cause the error to be negative
error += fabs(face_error);
}
error = (error < 0.0) ? -sqrt(-error) : sqrt(error);
error = sqrt(error);
return GlobalLpNorm(2.0, error, pfes->GetComm());
}
@@ -982,70 +985,65 @@ void ParGridFunction::SaveAsSerial(const char *fname, int precision,
MPI_Barrier(pmesh->GetComm());
}
GridFunction ParGridFunction::GetSerialGridFunction(int save_rank,
Mesh &serial_mesh) const
GridFunction ParGridFunction::GetSerialGridFunction(
int save_rank, FiniteElementSpace &serial_fes) const
{
ParFiniteElementSpace *pfespace = ParFESpace();
ParMesh *pmesh = pfespace->GetParMesh();
int vdim = pfespace->GetVDim();
auto *fec_serial = FiniteElementCollection::New(pfespace->FEColl()->Name());
auto *fespace_serial = new FiniteElementSpace(&serial_mesh,
fec_serial,
vdim,
pfespace->GetOrdering());
GridFunction serial_gf(&serial_fes);
GridFunction gf_serial(fespace_serial);
gf_serial.MakeOwner(fec_serial);
Array<real_t> vals;
Array<int> dofs;
MPI_Status status;
int n_send_recv;
int my_rank = pmesh->GetMyRank(),
nranks = pmesh->GetNRanks();
MPI_Comm my_comm = pmesh->GetComm();
const int vdim = pfespace->GetVDim();
int elem_count = 0; // To keep track of element count in serial mesh
const int my_rank = pmesh->GetMyRank();
const int nranks = pmesh->GetNRanks();
MPI_Comm comm = pmesh->GetComm();
if (my_rank == save_rank)
{
int elem_count = 0; // To keep track of element count in serial mesh
Vector nodeval;
for (int e = 0; e < pmesh->GetNE(); e++)
{
GetElementDofValues(e, nodeval);
fespace_serial->GetElementVDofs(elem_count++, dofs);
gf_serial.SetSubVector(dofs, nodeval);
serial_fes.GetElementVDofs(elem_count++, dofs);
serial_gf.SetSubVector(dofs, nodeval);
}
for (int p = 0; p < nranks; p++)
{
if (p == save_rank) { continue; }
MPI_Recv(&n_send_recv, 1, MPI_INT, p, 448, my_comm, &status);
int n_send_recv;
MPI_Recv(&n_send_recv, 1, MPI_INT, p, 448, comm, &status);
vals.SetSize(n_send_recv);
if (n_send_recv)
{
MPI_Recv(&vals[0], n_send_recv, MPITypeMap<real_t>::mpi_type, p, 449, my_comm,
MPI_Recv(&vals[0], n_send_recv, MPITypeMap<real_t>::mpi_type, p, 449, comm,
&status);
}
for (int i = 0; i < n_send_recv; )
{
fespace_serial->GetElementVDofs(elem_count++, dofs);
gf_serial.SetSubVector(dofs, &vals[i]);
serial_fes.GetElementVDofs(elem_count++, dofs);
serial_gf.SetSubVector(dofs, &vals[i]);
i += dofs.Size();
}
}
} // my_rank == save_rank
else
{
n_send_recv = 0;
int n_send_recv = 0;
Vector nodeval;
for (int e = 0; e < pmesh->GetNE(); e++)
{
const FiniteElement *fe = pfespace->GetFE(e);
n_send_recv += vdim*fe->GetDof();
}
MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 448, my_comm);
MPI_Send(&n_send_recv, 1, MPI_INT, save_rank, 448, comm);
vals.Reserve(n_send_recv);
vals.SetSize(0);
for (int e = 0; e < pmesh->GetNE(); e++)
@@ -1059,12 +1057,24 @@ GridFunction ParGridFunction::GetSerialGridFunction(int save_rank,
if (n_send_recv)
{
MPI_Send(&vals[0], n_send_recv, MPITypeMap<real_t>::mpi_type, save_rank, 449,
my_comm);
comm);
}
}
MPI_Barrier(my_comm);
return gf_serial;
return serial_gf;
}
GridFunction ParGridFunction::GetSerialGridFunction(int save_rank,
Mesh &serial_mesh) const
{
auto *serial_fec = pfes->FEColl()->Clone(pfes->FEColl()->GetOrder());
auto *serial_fes = new FiniteElementSpace(&serial_mesh,
serial_fec,
pfes->GetVDim(),
pfes->GetOrdering());
GridFunction serial_gf = GetSerialGridFunction(save_rank, *serial_fes);
serial_gf.MakeOwner(serial_fec); // Also assumes ownership of serial_fes
return serial_gf;
}
#ifdef MFEM_USE_ADIOS2
@@ -1226,34 +1236,22 @@ real_t GlobalLpNorm(const real_t p, real_t loc_norm, MPI_Comm comm)
{
real_t glob_norm;
// negative quadrature weights may cause the local norm to be negative
loc_norm = fabs(loc_norm);
if (p < infinity())
{
// negative quadrature weights may cause the error to be negative
if (loc_norm < 0.0)
{
loc_norm = -pow(-loc_norm, p);
}
else
{
loc_norm = pow(loc_norm, p);
}
loc_norm = pow(loc_norm, p);
MPI_Allreduce(&loc_norm, &glob_norm, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM,
comm);
MPI_Allreduce(&loc_norm, &glob_norm, 1, MPITypeMap<real_t>::mpi_type,
MPI_SUM, comm);
if (glob_norm < 0.0)
{
glob_norm = -pow(-glob_norm, 1.0/p);
}
else
{
glob_norm = pow(glob_norm, 1.0/p);
}
glob_norm = pow(fabs(glob_norm), 1.0/p);
}
else
{
MPI_Allreduce(&loc_norm, &glob_norm, 1, MPITypeMap<real_t>::mpi_type, MPI_MAX,
comm);
MPI_Allreduce(&loc_norm, &glob_norm, 1, MPITypeMap<real_t>::mpi_type,
MPI_MAX, comm);
}
return glob_norm;
@@ -1337,23 +1335,19 @@ real_t L2ZZErrorEstimator(BilinearFormIntegrator &flux_integrator,
ParLinearForm *b = new ParLinearForm(&smooth_flux_fes);
VectorGridFunctionCoefficient f(&flux);
if (xfes->GetNE())
{
MFEM_VERIFY(smooth_flux_fes.GetFE(0) != NULL,
"Could not obtain FE of smooth flux space.");
const FiniteElement *smooth_flux_fe = smooth_flux_fes.GetTypicalFE();
if (smooth_flux_fes.GetFE(0)->GetRangeType() == FiniteElement::SCALAR)
{
VectorMassIntegrator *vmass = new VectorMassIntegrator;
vmass->SetVDim(smooth_flux_fes.GetVDim());
a->AddDomainIntegrator(vmass);
b->AddDomainIntegrator(new VectorDomainLFIntegrator(f));
}
else
{
a->AddDomainIntegrator(new VectorFEMassIntegrator);
b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
}
if (smooth_flux_fe->GetRangeType() == FiniteElement::SCALAR)
{
VectorMassIntegrator *vmass = new VectorMassIntegrator;
vmass->SetVDim(smooth_flux_fes.GetVDim());
a->AddDomainIntegrator(vmass);
b->AddDomainIntegrator(new VectorDomainLFIntegrator(f));
}
else
{
a->AddDomainIntegrator(new VectorFEMassIntegrator);
b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
}
b->Assemble();

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