Compare commits

...
Author SHA1 Message Date
Stowell, Mark L 44fbd87bff Extending a unit test to include pyramids 2022-02-14 12:54:39 -08:00
Stowell, Mark L e456727573 Clean up 2022-02-01 20:14:38 -08:00
Stowell, Mark L ec8f2baeec Fixing the higher order integration rules for pyramids 2022-02-01 20:14:24 -08:00
Stowell, Mark L 47dbbf0869 Experimenting with arbitrary order H1 on pyramids 2022-01-31 17:22:19 -08:00
Tzanio Kolev bba2c08025 Merge pull request #2740 from mfem/vsx
vsx128 GNU fix [vsx]
2022-01-20 08:08:21 -08:00
Tzanio Kolev b23a3921bf Merge pull request #2743 from mfem/shadow-examples-dev
Fixing shadow variables in examples [shadow-examples-dev]
2022-01-19 09:56:40 -08:00
Will Pazner e4bcd7c58c Merge pull request #2746 from mfem/shadow-tests-dev
Fixing shadow variables in unit tests [shadow-tests-dev]
2022-01-18 15:08:30 -08:00
Veselin Dobrev 30a3c76325 Merge pull request #2771 from mfem/stopwatch-fix-comment
Fix erroneous comment in StopWatch
2022-01-18 12:12:35 -08:00
Stowell, Mark L 99e1a076ba Switching to ostream named os 2022-01-18 11:15:11 -08:00
Will Pazner 1ae61b0ada Merge remote-tracking branch 'origin/master' into shadow-tests-dev 2022-01-18 10:29:05 -08:00
Tzanio Kolev f0398ff391 Merge pull request #2732 from mfem/shadow-tmop-dev
Fixing shadowed variables in tmop files [shadow-tmop-dev]
2022-01-18 10:26:08 -08:00
Tzanio Kolev df1deca20e Merge pull request #2736 from mfem/shadow-gen-dev
Fixing shadow variables in general classes [shadow-gen-dev]
2022-01-17 17:53:37 -08:00
Tzanio Kolev d1b79a7fc3 Merge pull request #2744 from mfem/shadow-miniapps-dev
Fixing shadow variables in miniapps [shadow-miniapps-dev]
2022-01-17 17:53:00 -08:00
Tzanio Kolev 426a77be6c Merge pull request #2754 from mfem/shifted-bug-fix
Shifted bug fix
2022-01-17 17:52:17 -08:00
Will Pazner 20dced51fd Fix erroneous comment in StopWatch 2022-01-14 17:59:13 -08:00
Vladimir Z Tomov 00c4f59c76 Minor. 2022-01-13 18:47:38 -08:00
Ketan Mittal 5a6e0dad2e minor 2022-01-11 15:56:56 -08:00
Ketan Mittal 774794595b move temp_elvect->elvect outside the loop 2022-01-11 13:56:42 -08:00
camierjs cfa82dccc0 In device.?pp, use device_id for shadowed variable and switch out to os 2022-01-11 11:09:12 -08:00
camierjs 30803b8f00 Rename Memory<T>::New input arguments 2022-01-11 11:05:13 -08:00
Nabil Atallah 92112fccaa changed '=' sign to '+=' in line 644 otherwise at every integration point the values get overwritten 2022-01-05 16:24:51 -08:00
Nabil Atallah 70bd112ea4 added the sbm_aux.hpp file to the CMakeLists.txt and also added it to line 56 since the object files depend on it 2022-01-05 13:59:31 -08:00
Nabil Atallah 6ba7e82f91 Merge branch 'master' of https://github.com/mfem/mfem
Fixed a bug in the sbm_solver.cpp file of the shifted miniapp.
2022-01-05 13:38:44 -08:00
Nabil Atallah ba83609892 reset the temp_elvect vector to zero at the beginning of the loop over each integration point in sbm_solver.cpp belonging to the shifted miniapp, also fixed a typo in the comments related to the sign of the SBM penalty term 2022-01-05 11:28:49 -08:00
Stowell, Mark L 74fc2de695 Adjusting names in function declarations 2022-01-04 17:34:47 -08:00
Stowell, Mark L df6e73654a Fixing shadow variables in autodiff miniapps 2021-12-30 11:33:21 -08:00
Stowell, Mark L a07fc07206 Changes suggested by @camierjs 2021-12-30 11:04:44 -08:00
Stowell, Mark L 5e672f26bc Removing unneeded function after consulting @camierjs 2021-12-29 10:24:18 -08:00
Vladimir Z Tomov f3f37e8e5a Minor. 2021-12-28 15:19:24 -08:00
Stowell, Mark L 475d3d8102 Fixing shadow variables in unit tests 2021-12-28 11:42:51 -08:00
Veselin Dobrev 0f239c22e0 Merge pull request #2730 from mfem/ScaledOperatorFix
Fix size of ScaledOperator and add MultTranspose
2021-12-28 10:28:17 -08:00
Tzanio Kolev 783f0e0304 Merge pull request #2709 from mfem/new-compilers-warnings-fix
Fix some compiler warnings from new clang and gcc versions
2021-12-28 09:58:40 -08:00
Stowell, Mark L dd03eb6d79 Adding missing shadow vdofs 2021-12-27 14:38:20 -08:00
Stowell, Mark L 0f4bd5925a Fixing shadow variables in miniapps 2021-12-27 12:46:22 -08:00
Stowell, Mark L ca3e2b3098 make style 2021-12-27 10:42:01 -08:00
Stowell, Mark L b14bd1f237 Fixing shadow variables in examples 2021-12-27 10:41:09 -08:00
Stowell, Mark L fa25a70da6 Fixing shadow variables in general classes 2021-12-23 16:21:31 -08:00
camierjs e9b9152f59 vsx128 fix 2021-12-23 16:20:05 -08:00
Stowell, Mark L bd7527e922 Swapping leading underscores for trailing 2021-12-23 09:49:01 -08:00
Stowell, Mark L 60a1d3d1d4 Fixing shadowed variables in tmop files 2021-12-22 15:46:33 -08:00
Syun'ichi Shiraiwa 07ba5bd336 make style 2021-12-21 21:55:09 -05:00
Syun'ichi Shiraiwa 4027c86797 fix size of ScaledOperator and add MultTranspose 2021-12-21 21:52:54 -05:00
Tzanio Kolev 8300a563ae Merge pull request #2722 from mfem/pncmesh-getessvdof-fix
Fix `ParFiniteElementSpace::GetEssentialVDofs()` for non-conforming meshes
2021-12-21 08:36:14 -08:00
Tzanio Kolev 753f351934 Merge pull request #2519 from mfem/bicgstab-print-lvl-fix
Modernize print level semantics
2021-12-21 07:47:49 -08:00
Veselin Dobrev 9310e05a15 Override appropriately the SetPrintLevel methods in class KINSolver 2021-12-20 16:20:27 -08:00
termi-official 985fff881c Treat 'no convergence' as a warning. 2021-12-20 21:33:54 +01:00
termi-official 5b841fb239 Remove deprecation attribute from IterativeSolver::print_level together with all of its support code. 2021-12-20 20:53:59 +01:00
Tzanio Kolev 6f7b29ac14 Merge branch 'master' into bicgstab-print-lvl-fix 2021-12-19 17:58:19 -08:00
Tzanio Kolev 589d2775cb Merge pull request #2629 from mfem/simd-unary-plus
Add unary + to AutoSIMD
2021-12-19 12:14:36 -08:00
Tzanio Kolev 8a565cad67 Merge pull request #2677 from mfem/jacobi-abs-diag
Positive diagonal in Jacobi smoothers
2021-12-16 17:58:31 -08:00
Tzanio Kolev 5f9ee51d40 Merge pull request #2684 from mfem/tmop-renameandrefactor
TMOP clean up
2021-12-16 17:57:45 -08:00
Tzanio Kolev acb85daaff Merge pull request #2656 from mfem/lor-gridfunction-coeff
GridFunction coefficients that work with LOR preconditioning
2021-12-16 17:57:04 -08:00
Tzanio Kolev 36ec075849 Merge pull request #2702 from mfem/add-code-of-conduct
MFEM Code of Conduct
2021-12-16 14:12:31 -08:00
Veselin Dobrev 8b0262bd29 Fix an issue where some boundary dofs are not properly marked
as essential in ParFiniteElementSpace::GetEssentialVDofs() when
using a parallel non-conforming mesh.

This should address GitHub issue #2559.
2021-12-16 02:53:09 -08:00
Tzanio d9a18088a2 Updated to Contributor Covenant Code 2.1 2021-12-15 08:02:04 -08:00
Tzanio KolevandVeselin Dobrev 830ea90cf8 Update CODE_OF_CONDUCT.md
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-12-15 07:28:56 -08:00
Tzanio KolevandVeselin Dobrev 9377a43d28 Update CODE_OF_CONDUCT.md
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-12-15 07:28:51 -08:00
Tzanio KolevandVeselin Dobrev 87cd94a1fe Update CODE_OF_CONDUCT.md
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-12-15 07:28:44 -08:00
Tzanio KolevandVeselin Dobrev 1aa1e0633b Update CODE_OF_CONDUCT.md
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-12-15 07:28:36 -08:00
Tzanio KolevandVeselin Dobrev 57f3462a00 Update CODE_OF_CONDUCT.md
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-12-15 07:28:31 -08:00
Tzanio KolevandVeselin Dobrev 186f65ccc1 Update CODE_OF_CONDUCT.md
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-12-15 07:28:23 -08:00
Tzanio KolevandVeselin Dobrev 8e11743052 Update CODE_OF_CONDUCT.md
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-12-15 07:28:16 -08:00
Tzanio KolevandVeselin Dobrev 649163a36f Update CODE_OF_CONDUCT.md
Co-authored-by: Veselin Dobrev <v-dobrev@users.noreply.github.com>
2021-12-15 07:28:09 -08:00
Veselin Dobrev a58567695e Fix an error when building with HIP which may also be causing
problems with CUDA.

In OperatorJacobiSmoother, use absolute value of diagonal, if
requested, during setup instead of during action.

A few tweaks in SparseMatrix::Jacobi and SparseMatrix::DiagScale.

For the GitLab CI on Lassen, disable ATS.
2021-12-14 22:37:53 -08:00
Tzanio Kolev 53c04ef171 Update CONTRIBUTING.md 2021-12-14 21:52:00 -08:00
Veselin Dobrev 2c09747196 Fix some compiler warnings from new clang and gcc versions 2021-12-14 21:49:31 -08:00
Tzanio e9feadbbfc Small updates 2021-12-14 08:27:27 -08:00
Tzanio 81dceb94b6 Adressing comments 2021-12-13 13:21:20 -08:00
Tzanio Kolev 39022bce0f Merge pull request #2698 from mfem/nvwarnings
Remove nvcc warnings about partially overridden virtual functions [nvwarnings]
2021-12-13 13:13:38 -08:00
Tzanio 15242ffcf6 Editorial adjustments in CHANGELOG. 2021-12-13 13:08:53 -08:00
Will Pazner 9a5cafafc6 Merge remote-tracking branch 'origin/master' into simd-unary-plus 2021-12-13 11:37:29 -08:00
Will Pazner 11275857a3 Update CHANGELOG 2021-12-13 11:37:18 -08:00
Will Pazner d06a528958 Merge remote-tracking branch 'origin/master' into lor-gridfunction-coeff 2021-12-13 10:49:50 -08:00
Will Pazner f54b8bd6d8 Update CHANGELOG to mention LOR GridFunction coefficient support 2021-12-13 10:49:39 -08:00
Will Pazner 239c672988 Merge pull request #2655 from mfem/pmesh-mem-leak-fix
Fix Memory leaks in PMesh
2021-12-13 10:40:51 -08:00
Vladimir Z Tomov aabf4ce84d Fixed a wrong coefficient in the adaptive limiting. 2021-12-12 16:27:40 -08:00
Tzanio Kolev f95c2e156b Create CODE_OF_CONDUCT.md 2021-12-10 12:11:10 -08:00
camierjs 80fa63cb64 Remove nvcc warnings about partially overridden virtual functions 2021-12-08 10:46:29 -08:00
Veselin Dobrev 97796f0beb Merge branch 'master' into bicgstab-print-lvl-fix
Resolved conflict:
   CHANGELOG
2021-12-07 12:44:31 -08:00
Will Pazner c1562552f1 Make performance ex1 and ex1p templated on dimension 2021-12-02 10:17:06 -08:00
termi-official a44a8640d1 Change output behavior of warnings to mfem::out for consistency and update PrintLevel docs with the associated stream. 2021-12-01 17:24:26 +01:00
Ketan Mittal 001f1a8b79 add missing PC 3D metrics 2021-11-30 13:59:26 -08:00
Ketan Mittal 92e42d4332 fix spacing etc 2021-11-30 12:45:19 -08:00
Ketan Mittal 9c7150c93e Merge branch 'master' of https://github.com/mfem/mfem into tmop-renameandrefactor 2021-11-30 10:24:14 -08:00
Ketan Mittal 19a2ad26e1 minor 2021-11-30 10:24:12 -08:00
Veselin Dobrev 568562a7d5 Restore a comment that was deleted unintentionallly. 2021-11-26 22:14:42 -08:00
Veselin Dobrev aa8be1b59c In class IterativeSolver, silence the depracation warnings for
`print_level` in a way that works for both Clang and GCC.
2021-11-26 21:34:33 -08:00
Veselin Dobrev 85a79cbea5 Try to suppress deprecation warning with GCC from the
`IterativeSolver` constructors.
2021-11-26 20:17:19 -08:00
Veselin Dobrev 3bf7e07457 Tweak the Doxygen documentation for class IterativeSolver.
Suppress deprecation warnings only when modifying the `print_level`
data member of class `IterativeSolver`.
2021-11-26 20:05:44 -08:00
Vladimir Z Tomov c94cd73dd1 empty line. 2021-11-26 16:02:27 -08:00
Vladimir Z Tomov ff427a04a6 Minor. 2021-11-26 16:01:41 -08:00
Vladimir Z Tomov 2d10dd0abe Options to use abs values of the diagonal in OperatorJacobi, DSmoother. 2021-11-26 15:49:40 -08:00
termi-official a53353776d Update convergence criterion docs. 2021-11-26 17:08:39 +01:00
termi-official 2f1c03796a Adapt tmop print policy. 2021-11-26 16:39:06 +01:00
termi-official 199d19c195 Add documentation about warning suppression in solver. 2021-11-26 16:28:32 +01:00
Will Pazner eb6ef4a537 Minor 2021-11-24 17:47:27 -08:00
Will Pazner af7c58aa0e Minor solver output consistency fixes 2021-11-24 17:20:31 -08:00
Will Pazner d4f404cf74 Don't repeat last iteration in GMRES output 2021-11-24 10:53:53 -08:00
Will Pazner 2080fde2a1 Small changes to reduce diffs with old solver output 2021-11-24 10:44:38 -08:00
Will Pazner 7ff5874904 Typo 2021-11-21 13:30:50 -08:00
Will Pazner 757ee1a24a Merge remote-tracking branch 'origin/master' into lor-gridfunction-coeff 2021-11-20 13:13:17 -08:00
Will Pazner 861c7c4a04 Add unit tests for GridFunction coefficients on refined meshes 2021-11-20 13:13:16 -08:00
Will Pazner 60b5110031 Allow the same GridFunctionCoefficient (and related classes) to work on both coarse and refined meshes
Useful for LOR preconditioning with GridFunction coefficients. The same
Coefficient can be used on both the coarse and refined mesh.
2021-11-09 16:53:31 -08:00
Will Pazner fe08c6bd36 Add mesh data member to ElementTransformation 2021-11-09 15:55:36 -08:00
Tom Stitt 977e978ad7 fix one more leak 2021-11-09 15:50:22 -08:00
Tom Stitt db43873b7d delete face_nbr_el_to_face in ParMesh::Destroy 2021-11-09 13:43:48 -08:00
Will Pazner 40f672c230 Add unary + SIMD specializations 2021-11-02 13:33:38 -07:00
termi-official e49a744288 Apply style... 2021-11-02 18:50:49 +01:00
termi-official 388350029b Propagate first_and_last option into nonlinear iterative solvers. 2021-11-02 18:48:43 +01:00
termi-official 3c3d220460 Last MINRES iteration was sometimes missing. 2021-11-02 18:37:22 +01:00
termi-official 0279dd9787 Fix FGMRES one-by-off. 2021-11-02 18:34:29 +01:00
termi-official 46d800d05e Report correct norm in BiCGStab. 2021-11-02 18:29:20 +01:00
termi-official 4e1420f1e2 Fix GMRES final iteration report. 2021-11-02 18:29:02 +01:00
termi-official a9e93adb3f Deduplicate MINRES output. 2021-11-02 17:48:18 +01:00
termi-official 3bd47c26fd Make FGMRES output more consistent. 2021-11-02 17:21:01 +01:00
termi-official 3348ba2dbd Make BiCGStab output more consistent. 2021-11-02 17:07:46 +01:00
Ketan Mittal d8df06ab70 minor - put back accidentally removed lines 2021-11-01 10:33:07 -07:00
Ketan Mittal 5dcd85c7c7 make style 2021-11-01 09:18:20 -07:00
Ketan Mittal 047ca50acb Merge branch 'master' of https://github.com/mfem/mfem into tmop-renameandrefactor 2021-11-01 09:17:34 -07:00
Tzanio Kolev 4d1a0ac51d Update CHANGELOG 2021-10-31 14:59:55 -07:00
Tzanio c887336fa4 Updated CHANGELOG 2021-10-31 14:59:06 -07:00
Tzanio Kolev cde981b141 Merge branch 'master' into bicgstab-print-lvl-fix 2021-10-31 14:50:34 -07:00
Will Pazner 8d1780147d Add 2D compile-time option to performance/ex1[p]
Adds sample runs testing the 2D templated code to avoid regressions
2021-10-29 17:40:27 -07:00
Will Pazner f452882d29 Add unary + operator to AutoSIMD 2021-10-29 16:22:13 -07:00
Ketan Mittal 0d45eab46d initial commit with some refactoring and renaming 2021-10-20 10:38:36 -07:00
Will Pazner 15fbf80e57 Remove unneeded comment 2021-10-12 21:27:21 -07:00
Will Pazner e3450da53e Minor changes to MINRESSolver print level 2021-10-12 20:49:35 -07:00
Will Pazner 1c4b657f63 Minor changes to SLISolver printing 2021-10-12 20:37:12 -07:00
Will Pazner a19e625fc9 Delete empty comments 2021-10-12 18:10:40 -07:00
Will Pazner 37bd0ec75d Edits to IterativeSolver Doxygen comments 2021-10-12 18:03:59 -07:00
Will Pazner 020d2173c3 Minor changes to "FirstAndLast" print options 2021-10-12 11:39:54 -07:00
termi-official b889952837 Fix new macros in MSVC. 2021-09-29 16:54:26 +02:00
termi-official 8d96e40489 Make style... 2021-09-29 01:40:03 +02:00
termi-official d493efa295 Tweak docs. 2021-09-29 01:32:34 +02:00
termi-official a43de945bd Forgot a file. 2021-09-29 01:16:36 +02:00
termi-official 32a7939e4e Incorporate Will's changes. 2021-09-29 01:15:02 +02:00
termi-official 1f17768e33 Print warnings to mfem::err 2021-09-29 00:44:45 +02:00
termi-official 91f59a269c Revamp 'first and last' print option from legacy print level 3. 2021-09-29 00:41:59 +02:00
termi-official f8d501562f Exchange PrintLevel enum with struct+builder pattern. 2021-09-29 00:16:25 +02:00
termi-official b6530be3f9 Make style... 2021-09-28 21:45:51 +02:00
termi-official 3cbfee625a Add portable way to skip warnings generated by internal usage of deprecated variables. 2021-09-28 21:42:18 +02:00
Dennis Ogiermann 0ec9789849 Merge pull request #2572 from mfem/deprecate-print-level
Fix deprecation warnings for IterativeSolver::print_level
2021-09-28 18:25:50 +02:00
Will Pazner 7a20d17f90 Add pragma to ignore deprecated warnings in IterativeSolver::IterativeSolver 2021-09-27 15:47:04 -07:00
Will Pazner 317032fdbd Add bitwise or overload for PrintLevel 2021-09-27 15:34:20 -07:00
Will Pazner d6a0a5a13d Fix deprecation warnings for IterativeSolver::print_level 2021-09-27 15:21:07 -07:00
termi-official c1c39a51b5 Make style... 2021-09-27 23:40:41 +02:00
termi-official c5a7b179d8 Refactor setter/getter logic for print levels. 2021-09-27 23:36:47 +02:00
termi-official e88b99c2e2 Incorporate Will's suggestion: struct PrintOptions -> enum PrintLevel + deprecate old mechanism 2021-09-27 23:24:39 +02:00
Tzanio 793222a7e1 Merge branch 'master' into bicgstab-print-lvl-fix
Conflicts:
	CHANGELOG
2021-09-27 09:13:41 -07:00
termi-official 05bf01378c Add to changelog. 2021-09-27 18:11:53 +02:00
termi-official 71b7497037 Fix math string. 2021-09-27 17:30:49 +02:00
termi-official 5279744c6e Fix out of sync with upstream. 2021-09-27 17:04:05 +02:00
termi-official 19fae213a5 Fix some doxygen issues where no doc has been generated. 2021-09-27 16:53:42 +02:00
termi-official 0768f1940f Specify convergence docs. 2021-09-25 19:32:29 +02:00
termi-official 0c9296ab4b Propagate print_options through all solvers and unify output. 2021-09-25 19:13:40 +02:00
termi-official 7632309ed6 Fix hidden assumption taken when testing (all ranks print out if MPI is not properly initialized). 2021-09-25 17:27:54 +02:00
termi-official 439a3d773c Give recommendation and reasoning for new printing behavior. 2021-09-25 14:38:00 +02:00
termi-official ec2e958e04 Introduce PrintOptions as a new mechanism to set the reporting policy of iterative solvers + some Docs. 2021-09-25 14:28:25 +02:00
termi-official 53eb418526 Merge branch 'master' into bicgstab-print-lvl-fix 2021-09-08 15:10:26 +02:00
termi-official eea189ba98 Change BICGStabSolver print level semantics. 2021-09-08 14:55:03 +02:00
112 changed files with 2604 additions and 1219 deletions
+1 -1
View File
@@ -45,5 +45,5 @@ variables:
- echo ${MFEM_DATA_DIR}
- echo ${SPEC}
# Next script uses 'THREADS': leaving it empty --> it uses 'make all -j'
- lalloc 1 -W 30 -q pdebug tests/gitlab/build_and_test --spec "${SPEC}" --data-dir "${MFEM_DATA_DIR}" --data
- lalloc 1 -W 30 -q pdebug --atsdisable tests/gitlab/build_and_test --spec "${SPEC}" --data-dir "${MFEM_DATA_DIR}" --data
needs: [setup]
+13 -5
View File
@@ -10,10 +10,16 @@
Version 4.3.1 (development)
===========================
- Added support for automatic differentiation. Users can select between
native implementation and external library implementation at the
configuration phase. A parallel and two serial examples are implemented
in the autodiff miniapp directory.
- More explicit and consistent formating of the output of iterative solvers
with the new IterativeSolver::PrintLevel options. See linalg/solvers.hpp.
- Added support for automatic differentiation. Users can select between native
implementation and external library implementation during configuration. One
parallel and two serial examples are implemented in the miniapps/autodiff/
directory.
- GridFunctionCoefficient (and the related vector, gradient, divergence, and
curl classes) now work properly with LORDiscretization and LORSolver.
- Added support for mesh preprocessing to resolve fine scale problem data
before simulation. This feature uses adaptive mesh refinement to control the
@@ -71,13 +77,15 @@ Version 4.3.1 (development)
- Added initial TMOP-based capabilities for surface fitting and tangential
relaxation in the mesh-optimizer and pmesh-optimizer miniapps.
- Added ParMesh Adjaceny Set (adjset) creation support to the Conduit Mesh
Blueprint MFEM wrapper functions in ConduitDataCollection.
- `HypreParVector` and `Vector` now support move semantics, and the copy
constructor for `HypreParVector` now copies the local vector data.
- The HPC versions of ex1 and ex1p (in miniapps/performance) now support
runtime selection of either 2D or 3D meshes.
Version 4.3, released on July 29, 2021
======================================
+133
View File
@@ -0,0 +1,133 @@
# MFEM Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, caste, color, religion, or sexual
identity and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the overall
community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or advances of
any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email address,
without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at mfem@llnl.gov.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident. Anyone involved in the reported behavior will recuse
themselves from the investigation and decision making about the resolution of
the complaint.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series of
actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or permanent
ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within the
community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.1, available at
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
Community Impact Guidelines were inspired by
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
For answers to common questions about this code of conduct, see the FAQ at
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
[https://www.contributor-covenant.org/translations][translations].
[homepage]: https://www.contributor-covenant.org
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
[Mozilla CoC]: https://github.com/mozilla/diversity
[FAQ]: https://www.contributor-covenant.org/faq
[translations]: https://www.contributor-covenant.org/translations
+3
View File
@@ -21,6 +21,9 @@ documentation; new examples and miniapps; HPC performance improvements; etc.
MFEM is distributed under the terms of the BSD-3 license. All new contributions
must be made under this license.
Note also that MFEM has a [Code of Conduct](CODE_OF_CONDUCT.md). By participating
in the MFEM community, you agree to abide by its rules.
If you plan on contributing to MFEM, consider reviewing the
[issue tracker](https://github.com/mfem/mfem/issues) first to check if a thread
already exists for your desired feature or the bug you ran into. Use a pull
+3 -3
View File
@@ -12,6 +12,9 @@ to enable high-performance scalable finite element discretization research and
application development on a wide variety of platforms, ranging from laptops to
supercomputers.
We welcome contributions and feedback from the community. Please see the file
CONTRIBUTING.md for additional details about our development process.
* For building instructions, see the file INSTALL, or type "make help".
* Copyright and licensing information can be found in files LICENSE and NOTICE.
@@ -19,9 +22,6 @@ supercomputers.
* The best starting point for new users interested in MFEM's features is to
review the examples and miniapps at https://mfem.org/examples.
* Developers interested in contributing to the library, should read the
instructions and documentation in the CONTRIBUTING.md file.
Conceptually, MFEM can be viewed as a finite element toolbox that provides the
building blocks for developing finite element algorithms in a manner similar to
that of MATLAB for linear algebra methods. In particular, MFEM provides support
+13 -12
View File
@@ -149,7 +149,7 @@ void InitialDeformation(const Vector &x, Vector &y);
void InitialVelocity(const Vector &x, Vector &v);
void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes,
void visualize(ostream &os, Mesh *mesh, GridFunction *deformed_nodes,
GridFunction *field, const char *field_name = NULL,
bool init_vis = false);
@@ -376,10 +376,10 @@ int main(int argc, char *argv[])
}
void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes,
void visualize(ostream &os, Mesh *mesh, GridFunction *deformed_nodes,
GridFunction *field, const char *field_name, bool init_vis)
{
if (!out)
if (!os)
{
return;
}
@@ -389,24 +389,25 @@ void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes,
mesh->SwapNodes(nodes, owns_nodes);
out << "solution\n" << *mesh << *field;
os << "solution\n" << *mesh << *field;
mesh->SwapNodes(nodes, owns_nodes);
if (init_vis)
{
out << "window_size 800 800\n";
out << "window_title '" << field_name << "'\n";
os << "window_size 800 800\n";
os << "window_title '" << field_name << "'\n";
if (mesh->SpaceDimension() == 2)
{
out << "view 0 0\n"; // view from top
out << "keys jl\n"; // turn off perspective and light
os << "view 0 0\n"; // view from top
os << "keys jl\n"; // turn off perspective and light
}
out << "keys cm\n"; // show colorbar and mesh
out << "autoscale value\n"; // update value-range; keep mesh-extents fixed
out << "pause\n";
os << "keys cm\n"; // show colorbar and mesh
// update value-range; keep mesh-extents fixed
os << "autoscale value\n";
os << "pause\n";
}
out << flush;
os << flush;
}
+17 -13
View File
@@ -154,7 +154,8 @@ void InitialDeformation(const Vector &x, Vector &y);
void InitialVelocity(const Vector &x, Vector &v);
void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
void visualize(ostream &os, ParMesh *mesh,
ParGridFunction *deformed_nodes,
ParGridFunction *field, const char *field_name = NULL,
bool init_vis = false);
@@ -438,10 +439,11 @@ int main(int argc, char *argv[])
return 0;
}
void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
void visualize(ostream &os, ParMesh *mesh,
ParGridFunction *deformed_nodes,
ParGridFunction *field, const char *field_name, bool init_vis)
{
if (!out)
if (!os)
{
return;
}
@@ -451,25 +453,27 @@ void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
mesh->SwapNodes(nodes, owns_nodes);
out << "parallel " << mesh->GetNRanks() << " " << mesh->GetMyRank() << "\n";
out << "solution\n" << *mesh << *field;
os << "parallel " << mesh->GetNRanks()
<< " " << mesh->GetMyRank() << "\n";
os << "solution\n" << *mesh << *field;
mesh->SwapNodes(nodes, owns_nodes);
if (init_vis)
{
out << "window_size 800 800\n";
out << "window_title '" << field_name << "'\n";
os << "window_size 800 800\n";
os << "window_title '" << field_name << "'\n";
if (mesh->SpaceDimension() == 2)
{
out << "view 0 0\n"; // view from top
out << "keys jl\n"; // turn off perspective and light
os << "view 0 0\n"; // view from top
os << "keys jl\n"; // turn off perspective and light
}
out << "keys cm\n"; // show colorbar and mesh
out << "autoscale value\n"; // update value-range; keep mesh-extents fixed
out << "pause\n";
os << "keys cm\n"; // show colorbar and mesh
// update value-range; keep mesh-extents fixed
os << "autoscale value\n";
os << "pause\n";
}
out << flush;
os << flush;
}
+10 -10
View File
@@ -32,7 +32,7 @@ private:
mutable DenseTensor flux;
mutable Vector z;
void GetFlux(const DenseMatrix &state, DenseTensor &flux) const;
void GetFlux(const DenseMatrix &state_, DenseTensor &flux_) const;
public:
FE_Evolution(FiniteElementSpace &vfes_,
@@ -256,26 +256,26 @@ inline double ComputeMaxCharSpeed(const Vector &state, const int dim)
}
// Compute the flux at solution nodes.
void FE_Evolution::GetFlux(const DenseMatrix &x, DenseTensor &flux) const
void FE_Evolution::GetFlux(const DenseMatrix &x_, DenseTensor &flux_) const
{
const int dof = flux.SizeI();
const int dim = flux.SizeJ();
const int flux_dof = flux_.SizeI();
const int flux_dim = flux_.SizeJ();
for (int i = 0; i < dof; i++)
for (int i = 0; i < flux_dof; i++)
{
for (int k = 0; k < num_equation; k++) { state(k) = x(i, k); }
ComputeFlux(state, dim, f);
for (int k = 0; k < num_equation; k++) { state(k) = x_(i, k); }
ComputeFlux(state, flux_dim, f);
for (int d = 0; d < dim; d++)
for (int d = 0; d < flux_dim; d++)
{
for (int k = 0; k < num_equation; k++)
{
flux(i, d, k) = f(k, d);
flux_(i, d, k) = f(k, d);
}
}
// Update max char speed
const double mcs = ComputeMaxCharSpeed(state, dim);
const double mcs = ComputeMaxCharSpeed(state, flux_dim);
if (mcs > max_char_speed) { max_char_speed = mcs; }
}
}
+13 -11
View File
@@ -171,7 +171,7 @@ public:
};
// Visualization driver
void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes,
void visualize(ostream &os, Mesh *mesh, GridFunction *deformed_nodes,
GridFunction *field, const char *field_name = NULL,
bool init_vis = false);
@@ -542,10 +542,10 @@ RubberOperator::~RubberOperator()
// Inline visualization
void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes,
void visualize(ostream &os, Mesh *mesh, GridFunction *deformed_nodes,
GridFunction *field, const char *field_name, bool init_vis)
{
if (!out)
if (!os)
{
return;
}
@@ -555,23 +555,25 @@ void visualize(ostream &out, Mesh *mesh, GridFunction *deformed_nodes,
mesh->SwapNodes(nodes, owns_nodes);
out << "solution\n" << *mesh << *field;
os << "solution\n" << *mesh << *field;
mesh->SwapNodes(nodes, owns_nodes);
if (init_vis)
{
out << "window_size 800 800\n";
out << "window_title '" << field_name << "'\n";
os << "window_size 800 800\n";
os << "window_title '" << field_name << "'\n";
if (mesh->SpaceDimension() == 2)
{
out << "view 0 0\n"; // view from top
out << "keys jlA\n"; // turn off perspective and light, +anti-aliasing
os << "view 0 0\n"; // view from top
// turn off perspective and light, +anti-aliasing
os << "keys jlA\n";
}
out << "keys cmA\n"; // show colorbar and mesh, +anti-aliasing
out << "autoscale value\n"; // update value-range; keep mesh-extents fixed
os << "keys cmA\n"; // show colorbar and mesh, +anti-aliasing
// update value-range; keep mesh-extents fixed
os << "autoscale value\n";
}
out << flush;
os << flush;
}
void ReferenceConfiguration(const Vector &x, Vector &y)
+17 -12
View File
@@ -185,7 +185,8 @@ public:
};
// Visualization driver
void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
void visualize(ostream &os, ParMesh *mesh,
ParGridFunction *deformed_nodes,
ParGridFunction *field, const char *field_name = NULL,
bool init_vis = false);
@@ -617,10 +618,11 @@ RubberOperator::~RubberOperator()
// Inline visualization
void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
void visualize(ostream &os, ParMesh *mesh,
ParGridFunction *deformed_nodes,
ParGridFunction *field, const char *field_name, bool init_vis)
{
if (!out)
if (!os)
{
return;
}
@@ -630,24 +632,27 @@ void visualize(ostream &out, ParMesh *mesh, ParGridFunction *deformed_nodes,
mesh->SwapNodes(nodes, owns_nodes);
out << "parallel " << mesh->GetNRanks() << " " << mesh->GetMyRank() << "\n";
out << "solution\n" << *mesh << *field;
os << "parallel " << mesh->GetNRanks() << " " << mesh->GetMyRank() <<
"\n";
os << "solution\n" << *mesh << *field;
mesh->SwapNodes(nodes, owns_nodes);
if (init_vis)
{
out << "window_size 800 800\n";
out << "window_title '" << field_name << "'\n";
os << "window_size 800 800\n";
os << "window_title '" << field_name << "'\n";
if (mesh->SpaceDimension() == 2)
{
out << "view 0 0\n"; // view from top
out << "keys jlA\n"; // turn off perspective and light, +anti-aliasing
os << "view 0 0\n"; // view from top
// turn off perspective and light, +anti-aliasing
os << "keys jlA\n";
}
out << "keys cmA\n"; // show colorbar and mesh, +anti-aliasing
out << "autoscale value\n"; // update value-range; keep mesh-extents fixed
os << "keys cmA\n"; // show colorbar and mesh, +anti-aliasing
// update value-range; keep mesh-extents fixed
os << "autoscale value\n";
}
out << flush;
os << flush;
}
void ReferenceConfiguration(const Vector &x, Vector &y)
+19 -18
View File
@@ -75,7 +75,7 @@ Mesh * GenerateSerialMesh(int ref);
// alpha*n.Grad(sol) + beta*sol - gamma over the same boundary.
double IntegrateBC(const GridFunction &sol, const Array<int> &bdr_marker,
double alpha, double beta, double gamma,
double &err);
double &error);
int main(int argc, char *argv[])
{
@@ -302,26 +302,26 @@ int main(int argc, char *argv[])
{
// Integrate the solution on the Dirichlet boundary and compare to the
// expected value.
double err, avg = IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, err);
double error, avg = IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, error);
bool hom_dbc = (dbc_val == 0.0);
err /= hom_dbc ? 1.0 : fabs(dbc_val);
error /= hom_dbc ? 1.0 : fabs(dbc_val);
mfem::out << "Average of solution on Gamma_dbc:\t"
<< avg << ", \t"
<< (hom_dbc ? "absolute" : "relative")
<< " error " << err << endl;
<< " error " << error << endl;
}
{
// Integrate n.Grad(u) on the inhomogeneous Neumann boundary and compare
// to the expected value.
double err, avg = IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, err);
double error, avg = IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, error);
bool hom_nbc = (nbc_val == 0.0);
err /= hom_nbc ? 1.0 : fabs(nbc_val);
error /= hom_nbc ? 1.0 : fabs(nbc_val);
mfem::out << "Average of n.Grad(u) on Gamma_nbc:\t"
<< avg << ", \t"
<< (hom_nbc ? "absolute" : "relative")
<< " error " << err << endl;
<< " error " << error << endl;
}
{
// Integrate n.Grad(u) on the homogeneous Neumann boundary and compare to
@@ -330,25 +330,26 @@ int main(int argc, char *argv[])
nbc0_bdr = 0;
nbc0_bdr[3] = 1;
double err, avg = IntegrateBC(u, nbc0_bdr, 1.0, 0.0, 0.0, err);
double error, avg = IntegrateBC(u, nbc0_bdr, 1.0, 0.0, 0.0, error);
bool hom_nbc = true;
mfem::out << "Average of n.Grad(u) on Gamma_nbc0:\t"
<< avg << ", \t"
<< (hom_nbc ? "absolute" : "relative")
<< " error " << err << endl;
<< " error " << error << endl;
}
{
// Integrate n.Grad(u) + a * u on the Robin boundary and compare to the
// expected value.
double err, avg = IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val, err);
double error;
double avg = IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val, error);
bool hom_rbc = (rbc_b_val == 0.0);
err /= hom_rbc ? 1.0 : fabs(rbc_b_val);
error /= hom_rbc ? 1.0 : fabs(rbc_b_val);
mfem::out << "Average of n.Grad(u)+a*u on Gamma_rbc:\t"
<< avg << ", \t"
<< (hom_rbc ? "absolute" : "relative")
<< " error " << err << endl;
<< " error " << error << endl;
}
// 14. Save the refined mesh and the solution. This output can be viewed
@@ -637,11 +638,11 @@ Mesh * GenerateSerialMesh(int ref)
double IntegrateBC(const GridFunction &x, const Array<int> &bdr,
double alpha, double beta, double gamma,
double &err)
double &error)
{
double nrm = 0.0;
double avg = 0.0;
err = 0.0;
error = 0.0;
const bool a_is_zero = alpha == 0.0;
const bool b_is_zero = beta == 0.0;
@@ -705,20 +706,20 @@ double IntegrateBC(const GridFunction &x, const Array<int> &bdr,
// Integrate |alpha * n.Grad(x) + beta * x - gamma|^2
val -= gamma;
err += (val*val) * ip.weight * face_weight;
error += (val*val) * ip.weight * face_weight;
}
}
// Normalize by the length of the boundary
if (std::abs(nrm) > 0.0)
{
err /= nrm;
error /= nrm;
avg /= nrm;
}
// Compute l2 norm of the error in the boundary condition (negative
// quadrature weights may produce negative 'err')
err = (err >= 0.0) ? sqrt(err) : -sqrt(-err);
// quadrature weights may produce negative 'error')
error = (error >= 0.0) ? sqrt(error) : -sqrt(-error);
// Return the average value of alpha * n.Grad(x) + beta * x
return avg;
+17 -16
View File
@@ -75,7 +75,7 @@ Mesh * GenerateSerialMesh(int ref);
// alpha*n.Grad(sol) + beta*sol - gamma over the same boundary.
double IntegrateBC(const ParGridFunction &sol, const Array<int> &bdr_marker,
double alpha, double beta, double gamma,
double &err);
double &error);
int main(int argc, char *argv[])
{
@@ -321,26 +321,26 @@ int main(int argc, char *argv[])
{
// Integrate the solution on the Dirichlet boundary and compare to the
// expected value.
double err, avg = IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, err);
double error, avg = IntegrateBC(u, dbc_bdr, 0.0, 1.0, dbc_val, error);
bool hom_dbc = (dbc_val == 0.0);
err /= hom_dbc ? 1.0 : fabs(dbc_val);
error /= hom_dbc ? 1.0 : fabs(dbc_val);
mfem::out << "Average of solution on Gamma_dbc:\t"
<< avg << ", \t"
<< (hom_dbc ? "absolute" : "relative")
<< " error " << err << endl;
<< " error " << error << endl;
}
{
// Integrate n.Grad(u) on the inhomogeneous Neumann boundary and compare
// to the expected value.
double err, avg = IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, err);
double error, avg = IntegrateBC(u, nbc_bdr, 1.0, 0.0, nbc_val, error);
bool hom_nbc = (nbc_val == 0.0);
err /= hom_nbc ? 1.0 : fabs(nbc_val);
error /= hom_nbc ? 1.0 : fabs(nbc_val);
mfem::out << "Average of n.Grad(u) on Gamma_nbc:\t"
<< avg << ", \t"
<< (hom_nbc ? "absolute" : "relative")
<< " error " << err << endl;
<< " error " << error << endl;
}
{
// Integrate n.Grad(u) on the homogeneous Neumann boundary and compare to
@@ -349,25 +349,26 @@ int main(int argc, char *argv[])
nbc0_bdr = 0;
nbc0_bdr[3] = 1;
double err, avg = IntegrateBC(u, nbc0_bdr, 1.0, 0.0, 0.0, err);
double error, avg = IntegrateBC(u, nbc0_bdr, 1.0, 0.0, 0.0, error);
bool hom_nbc = true;
mfem::out << "Average of n.Grad(u) on Gamma_nbc0:\t"
<< avg << ", \t"
<< (hom_nbc ? "absolute" : "relative")
<< " error " << err << endl;
<< " error " << error << endl;
}
{
// Integrate n.Grad(u) + a * u on the Robin boundary and compare to the
// expected value.
double err, avg = IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val, err);
double error, avg = IntegrateBC(u, rbc_bdr, 1.0, rbc_a_val, rbc_b_val,
error);
bool hom_rbc = (rbc_b_val == 0.0);
err /= hom_rbc ? 1.0 : fabs(rbc_b_val);
error /= hom_rbc ? 1.0 : fabs(rbc_b_val);
mfem::out << "Average of n.Grad(u)+a*u on Gamma_rbc:\t"
<< avg << ", \t"
<< (hom_rbc ? "absolute" : "relative")
<< " error " << err << endl;
<< " error " << error << endl;
}
// 15. Save the refined mesh and the solution in parallel. This output can be
@@ -667,11 +668,11 @@ double IntegrateBC(const ParGridFunction &x, const Array<int> &bdr,
double loc_vals[3];
double &nrm = loc_vals[0];
double &avg = loc_vals[1];
double &err = loc_vals[2];
double &error = loc_vals[2];
nrm = 0.0;
avg = 0.0;
err = 0.0;
error = 0.0;
const bool a_is_zero = alpha == 0.0;
const bool b_is_zero = beta == 0.0;
@@ -735,7 +736,7 @@ double IntegrateBC(const ParGridFunction &x, const Array<int> &bdr,
// Integrate |alpha * n.Grad(x) + beta * x - gamma|^2
val -= gamma;
err += (val*val) * ip.weight * face_weight;
error += (val*val) * ip.weight * face_weight;
}
}
@@ -754,7 +755,7 @@ double IntegrateBC(const ParGridFunction &x, const Array<int> &bdr,
}
// Compute l2 norm of the error in the boundary condition (negative
// quadrature weights may produce negative 'err')
// quadrature weights may produce negative 'error')
glb_err = (glb_err >= 0.0) ? sqrt(glb_err) : -sqrt(-glb_err);
// Return the average value of alpha * n.Grad(x) + beta * x
+2 -2
View File
@@ -167,9 +167,9 @@ int main(int argc, char *argv[])
// 13. Compute error in the solution and its flux
FunctionCoefficient uCoef(uExact);
double err = x.ComputeL2Error(uCoef);
double error = x.ComputeL2Error(uCoef);
cout << "|u - u_h|_2 = " << err << endl;
cout << "|u - u_h|_2 = " << error << endl;
FiniteElementSpace flux_fespace(mesh, &fec, 3);
GridFunction flux(&flux_fespace);
+2 -2
View File
@@ -197,9 +197,9 @@ int main(int argc, char *argv[])
// 15. Compute error in the solution and its flux
FunctionCoefficient uCoef(uExact);
double err = x.ComputeL2Error(uCoef);
double error = x.ComputeL2Error(uCoef);
if (myid == 0) { cout << "|u - u_h|_2 = " << err << endl; }
if (myid == 0) { cout << "|u - u_h|_2 = " << error << endl; }
ParFiniteElementSpace flux_fespace(&pmesh, &fec, 3);
ParGridFunction flux(&flux_fespace);
+2 -2
View File
@@ -255,10 +255,10 @@ int main(int argc, char *argv[])
// 15. Compute and print the L^2 norm of the error.
{
double err = x.ComputeL2Error(E);
double error = x.ComputeL2Error(E);
if (myid == 0)
{
cout << "\n|| E_h - E ||_{L^2} = " << err << '\n' << endl;
cout << "\n|| E_h - E ||_{L^2} = " << error << '\n' << endl;
}
}
+2 -2
View File
@@ -256,10 +256,10 @@ int main(int argc, char *argv[])
// 15. Compute and print the L^2 norm of the error.
{
double err = x.ComputeL2Error(F);
double error = x.ComputeL2Error(F);
if (myid == 0)
{
cout << "\n|| F_h - F ||_{L^2} = " << err << '\n' << endl;
cout << "\n|| F_h - F ||_{L^2} = " << error << '\n' << endl;
}
}
+2 -2
View File
@@ -282,10 +282,10 @@ int main(int argc, char *argv[])
delete b;
// 12. Compute and print the L^2 norm of the error.
double err = x.ComputeL2Error(sol_coef);
double error = x.ComputeL2Error(sol_coef);
if (myid == 0)
{
cout << "\nL2 norm of error: " << err << endl;
cout << "\nL2 norm of error: " << error << endl;
}
// 13. Save the refined mesh and the solution. This output can be viewed
+98 -7
View File
@@ -21,6 +21,33 @@ namespace mfem
using namespace std;
// Given an ElementTransformation and IntegrationPoint in a refined mesh,
// return the ElementTransformation of the parent coarse element, and set
// coarse_ip to the location of the original ip within the coarse element.
ElementTransformation *RefinedToCoarse(
Mesh &coarse_mesh, const ElementTransformation &T,
const IntegrationPoint &ip, IntegrationPoint &coarse_ip)
{
Mesh &fine_mesh = *T.mesh;
// Get the element transformation of the coarse element containing the
// fine element.
int fine_element = T.ElementNo;
const CoarseFineTransformations &cf = fine_mesh.GetRefinementTransforms();
int coarse_element = cf.embeddings[fine_element].parent;
ElementTransformation *coarse_T = coarse_mesh.GetElementTransformation(
coarse_element);
// Transform the integration point from fine element coordinates to coarse
// element coordinates.
Geometry::Type geom = T.GetGeometryType();
IntegrationPointTransformation fine_to_coarse;
IsoparametricTransformation &emb_tr = fine_to_coarse.Transf;
emb_tr.SetIdentityTransformation(geom);
emb_tr.SetPointMat(cf.point_matrices[geom](cf.embeddings[fine_element].matrix));
fine_to_coarse.Transform(ip, coarse_ip);
coarse_T->SetIntPoint(&coarse_ip);
return coarse_T;
}
double PWConstCoefficient::Eval(ElementTransformation & T,
const IntegrationPoint & ip)
{
@@ -95,7 +122,17 @@ double FunctionCoefficient::Eval(ElementTransformation & T,
double GridFunctionCoefficient::Eval (ElementTransformation &T,
const IntegrationPoint &ip)
{
return GridF -> GetValue (T, ip, Component);
Mesh *gf_mesh = GridF->FESpace()->GetMesh();
if (T.mesh == gf_mesh)
{
return GridF->GetValue(T, ip, Component);
}
else
{
IntegrationPoint coarse_ip;
ElementTransformation *coarse_T = RefinedToCoarse(*gf_mesh, T, ip, coarse_ip);
return GridF->GetValue(*coarse_T, coarse_ip, Component);
}
}
void TransformedCoefficient::SetTime(double t)
@@ -305,13 +342,30 @@ void VectorGridFunctionCoefficient::SetGridFunction(const GridFunction *gf)
void VectorGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
GridFunc->GetVectorValue(T, ip, V);
Mesh *gf_mesh = GridFunc->FESpace()->GetMesh();
if (T.mesh == gf_mesh)
{
GridFunc->GetVectorValue(T, ip, V);
}
else
{
IntegrationPoint coarse_ip;
ElementTransformation *coarse_T = RefinedToCoarse(*gf_mesh, T, ip, coarse_ip);
GridFunc->GetVectorValue(*coarse_T, coarse_ip, V);
}
}
void VectorGridFunctionCoefficient::Eval(
DenseMatrix &M, ElementTransformation &T, const IntegrationRule &ir)
{
GridFunc->GetVectorValues(T, ir, M);
if (T.mesh == GridFunc->FESpace()->GetMesh())
{
GridFunc->GetVectorValues(T, ir, M);
}
else
{
VectorCoefficient::Eval(M, T, ir);
}
}
GradientGridFunctionCoefficient::GradientGridFunctionCoefficient (
@@ -331,13 +385,30 @@ void GradientGridFunctionCoefficient::SetGridFunction(const GridFunction *gf)
void GradientGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
GridFunc->GetGradient(T, V);
Mesh *gf_mesh = GridFunc->FESpace()->GetMesh();
if (T.mesh == gf_mesh)
{
GridFunc->GetGradient(T, V);
}
else
{
IntegrationPoint coarse_ip;
ElementTransformation *coarse_T = RefinedToCoarse(*gf_mesh, T, ip, coarse_ip);
GridFunc->GetGradient(*coarse_T, V);
}
}
void GradientGridFunctionCoefficient::Eval(
DenseMatrix &M, ElementTransformation &T, const IntegrationRule &ir)
{
GridFunc->GetGradients(T, ir, M);
if (T.mesh == GridFunc->FESpace()->GetMesh())
{
GridFunc->GetGradients(T, ir, M);
}
else
{
VectorCoefficient::Eval(M, T, ir);
}
}
CurlGridFunctionCoefficient::CurlGridFunctionCoefficient(
@@ -363,7 +434,17 @@ void CurlGridFunctionCoefficient::SetGridFunction(const GridFunction *gf)
void CurlGridFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
GridFunc->GetCurl(T, V);
Mesh *gf_mesh = GridFunc->FESpace()->GetMesh();
if (T.mesh == gf_mesh)
{
GridFunc->GetCurl(T, V);
}
else
{
IntegrationPoint coarse_ip;
ElementTransformation *coarse_T = RefinedToCoarse(*gf_mesh, T, ip, coarse_ip);
GridFunc->GetCurl(*coarse_T, V);
}
}
DivergenceGridFunctionCoefficient::DivergenceGridFunctionCoefficient (
@@ -375,7 +456,17 @@ DivergenceGridFunctionCoefficient::DivergenceGridFunctionCoefficient (
double DivergenceGridFunctionCoefficient::Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{
return GridFunc->GetDivergence(T);
Mesh *gf_mesh = GridFunc->FESpace()->GetMesh();
if (T.mesh == gf_mesh)
{
return GridFunc->GetDivergence(T);
}
else
{
IntegrationPoint coarse_ip;
ElementTransformation *coarse_T = RefinedToCoarse(*gf_mesh, T, ip, coarse_ip);
return GridFunc->GetDivergence(*coarse_T);
}
}
void VectorDeltaCoefficient::SetTime(double t)
+1
View File
@@ -574,6 +574,7 @@ public:
/// Evaluate the coefficient.
virtual void Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip);
using VectorCoefficient::Eval;
};
/// A general vector function coefficient
+1 -1
View File
@@ -330,7 +330,7 @@ ConduitDataCollection::BlueprintMeshToMesh(const Node &n_mesh,
}
else
{
Node &(n_bndry_conn_conv) =
Node &n_bndry_conn_conv =
n_conv["topologies"][bndry_topo_name]["elements/connectivity"];
n_bndry_conn.to_int_array(n_bndry_conn_conv);
bndry_indices = (n_bndry_conn_conv).value();
+1
View File
@@ -243,6 +243,7 @@ public:
void TransformDual(double *v) const;
void InvTransformDual(double *v) const;
using DofTransformation::InvTransformDual;
};
/// DoF transformation implementation for the Nedelec basis on tetrahedra
+2 -1
View File
@@ -21,7 +21,8 @@ ElementTransformation::ElementTransformation()
EvalState(0),
geom(Geometry::INVALID),
Attribute(-1),
ElementNo(-1)
ElementNo(-1),
mesh(nullptr)
{ }
double ElementTransformation::EvalWeight()
+6
View File
@@ -75,6 +75,12 @@ public:
int Attribute, ElementNo, ElementType;
/// The Mesh object containing the element.
/** If the element transformation belongs to a mesh, this will point to the
containing Mesh object. ElementNo will be the number of the element in
this Mesh. This will be NULL if the element does not belong to a mesh. */
class Mesh *mesh;
ElementTransformation();
/** @brief Force the reevaluation of the Jacobian in the next call. */
+51
View File
@@ -1993,6 +1993,57 @@ void Poly_1D::CalcDBinomTerms(const int p, const double x, const double y,
}
}
void Poly_1D::CalcJacobi(const int p, const double alpha, const double beta,
const double x, double *u)
{
// use the recursive definition for [-1,1]:
// 2(n+1)(n+a+b+1)(2n+a+b)P^{(a,b)}_{n+1}(z) =
// (2n+a+b+1)((2n+a+b+2)(2n+a+b)z+a^2-b^2)P^{(a,b)}_n(z)
// -2(n+a)(n+b)(2n+a+b+2)P^{(a,b)}_{n-1}(z)
u[0] = 1.;
if (p == 0) { return; }
double z = 2.*x - 1.;
u[1] = 0.5 * ((alpha + beta + 2.) * z + alpha - beta);
for (int n = 1; n < p; n++)
{
double c2 = 2.*(1. + n)*(1. + n + alpha + beta)*(2.*n + alpha + beta);
double c1 = (1. + 2.*n + alpha + beta) *
((2. + 2.*n + alpha + beta)*
(2.*n + alpha + beta)*z + pow(alpha,2) - pow(beta,2));
double c0 = 2.*(alpha + n)*(beta + n)*(2. + 2.*n + alpha + beta);
u[n+1] = (c1 * u[n] - c0 * u[n-1]) / c2;
}
}
void Poly_1D::CalcJacobi(const int p, const double alpha, const double beta,
const double x, double *u, double *d)
{
// use the recursive definition for [-1,1]:
// 2(n+1)(n+a+b+1)(2n+a+b)P^{(a,b)}_{n+1}(z) =
// (2n+a+b+1)((2n+a+b+2)(2n+a+b)z+a^2-b^2)P^{(a,b)}_n(z)
// -2(n+a)(n+b)(2n+a+b+2)P^{(a,b)}_{n-1}(z)
u[0] = 1.;
d[0] = 0.;
if (p == 0) { return; }
double z = 2.*x - 1.;
u[1] = 0.5 * ((alpha + beta + 2.) * z + alpha - beta);
d[1] = alpha + beta + 2.;
for (int n = 1; n < p; n++)
{
double c2 = 2.*(1. + n)*(1. + n + alpha + beta)*(2.*n + alpha + beta);
double c1 = (1. + 2.*n + alpha + beta) *
((2. + 2.*n + alpha + beta)*
(2.*n + alpha + beta)*z + pow(alpha,2) - pow(beta,2));
double c0 = 2.*(alpha + n)*(beta + n)*(2. + 2.*n + alpha + beta);
double dc1 = 2.*(1. + 2.*n + alpha + beta) *
(2. + 2.*n + alpha + beta)*(2.*n + alpha + beta);
u[n+1] = (c1 * u[n] - c0 * u[n-1]) / c2;
d[n+1] = (c1 * d[n] + dc1 * u[n] - c0 * d[n-1]) / c2;
}
}
void Poly_1D::CalcLegendre(const int p, const double x, double *u)
{
// use the recursive definition for [-1,1]:
+21
View File
@@ -1112,7 +1112,28 @@ public:
static void CalcBernstein(const int p, const double x, double *u, double *d)
{ CalcBinomTerms(p, x, 1. - x, u, d); }
// Evaluate the values of the Jacobi polynomials, P^{(\alpha,\beta)}_n,
// on [0,1] with degrees ranging from 0 to p and parameters alpha and beta
// at a point x. Internally the point is transformed to the traditional
// domain of [-1,1].
static void CalcJacobi(const int p, const double alpha, const double beta,
const double x, double *u);
// Evaluate the values and derivatives of the Jacobi polynomials,
// P^{(\alpha,\beta)}_n, on [0,1] with degrees ranging from 0 to p and
// parameters alpha and beta at a point x. Internally the point is
// transformed to the traditional domain of [-1,1].
static void CalcJacobi(const int p, const double alpha, const double beta,
const double x, double *u, double *d);
// Evaluate the values of the Legendre polynomials, P_n, on [0,1] with
// degrees ranging from 0 to p at a point x. Internally the point is
// transformed to the traditional domain of [-1,1].
static void CalcLegendre(const int p, const double x, double *u);
// Evaluate the values and derivatives of the Legendre polynomials, P_n,
// on [0,1] with degrees ranging from 0 to p at a point x. Internally the
// point is transformed to the traditional domain of [-1,1].
static void CalcLegendre(const int p, const double x, double *u, double *d);
~Poly_1D();
+311
View File
@@ -1040,4 +1040,315 @@ void H1_WedgeElement::CalcDShape(const IntegrationPoint &ip,
}
}
H1_PyramidElement::H1_PyramidElement(const int p, const int btype)
: NodalFiniteElement(3, Geometry::PYRAMID,
(p + 1) * (p + 2) * (2 * p + 3) / 6,
p, FunctionSpace::Qk)
{
const double *cp = poly1d.ClosedPoints(p, VerifyNodal(VerifyClosed(btype)));
const double **mcp = new const double*[p];
mcp[0] = NULL;
for (int k=1; k<p; k++)
{
mcp[k] = poly1d.ClosedPoints(k, VerifyNodal(VerifyClosed(btype)));
}
#ifndef MFEM_THREAD_SAFE
shape_x.SetSize(p + 1);
shape_y.SetSize(p + 1);
shape_z.SetSize(p + 1);
dshape_x.SetSize(p + 1);
dshape_y.SetSize(p + 1);
dshape_z.SetSize(p + 1);
ddshape_x.SetSize(p + 1);
ddshape_y.SetSize(p + 1);
ddshape_z.SetSize(p + 1);
u.SetSize(dof);
du.SetSize(dof, dim);
ddu.SetSize(dof, (dim * (dim + 1)) / 2);
#else
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1);
#endif
// vertices
Nodes.IntPoint(0).Set3(cp[0], cp[0], cp[0]);
Nodes.IntPoint(1).Set3(cp[p], cp[0], cp[0]);
Nodes.IntPoint(2).Set3(cp[p], cp[p], cp[0]);
Nodes.IntPoint(3).Set3(cp[0], cp[p], cp[0]);
Nodes.IntPoint(4).Set3(cp[0], cp[0], cp[p]);
// edges
int o = 5;
for (int i = 1; i < p; i++) // (0,1)
{
Nodes.IntPoint(o++).Set3(cp[i], cp[0], cp[0]);
}
for (int i = 1; i < p; i++) // (1,2)
{
Nodes.IntPoint(o++).Set3(cp[p], cp[i], cp[0]);
}
for (int i = 1; i < p; i++) // (3,2)
{
Nodes.IntPoint(o++).Set3(cp[i], cp[p], cp[0]);
}
for (int i = 1; i < p; i++) // (0,3)
{
Nodes.IntPoint(o++).Set3(cp[0], cp[i], cp[0]);
}
for (int i = 1; i < p; i++) // (0,4)
{
Nodes.IntPoint(o++).Set3(cp[0], cp[0], cp[i]);
}
for (int i = 1; i < p; i++) // (1,4)
{
Nodes.IntPoint(o++).Set3(cp[p-i], cp[0], cp[i]);
}
for (int i = 1; i < p; i++) // (2,4)
{
Nodes.IntPoint(o++).Set3(cp[p-i], cp[p-i], cp[i]);
}
for (int i = 1; i < p; i++) // (3,4)
{
Nodes.IntPoint(o++).Set3(cp[0], cp[p-i], cp[i]);
}
// quadrilateral face
for (int j = 1; j < p; j++)
{
for (int i = 1; i < p; i++)
{
Nodes.IntPoint(o++).Set3(cp[i], cp[j], cp[0]);
}
}
// triangular faces
for (int j = 1; j < p; j++)
for (int i = 1; i + j < p; i++) // (0,1,4)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set3(cp[i]/w, cp[0], cp[j]/w);
}
for (int j = 1; j < p; j++)
for (int i = 1; i + j < p; i++) // (1,2,4)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set3(1.0 - cp[j]/w, cp[i]/w, cp[j]/w);
}
for (int j = 1; j < p; j++)
for (int i = 1; i + j < p; i++) // (3,4,2)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set3(cp[j]/w, 1.0 - cp[i]/w, cp[i]/w);
}
for (int j = 1; j < p; j++)
for (int i = 1; i + j < p; i++) // (0,4,3)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set3(cp[0], cp[j]/w, cp[i]/w);
}
// interior
for (int k = 1; k < p - 1; k++)
{
double wk = 1.0 - cp[k];
for (int j = 1; j < p - k; j++)
{
for (int i = 1; i < p - k; i++)
{
Nodes.IntPoint(o++).Set3(mcp[p-k][i] * wk,
mcp[p-k][j] * wk,
cp[k]);
}
}
}
MFEM_ASSERT(o == dof,
"Number of nodes does not match the "
"number of degrees of freedom");
DenseMatrix T(dof);
for (int m = 0; m < dof; m++)
{
const IntegrationPoint &ip = Nodes.IntPoint(m);
double oz = 1.0 - ip.z;
double tol = 1e-6;
double x = (ip.z < 1.0) ? (ip.x / (1.0 - ip.z)) : 0.0;
double y = (ip.z < 1.0) ? (ip.y / (1.0 - ip.z)) : 0.0;
double z = ip.z;
poly1d.CalcLegendre(p, x, shape_x);
poly1d.CalcLegendre(p, y, shape_y);
o = 0;
for (int i = 0; i <= p; i++)
{
for (int j = 0; j <= p; j++)
{
int maxij = std::max(i, j);
poly1d.CalcJacobi(p - maxij, 2.0 * (maxij + 1.0), 0.0, z, shape_z);
for (int k = 0; k <= p - maxij; k++)
{
if (oz <= tol)
{
if (maxij == 0)
{
T(o++, m) = shape_z(k);
}
else
{
T(o++, m) = 0.0;
}
}
else
{
T(o++, m) = shape_x(i) * shape_y(j) * shape_z(k) *
pow(1.0 - ip.z, maxij);
}
}
}
}
}
Ti.Factor(T);
delete [] mcp;
}
void H1_PyramidElement::CalcShape(const IntegrationPoint &ip,
Vector &shape) const
{
const int p = order;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(order+1);
Vector shape_y(order+1);
Vector shape_z(order+1);
Vector u(dof);
#endif
double oz = 1.0 - ip.z;
double tol = 1e-6;
double x = (ip.z < 1.0) ? (ip.x / (1.0 - ip.z)) : 0.0;
double y = (ip.z < 1.0) ? (ip.y / (1.0 - ip.z)) : 0.0;
double z = ip.z;
poly1d.CalcLegendre(p, x, shape_x);
poly1d.CalcLegendre(p, y, shape_y);
for (int o = 0, i = 0; i <= p; i++)
{
for (int j = 0; j <= p; j++)
{
int maxij = std::max(i, j);
poly1d.CalcJacobi(p - maxij, 2.0 * (maxij + 1.0), 0.0, z, shape_z);
for (int k = 0; k <= p - maxij; k++)
{
if (oz <= tol)
{
if (maxij == 0)
{
u(o++) = shape_z(k);
}
else
{
u(o++) = 0.0;
}
}
else
{
u(o++) =
shape_x(i) * shape_y(j) * shape_z(k) * pow(1.0 - ip.z, maxij);
}
}
}
}
Ti.Mult(u, shape);
}
void H1_PyramidElement::CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const
{
const int p = order;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1);
Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1);
DenseMatrix du(dof, dim);
#endif
double oz = 1.0 - ip.z;
double tol = 1e-6;
if (oz <= tol)
{
mfem::out << "H1_PyramidElement::CalcDShape near apex" << std::endl;
}
double x = (ip.z < 1.0) ? (ip.x / (1.0 - ip.z)) : 0.0;
double y = (ip.z < 1.0) ? (ip.y / (1.0 - ip.z)) : 0.0;
double z = ip.z;
poly1d.CalcLegendre(p, x, shape_x, dshape_x);
poly1d.CalcLegendre(p, y, shape_y, dshape_y);
for (int o = 0, i = 0; i <= p; i++)
{
for (int j = 0; j <= p; j++)
{
int maxij = std::max(i, j);
poly1d.CalcJacobi(p - maxij, 2.0 * (maxij + 1.0), 0.0, z,
shape_z, dshape_z);
for (int k = 0; k <= p - maxij; k++)
{
if (oz > tol)
{
du(o, 0) = dshape_x(i) * shape_y(j) * shape_z(k) *
pow(1.0 - ip.z, maxij - 1);
du(o, 1) = shape_x(i) * dshape_y(j) * shape_z(k) *
pow(1.0 - ip.z, maxij - 1);
du(o, 2) = (ip.x * dshape_x(i) * shape_y(j) * shape_z(k) +
ip.y * shape_x(i) * dshape_y(j) * shape_z(k) -
shape_x(i) * shape_y(j) * (1.0 - ip.z) *
(shape_z(k) * maxij -
(1.0 - ip.z) * dshape_z(k))
) * pow(1.0 - ip.z, maxij - 2);
}
else
{
// The gradient is multivalued at the apex. The following
// values were produced by setting x and y equal to zero
// and computing the limit as z->1.
du(o, 0) = 0.0;
du(o, 1) = 0.0;
du(o, 2) = 0.0;
if (i == 0 && j == 0)
{
du(o, 2) = k * (k + 1) * (k + 2) * (k + 3) / 6;
}
else if (i == 0 && j == 1)
{
du(o, 1) = -(k + 1) * (k + 2) * (k + 3) * (k + 4) / 24;
}
else if (i == 1 && j == 0)
{
du(o, 0) = -(k + 1) * (k + 2) * (k + 3) * (k + 4) / 24;
}
}
o++;
}
}
}
Ti.Mult(du, dshape);
}
}
+25
View File
@@ -148,6 +148,31 @@ public:
DenseMatrix &dshape) const;
};
class H1_PyramidElement : public NodalFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
// mutable Vector shape_0, shape_1, shape_2;
// mutable Vector dshape_0_0, dshape_1_0, dshape_2_0;
// mutable Vector dshape_0_1, dshape_1_1, dshape_2_1;
// mutable Vector u;
// mutable DenseMatrix du;
mutable Vector shape_x, shape_y, shape_z;
mutable Vector dshape_x, dshape_y, dshape_z, u;
mutable Vector ddshape_x, ddshape_y, ddshape_z;
mutable DenseMatrix du, ddu;
#endif
DenseMatrixInverse Ti;
public:
H1_PyramidElement(const int p,
const int btype = BasisType::GaussLobatto);
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
};
} // namespace mfem
#endif
+3 -12
View File
@@ -1749,7 +1749,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
H1_dof[Geometry::TETRAHEDRON] = (TriDof*pm3)/3;
H1_dof[Geometry::CUBE] = QuadDof*pm1;
H1_dof[Geometry::PRISM] = TriDof*pm1;
H1_dof[Geometry::PYRAMID] = 0;
H1_dof[Geometry::PYRAMID] = pm1*pm2*(2*p-3)/6;
if (b_type == BasisType::Positive)
{
H1_Elements[Geometry::TETRAHEDRON] = new H1Pos_TetrahedronElement(p);
@@ -1763,7 +1763,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
H1_Elements[Geometry::CUBE] = new H1_HexahedronElement(p, btype);
H1_Elements[Geometry::PRISM] = new H1_WedgeElement(p, btype);
}
H1_Elements[Geometry::PYRAMID] = new LinearPyramidFiniteElement;
H1_Elements[Geometry::PYRAMID] = new H1_PyramidElement(p, btype);
const int &TetDof = H1_dof[Geometry::TETRAHEDRON];
TetDofOrd[0] = new int[24*TetDof];
@@ -1861,16 +1861,7 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
const FiniteElement *
H1_FECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
if (GeomType != Geometry::PYRAMID || this->GetOrder() == 1)
{
return H1_Elements[GeomType];
}
else
{
MFEM_ABORT("H1 Pyramid basis functions are not yet supported "
"for order > 1.");
return NULL;
}
return H1_Elements[GeomType];
}
const int *H1_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
+1 -2
View File
@@ -112,7 +112,7 @@ FmsFieldToGridFunction(FmsMesh fms_mesh, FmsField f, Mesh *mesh,
// NOTE: transplanted from the FmsMeshToMesh function
// We should do this work once and save it.
//--------------------------------------------------
FmsInt dim, n_vert, n_elem, space_dim;
FmsInt dim, n_elem, space_dim;
// Find the first component that has coordinates - that will be the new mfem
// mesh.
@@ -144,7 +144,6 @@ FmsFieldToGridFunction(FmsMesh fms_mesh, FmsField f, Mesh *mesh,
n_ents[et] += num_ents;
}
}
n_vert = n_ents[FMS_VERTEX];
//--------------------------------------------------
// Interrogate the field.
+1 -1
View File
@@ -1675,7 +1675,7 @@ IntegrationRule *IntegrationRules::PyramidIntegrationRule(int Order)
ipp.x = ipc.x * (1.0 - ipc.z);
ipp.y = ipc.y * (1.0 - ipc.z);
ipp.z = ipc.z;
ipp.weight = ipc.weight / 3.0;
ipp.weight = 4.0 * ipc.weight * pow(1.0 - ipc.z, 2);
}
return PyramidIntRules[Order];
}
+5 -7
View File
@@ -1010,12 +1010,9 @@ void ParFiniteElementSpace::GetEssentialVDofs(const Array<int> &bdr_attr_is_ess,
{
FiniteElementSpace::GetEssentialVDofs(bdr_attr_is_ess, ess_dofs, component);
if (Conforming())
{
// Make sure that processors without boundary elements mark
// their boundary dofs (if they have any).
Synchronize(ess_dofs);
}
// Make sure that processors without boundary elements mark
// their boundary dofs (if they have any).
Synchronize(ess_dofs);
}
void ParFiniteElementSpace::GetEssentialTrueDofs(const Array<int>
@@ -1041,7 +1038,8 @@ void ParFiniteElementSpace::GetEssentialTrueDofs(const Array<int>
{
if (bool(ted[i]) != bool(true_ess_dofs2[i])) { counter++; }
}
MFEM_VERIFY(counter == 0, "internal MFEM error: counter = " << counter);
MFEM_VERIFY(counter == 0, "internal MFEM error: counter = " << counter
<< ", rank = " << MyRank);
#endif
MarkerToList(true_ess_dofs, ess_tdof_list);
+4 -4
View File
@@ -65,13 +65,13 @@ static void Values2D(const int NE,
MFEM_SHARED double sm0[NBZ][MDQ*MDQ];
MFEM_SHARED double sm1[NBZ][MDQ*MDQ];
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,sB);
ConstDeviceMatrix B(sB, D1D,Q1D);
DeviceMatrix DD(sm0[tidz], MD1, MD1);
DeviceMatrix DQ(sm1[tidz], MD1, MQ1);
DeviceMatrix QQ(sm0[tidz], MQ1, MQ1);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,sB);
for (int c = 0; c < VDIM; c++)
{
kernels::internal::LoadX(e,D1D,c,x,DD);
@@ -126,14 +126,14 @@ static void Values3D(const int NE,
MFEM_SHARED double sm0[MDQ*MDQ*MDQ];
MFEM_SHARED double sm1[MDQ*MDQ*MDQ];
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,sB);
ConstDeviceMatrix B(sB, D1D,Q1D);
DeviceCube DDD(sm0, MD1,MD1,MD1);
DeviceCube DDQ(sm1, MD1,MD1,MQ1);
DeviceCube DQQ(sm0, MD1,MQ1,MQ1);
DeviceCube QQQ(sm1, MQ1,MQ1,MQ1);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,sB);
for (int c = 0; c < VDIM; c++)
{
kernels::internal::LoadX(e,D1D,c,x,DDD);
+275 -267
View File
File diff suppressed because it is too large Load Diff
+30 -27
View File
@@ -1133,7 +1133,7 @@ protected:
// Evaluation of the discrete target specification on different meshes.
// Owned.
AdaptivityEvaluator *adapt_eval;
AdaptivityEvaluator *adapt_lim_eval;
void SetDiscreteTargetBase(const GridFunction &tspec_);
void SetTspecAtIndex(int idx, const GridFunction &tspec_);
@@ -1156,7 +1156,7 @@ public:
#endif
amr_el(-1), lim_min_size(-0.1),
good_tspec(false), good_tspec_grad(false), good_tspec_hess(false),
adapt_eval(NULL) { }
adapt_lim_eval(NULL) { }
virtual ~DiscreteAdaptTC();
@@ -1232,8 +1232,8 @@ public:
void SetAdaptivityEvaluator(AdaptivityEvaluator *ae)
{
if (adapt_eval) { delete adapt_eval; }
adapt_eval = ae;
if (adapt_lim_eval) { delete adapt_lim_eval; }
adapt_lim_eval = ae;
}
const Vector &GetTspecPert1H() { return tspec_pert1h; }
@@ -1315,15 +1315,15 @@ protected:
int integ_order;
// Weight Coefficient multiplying the quality metric term.
Coefficient *coeff1; // not owned, if NULL -> coeff1 is 1.
Coefficient *metric_coeff; // not owned, if NULL -> metric_coeff is 1.
// Normalization factor for the metric term.
double metric_normal;
// Nodes and weight Coefficient used for "limiting" the TMOP_Integrator.
// These are both NULL when there is no limiting.
// The class doesn't own nodes0 and coeff0.
const GridFunction *nodes0;
Coefficient *coeff0;
// The class doesn't own lim_nodes0 and lim_coeff.
const GridFunction *lim_nodes0;
Coefficient *lim_coeff;
// Limiting reference distance. Not owned.
const GridFunction *lim_dist;
// Limiting function. Owned.
@@ -1332,20 +1332,21 @@ protected:
double lim_normal;
// Adaptive limiting.
const GridFunction *zeta_0; // Not owned.
const GridFunction *adapt_lim_gf0; // Not owned.
#ifdef MFEM_USE_MPI
const ParGridFunction *pzeta_0;
const ParGridFunction *adapt_lim_pgf0;
#endif
GridFunction *zeta; // Owned. Updated by adapt_eval.
Coefficient *coeff_zeta; // Not owned.
AdaptivityEvaluator *adapt_eval; // Not owned.
GridFunction *adapt_lim_gf; // Owned. Updated by adapt_lim_eval.
Coefficient *adapt_lim_coeff; // Not owned.
AdaptivityEvaluator *adapt_lim_eval; // Not owned.
// Surface fitting.
GridFunction *sigma, *sigma_bar; // Owned. Updated by sigma_eval.
const Array<bool> *sigma_marker; // Not owned.
Coefficient *coeff_sigma; // Not owned.
AdaptivityEvaluator *sigma_eval; // Not owned.
double sigma_normal;
GridFunction *surf_fit_gf,
*surf_fit_gf_bar; // Owned, Updated by surf_fit_eval.
const Array<bool> *surf_fit_marker; // Not owned.
Coefficient *surf_fit_coeff; // Not owned.
AdaptivityEvaluator *surf_fit_eval; // Not owned.
double surf_fit_normal;
DiscreteAdaptTC *discr_tc;
@@ -1416,7 +1417,7 @@ protected:
void ComputeNormalizationEnergies(const GridFunction &x,
double &metric_energy, double &lim_energy,
double &sigma_energy);
double &surf_fit_gf_energy);
void AssembleElementVectorExact(const FiniteElement &el,
ElementTransformation &T,
@@ -1471,7 +1472,7 @@ protected:
void DisableLimiting()
{
nodes0 = NULL; coeff0 = NULL; lim_dist = NULL;
lim_nodes0 = NULL; lim_coeff = NULL; lim_dist = NULL;
delete lim_func; lim_func = NULL;
}
@@ -1531,12 +1532,14 @@ public:
TMOP_Integrator(TMOP_QualityMetric *m, TargetConstructor *tc,
TMOP_QualityMetric *hm)
: h_metric(hm), metric(m), targetC(tc), IntegRules(NULL),
integ_order(-1), coeff1(NULL), metric_normal(1.0),
nodes0(NULL), coeff0(NULL),
integ_order(-1), metric_coeff(NULL), metric_normal(1.0),
lim_nodes0(NULL), lim_coeff(NULL),
lim_dist(NULL), lim_func(NULL), lim_normal(1.0),
zeta_0(NULL), zeta(NULL), coeff_zeta(NULL), adapt_eval(NULL),
sigma(NULL), sigma_bar(NULL), sigma_marker(NULL), coeff_sigma(NULL),
sigma_eval(NULL), sigma_normal(1.0),
adapt_lim_gf0(NULL), adapt_lim_gf(NULL), adapt_lim_coeff(NULL),
adapt_lim_eval(NULL),
surf_fit_gf(NULL), surf_fit_gf_bar(NULL), surf_fit_marker(NULL),
surf_fit_coeff(NULL),
surf_fit_eval(NULL), surf_fit_normal(1.0),
discr_tc(dynamic_cast<DiscreteAdaptTC *>(tc)),
fdflag(false), dxscale(1.0e3), fd_call_flag(false), exact_action(false)
{ PA.enabled = false; }
@@ -1564,7 +1567,7 @@ public:
Note that the Coefficient is evaluated in the physical configuration and
not in the target configuration which may be undefined. */
void SetCoefficient(Coefficient &w1) { coeff1 = &w1; }
void SetCoefficient(Coefficient &w1) { metric_coeff = &w1; }
/** @brief Limiting of the mesh displacements (general version).
@@ -1631,7 +1634,7 @@ public:
void GetSurfaceFittingErrors(double &err_avg, double &err_max);
/// Update the original/reference nodes used for limiting.
void SetLimitingNodes(const GridFunction &n0) { nodes0 = &n0; }
void SetLimitingNodes(const GridFunction &n0) { lim_nodes0 = &n0; }
/** @brief Computes the integral of W(Jacobian(Trt)) over a target zone.
@param[in] el Type of FiniteElement.
+21 -21
View File
@@ -38,13 +38,13 @@ void TMOP_Integrator::AssembleGradPA(const Vector &xe,
if (PA.dim == 2)
{
AssembleGradPA_2D(xe);
if (coeff0) { AssembleGradPA_C0_2D(xe); }
if (lim_coeff) { AssembleGradPA_C0_2D(xe); }
}
if (PA.dim == 3)
{
AssembleGradPA_3D(xe);
if (coeff0) { AssembleGradPA_C0_3D(xe); }
if (lim_coeff) { AssembleGradPA_C0_3D(xe); }
}
}
@@ -53,8 +53,8 @@ void TMOP_Integrator::AssemblePA_Limiting()
const MemoryType mt = (pa_mt == MemoryType::DEFAULT) ?
Device::GetDeviceMemoryType() : pa_mt;
// Return immediately if limiting is not enabled
if (coeff0 == nullptr) { return; }
MFEM_VERIFY(nodes0, "internal error");
if (lim_coeff == nullptr) { return; }
MFEM_VERIFY(lim_nodes0, "internal error");
MFEM_VERIFY(PA.enabled, "AssemblePA_Limiting but PA is not enabled!");
MFEM_VERIFY(lim_func, "No TMOP_LimiterFunction specification!")
@@ -68,14 +68,14 @@ void TMOP_Integrator::AssemblePA_Limiting()
const ElementDofOrdering ordering = ElementDofOrdering::LEXICOGRAPHIC;
// H0 for coeff0, (dim x dim) Q-vector
// H0 for lim_coeff, (dim x dim) Q-vector
PA.H0.UseDevice(true);
PA.H0.SetSize(PA.dim * PA.dim * PA.nq * NE, mt);
// coeff0 -> PA.C0 (Q-vector)
// lim_coeff -> PA.C0 (Q-vector)
PA.C0.UseDevice(true);
if (ConstantCoefficient* cQ =
dynamic_cast<ConstantCoefficient*>(coeff0))
dynamic_cast<ConstantCoefficient*>(lim_coeff))
{
PA.C0.SetSize(1, Device::GetMemoryType());
PA.C0.HostWrite();
@@ -90,17 +90,17 @@ void TMOP_Integrator::AssemblePA_Limiting()
ElementTransformation& T = *fes->GetElementTransformation(e);
for (int q = 0; q < ir.GetNPoints(); ++q)
{
C0(q,e) = coeff0->Eval(T, ir.IntPoint(q));
C0(q,e) = lim_coeff->Eval(T, ir.IntPoint(q));
}
}
}
// nodes0 -> PA.X0 (E-vector)
MFEM_VERIFY(nodes0->FESpace() == fes, "");
// lim_nodes0 -> PA.X0 (E-vector)
MFEM_VERIFY(lim_nodes0->FESpace() == fes, "");
const Operator *n0_R = fes->GetElementRestriction(ordering);
PA.X0.SetSize(n0_R->Height(), Device::GetMemoryType());
PA.X0.UseDevice(true);
n0_R->Mult(*nodes0, PA.X0);
n0_R->Mult(*lim_nodes0, PA.X0);
// Limiting distances: lim_dist -> PA.LD (E-vector)
// TODO: remove the hack for the case lim_dist == NULL.
@@ -217,8 +217,8 @@ void TMOP_Integrator::AssemblePA(const FiniteElementSpace &fes)
PA.Jtr_needs_update = true;
PA.Jtr_debug_grad = false;
// Limiting: coeff0 -> PA.C0, nodes0 -> PA.X0, lim_dist -> PA.LD, PA.H0
if (coeff0) { AssemblePA_Limiting(); }
// Limiting: lim_coeff -> PA.C0, lim_nodes0 -> PA.X0, lim_dist -> PA.LD, PA.H0
if (lim_coeff) { AssemblePA_Limiting(); }
}
void TMOP_Integrator::AssembleGradDiagonalPA(Vector &de) const
@@ -236,13 +236,13 @@ void TMOP_Integrator::AssembleGradDiagonalPA(Vector &de) const
if (PA.dim == 2)
{
AssembleDiagonalPA_2D(de);
if (coeff0) { AssembleDiagonalPA_C0_2D(de); }
if (lim_coeff) { AssembleDiagonalPA_C0_2D(de); }
}
if (PA.dim == 3)
{
AssembleDiagonalPA_3D(de);
if (coeff0) { AssembleDiagonalPA_C0_3D(de); }
if (lim_coeff) { AssembleDiagonalPA_C0_3D(de); }
}
}
@@ -258,13 +258,13 @@ void TMOP_Integrator::AddMultPA(const Vector &xe, Vector &ye) const
if (PA.dim == 2)
{
AddMultPA_2D(xe,ye);
if (coeff0) { AddMultPA_C0_2D(xe,ye); }
if (lim_coeff) { AddMultPA_C0_2D(xe,ye); }
}
if (PA.dim == 3)
{
AddMultPA_3D(xe,ye);
if (coeff0) { AddMultPA_C0_3D(xe,ye); }
if (lim_coeff) { AddMultPA_C0_3D(xe,ye); }
}
}
@@ -283,13 +283,13 @@ void TMOP_Integrator::AddMultGradPA(const Vector &re, Vector &ce) const
if (PA.dim == 2)
{
AddMultGradPA_2D(re,ce);
if (coeff0) { AddMultGradPA_C0_2D(re,ce); }
if (lim_coeff) { AddMultGradPA_C0_2D(re,ce); }
}
if (PA.dim == 3)
{
AddMultGradPA_3D(re,ce);
if (coeff0) { AddMultGradPA_C0_3D(re,ce); }
if (lim_coeff) { AddMultGradPA_C0_3D(re,ce); }
}
}
@@ -307,13 +307,13 @@ double TMOP_Integrator::GetLocalStateEnergyPA(const Vector &xe) const
if (PA.dim == 2)
{
energy = GetLocalStateEnergyPA_2D(xe);
if (coeff0) { energy += GetLocalStateEnergyPA_C0_2D(xe); }
if (lim_coeff) { energy += GetLocalStateEnergyPA_C0_2D(xe); }
}
if (PA.dim == 3)
{
energy = GetLocalStateEnergyPA_3D(xe);
if (coeff0) { energy += GetLocalStateEnergyPA_C0_3D(xe); }
if (lim_coeff) { energy += GetLocalStateEnergyPA_C0_3D(xe); }
}
return energy;
+3 -3
View File
@@ -181,9 +181,9 @@ template<int T_D1D, int T_Q1D, int T_MAX> return_t kernel(__VA_ARGS__)
if (K##kernel.Find(id)) { return K##kernel.At(id)(__VA_ARGS__,0,0); }\
else {\
constexpr int T_MAX = 4;\
const int D1D = (id>>4)&0xF, Q1D = id&0xF;\
MFEM_VERIFY(D1D <= MAX_D1D && Q1D <= MAX_Q1D, "Max size error!");\
return kernel<0,0,T_MAX>(__VA_ARGS__,D1D,Q1D); }
const int d1d = (id>>4)&0xF, q1d = id&0xF;\
MFEM_VERIFY(d1d <= MAX_D1D && q1d <= MAX_Q1D, "Max size error!");\
return kernel<0,0,T_MAX>(__VA_ARGS__,d1d,q1d); }
} // namespace kernels
+2 -1
View File
@@ -55,6 +55,8 @@ MFEM_REGISTER_TMOP_KERNELS(void, DatcSize,
MFEM_SHARED double sm0[MDQ*MDQ*MDQ];
MFEM_SHARED double sm1[MDQ*MDQ*MDQ];
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,sB);
ConstDeviceMatrix B(sB, D1D, Q1D);
DeviceCube DDD(sm0, MD1,MD1,MD1);
DeviceCube DDQ(sm1, MD1,MD1,MQ1);
@@ -88,7 +90,6 @@ MFEM_REGISTER_TMOP_KERNELS(void, DatcSize,
}
min = min_size[0];
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,sB);
kernels::internal::EvalX(D1D,Q1D,B,DDD,DDQ);
kernels::internal::EvalY(D1D,Q1D,B,DDQ,DQQ);
kernels::internal::EvalZ(D1D,Q1D,B,DQQ,QQQ);
+3 -3
View File
@@ -97,9 +97,9 @@ MFEM_REGISTER_TMOP_KERNELS(void, AssembleDiagonalPA_Kernel_2D,
const double *Jtr = &J(0,0,qx,qy,e);
// Jrt = Jtr^{-1}
double j[4];
ConstDeviceMatrix Jrt(j,2,2);
kernels::CalcInverse<2>(Jtr, j);
double jrt_data[4];
ConstDeviceMatrix Jrt(jrt_data,2,2);
kernels::CalcInverse<2>(Jtr, jrt_data);
const double gg = G(qy,dy) * G(qy,dy);
const double gb = G(qy,dy) * B(qy,dy);
+4 -4
View File
@@ -68,8 +68,8 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultGradPA_Kernel_C0_2D,
double Xh[2];
kernels::internal::PullEval<MQ1,NBZ>(Q1D,qx,qy,QQ,Xh);
double B[4];
DeviceMatrix H(B,2,2);
double H_data[4];
DeviceMatrix H(H_data,2,2);
for (int i = 0; i < DIM; i++)
{
for (int j = 0; j < DIM; j++)
@@ -78,9 +78,9 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultGradPA_Kernel_C0_2D,
}
}
// p2 = B . Xh
// p2 = H . Xh
double p2[2];
kernels::Mult(2,2,B,Xh,p2);
kernels::Mult(2,2,H_data,Xh,p2);
kernels::internal::PushEval<MQ1,NBZ>(Q1D,qx,qy,p2,QQ);
}
}
+4 -4
View File
@@ -70,8 +70,8 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultGradPA_Kernel_C0_3D,
double Xh[3];
kernels::internal::PullEval<MQ1>(Q1D,qx,qy,qz,QQQ,Xh);
double B[9];
DeviceMatrix H(B,3,3);
double H_data[9];
DeviceMatrix H(H_data,3,3);
for (int i = 0; i < DIM; i++)
{
for (int j = 0; j < DIM; j++)
@@ -80,9 +80,9 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultGradPA_Kernel_C0_3D,
}
}
// p2 = B . Xh
// p2 = H . Xh
double p2[3];
kernels::Mult(3,3,B,Xh,p2);
kernels::Mult(3,3,H_data,Xh,p2);
kernels::internal::PushEval<MQ1>(Q1D,qx,qy,qz,p2,QQQ);
}
}
+1 -2
View File
@@ -55,6 +55,7 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_Kernel_C0_3D,
constexpr int MDQ = (MQ1 > MD1) ? MQ1 : MD1;
MFEM_SHARED double sBLD[MQ1*MD1];
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,bld,sBLD);
ConstDeviceMatrix BLD(sBLD, D1D, Q1D);
MFEM_SHARED double sm0[MDQ*MDQ*MDQ];
@@ -66,8 +67,6 @@ MFEM_REGISTER_TMOP_KERNELS(void, SetupGradPA_Kernel_C0_3D,
kernels::internal::LoadX(e,D1D,LD,DDD);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,bld,sBLD);
kernels::internal::EvalX(D1D,Q1D,BLD,DDD,DDQ);
kernels::internal::EvalY(D1D,Q1D,BLD,DDQ,DQQ);
kernels::internal::EvalZ(D1D,Q1D,BLD,DQQ,QQQ);
+1 -1
View File
@@ -62,6 +62,7 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultPA_Kernel_C0_3D,
MFEM_SHARED double B[MQ1*MD1];
MFEM_SHARED double sBLD[MQ1*MD1];
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,bld,sBLD);
ConstDeviceMatrix BLD(sBLD, D1D, Q1D);
MFEM_SHARED double sm0[MDQ*MDQ*MDQ];
@@ -86,7 +87,6 @@ MFEM_REGISTER_TMOP_KERNELS(void, AddMultPA_Kernel_C0_3D,
kernels::internal::LoadX<MD1>(e,D1D,X1,DDD1);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,B);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,bld,sBLD);
kernels::internal::EvalX(D1D,Q1D,BLD,DDD,DDQ);
kernels::internal::EvalY(D1D,Q1D,BLD,DDQ,DQQ);
+1 -1
View File
@@ -63,6 +63,7 @@ MFEM_REGISTER_TMOP_KERNELS(double, EnergyPA_C0_3D,
MFEM_SHARED double B[MQ1*MD1];
MFEM_SHARED double sBLD[MQ1*MD1];
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,bld,sBLD);
ConstDeviceMatrix BLD(sBLD, D1D, Q1D);
MFEM_SHARED double sm0[MDQ*MDQ*MDQ];
@@ -87,7 +88,6 @@ MFEM_REGISTER_TMOP_KERNELS(double, EnergyPA_C0_3D,
kernels::internal::LoadX<MD1>(e,D1D,X1,DDD1);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,b,B);
kernels::internal::LoadB<MD1,MQ1>(D1D,Q1D,bld,sBLD);
kernels::internal::EvalX(D1D,Q1D,BLD,DDD,DDQ);
kernels::internal::EvalY(D1D,Q1D,BLD,DDQ,DQQ);
+10 -10
View File
@@ -837,26 +837,26 @@ void TMOPHRSolver::ParUpdate()
}
#endif
void TMOPHRSolver::UpdateNonlinearFormAndBC(Mesh *mesh, NonlinearForm *nlf)
void TMOPHRSolver::UpdateNonlinearFormAndBC(Mesh *mesh_, NonlinearForm *nlf_)
{
const FiniteElementSpace &fes = *mesh->GetNodalFESpace();
const FiniteElementSpace &fes = *mesh_->GetNodalFESpace();
// Update Nonlinear form and Set Essential BC
nlf->Update();
nlf_->Update();
const int dim = fes.GetFE(0)->GetDim();
if (move_bnd == false)
{
Array<int> ess_bdr(mesh->bdr_attributes.Max());
Array<int> ess_bdr(mesh_->bdr_attributes.Max());
ess_bdr = 1;
nlf->SetEssentialBC(ess_bdr);
nlf_->SetEssentialBC(ess_bdr);
}
else
{
const int nd = fes.GetBE(0)->GetDof();
int n = 0;
for (int i = 0; i < mesh->GetNBE(); i++)
for (int i = 0; i < mesh_->GetNBE(); i++)
{
const int attr = mesh->GetBdrElement(i)->GetAttribute();
const int attr = mesh_->GetBdrElement(i)->GetAttribute();
MFEM_VERIFY(!(dim == 2 && attr == 3),
"Boundary attribute 3 must be used only for 3D meshes. "
"Adjust the attributes (1/2/3/4 for fixed x/y/z/all "
@@ -866,9 +866,9 @@ void TMOPHRSolver::UpdateNonlinearFormAndBC(Mesh *mesh, NonlinearForm *nlf)
}
Array<int> ess_vdofs(n), vdofs;
n = 0;
for (int i = 0; i < mesh->GetNBE(); i++)
for (int i = 0; i < mesh_->GetNBE(); i++)
{
const int attr = mesh->GetBdrElement(i)->GetAttribute();
const int attr = mesh_->GetBdrElement(i)->GetAttribute();
fes.GetBdrElementVDofs(i, vdofs);
if (attr == 1) // Fix x components.
{
@@ -891,7 +891,7 @@ void TMOPHRSolver::UpdateNonlinearFormAndBC(Mesh *mesh, NonlinearForm *nlf)
{ ess_vdofs[n++] = vdofs[j]; }
}
}
nlf->SetEssentialVDofs(ess_vdofs);
nlf_->SetEssentialVDofs(ess_vdofs);
}
}
+16 -10
View File
@@ -444,15 +444,19 @@ double TMOPNewtonSolver::ComputeScalingFactor(const Vector &x,
if (untangling == false && min_detT_out < 0.0)
{
// No untangling, and detJ got negative -- no good.
if (print_level >= 0)
{ mfem::out << "Scale = " << scale << " Neg det(J) found.\n"; }
if (print_options.iterations)
{
mfem::out << "Scale = " << scale << " Neg det(J) found.\n";
}
scale *= detJ_factor; continue;
}
if (untangling == true && min_detT_out < *min_det_ptr)
{
// Untangling, and detJ got even more negative -- no good.
if (print_level >= 0)
{ mfem::out << "Scale = " << scale << " Neg det(J) decreased.\n"; }
if (print_options.iterations)
{
mfem::out << "Scale = " << scale << " Neg det(J) decreased.\n";
}
scale *= detJ_factor; continue;
}
@@ -477,7 +481,7 @@ double TMOPNewtonSolver::ComputeScalingFactor(const Vector &x,
if (energy_out > energy_in + 0.2*fabs(energy_in) ||
std::isnan(energy_out) != 0)
{
if (print_level >= 0)
if (print_options.iterations)
{
mfem::out << "Scale = " << scale << " Increasing energy: "
<< energy_in << " --> " << energy_out << '\n';
@@ -492,7 +496,7 @@ double TMOPNewtonSolver::ComputeScalingFactor(const Vector &x,
if (norm_out > 1.2*norm_in)
{
if (print_level >= 0)
if (print_options.iterations)
{
mfem::out << "Scale = " << scale << " Norm increased: "
<< norm_in << " --> " << norm_out << '\n';
@@ -508,13 +512,15 @@ double TMOPNewtonSolver::ComputeScalingFactor(const Vector &x,
if (min_detT_out > 0.0)
{
*min_det_ptr = 0.0;
if (print_level >= 0)
if (print_options.summary || print_options.iterations ||
print_options.first_and_last)
{ mfem::out << "The mesh has been untangled at the used points!\n"; }
}
else { *min_det_ptr = untangle_factor * min_detT_out; }
}
if (print_level >= 0)
if (print_options.summary || print_options.iterations ||
print_options.first_and_last)
{
if (untangling)
{
@@ -568,9 +574,9 @@ void TMOPNewtonSolver::ProcessNewState(const Vector &x) const
if (parallel)
{
#ifdef MFEM_USE_MPI
const ParNonlinearForm *nlf =
const ParNonlinearForm *pnlf =
dynamic_cast<const ParNonlinearForm *>(oper);
const ParFiniteElementSpace *pfesc = nlf->ParFESpace();
const ParFiniteElementSpace *pfesc = pnlf->ParFESpace();
Vector x_loc(pfesc->GetVSize());
pfesc->GetProlongationMatrix()->Mult(x, x_loc);
for (int i = 0; i < integs.Size(); i++)
+14 -14
View File
@@ -177,7 +177,7 @@ Device::~Device()
Get().device_mem_class = MemoryClass::HOST;
}
void Device::Configure(const std::string &device, const int dev)
void Device::Configure(const std::string &device, const int device_id)
{
// If a device was configured via the environment, skip the configuration,
// and avoid the 'singleton_device' to destroy the mm.
@@ -240,7 +240,7 @@ void Device::Configure(const std::string &device, const int dev)
#endif
// Perform setup.
Get().Setup(dev);
Get().Setup(device_id);
// Enable the device
Enable();
@@ -276,35 +276,35 @@ void Device::SetMemoryTypes(MemoryType h_mt, MemoryType d_mt)
// the call mm.Configure(...) in UpdateMemoryTypeAndClass()
}
void Device::Print(std::ostream &out)
void Device::Print(std::ostream &os)
{
out << "Device configuration: ";
os << "Device configuration: ";
bool add_comma = false;
for (int i = 0; i < Backend::NUM_BACKENDS; i++)
{
if (backends & internal::backend_list[i])
{
if (add_comma) { out << ','; }
if (add_comma) { os << ','; }
add_comma = true;
out << internal::backend_name[i];
os << internal::backend_name[i];
}
}
out << '\n';
os << '\n';
#ifdef MFEM_USE_CEED
if (Allows(Backend::CEED_MASK))
{
const char *ceed_backend;
CeedGetResource(internal::ceed, &ceed_backend);
out << "libCEED backend: " << ceed_backend << '\n';
os << "libCEED backend: " << ceed_backend << '\n';
}
#endif
out << "Memory configuration: "
<< MemoryTypeName[static_cast<int>(host_mem_type)];
os << "Memory configuration: "
<< MemoryTypeName[static_cast<int>(host_mem_type)];
if (Device::Allows(Backend::DEVICE_MASK))
{
out << ',' << MemoryTypeName[static_cast<int>(device_mem_type)];
os << ',' << MemoryTypeName[static_cast<int>(device_mem_type)];
}
out << std::endl;
os << std::endl;
}
void Device::UpdateMemoryTypeAndClass()
@@ -502,12 +502,12 @@ static void CeedDeviceSetup(const char* ceed_spec)
#endif
}
void Device::Setup(const int device)
void Device::Setup(const int device_id)
{
MFEM_VERIFY(ngpu == -1, "the mfem::Device is already configured!");
ngpu = 0;
dev = device;
dev = device_id;
#ifndef MFEM_USE_CUDA
MFEM_VERIFY(!Allows(Backend::CUDA_MASK),
"the CUDA backends require MFEM built with MFEM_USE_CUDA=YES");
+1 -1
View File
@@ -150,7 +150,7 @@ private:
static Device& Get() { return device_singleton; }
/// Setup switcher based on configuration settings
void Setup(const int dev = 0);
void Setup(const int device_id = 0);
void MarkBackend(Backend::Id b) { backends |= b; }
+4 -4
View File
@@ -1228,12 +1228,12 @@ Graph::reweight(uint k)
// Linearly order graph.
void
Graph::order(Functional* functional, uint iterations, uint window, uint period,
uint seed, Progress* progress)
Graph::order(Functional* functional_, uint iterations, uint window, uint period,
uint seed, Progress* progress_)
{
// Initialize graph.
this->functional = functional;
progress = this->progress = progress ? progress : new Progress;
this->functional = functional_;
progress_ = this->progress = progress_ ? progress_ : new Progress;
for (level = 0; (1u << level) < nodes(); level++);
place();
Float mincost = cost();
+5 -4
View File
@@ -849,13 +849,14 @@ inline void Memory<T>::New(int size, MemoryType mt)
}
template <typename T>
inline void Memory<T>::New(int size, MemoryType h_mt, MemoryType d_mt)
inline void Memory<T>::New(int size, MemoryType host_mt, MemoryType device_mt)
{
capacity = size;
const size_t bytes = size*sizeof(T);
this->h_mt = h_mt;
T *h_tmp = (h_mt == MemoryType::HOST) ? NewHOST(size) : nullptr;
h_ptr = (T*)MemoryManager::New_(h_tmp, bytes, h_mt, d_mt, VALID_HOST, flags);
this->h_mt = host_mt;
T *h_tmp = (host_mt == MemoryType::HOST) ? NewHOST(size) : nullptr;
h_ptr = (T*)MemoryManager::New_(h_tmp, bytes, host_mt, device_mt,
VALID_HOST, flags);
}
template <typename T>
+1 -1
View File
@@ -42,7 +42,7 @@ public:
/// Clear the elapsed time on the stopwatch and restart it if it's running.
void Clear();
/// Clear the elapsed time and start the stopwatch.
/// Start the stopwatch. The elapsed time is @b not cleared.
void Start();
/// Stop the stopwatch.
+3 -3
View File
@@ -327,7 +327,7 @@ void EliminationSolver::Mult(const Vector& rhs, Vector& sol) const
krylov->SetMaxIter(max_iter);
krylov->SetRelTol(rel_tol);
krylov->SetAbsTol(abs_tol);
krylov->SetPrintLevel(print_level);
krylov->SetPrintLevel(print_options);
Vector rtilde(rhs.Size());
if (constraint_rhs.Size() > 0)
@@ -447,7 +447,7 @@ void PenaltyConstrainedSolver::Mult(const Vector& b, Vector& x) const
krylov->SetRelTol(rel_tol);
krylov->SetAbsTol(abs_tol);
krylov->SetMaxIter(max_iter);
krylov->SetPrintLevel(print_level);
krylov->SetPrintLevel(print_options);
krylov->Mult(penalized_rhs, x);
final_iter = krylov->GetNumIterations();
final_norm = krylov->GetFinalNorm();
@@ -574,7 +574,7 @@ void SchurConstrainedSolver::LagrangeSystemMult(const Vector& x,
gmres->SetRelTol(rel_tol);
gmres->SetAbsTol(abs_tol);
gmres->SetMaxIter(max_iter);
gmres->SetPrintLevel(print_level);
gmres->SetPrintLevel(print_options);
gmres->SetPreconditioner(
const_cast<BlockDiagonalPreconditioner&>(*block_pc));
+5 -1
View File
@@ -701,11 +701,15 @@ private:
public:
/// Create an operator which is a scalar multiple of A.
explicit ScaledOperator(const Operator *A, double a)
: Operator(A->Width(), A->Height()), A_(*A), a_(a) { }
: Operator(A->Height(), A->Width()), A_(*A), a_(a) { }
/// Operator application
virtual void Mult(const Vector &x, Vector &y) const
{ A_.Mult(x, y); y *= a_; }
/// Application of the transpose.
virtual void MultTranspose(const Vector &x, Vector &y) const
{ A_.MultTranspose(x, y); y *= a_; }
};
+9
View File
@@ -29,6 +29,10 @@ struct MFEM_AUTOSIMD_ALIGN__ AutoSIMD
scalar_t vec[size];
AutoSIMD() = default;
AutoSIMD(const AutoSIMD &) = default;
inline MFEM_ALWAYS_INLINE scalar_t &operator[](int i)
{
return vec[i];
@@ -117,6 +121,11 @@ struct MFEM_AUTOSIMD_ALIGN__ AutoSIMD
return r;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+() const
{
return *this;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+(const AutoSIMD &v) const
{
AutoSIMD r;
+9 -1
View File
@@ -38,6 +38,10 @@ template <> struct AutoSIMD<double,2,16>
double vec[size];
};
AutoSIMD() = default;
AutoSIMD(const AutoSIMD &) = default;
inline MFEM_ALWAYS_INLINE double &operator[](int i)
{
return vec[i];
@@ -115,6 +119,11 @@ template <> struct AutoSIMD<double,2,16>
return r;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+() const
{
return *this;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+(const AutoSIMD &v) const
{
AutoSIMD r;
@@ -251,4 +260,3 @@ AutoSIMD<double,2,16> operator/(const double &e,
#endif // __SSE2__
#endif // MFEM_SIMD_M128_HPP
+9
View File
@@ -38,6 +38,10 @@ template <> struct AutoSIMD<double,4,32>
double vec[size];
};
AutoSIMD() = default;
AutoSIMD(const AutoSIMD &) = default;
inline MFEM_ALWAYS_INLINE double &operator[](int i)
{
return vec[i];
@@ -115,6 +119,11 @@ template <> struct AutoSIMD<double,4,32>
return r;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+() const
{
return *this;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+(const AutoSIMD &v) const
{
AutoSIMD r;
+9
View File
@@ -39,6 +39,10 @@ template <> struct AutoSIMD<double,8,64>
double vec[size];
};
AutoSIMD() = default;
AutoSIMD(const AutoSIMD &) = default;
inline MFEM_ALWAYS_INLINE double &operator[](int i)
{
return vec[i];
@@ -120,6 +124,11 @@ template <> struct AutoSIMD<double,8,64>
return r;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+() const
{
return *this;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+(const AutoSIMD &v) const
{
AutoSIMD r;
+9
View File
@@ -34,6 +34,10 @@ template <> struct AutoSIMD<double,4,32>
double vec[size];
};
AutoSIMD() = default;
AutoSIMD(const AutoSIMD &) = default;
inline __ATTRS_ai double &operator[](int i) { return vec[i]; }
inline __ATTRS_ai const double &operator[](int i) const { return vec[i]; }
@@ -105,6 +109,11 @@ template <> struct AutoSIMD<double,4,32>
return r;
}
inline __ATTRS_ai AutoSIMD operator+() const
{
return *this;
}
inline __ATTRS_ai AutoSIMD operator+(const AutoSIMD &v) const
{
AutoSIMD r;
+9
View File
@@ -33,6 +33,10 @@ template <> struct MFEM_AUTOSIMD_ALIGN_SVE AutoSIMD<double,8,64>
double vec[size];
AutoSIMD() = default;
AutoSIMD(const AutoSIMD &) = default;
inline MFEM_ALWAYS_INLINE double &operator[](int i)
{
return vec[i];
@@ -123,6 +127,11 @@ template <> struct MFEM_AUTOSIMD_ALIGN_SVE AutoSIMD<double,8,64>
return r;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+() const
{
return *this;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+(const AutoSIMD &v) const
{
AutoSIMD r;
+17
View File
@@ -17,6 +17,10 @@
#include "../../config/tconfig.hpp"
#include <altivec.h>
#ifdef __GNUC__
#undef bool
#endif
namespace mfem
{
@@ -34,6 +38,10 @@ template <> struct AutoSIMD<double,2,16>
double vec[size];
};
AutoSIMD() = default;
AutoSIMD(const AutoSIMD &) = default;
inline MFEM_ALWAYS_INLINE double &operator[](int i)
{
return vec[i];
@@ -107,10 +115,19 @@ template <> struct AutoSIMD<double,2,16>
inline MFEM_ALWAYS_INLINE AutoSIMD operator-() const
{
AutoSIMD r;
#ifndef __GNUC__
r.vd = vec_neg(vd);
#else
r.vd = vec_splats(0.0) - vd;
#endif
return r;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+() const
{
return *this;
}
inline MFEM_ALWAYS_INLINE AutoSIMD operator+(const AutoSIMD &v) const
{
AutoSIMD r;
+370 -181
View File
File diff suppressed because it is too large Load Diff
+158 -9
View File
@@ -56,7 +56,7 @@ public:
{
}
/** @brief This method is invoked by ItertiveSolver::SetMonitor, informing
/** @brief This method is invoked by IterativeSolver::SetMonitor, informing
the monitor which IterativeSolver is using it. */
void SetIterativeSolver(const IterativeSolver &solver)
{ iter_solver = &solver; }
@@ -65,10 +65,55 @@ public:
/// Abstract base class for iterative solver
class IterativeSolver : public Solver
{
public:
/** @brief Settings for the output behavior of the IterativeSolver.
By default, all output is suppressed. The construction of the desired
print level can be achieved through a builder pattern, for example
PrintLevel().Errors().Warnings()
constructs the print level with only errors and warnings enabled.
*/
struct PrintLevel
{
/** @brief If a fatal problem has been detected the failure will be
reported to @ref mfem::err. */
bool errors = false;
/** @brief If a non-fatal problem has been detected some context-specific
information will be reported to @ref mfem::out */
bool warnings = false;
/** @brief Detailed information about each iteration will be reported to
@ref mfem::out */
bool iterations = false;
/** @brief A summary of the solver process will be reported after the last
iteration to @ref mfem::out */
bool summary = false;
/** @brief Information about the first and last iteration will be printed
to @ref mfem::out */
bool first_and_last = false;
/// Initializes the print level to suppress
PrintLevel() = default;
/** @name Builder
These methods are utilized to construct PrintLevel objects through a
builder approach by chaining the function calls in this group. */
///@{
PrintLevel &None() { *this = PrintLevel(); return *this; }
PrintLevel &Warnings() { warnings=true; return *this; }
PrintLevel &Errors() { errors=true; return *this; }
PrintLevel &Iterations() { iterations=true; return *this; }
PrintLevel &FirstAndLast() { first_and_last=true; return *this; }
PrintLevel &Summary() { summary=true; return *this; }
PrintLevel &All() { return Warnings().Errors().Iterations().FirstAndLast().Summary(); }
///@}
};
#ifdef MFEM_USE_MPI
private:
int dot_prod_type; // 0 - local, 1 - global over 'comm'
MPI_Comm comm;
MPI_Comm comm = MPI_COMM_NULL;
#endif
protected:
@@ -76,13 +121,52 @@ protected:
Solver *prec;
IterativeSolverMonitor *monitor = nullptr;
int max_iter, print_level;
double rel_tol, abs_tol;
/// @name Reporting (protected attributes and member functions)
///@{
// stats
mutable int final_iter, converged;
/** @brief (DEPRECATED) Legacy print level definition, which is left for
compatibility with custom iterative solvers.
@deprecated #print_options should be used instead. */
int print_level = -1;
/** @brief Output behavior for the iterative solver.
This primarily controls the output behavior of the iterative solvers
provided by this library. This member must be synchronized with
#print_level to ensure compatibility with custom iterative solvers. */
PrintLevel print_options;
/// Convert a legacy print level integer to a PrintLevel object
PrintLevel FromLegacyPrintLevel(int);
/// @brief Use some heuristics to guess a legacy print level corresponding to
/// the given PrintLevel.
static int GuessLegacyPrintLevel(PrintLevel);
///@}
/// @name Convergence (protected attributes)
///@{
/// Limit for the number of iterations the solver is allowed to do
int max_iter;
/// Relative tolerance.
double rel_tol;
/// Absolute tolerance.
double abs_tol;
///@}
/// @name Solver statistics (protected attributes)
///@{
mutable int final_iter;
mutable bool converged;
mutable double final_norm;
///@}
double Dot(const Vector &x, const Vector &y) const;
double Norm(const Vector &x) const { return sqrt(Dot(x, x)); }
void Monitor(int it, double norm, const Vector& r, const Vector& x,
@@ -95,20 +179,80 @@ public:
IterativeSolver(MPI_Comm comm_);
#endif
/** @name Convergence
@brief Termination criteria for the iterative solvers.
@details While the convergence criterion is solver specific, most of the
provided iterative solvers use one of the following criteria
\f$ ||r||_X \leq tol_{rel}||r_0||_X \f$,
\f$ ||r||_X \leq tol_{abs} \f$,
\f$ ||r||_X \leq \max\{ tol_{abs}, tol_{rel} ||r_0||_X \} \f$,
where X denotes the space in which the norm is measured. The choice of
X depends on the specific iterative solver.
*/
///@{
void SetRelTol(double rtol) { rel_tol = rtol; }
void SetAbsTol(double atol) { abs_tol = atol; }
void SetMaxIter(int max_it) { max_iter = max_it; }
void SetPrintLevel(int print_lvl);
///@}
/** @name Reporting
These options control the internal reporting behavior into ::mfem::out
and ::mfem::err of the iterative solvers.
*/
///@{
/// @brief Legacy method to set the level of verbosity of the solver output.
/** This is the old way to control what information will be printed to
::mfem::out and ::mfem::err. The behavior for the print level for all
iterative solvers is:
- -1: Suppress all outputs.
- 0: Print information about all detected issues (e.g. no convergence).
- 1: Same as level 0, but with detailed information about each
iteration.
- 2: Print detected issues and a summary when the solver terminates.
- 3: Same as 2, but print also the first and last iterations.
- >3: Custom print options which are dependent on the specific solver.
In parallel, only rank 0 produces output.
@note It is recommended to use @ref SetPrintLevel(PrintLevel) instead.
@note Some derived classes, like KINSolver, redefine this method and use
their own set of print level constants. */
virtual void SetPrintLevel(int print_lvl);
/// @brief Set the level of verbosity of the solver output.
/** In parallel, only rank 0 produces outputs. Errors are output to
::mfem::err and all other information to ::mfem::out.
@note Not all subclasses of IterativeSolver support all possible options.
@note Some derived classes, like KINSolver, disable this method in favor
of SetPrintLevel(int).
@sa PrintLevel for possible options.
*/
virtual void SetPrintLevel(PrintLevel);
///@}
/// @name Solver statistics
///@{
int GetNumIterations() const { return final_iter; }
int GetConverged() const { return converged; }
bool GetConverged() const { return converged; }
double GetFinalNorm() const { return final_norm; }
///@}
/// This should be called before SetOperator
virtual void SetPreconditioner(Solver &pr);
/// Also calls SetOperator for the preconditioner if there is one
virtual void SetOperator(const Operator &op);
virtual void SetOperator(const Operator &op) override;
/// Set the iterative solver monitor
void SetMonitor(IterativeSolverMonitor &m)
@@ -163,6 +307,9 @@ public:
~OperatorJacobiSmoother() {}
/// Replace diagonal entries with their absolute values.
void SetPositiveDiagonal(bool pos_diag = true) { use_abs_diag = pos_diag; }
void Mult(const Vector &x, Vector &y) const;
void MultTranspose(const Vector &x, Vector &y) const { Mult(x, y); }
@@ -184,6 +331,8 @@ private:
const double damping;
const Array<int> *ess_tdof_list; // not owned; may be NULL
mutable Vector residual;
/// Uses absolute values of the diagonal entries.
bool use_abs_diag = false;
const Operator *oper; // not owned
+8 -5
View File
@@ -2382,7 +2382,7 @@ double SparseMatrix::GetJacobiScaling() const
}
void SparseMatrix::Jacobi(const Vector &b, const Vector &x0, Vector &x1,
double sc) const
double sc, bool use_abs_diag) const
{
MFEM_VERIFY(Finalized(), "Matrix must be finalized.");
@@ -2403,7 +2403,8 @@ void SparseMatrix::Jacobi(const Vector &b, const Vector &x0, Vector &x1,
}
if (d >= 0 && A[d] != 0.0)
{
x1(i) = sc * (sum / A[d]) + (1.0 - sc) * x0(i);
const double diag = (use_abs_diag) ? fabs(A[d]) : A[d];
x1(i) = sc * (sum / diag) + (1.0 - sc) * x0(i);
}
else
{
@@ -2412,7 +2413,8 @@ void SparseMatrix::Jacobi(const Vector &b, const Vector &x0, Vector &x1,
}
}
void SparseMatrix::DiagScale(const Vector &b, Vector &x, double sc) const
void SparseMatrix::DiagScale(const Vector &b, Vector &x,
double sc, bool use_abs_diag) const
{
MFEM_VERIFY(Finalized(), "Matrix must be finalized.");
@@ -2438,11 +2440,12 @@ void SparseMatrix::DiagScale(const Vector &b, Vector &x, double sc) const
}
if (Jp[j] == i)
{
if (!(std::abs(Ap[j]) > 0.0))
const double diag = (use_abs_diag) ? fabs(Ap[j]) : Ap[j];
if (diag == 0.0)
{
MFEM_ABORT_KERNEL("Zero diagonal in SparseMatrix::DiagScale");
}
xp[i] = sc * bp[i] / Ap[j];
xp[i] = sc * bp[i] / diag;
break;
}
}
+7 -3
View File
@@ -446,10 +446,14 @@ public:
/// Determine appropriate scaling for Jacobi iteration
double GetJacobiScaling() const;
/** One scaled Jacobi iteration for the system A x = b.
x1 = x0 + sc D^{-1} (b - A x0) where D is the diag of A. */
void Jacobi(const Vector &b, const Vector &x0, Vector &x1, double sc) const;
x1 = x0 + sc D^{-1} (b - A x0) where D is the diag of A.
Absolute values of D are used when use_abs_diag = true. */
void Jacobi(const Vector &b, const Vector &x0, Vector &x1,
double sc, bool use_abs_diag = false) const;
void DiagScale(const Vector &b, Vector &x, double sc = 1.0) const;
/// x = sc b / A_ii. When use_abs_diag = true, |A_ii| is used.
void DiagScale(const Vector &b, Vector &x,
double sc = 1.0, bool use_abs_diag = false) const;
/** x1 = x0 + sc D^{-1} (b - A x0) where \f$ D_{ii} = \sum_j |A_{ij}| \f$. */
void Jacobi2(const Vector &b, const Vector &x0, Vector &x1,
+2 -2
View File
@@ -65,7 +65,7 @@ void DSmoother::Mult(const Vector &x, Vector &y) const
{
if (!iterative_mode && type == 0 && iterations == 1)
{
oper->DiagScale(x, y, scale);
oper->DiagScale(x, y, scale, use_abs_diag);
return;
}
@@ -90,7 +90,7 @@ void DSmoother::Mult(const Vector &x, Vector &y) const
{
if (type == 0)
{
oper->Jacobi(x, *p, *r, scale);
oper->Jacobi(x, *p, *r, scale, use_abs_diag);
}
else if (type == 1)
{
+5
View File
@@ -58,6 +58,8 @@ protected:
int type; // 0, 1, 2 - scaled Jacobi, scaled l1-Jacobi, scaled lumped-Jacobi
double scale;
int iterations;
/// Uses abs values of the diagonal entries. Relevant only when type = 0.
bool use_abs_diag = false;
mutable Vector z;
@@ -69,6 +71,9 @@ public:
/// Create Jacobi smoother.
DSmoother(const SparseMatrix &a, int t = 0, double s = 1., int it = 1);
/// Replace diag entries with their abs values. Relevant only when type = 0.
void SetPositiveDiagonal(bool pos_diag = true) { use_abs_diag = pos_diag; }
/// Matrix vector multiplication with Jacobi smoother.
virtual void Mult(const Vector &x, Vector &y) const;
};
+5
View File
@@ -1976,6 +1976,11 @@ void KINSolver::SetMAA(int m_aa)
}
}
void KINSolver::SetPrintLevel(PrintLevel)
{
MFEM_ABORT("this method is not supported! Use SetPrintLevel(int) instead.");
}
// Compute the scaling vectors and solve nonlinear system
void KINSolver::Mult(const Vector&, Vector &x) const
{
+6
View File
@@ -833,6 +833,12 @@ public:
/** @note Only valid in combination with JFNK */
void SetLSMaxRestarts(int m) { maxlrs = m; }
/// Set the print level for the KINSetPrintLevel function.
virtual void SetPrintLevel(int print_lvl) { print_level = print_lvl; }
/// This method is not supported and will throw an error.
virtual void SetPrintLevel(PrintLevel);
/// Solve the nonlinear system \f$ F(x) = 0 \f$.
/** This method computes the x_scale and fx_scale vectors and calls the
other Mult(Vector&, Vector&, Vector&) const method. The x_scale vector
+8
View File
@@ -350,6 +350,7 @@ void Mesh::GetElementTransformation(int i, IsoparametricTransformation *ElTr)
ElTr->Attribute = GetAttribute(i);
ElTr->ElementNo = i;
ElTr->ElementType = ElementTransformation::ELEMENT;
ElTr->mesh = this;
ElTr->Reset();
if (Nodes == NULL)
{
@@ -382,6 +383,7 @@ void Mesh::GetElementTransformation(int i, const Vector &nodes,
ElTr->Attribute = GetAttribute(i);
ElTr->ElementNo = i;
ElTr->ElementType = ElementTransformation::ELEMENT;
ElTr->mesh = this;
DenseMatrix &pm = ElTr->GetPointMat();
ElTr->Reset();
nodes.HostRead();
@@ -437,6 +439,7 @@ void Mesh::GetBdrElementTransformation(int i, IsoparametricTransformation* ElTr)
ElTr->Attribute = GetBdrAttribute(i);
ElTr->ElementNo = i; // boundary element number
ElTr->ElementType = ElementTransformation::BDR_ELEMENT;
ElTr->mesh = this;
DenseMatrix &pm = ElTr->GetPointMat();
ElTr->Reset();
if (Nodes == NULL)
@@ -481,6 +484,7 @@ void Mesh::GetBdrElementTransformation(int i, IsoparametricTransformation* ElTr)
"Mesh requires nodal Finite Element.");
IntegrationRule eir(face_el->GetDof());
FaceElemTr.Loc1.Transf.ElementNo = elem_id;
FaceElemTr.Loc1.Transf.mesh = this;
FaceElemTr.Loc1.Transf.ElementType = ElementTransformation::ELEMENT;
FaceElemTr.Loc1.Transform(face_el->GetNodes(), eir);
Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
@@ -495,6 +499,7 @@ void Mesh::GetFaceTransformation(int FaceNo, IsoparametricTransformation *FTr)
FTr->Attribute = (Dim == 1) ? 1 : faces[FaceNo]->GetAttribute();
FTr->ElementNo = FaceNo;
FTr->ElementType = ElementTransformation::FACE;
FTr->mesh = this;
DenseMatrix &pm = FTr->GetPointMat();
FTr->Reset();
if (Nodes == NULL)
@@ -551,6 +556,7 @@ void Mesh::GetFaceTransformation(int FaceNo, IsoparametricTransformation *FTr)
IntegrationRule eir(face_el->GetDof());
FaceElemTr.Loc1.Transf.ElementNo = face_info.Elem1No;
FaceElemTr.Loc1.Transf.ElementType = ElementTransformation::ELEMENT;
FaceElemTr.Loc1.Transf.mesh = this;
FaceElemTr.Loc1.Transform(face_el->GetNodes(), eir);
Nodes->GetVectorValues(FaceElemTr.Loc1.Transf, eir, pm);
@@ -580,6 +586,7 @@ void Mesh::GetEdgeTransformation(int EdgeNo, IsoparametricTransformation *EdTr)
EdTr->Attribute = 1;
EdTr->ElementNo = EdgeNo;
EdTr->ElementType = ElementTransformation::EDGE;
EdTr->mesh = this;
DenseMatrix &pm = EdTr->GetPointMat();
EdTr->Reset();
if (Nodes == NULL)
@@ -1098,6 +1105,7 @@ FaceElementTransformations *Mesh::GetBdrFaceTransformations(int BdrElemNo)
tr->Attribute = boundary[BdrElemNo]->GetAttribute();
tr->ElementNo = BdrElemNo;
tr->ElementType = ElementTransformation::BDR_FACE;
tr->mesh = this;
return tr;
}
+2
View File
@@ -737,6 +737,8 @@ protected: // implementation
Point() { dim = 0; }
Point(const Point &) = default;
Point(double x)
{ dim = 1; coord[0] = x; }
+5
View File
@@ -1890,6 +1890,7 @@ void ParMesh::GetFaceNbrElementTransformation(
ElTr->Attribute = elem->GetAttribute();
ElTr->ElementNo = NumOfElements + i;
ElTr->ElementType = ElementTransformation::ELEMENT;
ElTr->mesh = this;
ElTr->Reset();
if (Nodes == NULL)
@@ -2711,6 +2712,7 @@ STable3D *ParMesh::GetFaceNbrElementToFaceTable(int ret_ftbl)
}
face_nbr_el_to_face->Finalize();
delete sfaces_tbl;
if (ret_ftbl)
{
return faces_tbl;
@@ -6178,6 +6180,9 @@ void ParMesh::Destroy()
FreeElement(shared_edges[i]);
}
shared_edges.DeleteAll();
delete face_nbr_el_to_face;
face_nbr_el_to_face = NULL;
}
ParMesh::~ParMesh()
+2 -2
View File
@@ -804,11 +804,11 @@ public:
mfem::ad::ADFloatType aa;
mfem::ad::ADVectorType lvec(ndof);
for (int i = 0; i < ir.GetNPoints(); i++)
for (int q = 0; q < ir.GetNPoints(); q++)
{
lvec=0.0;
const IntegrationPoint &ip = ir.IntPoint(i);
const IntegrationPoint &ip = ir.IntPoint(q);
trans.SetIntPoint(&ip);
w = trans.Weight();
detJ = (square ? w : w * w);
+2 -2
View File
@@ -485,7 +485,7 @@ int main(int argc, char *argv[])
<< std::endl;
}
// Compute the energy
double energy = nr->GetEnergy(*sv);
energy = nr->GetEnergy(*sv);
if (myrank==0)
{
std::cout << "[pp="<<i<<"] The total energy of the system is E=" << energy
@@ -517,7 +517,7 @@ int main(int argc, char *argv[])
<< std::endl;
}
// Compute the energy
double energy = nr->GetEnergy(*sv);
energy = nr->GetEnergy(*sv);
if (myrank==0)
{
std::cout << "[pp="<<pp<<"] The total energy of the system is E=" << energy
+13 -13
View File
@@ -678,22 +678,22 @@ void MagneticDiffusionEOperator::buildA1(double muInv,
dt_A1 = dt;
}
void MagneticDiffusionEOperator::buildA2(MeshDependentCoefficient &InvTcond,
MeshDependentCoefficient &InvTcap,
double dt)
void MagneticDiffusionEOperator::buildA2(MeshDependentCoefficient &InvTcond_,
MeshDependentCoefficient &InvTcap_,
double dt_)
{
if ( a2 != NULL ) { delete a2; }
InvTcap.SetScaleFactor(dt);
InvTcap_.SetScaleFactor(dt_);
a2 = new ParBilinearForm(&HDivFESpace);
a2->AddDomainIntegrator(new VectorFEMassIntegrator(InvTcond));
a2->AddDomainIntegrator(new DivDivIntegrator(InvTcap));
a2->AddDomainIntegrator(new VectorFEMassIntegrator(InvTcond_));
a2->AddDomainIntegrator(new DivDivIntegrator(InvTcap_));
if (STATIC_COND == 1) { a2->EnableStaticCondensation(); }
a2->Assemble();
// Don't finalize or parallel assemble this is done in FormLinearSystem.
dt_A2 = dt;
dt_A2 = dt_;
}
void MagneticDiffusionEOperator::buildM1(MeshDependentCoefficient &Sigma)
@@ -719,13 +719,13 @@ void MagneticDiffusionEOperator::buildM2(MeshDependentCoefficient &Alpha)
// Don't finalize or parallel assemble this is done in FormLinearSystem.
}
void MagneticDiffusionEOperator::buildM3(MeshDependentCoefficient &Tcapacity)
void MagneticDiffusionEOperator::buildM3(MeshDependentCoefficient &Tcapacity_)
{
if ( m3 != NULL ) { delete m3; }
// ConstantCoefficient Sigma(sigma);
m3 = new ParBilinearForm(&L2FESpace);
m3->AddDomainIntegrator(new MassIntegrator(Tcapacity));
m3->AddDomainIntegrator(new MassIntegrator(Tcapacity_));
m3->Assemble();
m3->Finalize();
M3 = m3->ParallelAssemble();
@@ -741,13 +741,13 @@ void MagneticDiffusionEOperator::buildS1(double muInv)
s1->Assemble();
}
void MagneticDiffusionEOperator::buildS2(MeshDependentCoefficient &InvTcap)
void MagneticDiffusionEOperator::buildS2(MeshDependentCoefficient &InvTcap_)
{
if ( s2 != NULL ) { delete s2; }
// ConstantCoefficient param(a);
s2 = new ParBilinearForm(&HDivFESpace);
s2->AddDomainIntegrator(new DivDivIntegrator(InvTcap));
s2->AddDomainIntegrator(new DivDivIntegrator(InvTcap_));
s2->Assemble();
}
@@ -768,13 +768,13 @@ void MagneticDiffusionEOperator::buildCurl(double muInv)
// no ParallelAssemble since this will be applied to GridFunctions
}
void MagneticDiffusionEOperator::buildDiv(MeshDependentCoefficient &InvTcap)
void MagneticDiffusionEOperator::buildDiv(MeshDependentCoefficient &InvTcap_)
{
if ( weakDiv != NULL ) { delete weakDiv; }
if ( weakDivC != NULL ) { delete weakDivC; }
weakDivC = new ParMixedBilinearForm(&HDivFESpace, &L2FESpace);
weakDivC->AddDomainIntegrator(new VectorFEDivergenceIntegrator(InvTcap));
weakDivC->AddDomainIntegrator(new VectorFEDivergenceIntegrator(InvTcap_));
weakDivC->Assemble();
weakDiv = new ParMixedBilinearForm(&HDivFESpace, &L2FESpace);
+4 -4
View File
@@ -1143,8 +1143,8 @@ int main (int argc, char *argv[])
if (mk == 'S')
{
const char mesh_file[] = "mesh-explorer.mesh";
ofstream omesh(mesh_file);
const char omesh_file[] = "mesh-explorer.mesh";
ofstream omesh(omesh_file);
omesh.precision(14);
mesh->Print(omesh);
cout << "New mesh file: " << mesh_file << endl;
@@ -1152,8 +1152,8 @@ int main (int argc, char *argv[])
if (mk == 'V')
{
const char mesh_file[] = "mesh-explorer.vtk";
ofstream omesh(mesh_file);
const char omesh_file[] = "mesh-explorer.vtk";
ofstream omesh(omesh_file);
omesh.precision(14);
mesh->PrintVTK(omesh);
cout << "New VTK mesh file: " << mesh_file << endl;
+90 -79
View File
@@ -326,7 +326,7 @@ int main(int argc, char *argv[])
// In addition, compute average mesh size and total volume.
Vector h0(fespace->GetNDofs());
h0 = infinity();
double volume = 0.0;
double mesh_volume = 0.0;
Array<int> dofs;
for (int i = 0; i < mesh->GetNE(); i++)
{
@@ -338,9 +338,9 @@ int main(int argc, char *argv[])
{
h0(dofs[j]) = min(h0(dofs[j]), hi);
}
volume += mesh->GetElementVolume(i);
mesh_volume += mesh->GetElementVolume(i);
}
const double small_phys_size = pow(volume, 1.0 / dim) / 100.0;
const double small_phys_size = pow(mesh_volume, 1.0 / dim) / 100.0;
// 8. Add a random perturbation to the nodes in the interior of the domain.
// We define a random grid function of fespace and make sure that it is
@@ -413,6 +413,10 @@ int main(int argc, char *argv[])
case 315: metric = new TMOP_Metric_315; break;
case 316: metric = new TMOP_Metric_316; break;
case 321: metric = new TMOP_Metric_321; break;
case 328: metric = new TMOP_Metric_328(0.5); break;
case 332: metric = new TMOP_Metric_332(0.5); break;
case 333: metric = new TMOP_Metric_333(0.5); break;
case 334: metric = new TMOP_Metric_334(0.5); break;
// case 352: metric = new TMOP_Metric_352(tauval); break;
// A-metrics
case 11: metric = new TMOP_AMetric_011; break;
@@ -461,7 +465,7 @@ int main(int argc, char *argv[])
H1_FECollection ind_fec(mesh_poly_deg, dim);
FiniteElementSpace ind_fes(mesh, &ind_fec);
FiniteElementSpace ind_fesv(mesh, &ind_fec, dim);
GridFunction size(&ind_fes), aspr(&ind_fes), disc(&ind_fes), ori(&ind_fes);
GridFunction size(&ind_fes), aspr(&ind_fes), ori(&ind_fes);
GridFunction aspr3d(&ind_fesv);
const AssemblyLevel al =
@@ -499,13 +503,13 @@ int main(int argc, char *argv[])
}
if (dim == 2)
{
FunctionCoefficient ind_coeff(discrete_size_2d);
size.ProjectCoefficient(ind_coeff);
FunctionCoefficient size_coeff(discrete_size_2d);
size.ProjectCoefficient(size_coeff);
}
else if (dim == 3)
{
FunctionCoefficient ind_coeff(discrete_size_3d);
size.ProjectCoefficient(ind_coeff);
FunctionCoefficient size_coeff(discrete_size_3d);
size.ProjectCoefficient(size_coeff);
}
tc->SetSerialDiscreteTargetSize(size);
target_c = tc;
@@ -513,12 +517,12 @@ int main(int argc, char *argv[])
}
case 6: // Discrete size + aspect ratio - 2D
{
GridFunction d_x(&ind_fes), d_y(&ind_fes);
GridFunction d_x(&ind_fes), d_y(&ind_fes), disc(&ind_fes);
target_t = TargetConstructor::GIVEN_SHAPE_AND_SIZE;
DiscreteAdaptTC *tc = new DiscreteAdaptTC(target_t);
FunctionCoefficient ind_coeff(material_indicator_2d);
disc.ProjectCoefficient(ind_coeff);
FunctionCoefficient mat_coeff(material_indicator_2d);
disc.ProjectCoefficient(mat_coeff);
if (adapt_eval == 0)
{
tc->SetAdaptivityEvaluator(new AdvectorCG(al));
@@ -648,8 +652,8 @@ int main(int argc, char *argv[])
if (metric_id == 14 || metric_id == 36)
{
ConstantCoefficient ind_coeff(0.1*0.1);
size.ProjectCoefficient(ind_coeff);
ConstantCoefficient size_coeff(0.1*0.1);
size.ProjectCoefficient(size_coeff);
tc->SetSerialDiscreteTargetSize(size);
}
@@ -686,16 +690,16 @@ int main(int argc, char *argv[])
target_c = new TargetConstructor(target_t);
}
target_c->SetNodes(x0);
TMOP_Integrator *he_nlf_integ = new TMOP_Integrator(metric, target_c,
h_metric);
TMOP_Integrator *tmop_integ = new TMOP_Integrator(metric, target_c,
h_metric);
// Finite differences for computations of derivatives.
if (fdscheme)
{
MFEM_VERIFY(pa == false, "PA for finite differences is not implemented.");
he_nlf_integ->EnableFiniteDifferences(x);
tmop_integ->EnableFiniteDifferences(x);
}
he_nlf_integ->SetExactActionFlag(exactaction);
tmop_integ->SetExactActionFlag(exactaction);
// Setup the quadrature rules for the TMOP integrator.
IntegrationRules *irules = NULL;
@@ -706,7 +710,7 @@ int main(int argc, char *argv[])
case 3: irules = &IntRulesCU; break;
default: cout << "Unknown quad_type: " << quad_type << endl; return 3;
}
he_nlf_integ->SetIntegrationRules(*irules, quad_order);
tmop_integ->SetIntegrationRules(*irules, quad_order);
if (dim == 2)
{
cout << "Triangle quadrature points: "
@@ -732,49 +736,50 @@ int main(int argc, char *argv[])
// The small_phys_size is relevant only with proper normalization.
if (normalization) { dist = small_phys_size; }
ConstantCoefficient lim_coeff(lim_const);
if (lim_const != 0.0) { he_nlf_integ->EnableLimiting(x0, dist, lim_coeff); }
if (lim_const != 0.0) { tmop_integ->EnableLimiting(x0, dist, lim_coeff); }
// Adaptive limiting.
GridFunction zeta_0(&ind_fes);
ConstantCoefficient coef_zeta(adapt_lim_const);
AdaptivityEvaluator *adapt_evaluator = NULL;
GridFunction adapt_lim_gf0(&ind_fes);
ConstantCoefficient adapt_lim_coeff(adapt_lim_const);
AdaptivityEvaluator *adapt_lim_eval = NULL;
if (adapt_lim_const > 0.0)
{
MFEM_VERIFY(pa == false, "PA is not implemented for adaptive limiting");
FunctionCoefficient alim_coeff(adapt_lim_fun);
zeta_0.ProjectCoefficient(alim_coeff);
FunctionCoefficient adapt_lim_gf0_coeff(adapt_lim_fun);
adapt_lim_gf0.ProjectCoefficient(adapt_lim_gf0_coeff);
if (adapt_eval == 0) { adapt_evaluator = new AdvectorCG(al); }
if (adapt_eval == 0) { adapt_lim_eval = new AdvectorCG(al); }
else if (adapt_eval == 1)
{
#ifdef MFEM_USE_GSLIB
adapt_evaluator = new InterpolatorFP;
adapt_lim_eval = new InterpolatorFP;
#else
MFEM_ABORT("MFEM is not built with GSLIB support!");
#endif
}
else { MFEM_ABORT("Bad interpolation option."); }
he_nlf_integ->EnableAdaptiveLimiting(zeta_0, coef_zeta, *adapt_evaluator);
tmop_integ->EnableAdaptiveLimiting(adapt_lim_gf0, adapt_lim_coeff,
*adapt_lim_eval);
if (visualization)
{
socketstream vis1;
common::VisualizeField(vis1, "localhost", 19916, zeta_0, "Zeta 0",
common::VisualizeField(vis1, "localhost", 19916, adapt_lim_gf0, "Zeta 0",
300, 600, 300, 300);
}
}
// Surface fitting.
L2_FECollection mat_coll(0, dim);
H1_FECollection sigma_fec(mesh_poly_deg, dim);
FiniteElementSpace sigma_fes(mesh, &sigma_fec);
H1_FECollection surf_fit_fec(mesh_poly_deg, dim);
FiniteElementSpace surf_fit_fes(mesh, &surf_fit_fec);
FiniteElementSpace mat_fes(mesh, &mat_coll);
GridFunction mat(&mat_fes);
GridFunction marker_gf(&sigma_fes);
GridFunction ls_0(&sigma_fes);
Array<bool> marker(ls_0.Size());
ConstantCoefficient coef_ls(surface_fit_const);
GridFunction surf_fit_mat_gf(&surf_fit_fes);
GridFunction surf_fit_gf0(&surf_fit_fes);
Array<bool> surf_fit_marker(surf_fit_gf0.Size());
ConstantCoefficient surf_fit_coeff(surface_fit_const);
AdaptivityEvaluator *adapt_surface = NULL;
if (surface_fit_const > 0.0)
{
@@ -784,27 +789,27 @@ int main(int argc, char *argv[])
"Surface fitting with PA is not implemented yet.");
FunctionCoefficient ls_coeff(surface_level_set);
ls_0.ProjectCoefficient(ls_coeff);
surf_fit_gf0.ProjectCoefficient(ls_coeff);
for (int i = 0; i < mesh->GetNE(); i++)
{
mat(i) = material_id(i, ls_0);
mat(i) = material_id(i, surf_fit_gf0);
mesh->SetAttribute(i, mat(i) + 1);
}
GridFunctionCoefficient coeff_mat(&mat);
marker_gf.ProjectDiscCoefficient(coeff_mat, GridFunction::ARITHMETIC);
for (int j = 0; j < marker.Size(); j++)
GridFunctionCoefficient mat_coeff(&mat);
surf_fit_mat_gf.ProjectDiscCoefficient(mat_coeff, GridFunction::ARITHMETIC);
for (int j = 0; j < surf_fit_marker.Size(); j++)
{
if (marker_gf(j) > 0.1 && marker_gf(j) < 0.9)
if (surf_fit_mat_gf(j) > 0.1 && surf_fit_mat_gf(j) < 0.9)
{
marker[j] = true;
marker_gf(j) = 1.0;
surf_fit_marker[j] = true;
surf_fit_mat_gf(j) = 1.0;
}
else
{
marker[j] = false;
marker_gf(j) = 0.0;
surf_fit_marker[j] = false;
surf_fit_mat_gf(j) = 0.0;
}
}
@@ -819,22 +824,24 @@ int main(int argc, char *argv[])
}
else { MFEM_ABORT("Bad interpolation option."); }
he_nlf_integ->EnableSurfaceFitting(ls_0, marker, coef_ls, *adapt_surface);
tmop_integ->EnableSurfaceFitting(surf_fit_gf0, surf_fit_marker,
surf_fit_coeff, *adapt_surface);
if (visualization)
{
socketstream vis1, vis2, vis3;
common::VisualizeField(vis1, "localhost", 19916, ls_0, "Level Set 0",
common::VisualizeField(vis1, "localhost", 19916, surf_fit_gf0, "Level Set 0",
300, 600, 300, 300);
common::VisualizeField(vis2, "localhost", 19916, mat, "Materials",
600, 600, 300, 300);
common::VisualizeField(vis3, "localhost", 19916, marker_gf, "Dofs to Move",
common::VisualizeField(vis3, "localhost", 19916, surf_fit_mat_gf,
"Dofs to Move",
900, 600, 300, 300);
}
}
// Has to be after the enabling of the limiting / alignment, as it computes
// normalization factors for these terms as well.
if (normalization) { he_nlf_integ->EnableNormalization(x0); }
if (normalization) { tmop_integ->EnableNormalization(x0); }
// 12. Setup the final NonlinearForm (which defines the integral of interest,
// its first and second derivatives). Here we can use a combination of
@@ -844,39 +851,39 @@ int main(int argc, char *argv[])
// metric; one should update those in the code.
NonlinearForm a(fespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
ConstantCoefficient *coeff1 = NULL;
ConstantCoefficient *metric_coeff1 = NULL;
TMOP_QualityMetric *metric2 = NULL;
TargetConstructor *target_c2 = NULL;
FunctionCoefficient coeff2(weight_fun);
FunctionCoefficient metric_coeff2(weight_fun);
// Explicit combination of metrics.
if (combomet > 0)
{
// First metric.
coeff1 = new ConstantCoefficient(1.0);
he_nlf_integ->SetCoefficient(*coeff1);
metric_coeff1 = new ConstantCoefficient(1.0);
tmop_integ->SetCoefficient(*metric_coeff1);
// Second metric.
if (dim == 2) { metric2 = new TMOP_Metric_077; }
else { metric2 = new TMOP_Metric_315; }
TMOP_Integrator *he_nlf_integ2 = NULL;
TMOP_Integrator *tmop_integ2 = NULL;
if (combomet == 1)
{
target_c2 = new TargetConstructor(
TargetConstructor::IDEAL_SHAPE_EQUAL_SIZE);
target_c2->SetVolumeScale(0.01);
target_c2->SetNodes(x0);
he_nlf_integ2 = new TMOP_Integrator(metric2, target_c2, h_metric);
he_nlf_integ2->SetCoefficient(coeff2);
tmop_integ2 = new TMOP_Integrator(metric2, target_c2, h_metric);
tmop_integ2->SetCoefficient(metric_coeff2);
}
else { he_nlf_integ2 = new TMOP_Integrator(metric2, target_c, h_metric); }
he_nlf_integ2->SetIntegrationRules(*irules, quad_order);
if (fdscheme) { he_nlf_integ2->EnableFiniteDifferences(x); }
he_nlf_integ2->SetExactActionFlag(exactaction);
else { tmop_integ2 = new TMOP_Integrator(metric2, target_c, h_metric); }
tmop_integ2->SetIntegrationRules(*irules, quad_order);
if (fdscheme) { tmop_integ2->EnableFiniteDifferences(x); }
tmop_integ2->SetExactActionFlag(exactaction);
TMOPComboIntegrator *combo = new TMOPComboIntegrator;
combo->AddTMOPIntegrator(he_nlf_integ);
combo->AddTMOPIntegrator(he_nlf_integ2);
combo->AddTMOPIntegrator(tmop_integ);
combo->AddTMOPIntegrator(tmop_integ2);
if (normalization) { combo->EnableNormalization(x0); }
if (lim_const != 0.0) { combo->EnableLimiting(x0, dist, lim_coeff); }
@@ -884,7 +891,7 @@ int main(int argc, char *argv[])
}
else
{
a.AddDomainIntegrator(he_nlf_integ);
a.AddDomainIntegrator(tmop_integ);
}
if (pa) { a.Setup(); }
@@ -930,13 +937,13 @@ int main(int argc, char *argv[])
if (lim_const > 0.0 || adapt_lim_const > 0.0 || surface_fit_const > 0.0)
{
lim_coeff.constant = 0.0;
coef_zeta.constant = 0.0;
coef_ls.constant = 0.0;
adapt_lim_coeff.constant = 0.0;
surf_fit_coeff.constant = 0.0;
init_metric_energy = a.GetGridFunctionEnergy(x) /
(hradaptivity ? mesh->GetNE() : 1);
lim_coeff.constant = lim_const;
coef_zeta.constant = adapt_lim_const;
coef_ls.constant = surface_fit_const;
adapt_lim_coeff.constant = adapt_lim_const;
surf_fit_coeff.constant = surface_fit_const;
}
// Visualize the starting mesh and metric values.
@@ -972,7 +979,7 @@ int main(int argc, char *argv[])
if (attr == 1 || attr == 2 || attr == 3) { n += nd; }
if (attr == 4) { n += nd * dim; }
}
Array<int> ess_vdofs(n), vdofs;
Array<int> ess_vdofs(n);
n = 0;
for (int i = 0; i < mesh->GetNBE(); i++)
{
@@ -1033,11 +1040,15 @@ int main(int argc, char *argv[])
if (pa)
{
MFEM_VERIFY(lin_solver != 4, "PA l1-Jacobi is not implemented");
S_prec = new OperatorJacobiSmoother;
auto js = new OperatorJacobiSmoother;
js->SetPositiveDiagonal(true);
S_prec = js;
}
else
{
S_prec = new DSmoother((lin_solver == 3) ? 0 : 1, 1.0, 1);
auto ds = new DSmoother((lin_solver == 3) ? 0 : 1, 1.0, 1);
ds->SetPositiveDiagonal(true);
S_prec = ds;
}
minres->SetPreconditioner(*S_prec);
}
@@ -1080,7 +1091,7 @@ int main(int argc, char *argv[])
hr_solver.AddGridFunctionForUpdate(&x0);
if (adapt_lim_const > 0.)
{
hr_solver.AddGridFunctionForUpdate(&zeta_0);
hr_solver.AddGridFunctionForUpdate(&adapt_lim_gf0);
hr_solver.AddFESpaceForUpdate(&ind_fes);
}
hr_solver.Mult();
@@ -1099,13 +1110,13 @@ int main(int argc, char *argv[])
if (lim_const > 0.0 || adapt_lim_const > 0.0)
{
lim_coeff.constant = 0.0;
coef_zeta.constant = 0.0;
coef_ls.constant = 0.0;
adapt_lim_coeff.constant = 0.0;
surf_fit_coeff.constant = 0.0;
fin_metric_energy = a.GetGridFunctionEnergy(x) /
(hradaptivity ? mesh->GetNE() : 1);
lim_coeff.constant = lim_const;
coef_zeta.constant = adapt_lim_const;
coef_ls.constant = surface_fit_const;
adapt_lim_coeff.constant = adapt_lim_const;
surf_fit_coeff.constant = surface_fit_const;
}
std::cout << std::scientific << std::setprecision(4);
cout << "Initial strain energy: " << init_energy
@@ -1127,7 +1138,7 @@ int main(int argc, char *argv[])
if (adapt_lim_const > 0.0 && visualization)
{
socketstream vis0;
common::VisualizeField(vis0, "localhost", 19916, zeta_0, "Xi 0",
common::VisualizeField(vis0, "localhost", 19916, adapt_lim_gf0, "Xi 0",
600, 600, 300, 300);
}
@@ -1138,11 +1149,11 @@ int main(int argc, char *argv[])
socketstream vis2, vis3;
common::VisualizeField(vis2, "localhost", 19916, mat, "Materials",
600, 900, 300, 300);
common::VisualizeField(vis3, "localhost", 19916, marker_gf, "Surface dof",
common::VisualizeField(vis3, "localhost", 19916, surf_fit_mat_gf, "Surface dof",
900, 900, 300, 300);
}
double err_avg, err_max;
he_nlf_integ->GetSurfaceFittingErrors(err_avg, err_max);
tmop_integ->GetSurfaceFittingErrors(err_avg, err_max);
std::cout << "Avg fitting error: " << err_avg << std::endl
<< "Max fitting error: " << err_max << std::endl;
}
@@ -1166,8 +1177,8 @@ int main(int argc, char *argv[])
delete S_prec;
delete target_c2;
delete metric2;
delete coeff1;
delete adapt_evaluator;
delete metric_coeff1;
delete adapt_lim_eval;
delete adapt_surface;
delete target_c;
delete hr_adapt_coeff;
+7 -6
View File
@@ -392,16 +392,17 @@ public:
void Amr()
{
MFEM_VERIFY(opt.amr_threshold >= 0.0 && opt.amr_threshold <= 1.0, "");
Mesh *mesh = S.mesh;
Mesh *smesh = S.mesh;
Array<Refinement> amr;
const int NE = mesh->GetNE();
const int NE = smesh->GetNE();
DenseMatrix Jadjt, Jadj(DIM, SDIM);
for (int e = 0; e < NE; e++)
{
double minW = +NL_DMAX;
double maxW = -NL_DMAX;
ElementTransformation *eTr = mesh->GetElementTransformation(e);
const Geometry::Type &type = mesh->GetElement(e)->GetGeometryType();
ElementTransformation *eTr = smesh->GetElementTransformation(e);
const Geometry::Type &type =
smesh->GetElement(e)->GetGeometryType();
const IntegrationRule *ir = &IntRules.Get(type, opt.order);
const int NQ = ir->GetNPoints();
for (int q = 0; q < NQ; q++)
@@ -424,8 +425,8 @@ public:
}
if (amr.Size()>0)
{
mesh->GetNodes()->HostReadWrite();
mesh->GeneralRefinement(amr);
smesh->GetNodes()->HostReadWrite();
smesh->GeneralRefinement(amr);
S.fes->Update();
x.HostReadWrite();
x.Update();
+91 -82
View File
@@ -358,9 +358,9 @@ int main (int argc, char *argv[])
}
vol_loc += pmesh->GetElementVolume(i);
}
double volume;
MPI_Allreduce(&vol_loc, &volume, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
const double small_phys_size = pow(volume, 1.0 / dim) / 100.0;
double vol_glb;
MPI_Allreduce(&vol_loc, &vol_glb, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
const double small_phys_size = pow(vol_glb, 1.0 / dim) / 100.0;
// 9. Add a random perturbation to the nodes in the interior of the domain.
// We define a random grid function of fespace and make sure that it is
@@ -438,6 +438,10 @@ int main (int argc, char *argv[])
case 315: metric = new TMOP_Metric_315; break;
case 316: metric = new TMOP_Metric_316; break;
case 321: metric = new TMOP_Metric_321; break;
case 328: metric = new TMOP_Metric_328(0.5); break;
case 332: metric = new TMOP_Metric_332(0.5); break;
case 333: metric = new TMOP_Metric_333(0.5); break;
case 334: metric = new TMOP_Metric_334(0.5); break;
// case 352: metric = new TMOP_Metric_352(tauval); break;
// A-metrics
case 11: metric = new TMOP_AMetric_011; break;
@@ -486,7 +490,7 @@ int main (int argc, char *argv[])
H1_FECollection ind_fec(mesh_poly_deg, dim);
ParFiniteElementSpace ind_fes(pmesh, &ind_fec);
ParFiniteElementSpace ind_fesv(pmesh, &ind_fec, dim);
ParGridFunction size(&ind_fes), aspr(&ind_fes), disc(&ind_fes), ori(&ind_fes);
ParGridFunction size(&ind_fes), aspr(&ind_fes), ori(&ind_fes);
ParGridFunction aspr3d(&ind_fesv);
const AssemblyLevel al =
@@ -524,13 +528,13 @@ int main (int argc, char *argv[])
}
if (dim == 2)
{
FunctionCoefficient ind_coeff(discrete_size_2d);
size.ProjectCoefficient(ind_coeff);
FunctionCoefficient size_coeff(discrete_size_2d);
size.ProjectCoefficient(size_coeff);
}
else if (dim == 3)
{
FunctionCoefficient ind_coeff(discrete_size_3d);
size.ProjectCoefficient(ind_coeff);
FunctionCoefficient size_coeff(discrete_size_3d);
size.ProjectCoefficient(size_coeff);
}
tc->SetParDiscreteTargetSize(size);
target_c = tc;
@@ -538,12 +542,12 @@ int main (int argc, char *argv[])
}
case 6: // material indicator 2D
{
ParGridFunction d_x(&ind_fes), d_y(&ind_fes);
ParGridFunction d_x(&ind_fes), d_y(&ind_fes), disc(&ind_fes);
target_t = TargetConstructor::GIVEN_SHAPE_AND_SIZE;
DiscreteAdaptTC *tc = new DiscreteAdaptTC(target_t);
FunctionCoefficient ind_coeff(material_indicator_2d);
disc.ProjectCoefficient(ind_coeff);
FunctionCoefficient mat_coeff(material_indicator_2d);
disc.ProjectCoefficient(mat_coeff);
if (adapt_eval == 0)
{
tc->SetAdaptivityEvaluator(new AdvectorCG(al));
@@ -678,8 +682,8 @@ int main (int argc, char *argv[])
if (metric_id == 14 || metric_id == 36)
{
ConstantCoefficient ind_coeff(0.1*0.1);
size.ProjectCoefficient(ind_coeff);
ConstantCoefficient size_coeff(0.1*0.1);
size.ProjectCoefficient(size_coeff);
tc->SetParDiscreteTargetSize(size);
}
@@ -719,16 +723,16 @@ int main (int argc, char *argv[])
target_c = new TargetConstructor(target_t, MPI_COMM_WORLD);
}
target_c->SetNodes(x0);
TMOP_Integrator *he_nlf_integ = new TMOP_Integrator(metric, target_c,
h_metric);
TMOP_Integrator *tmop_integ = new TMOP_Integrator(metric, target_c,
h_metric);
// Finite differences for computations of derivatives.
if (fdscheme)
{
MFEM_VERIFY(pa == false, "PA for finite differences is not implemented.");
he_nlf_integ->EnableFiniteDifferences(x);
tmop_integ->EnableFiniteDifferences(x);
}
he_nlf_integ->SetExactActionFlag(exactaction);
tmop_integ->SetExactActionFlag(exactaction);
// Setup the quadrature rules for the TMOP integrator.
IntegrationRules *irules = NULL;
@@ -741,7 +745,7 @@ int main (int argc, char *argv[])
if (myid == 0) { cout << "Unknown quad_type: " << quad_type << endl; }
return 3;
}
he_nlf_integ->SetIntegrationRules(*irules, quad_order);
tmop_integ->SetIntegrationRules(*irules, quad_order);
if (myid == 0 && dim == 2)
{
cout << "Triangle quadrature points: "
@@ -767,49 +771,50 @@ int main (int argc, char *argv[])
// The small_phys_size is relevant only with proper normalization.
if (normalization) { dist = small_phys_size; }
ConstantCoefficient lim_coeff(lim_const);
if (lim_const != 0.0) { he_nlf_integ->EnableLimiting(x0, dist, lim_coeff); }
if (lim_const != 0.0) { tmop_integ->EnableLimiting(x0, dist, lim_coeff); }
// Adaptive limiting.
ParGridFunction zeta_0(&ind_fes);
ConstantCoefficient coef_zeta(adapt_lim_const);
AdaptivityEvaluator *adapt_evaluator = NULL;
ParGridFunction adapt_lim_gf0(&ind_fes);
ConstantCoefficient adapt_lim_coeff(adapt_lim_const);
AdaptivityEvaluator *adapt_lim_eval = NULL;
if (adapt_lim_const > 0.0)
{
MFEM_VERIFY(pa == false, "PA is not implemented for adaptive limiting");
FunctionCoefficient alim_coeff(adapt_lim_fun);
zeta_0.ProjectCoefficient(alim_coeff);
FunctionCoefficient adapt_lim_gf0_coeff(adapt_lim_fun);
adapt_lim_gf0.ProjectCoefficient(adapt_lim_gf0_coeff);
if (adapt_eval == 0) { adapt_evaluator = new AdvectorCG(al); }
if (adapt_eval == 0) { adapt_lim_eval = new AdvectorCG(al); }
else if (adapt_eval == 1)
{
#ifdef MFEM_USE_GSLIB
adapt_evaluator = new InterpolatorFP;
adapt_lim_eval = new InterpolatorFP;
#else
MFEM_ABORT("MFEM is not built with GSLIB support!");
#endif
}
else { MFEM_ABORT("Bad interpolation option."); }
he_nlf_integ->EnableAdaptiveLimiting(zeta_0, coef_zeta, *adapt_evaluator);
tmop_integ->EnableAdaptiveLimiting(adapt_lim_gf0, adapt_lim_coeff,
*adapt_lim_eval);
if (visualization)
{
socketstream vis1;
common::VisualizeField(vis1, "localhost", 19916, zeta_0, "Zeta 0",
common::VisualizeField(vis1, "localhost", 19916, adapt_lim_gf0, "Zeta 0",
300, 600, 300, 300);
}
}
// Surface fitting.
L2_FECollection mat_coll(0, dim);
H1_FECollection sigma_fec(mesh_poly_deg, dim);
ParFiniteElementSpace sigma_fes(pmesh, &sigma_fec);
H1_FECollection surf_fit_fec(mesh_poly_deg, dim);
ParFiniteElementSpace surf_fit_fes(pmesh, &surf_fit_fec);
ParFiniteElementSpace mat_fes(pmesh, &mat_coll);
ParGridFunction mat(&mat_fes);
ParGridFunction marker_gf(&sigma_fes);
ParGridFunction ls_0(&sigma_fes);
Array<bool> marker(ls_0.Size());
ConstantCoefficient coef_ls(surface_fit_const);
ParGridFunction surf_fit_mat_gf(&surf_fit_fes);
ParGridFunction surf_fit_gf0(&surf_fit_fes);
Array<bool> surf_fit_marker(surf_fit_gf0.Size());
ConstantCoefficient surf_fit_coeff(surface_fit_const);
AdaptivityEvaluator *adapt_surface = NULL;
if (surface_fit_const > 0.0)
{
@@ -819,27 +824,27 @@ int main (int argc, char *argv[])
"Surface fitting with PA is not implemented yet.");
FunctionCoefficient ls_coeff(surface_level_set);
ls_0.ProjectCoefficient(ls_coeff);
surf_fit_gf0.ProjectCoefficient(ls_coeff);
for (int i = 0; i < pmesh->GetNE(); i++)
{
mat(i) = material_id(i, ls_0);
mat(i) = material_id(i, surf_fit_gf0);
pmesh->SetAttribute(i, mat(i) + 1);
}
GridFunctionCoefficient coeff_mat(&mat);
marker_gf.ProjectDiscCoefficient(coeff_mat, GridFunction::ARITHMETIC);
for (int j = 0; j < marker.Size(); j++)
surf_fit_mat_gf.ProjectDiscCoefficient(coeff_mat, GridFunction::ARITHMETIC);
for (int j = 0; j < surf_fit_marker.Size(); j++)
{
if (marker_gf(j) > 0.1 && marker_gf(j) < 0.9)
if (surf_fit_mat_gf(j) > 0.1 && surf_fit_mat_gf(j) < 0.9)
{
marker[j] = true;
marker_gf(j) = 1.0;
surf_fit_marker[j] = true;
surf_fit_mat_gf(j) = 1.0;
}
else
{
marker[j] = false;
marker_gf(j) = 0.0;
surf_fit_marker[j] = false;
surf_fit_mat_gf(j) = 0.0;
}
}
@@ -854,22 +859,24 @@ int main (int argc, char *argv[])
}
else { MFEM_ABORT("Bad interpolation option."); }
he_nlf_integ->EnableSurfaceFitting(ls_0, marker, coef_ls, *adapt_surface);
tmop_integ->EnableSurfaceFitting(surf_fit_gf0, surf_fit_marker, surf_fit_coeff,
*adapt_surface);
if (visualization)
{
socketstream vis1, vis2, vis3;
common::VisualizeField(vis1, "localhost", 19916, ls_0, "Level Set 0",
common::VisualizeField(vis1, "localhost", 19916, surf_fit_gf0, "Level Set 0",
300, 600, 300, 300);
common::VisualizeField(vis2, "localhost", 19916, mat, "Materials",
600, 600, 300, 300);
common::VisualizeField(vis3, "localhost", 19916, marker_gf, "Dofs to Move",
common::VisualizeField(vis3, "localhost", 19916, surf_fit_mat_gf,
"Dofs to Move",
900, 600, 300, 300);
}
}
// Has to be after the enabling of the limiting / alignment, as it computes
// normalization factors for these terms as well.
if (normalization) { he_nlf_integ->ParEnableNormalization(x0); }
if (normalization) { tmop_integ->ParEnableNormalization(x0); }
// 13. Setup the final NonlinearForm (which defines the integral of interest,
// its first and second derivatives). Here we can use a combination of
@@ -879,39 +886,39 @@ int main (int argc, char *argv[])
// metric; one should update those in the code.
ParNonlinearForm a(pfespace);
if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
ConstantCoefficient *coeff1 = NULL;
ConstantCoefficient *metric_coeff1 = NULL;
TMOP_QualityMetric *metric2 = NULL;
TargetConstructor *target_c2 = NULL;
FunctionCoefficient coeff2(weight_fun);
FunctionCoefficient metric_coeff2(weight_fun);
// Explicit combination of metrics.
if (combomet > 0)
{
// First metric.
coeff1 = new ConstantCoefficient(1.0);
he_nlf_integ->SetCoefficient(*coeff1);
metric_coeff1 = new ConstantCoefficient(1.0);
tmop_integ->SetCoefficient(*metric_coeff1);
// Second metric.
if (dim == 2) { metric2 = new TMOP_Metric_077; }
else { metric2 = new TMOP_Metric_315; }
TMOP_Integrator *he_nlf_integ2 = NULL;
TMOP_Integrator *tmop_integ2 = NULL;
if (combomet == 1)
{
target_c2 = new TargetConstructor(
TargetConstructor::IDEAL_SHAPE_EQUAL_SIZE, MPI_COMM_WORLD);
target_c2->SetVolumeScale(0.01);
target_c2->SetNodes(x0);
he_nlf_integ2 = new TMOP_Integrator(metric2, target_c2, h_metric);
he_nlf_integ2->SetCoefficient(coeff2);
tmop_integ2 = new TMOP_Integrator(metric2, target_c2, h_metric);
tmop_integ2->SetCoefficient(metric_coeff2);
}
else { he_nlf_integ2 = new TMOP_Integrator(metric2, target_c, h_metric); }
he_nlf_integ2->SetIntegrationRules(*irules, quad_order);
if (fdscheme) { he_nlf_integ2->EnableFiniteDifferences(x); }
he_nlf_integ2->SetExactActionFlag(exactaction);
else { tmop_integ2 = new TMOP_Integrator(metric2, target_c, h_metric); }
tmop_integ2->SetIntegrationRules(*irules, quad_order);
if (fdscheme) { tmop_integ2->EnableFiniteDifferences(x); }
tmop_integ2->SetExactActionFlag(exactaction);
TMOPComboIntegrator *combo = new TMOPComboIntegrator;
combo->AddTMOPIntegrator(he_nlf_integ);
combo->AddTMOPIntegrator(he_nlf_integ2);
combo->AddTMOPIntegrator(tmop_integ);
combo->AddTMOPIntegrator(tmop_integ2);
if (normalization) { combo->ParEnableNormalization(x0); }
if (lim_const != 0.0) { combo->EnableLimiting(x0, dist, lim_coeff); }
@@ -919,7 +926,7 @@ int main (int argc, char *argv[])
}
else
{
a.AddDomainIntegrator(he_nlf_integ);
a.AddDomainIntegrator(tmop_integ);
}
if (pa) { a.Setup(); }
@@ -971,13 +978,13 @@ int main (int argc, char *argv[])
if (lim_const > 0.0 || adapt_lim_const > 0.0 || surface_fit_const > 0.0)
{
lim_coeff.constant = 0.0;
coef_zeta.constant = 0.0;
coef_ls.constant = 0.0;
adapt_lim_coeff.constant = 0.0;
surf_fit_coeff.constant = 0.0;
init_metric_energy = a.GetParGridFunctionEnergy(x) /
(hradaptivity ? pmesh->GetGlobalNE() : 1);
lim_coeff.constant = lim_const;
coef_zeta.constant = adapt_lim_const;
coef_ls.constant = surface_fit_const;
adapt_lim_coeff.constant = adapt_lim_const;
surf_fit_coeff.constant = surface_fit_const;
}
// Visualize the starting mesh and metric values.
@@ -990,9 +997,8 @@ int main (int argc, char *argv[])
// 14. Fix all boundary nodes, or fix only a given component depending on the
// boundary attributes of the given mesh. Attributes 1/2/3 correspond to
// fixed x/y/z components of the node. Attribute 4 corresponds to an
// entirely fixed node. Other boundary attributes do not affect the node
// movement boundary conditions.
// fixed x/y/z components of the node. Attribute dim+1 corresponds to
// an entirely fixed node.
if (move_bnd == false)
{
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
@@ -1013,7 +1019,7 @@ int main (int argc, char *argv[])
if (attr == 1 || attr == 2 || attr == 3) { n += nd; }
if (attr == 4) { n += nd * dim; }
}
Array<int> ess_vdofs(n), vdofs;
Array<int> ess_vdofs(n);
n = 0;
for (int i = 0; i < pmesh->GetNBE(); i++)
{
@@ -1074,13 +1080,16 @@ int main (int argc, char *argv[])
if (pa)
{
MFEM_VERIFY(lin_solver != 4, "PA l1-Jacobi is not implemented");
S_prec = new OperatorJacobiSmoother;
auto js = new OperatorJacobiSmoother;
js->SetPositiveDiagonal(true);
S_prec = js;
}
else
{
HypreSmoother *hs = new HypreSmoother;
auto hs = new HypreSmoother;
hs->SetType((lin_solver == 3) ? HypreSmoother::Jacobi
: HypreSmoother::l1Jacobi, 1);
/* */ : HypreSmoother::l1Jacobi, 1);
hs->SetPositiveDiagonal(true);
S_prec = hs;
}
minres->SetPreconditioner(*S_prec);
@@ -1124,7 +1133,7 @@ int main (int argc, char *argv[])
hr_solver.AddGridFunctionForUpdate(&x0);
if (adapt_lim_const > 0.)
{
hr_solver.AddGridFunctionForUpdate(&zeta_0);
hr_solver.AddGridFunctionForUpdate(&adapt_lim_gf0);
hr_solver.AddFESpaceForUpdate(&ind_fes);
}
hr_solver.Mult();
@@ -1146,13 +1155,13 @@ int main (int argc, char *argv[])
if (lim_const > 0.0 || adapt_lim_const > 0.0 || surface_fit_const > 0.0)
{
lim_coeff.constant = 0.0;
coef_zeta.constant = 0.0;
coef_ls.constant = 0.0;
adapt_lim_coeff.constant = 0.0;
surf_fit_coeff.constant = 0.0;
fin_metric_energy = a.GetParGridFunctionEnergy(x) /
(hradaptivity ? pmesh->GetGlobalNE() : 1);
lim_coeff.constant = lim_const;
coef_zeta.constant = adapt_lim_const;
coef_ls.constant = surface_fit_const;
adapt_lim_coeff.constant = adapt_lim_const;
surf_fit_coeff.constant = surface_fit_const;
}
if (myid == 0)
{
@@ -1177,7 +1186,7 @@ int main (int argc, char *argv[])
if (adapt_lim_const > 0.0 && visualization)
{
socketstream vis0;
common::VisualizeField(vis0, "localhost", 19916, zeta_0, "Xi 0",
common::VisualizeField(vis0, "localhost", 19916, adapt_lim_gf0, "Xi 0",
600, 600, 300, 300);
}
@@ -1188,11 +1197,11 @@ int main (int argc, char *argv[])
socketstream vis2, vis3;
common::VisualizeField(vis2, "localhost", 19916, mat,
"Materials", 600, 900, 300, 300);
common::VisualizeField(vis3, "localhost", 19916, marker_gf,
common::VisualizeField(vis3, "localhost", 19916, surf_fit_mat_gf,
"Surface dof", 900, 900, 300, 300);
}
double err_avg, err_max;
he_nlf_integ->GetSurfaceFittingErrors(err_avg, err_max);
tmop_integ->GetSurfaceFittingErrors(err_avg, err_max);
if (myid == 0)
{
std::cout << "Avg fitting error: " << err_avg << std::endl
@@ -1226,8 +1235,8 @@ int main (int argc, char *argv[])
delete S_prec;
delete target_c2;
delete metric2;
delete coeff1;
delete adapt_evaluator;
delete metric_coeff1;
delete adapt_lim_eval;
delete adapt_surface;
delete target_c;
delete hr_adapt_coeff;
+8 -6
View File
@@ -399,16 +399,18 @@ public:
void Amr()
{
MFEM_VERIFY(opt.amr_threshold >= 0.0 && opt.amr_threshold <= 1.0, "");
Mesh *mesh = S.mesh;
Mesh *smesh = S.mesh;
Array<Refinement> amr;
const int NE = mesh->GetNE();
const int NE = smesh->GetNE();
DenseMatrix Jadjt, Jadj(DIM, SDIM);
for (int e = 0; e < NE; e++)
{
double minW = +NL_DMAX;
double maxW = -NL_DMAX;
ElementTransformation *eTr = mesh->GetElementTransformation(e);
const Geometry::Type &type = mesh->GetElement(e)->GetGeometryType();
ElementTransformation *eTr = smesh->GetElementTransformation(e);
const Geometry::Type &type =
smesh->GetElement(e)->GetGeometryType();
const IntegrationRule *ir = &IntRules.Get(type, opt.order);
const int NQ = ir->GetNPoints();
for (int q = 0; q < NQ; q++)
@@ -431,8 +433,8 @@ public:
}
if (amr.Size()>0)
{
mesh->GetNodes()->HostReadWrite();
mesh->GeneralRefinement(amr);
smesh->GetNodes()->HostReadWrite();
smesh->GeneralRefinement(amr);
S.fes->Update();
x.HostReadWrite();
x.Update();
+5 -5
View File
@@ -185,9 +185,9 @@ Mesh* Make2D(int nsteps, double rstep, double phi, double aspect, int order,
for (int j = 0, k = 0; j < coords.Size(); k++, j += 2)
{
int sfc = ((i & 1) ? coords[j] : (width-1 - coords[j]))
+ coords[j+1]*width;
int old_index = beg + sfc;
int sfc_index = ((i & 1) ? coords[j] : (width-1 - coords[j]))
+ coords[j+1]*width;
int old_index = beg + sfc_index;
ordering[old_index] = beg + k;
new_params[beg + k] = params[old_index];
@@ -221,7 +221,7 @@ Mesh* Make2D(int nsteps, double rstep, double phi, double aspect, int order,
for (int j = 0; j < dofs.Size(); j++)
{
double r, a;
double a;
if (geom == Geometry::SQUARE)
{
r = par.r + ir[j].x * par.dr;
@@ -449,7 +449,7 @@ Mesh* Make3D(int nsteps, double rstep, double aspect, int order, bool sfc)
{
const IntegrationPoint &ip = ir[j];
double u, v, w, r;
double u, v, w;
if (geom == Geometry::PRISM)
{
double l1 = 1.0 - ip.x - ip.y;
+10 -10
View File
@@ -158,22 +158,22 @@ int main(int argc, char *argv[])
const int s = sd+1;
if (dim == 2)
{
for (int j = 0; j <= sd; j++)
for (int i = 0; i < sd; i++)
for (int jj = 0; jj <= sd; jj++)
for (int ii = 0; ii < sd; ii++)
{
dx += abs(mat[j*s + i+1] - mat[j*s + i]);
dy += abs(mat[(i+1)*s + j] - mat[i*s + j]);
dx += abs(mat[jj*s + ii+1] - mat[jj*s + ii]);
dy += abs(mat[(ii+1)*s + jj] - mat[ii*s + jj]);
}
}
else if (dim == 3)
{
for (int k = 0; k <= sd; k++)
for (int j = 0; j <= sd; j++)
for (int i = 0; i < sd; i++)
for (int kk = 0; kk <= sd; kk++)
for (int jj = 0; jj <= sd; jj++)
for (int ii = 0; ii < sd; ii++)
{
dx += abs(mat[(k*s + j)*s + i+1] - mat[(k*s + j)*s + i]);
dy += abs(mat[(k*s + i+1)*s + j] - mat[(k*s + i)*s + j]);
dz += abs(mat[((i+1)*s + j)*s + k] - mat[(i*s + j)*s + k]);
dx += abs(mat[(kk*s + jj)*s + ii+1] - mat[(kk*s + jj)*s + ii]);
dy += abs(mat[(kk*s + ii+1)*s + jj] - mat[(kk*s + ii)*s + jj]);
dz += abs(mat[((ii+1)*s + jj)*s + kk] - mat[(ii*s + jj)*s + kk]);
}
}
type = 0;
+12 -10
View File
@@ -127,18 +127,20 @@ int main(int argc, char *argv[])
}
// Add Elements of the desired type
int v[8];
for (int i=0; i < nphi_; i++)
{
if (el_type_ == Element::WEDGE)
int v[8];
for (int i=0; i < nphi_; i++)
{
for (int j = 0; j < 6; j++) { v[j] = 3*i+j; }
mesh->AddWedge(v);
}
else
{
for (int j = 0; j < 8; j++) { v[j] = 4*i+j; }
mesh->AddHex(v);
if (el_type_ == Element::WEDGE)
{
for (int j = 0; j < 6; j++) { v[j] = 3*i+j; }
mesh->AddWedge(v);
}
else
{
for (int j = 0; j < 8; j++) { v[j] = 4*i+j; }
mesh->AddHex(v);
}
}
}
mesh->FinalizeTopology();
+6 -5
View File
@@ -341,11 +341,12 @@ void NavierSolver::UpdateTimestepHistory(double dt)
un_gf.SetFromTrueDofs(un);
}
void NavierSolver::Step(double &time, double dt, int cur_step, bool provisional)
void NavierSolver::Step(double &time, double dt, int current_step,
bool provisional)
{
sw_step.Start();
SetTimeIntegrationCoefficients(cur_step);
SetTimeIntegrationCoefficients(current_step);
// Set current time for velocity Dirichlet boundary conditions.
for (auto &vel_dbc : vel_dbcs)
@@ -850,7 +851,7 @@ void NavierSolver::ComputeCurl2D(ParGridFunction &u,
double NavierSolver::ComputeCFL(ParGridFunction &u, double dt)
{
ParMesh *pmesh = u.ParFESpace()->GetParMesh();
ParMesh *pmesh_u = u.ParFESpace()->GetParMesh();
FiniteElementSpace *fes = u.FESpace();
int vdim = fes->GetVDim();
@@ -879,7 +880,7 @@ double NavierSolver::ComputeCFL(ParGridFunction &u, double dt)
ut.SetSize(uz.Size());
}
double hmin = pmesh->GetElementSize(e, 1) /
double hmin = pmesh_u->GetElementSize(e, 1) /
(double) fes->GetElementOrder(0);
for (int i = 0; i < ir.GetNPoints(); ++i)
@@ -924,7 +925,7 @@ double NavierSolver::ComputeCFL(ParGridFunction &u, double dt)
1,
MPI_DOUBLE,
MPI_MAX,
pmesh->GetComm());
pmesh_u->GetComm());
return cflmax_global;
}
+5 -5
View File
@@ -366,11 +366,11 @@ int main(int argc, char *argv[])
pvdc.Save();
}
double u_inf_loc = u_gf->Normlinf();
double p_inf_loc = p_gf->Normlinf();
double u_inf = GlobalLpNorm(infinity(), u_inf_loc, MPI_COMM_WORLD);
double p_inf = GlobalLpNorm(infinity(), p_inf_loc, MPI_COMM_WORLD);
double ke = kin_energy.ComputeKineticEnergy(*u_gf);
u_inf_loc = u_gf->Normlinf();
p_inf_loc = p_gf->Normlinf();
u_inf = GlobalLpNorm(infinity(), u_inf_loc, MPI_COMM_WORLD);
p_inf = GlobalLpNorm(infinity(), p_inf_loc, MPI_COMM_WORLD);
ke = kin_energy.ComputeKineticEnergy(*u_gf);
if (mpi.Root())
{
printf("%.5E %.5E %.5E %.5E %.5E\n", t, dt, u_inf, p_inf, ke);
+3 -3
View File
@@ -109,11 +109,11 @@ public:
w *= Q->Eval(Trans, ip);
}
for (int j = 0; j < nd; j++)
for (int jj = 0; jj < nd; jj++)
{
for (int i = 0; i < nd; i++)
for (int ii = 0; ii < nd; ii++)
{
elmat(i, j) += w*shape(i)*laplace(j);
elmat(ii, jj) += w*shape(ii)*laplace(jj);
}
}
}
+3 -3
View File
@@ -121,11 +121,11 @@ public:
w *= Q->Eval(Trans, ip);
}
for (int j = 0; j < nd; j++)
for (int jj = 0; jj < nd; jj++)
{
for (int i = 0; i < nd; i++)
for (int ii = 0; ii < nd; ii++)
{
elmat(i, j) += w*shape(i)*laplace(j);
elmat(ii, jj) += w*shape(ii)*laplace(jj);
}
}
}
+78 -31
View File
@@ -13,6 +13,15 @@
// ex1 -m ../../data/ball-nurbs.mesh -std -asm -pc ho -sc
// ex1 -m ../../data/pipe-nurbs.mesh -perf -mf -pc lor
// ex1 -m ../../data/pipe-nurbs.mesh -std -asm -pc ho -sc
// ex1 -m ../../data/star.mesh -perf -mf -pc lor
// ex1 -m ../../data/star.mesh -perf -asm -pc ho
// ex1 -m ../../data/star.mesh -perf -asm -pc ho -sc
// ex1 -m ../../data/star.mesh -std -asm -pc ho
// ex1 -m ../../data/star.mesh -std -asm -pc ho -sc
// ex1 -m ../../data/amr-quad.mesh -perf -asm -pc ho -sc
// ex1 -m ../../data/amr-quad.mesh -std -asm -pc ho -sc
// ex1 -m ../../data/disc-nurbs.mesh -perf -asm -pc ho -sc
// ex1 -m ../../data/disc-nurbs.mesh -std -asm -pc ho -sc
//
// Description: This example code demonstrates the use of MFEM to define a
// simple finite element discretization of the Laplace problem
@@ -36,29 +45,45 @@
using namespace std;
using namespace mfem;
enum class PCType { NONE, LOR, HO };
// Define template parameters for optimized build.
const Geometry::Type geom = Geometry::CUBE; // mesh elements (default: hex)
const int mesh_p = 3; // mesh curvature (default: 3)
const int sol_p = 3; // solution order (default: 3)
const int rdim = Geometry::Constants<geom>::Dimension;
const int ir_order = 2*sol_p+rdim-1;
template <int dim> struct geom_t { };
template <>
struct geom_t<2> { static const Geometry::Type value = Geometry::SQUARE; };
template <>
struct geom_t<3> { static const Geometry::Type value = Geometry::CUBE; };
// Static mesh type
typedef H1_FiniteElement<geom,mesh_p> mesh_fe_t;
typedef H1_FiniteElementSpace<mesh_fe_t> mesh_fes_t;
typedef TMesh<mesh_fes_t> mesh_t;
const int mesh_p = 3; // mesh curvature (default: 3)
const int sol_p = 3; // solution order (default: 3)
// Static solution finite element space type
typedef H1_FiniteElement<geom,sol_p> sol_fe_t;
typedef H1_FiniteElementSpace<sol_fe_t> sol_fes_t;
template <int dim>
struct ex1_t
{
static const Geometry::Type geom = geom_t<dim>::value;
static const int rdim = Geometry::Constants<geom>::Dimension;
static const int ir_order = 2*sol_p+rdim-1;
// Static quadrature, coefficient and integrator types
typedef TIntegrationRule<geom,ir_order> int_rule_t;
typedef TConstantCoefficient<> coeff_t;
typedef TIntegrator<coeff_t,TDiffusionKernel> integ_t;
// Static mesh type
using mesh_fe_t = H1_FiniteElement<geom,mesh_p>;
using mesh_fes_t = H1_FiniteElementSpace<mesh_fe_t>;
using mesh_t = TMesh<mesh_fes_t>;
// Static bilinear form type, combining the above types
typedef TBilinearForm<mesh_t,sol_fes_t,int_rule_t,integ_t> HPCBilinearForm;
// Static solution finite element space type
using sol_fe_t = H1_FiniteElement<geom,sol_p>;
using sol_fes_t = H1_FiniteElementSpace<sol_fe_t>;
// Static quadrature, coefficient and integrator types
using int_rule_t = TIntegrationRule<geom,ir_order>;
using coeff_t = TConstantCoefficient<>;
using integ_t = TIntegrator<coeff_t,TDiffusionKernel>;
using HPCBilinearForm = TBilinearForm<mesh_t,sol_fes_t,int_rule_t,integ_t>;
static int run(Mesh *mesh, int ref_levels, int order, int basis,
bool static_cond, PCType pc_choice, bool perf,
bool matrix_free, bool visualization);
};
int main(int argc, char *argv[])
{
@@ -113,11 +138,10 @@ int main(int argc, char *argv[])
"--standard-version is not compatible with --matrix-free");
args.PrintOptions(cout);
enum PCType { NONE, LOR, HO };
PCType pc_choice;
if (!strcmp(pc, "ho")) { pc_choice = HO; }
else if (!strcmp(pc, "lor")) { pc_choice = LOR; }
else if (!strcmp(pc, "none")) { pc_choice = NONE; }
if (!strcmp(pc, "ho")) { pc_choice = PCType::HO; }
else if (!strcmp(pc, "lor")) { pc_choice = PCType::LOR; }
else if (!strcmp(pc, "none")) { pc_choice = PCType::NONE; }
else
{
mfem_error("Invalid Preconditioner specified");
@@ -137,6 +161,29 @@ int main(int argc, char *argv[])
Mesh *mesh = new Mesh(mesh_file, 1, 1);
int dim = mesh->Dimension();
if (dim == 2)
{
return ex1_t<2>::run(mesh, ref_levels, order, basis, static_cond,
pc_choice, perf, matrix_free, visualization);
}
else if (dim == 3)
{
return ex1_t<3>::run(mesh, ref_levels, order, basis, static_cond,
pc_choice, perf, matrix_free, visualization);
}
else
{
MFEM_ABORT("Dimension must be 2 or 3.")
}
return 0;
}
template <int dim>
int ex1_t<dim>::run(Mesh *mesh, int ref_levels, int order, int basis,
bool static_cond, PCType pc_choice, bool perf,
bool matrix_free, bool visualization)
{
// 3. Check if the optimized version matches the given mesh
if (perf)
{
@@ -172,8 +219,8 @@ int main(int argc, char *argv[])
}
if (mesh->MeshGenerator() & 1) // simplex mesh
{
MFEM_VERIFY(pc_choice != LOR, "triangle and tet meshes do not support"
" the LOR preconditioner yet");
MFEM_VERIFY(pc_choice != PCType::LOR, "triangle and tet meshes do not "
" support the LOR preconditioner yet");
}
// 5. Define a finite element space on the mesh. Here we use continuous
@@ -202,7 +249,7 @@ int main(int argc, char *argv[])
Mesh mesh_lor;
FiniteElementCollection *fec_lor = NULL;
FiniteElementSpace *fespace_lor = NULL;
if (pc_choice == LOR)
if (pc_choice == PCType::LOR)
{
int basis_lor = basis;
if (basis == BasisType::Positive) { basis_lor=BasisType::ClosedUniform; }
@@ -253,8 +300,8 @@ int main(int argc, char *argv[])
// Optionally setup a form to be assembled for preconditioning (a_pc).
BilinearForm *a = new BilinearForm(fespace);
BilinearForm *a_pc = NULL;
if (pc_choice == LOR) { a_pc = new BilinearForm(fespace_lor); }
if (pc_choice == HO) { a_pc = new BilinearForm(fespace); }
if (pc_choice == PCType::LOR) { a_pc = new BilinearForm(fespace_lor); }
if (pc_choice == PCType::HO) { a_pc = new BilinearForm(fespace); }
// 11. Assemble the bilinear form and the corresponding linear system,
// applying any necessary transformations such as: eliminating boundary
@@ -263,7 +310,7 @@ int main(int argc, char *argv[])
if (static_cond)
{
a->EnableStaticCondensation();
MFEM_VERIFY(pc_choice != LOR,
MFEM_VERIFY(pc_choice != PCType::LOR,
"cannot use LOR preconditioner with static condensation");
}
@@ -322,7 +369,7 @@ int main(int argc, char *argv[])
tic_toc.Start();
SparseMatrix A_pc;
if (pc_choice == LOR)
if (pc_choice == PCType::LOR)
{
// TODO: assemble the LOR matrix using the performance code
a_pc->AddDomainIntegrator(new DiffusionIntegrator(one));
@@ -330,7 +377,7 @@ int main(int argc, char *argv[])
a_pc->Assemble();
a_pc->FormSystemMatrix(ess_tdof_list, A_pc);
}
else if (pc_choice == HO)
else if (pc_choice == PCType::HO)
{
if (!matrix_free)
{
@@ -348,7 +395,7 @@ int main(int argc, char *argv[])
cout << " done, " << tic_toc.RealTime() << "s." << endl;
// Solve with CG or PCG, depending if the matrix A_pc is available
if (pc_choice != NONE)
if (pc_choice != PCType::NONE)
{
GSSmoother M(A_pc);
PCG(*a_oper, M, B, X, 1, 500, 1e-12, 0.0);
+88 -31
View File
@@ -13,6 +13,15 @@
// mpirun -np 4 ex1p -m ../../data/ball-nurbs.mesh -std -asm -pc ho -sc
// mpirun -np 4 ex1p -m ../../data/pipe-nurbs.mesh -perf -mf -pc lor
// mpirun -np 4 ex1p -m ../../data/pipe-nurbs.mesh -std -asm -pc ho -sc
// mpirun -np 4 ex1p -m ../../data/star.mesh -perf -mf -pc lor
// mpirun -np 4 ex1p -m ../../data/star.mesh -perf -asm -pc ho
// mpirun -np 4 ex1p -m ../../data/star.mesh -perf -asm -pc ho -sc
// mpirun -np 4 ex1p -m ../../data/star.mesh -std -asm -pc ho
// mpirun -np 4 ex1p -m ../../data/star.mesh -std -asm -pc ho -sc
// mpirun -np 4 ex1p -m ../../data/amr-quad.mesh -perf -asm -pc ho -sc
// mpirun -np 4 ex1p -m ../../data/amr-quad.mesh -std -asm -pc ho -sc
// mpirun -np 4 ex1p -m ../../data/disc-nurbs.mesh -perf -asm -pc ho -sc
// mpirun -np 4 ex1p -m ../../data/disc-nurbs.mesh -std -asm -pc ho -sc
//
// Description: This example code demonstrates the use of MFEM to define a
// simple finite element discretization of the Laplace problem
@@ -36,29 +45,45 @@
using namespace std;
using namespace mfem;
enum class PCType { NONE, LOR, HO };
// Define template parameters for optimized build.
const Geometry::Type geom = Geometry::CUBE; // mesh elements (default: hex)
const int mesh_p = 3; // mesh curvature (default: 3)
const int sol_p = 3; // solution order (default: 3)
const int rdim = Geometry::Constants<geom>::Dimension;
const int ir_order = 2*sol_p+rdim-1;
template <int dim> struct geom_t { };
template <>
struct geom_t<2> { static const Geometry::Type value = Geometry::SQUARE; };
template <>
struct geom_t<3> { static const Geometry::Type value = Geometry::CUBE; };
// Static mesh type
typedef H1_FiniteElement<geom,mesh_p> mesh_fe_t;
typedef H1_FiniteElementSpace<mesh_fe_t> mesh_fes_t;
typedef TMesh<mesh_fes_t> mesh_t;
const int mesh_p = 3; // mesh curvature (default: 3)
const int sol_p = 3; // solution order (default: 3)
// Static solution finite element space type
typedef H1_FiniteElement<geom,sol_p> sol_fe_t;
typedef H1_FiniteElementSpace<sol_fe_t> sol_fes_t;
template <int dim>
struct ex1_t
{
static const Geometry::Type geom = geom_t<dim>::value;
static const int rdim = Geometry::Constants<geom>::Dimension;
static const int ir_order = 2*sol_p+rdim-1;
// Static quadrature, coefficient and integrator types
typedef TIntegrationRule<geom,ir_order> int_rule_t;
typedef TConstantCoefficient<> coeff_t;
typedef TIntegrator<coeff_t,TDiffusionKernel> integ_t;
// Static mesh type
using mesh_fe_t = H1_FiniteElement<geom,mesh_p>;
using mesh_fes_t = H1_FiniteElementSpace<mesh_fe_t>;
using mesh_t = TMesh<mesh_fes_t>;
// Static bilinear form type, combining the above types
typedef TBilinearForm<mesh_t,sol_fes_t,int_rule_t,integ_t> HPCBilinearForm;
// Static solution finite element space type
using sol_fe_t = H1_FiniteElement<geom,sol_p>;
using sol_fes_t = H1_FiniteElementSpace<sol_fe_t>;
// Static quadrature, coefficient and integrator types
using int_rule_t = TIntegrationRule<geom,ir_order>;
using coeff_t = TConstantCoefficient<>;
using integ_t = TIntegrator<coeff_t,TDiffusionKernel>;
using HPCBilinearForm = TBilinearForm<mesh_t,sol_fes_t,int_rule_t,integ_t>;
static int run(Mesh *mesh, int ser_ref_levels, int par_ref_levels, int order,
int basis, bool static_cond, PCType pc_choice, bool perf,
bool matrix_free, bool visualization);
};
int main(int argc, char *argv[])
{
@@ -69,7 +94,11 @@ int main(int argc, char *argv[])
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
// 2. Parse command-line options.
#ifdef MFEM_HPC_EX1_2D
const char *mesh_file = "../../data/star.mesh";
#else
const char *mesh_file = "../../data/fichera.mesh";
#endif
int ser_ref_levels = -1;
int par_ref_levels = 1;
int order = sol_p;
@@ -133,11 +162,10 @@ int main(int argc, char *argv[])
args.PrintOptions(cout);
}
enum PCType { NONE, LOR, HO };
PCType pc_choice;
if (!strcmp(pc, "ho")) { pc_choice = HO; }
else if (!strcmp(pc, "lor")) { pc_choice = LOR; }
else if (!strcmp(pc, "none")) { pc_choice = NONE; }
if (!strcmp(pc, "ho")) { pc_choice = PCType::HO; }
else if (!strcmp(pc, "lor")) { pc_choice = PCType::LOR; }
else if (!strcmp(pc, "none")) { pc_choice = PCType::NONE; }
else
{
mfem_error("Invalid Preconditioner specified");
@@ -163,6 +191,35 @@ int main(int argc, char *argv[])
Mesh *mesh = new Mesh(mesh_file, 1, 1);
int dim = mesh->Dimension();
if (dim == 2)
{
return ex1_t<2>::run(mesh, ser_ref_levels, par_ref_levels, order, basis,
static_cond, pc_choice, perf, matrix_free,
visualization);
}
else if (dim == 3)
{
return ex1_t<3>::run(mesh, ser_ref_levels, par_ref_levels, order,
basis, static_cond, pc_choice, perf, matrix_free,
visualization);
}
else
{
MFEM_ABORT("Dimension must be 2 or 3.")
}
return 0;
}
template <int dim>
int ex1_t<dim>::run(Mesh *mesh, int ser_ref_levels, int par_ref_levels,
int order, int basis, bool static_cond, PCType pc_choice,
bool perf, bool matrix_free, bool visualization)
{
int num_procs, myid;
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
// 4. Check if the optimized version matches the given mesh
if (perf)
{
@@ -230,8 +287,8 @@ int main(int argc, char *argv[])
}
if (pmesh->MeshGenerator() & 1) // simplex mesh
{
MFEM_VERIFY(pc_choice != LOR, "triangle and tet meshes do not support"
" the LOR preconditioner yet");
MFEM_VERIFY(pc_choice != PCType::LOR, "triangle and tet meshes do not "
"support the LOR preconditioner yet");
}
// 7. Define a parallel finite element space on the parallel mesh. Here we
@@ -264,7 +321,7 @@ int main(int argc, char *argv[])
ParMesh pmesh_lor;
FiniteElementCollection *fec_lor = NULL;
ParFiniteElementSpace *fespace_lor = NULL;
if (pc_choice == LOR)
if (pc_choice == PCType::LOR)
{
int basis_lor = basis;
if (basis == BasisType::Positive) { basis_lor=BasisType::ClosedUniform; }
@@ -318,8 +375,8 @@ int main(int argc, char *argv[])
// that will hold the matrix corresponding to the Laplacian operator.
ParBilinearForm *a = new ParBilinearForm(fespace);
ParBilinearForm *a_pc = NULL;
if (pc_choice == LOR) { a_pc = new ParBilinearForm(fespace_lor); }
if (pc_choice == HO) { a_pc = new ParBilinearForm(fespace); }
if (pc_choice == PCType::LOR) { a_pc = new ParBilinearForm(fespace_lor); }
if (pc_choice == PCType::HO) { a_pc = new ParBilinearForm(fespace); }
// 13. Assemble the parallel bilinear form and the corresponding linear
// system, applying any necessary transformations such as: parallel
@@ -328,7 +385,7 @@ int main(int argc, char *argv[])
if (static_cond)
{
a->EnableStaticCondensation();
MFEM_VERIFY(pc_choice != LOR,
MFEM_VERIFY(pc_choice != PCType::LOR,
"cannot use LOR preconditioner with static condensation");
}
@@ -404,7 +461,7 @@ int main(int argc, char *argv[])
tic_toc.Start();
HypreParMatrix A_pc;
if (pc_choice == LOR)
if (pc_choice == PCType::LOR)
{
// TODO: assemble the LOR matrix using the performance code
a_pc->AddDomainIntegrator(new DiffusionIntegrator(one));
@@ -412,7 +469,7 @@ int main(int argc, char *argv[])
a_pc->Assemble();
a_pc->FormSystemMatrix(ess_tdof_list, A_pc);
}
else if (pc_choice == HO)
else if (pc_choice == PCType::HO)
{
if (!matrix_free)
{
@@ -441,7 +498,7 @@ int main(int argc, char *argv[])
HypreSolver *amg = NULL;
pcg->SetOperator(*a_oper);
if (pc_choice != NONE)
if (pc_choice != PCType::NONE)
{
amg = new HypreBoomerAMG(A_pc);
pcg->SetPreconditioner(*amg);
+1
View File
@@ -17,6 +17,7 @@ if (MFEM_USE_MPI)
list(APPEND DIST_COMMON_HEADERS
dist_solver.hpp
sbm_solver.hpp
sbm_aux.hpp
marking.hpp)
convert_filenames_to_full_paths(DIST_COMMON_SOURCES)
+3 -3
View File
@@ -604,7 +604,7 @@ int main(int argc, char *argv[])
if (dirichlet_level_set_type == 2 || dirichlet_level_set_type == 3 ||
(dirichlet_level_set_type == -1 && neumann_level_set_type == 2))
{
ParGridFunction err(x);
ParGridFunction error(x);
Vector pxyz(dim);
pxyz(0) = 0.;
for (int i = 0; i < nodes_cnt; i++)
@@ -620,7 +620,7 @@ int main(int argc, char *argv[])
{
exact_val = dirichlet_velocity_xy_sinusoidal(pxyz);
}
err(i) = std::fabs(x(i) - exact_val);
error(i) = std::fabs(x(i) - exact_val);
}
if (visualization)
@@ -628,7 +628,7 @@ int main(int argc, char *argv[])
char vishost[] = "localhost";
int visport = 19916, s = 350;
socketstream sol_sock;
common::VisualizeField(sol_sock, vishost, visport, err,
common::VisualizeField(sol_sock, vishost, visport, error,
"Error", 2*s, 0, s, s, "Rj");
}
+2 -2
View File
@@ -211,13 +211,13 @@ void HeatDistanceSolver::ComputeScalarDistance(Coefficient &zero_level_set,
a_n.RecoverFEMSolution(X, b, u_neumann);
delete prec2;
for (int i = 0; i < diffused_source.Size(); i++)
for (int ii = 0; ii < diffused_source.Size(); ii++)
{
// This assumes that the magnitudes of the two solutions are somewhat
// similar; otherwise one of the solutions would dominate and the BC
// won't look correct. To avoid this, it's good to have the source
// away from the boundary (i.e. have more resolution).
diffused_source(i) = 0.5 * (u_neumann(i) + u_dirichlet(i));
diffused_source(ii) = 0.5 * (u_neumann(ii) + u_dirichlet(ii));
}
source = diffused_source;
}
+3 -3
View File
@@ -53,15 +53,15 @@ COMMON_LIB += $(if $(MFEM_SHARED:YES=),,\
%: %.cpp
%.o: %.cpp
%.o: $(SRC)%.cpp $(wildcard $(SRC)%.hpp) $(MFEM_LIB_FILE) $(CONFIG_MK) | lib-common
%.o: $(SRC)%.cpp sbm_aux.hpp $(wildcard $(SRC)%.hpp) $(MFEM_LIB_FILE) $(CONFIG_MK) | lib-common
$(MFEM_CXX) $(MFEM_FLAGS) -c $< -o $@
all: $(MINIAPPS)
distance: sbm_aux.hpp $(DISTANCE_OBJ)
distance: $(DISTANCE_OBJ)
$(MFEM_CXX) $(MFEM_LINK_FLAGS) -o $@ $(DISTANCE_OBJ) $(COMMON_LIB) $(MFEM_LIBS)
diffusion: sbm_aux.hpp $(DIFFUSION_OBJ)
diffusion: $(DIFFUSION_OBJ)
$(MFEM_CXX) $(MFEM_LINK_FLAGS) -o $@ $(DIFFUSION_OBJ) $(COMMON_LIB) $(MFEM_LIBS)
# Rule for building lib-common
+10 -24
View File
@@ -233,7 +233,7 @@ void SBM2DirichletIntegrator::AssembleFaceMatrix(
Vector D(vD->GetVDim());
// Assemble: -< \nabla u.n, w >
// -< u + \nabla u.d + h.o.t, \nabla w.n>
// -<alpha h^{-1} (u + \nabla u.d + h.o.t), w + \nabla w.d + h.o.t>
// +<alpha h^{-1} (u + \nabla u.d + h.o.t), w + \nabla w.d + h.o.t>
for (int p = 0; p < ir->GetNPoints(); p++)
{
const IntegrationPoint &ip = ir->IntPoint(p);
@@ -324,10 +324,9 @@ void SBM2DirichletIntegrator::AssembleFaceMatrix(
w = ip.weight*alpha*hinvdx;
// + <alpha * hinv * u + grad u.d + h.o.t, w + grad w.d + h.o.t> - Term 4
AddMult_a_VVt(w, wrk, temp_elmat);
int offset = elem1f ? 0 : ndof1;
elmat.CopyMN(temp_elmat, offset, offset);
} // p < ir->GetNPoints()
int offset = elem1f ? 0 : ndof1;
elmat.CopyMN(temp_elmat, offset, offset);
for (int i = 0; i < dkphi_dxk.Size(); i++)
{
@@ -436,8 +435,8 @@ void SBM2DirichletLFIntegrator::AssembleRHSElementVect(
}
}
temp_elvect.SetSize(ndof);
temp_elvect = 0.0;
int offset = elem1f ? 0 : ndof1;
temp_elvect.SetDataAndSize(elvect.GetData()+offset, ndof);
nor.SetSize(dim);
nh.SetSize(dim);
@@ -541,10 +540,9 @@ void SBM2DirichletLFIntegrator::AssembleRHSElementVect(
Vector D(vD->GetVDim());
Vector wrk = shape;
// Assemble: -< u_D, \nabla w.n >
// -<alpha h^{-1} u_D, w + \nabla w.d + h.o.t>
// +<alpha h^{-1} u_D, w + \nabla w.d + h.o.t>
for (int p = 0; p < ir->GetNPoints(); p++)
{
const IntegrationPoint &ip = ir->IntPoint(p);
// Set the integration point in the face and the neighboring element
@@ -636,12 +634,6 @@ void SBM2DirichletLFIntegrator::AssembleRHSElementVect(
wrk += dshape_dd; // \grad w .d
wrk += q_hess_dot_d;
temp_elvect.Add(w, wrk); // <u, gradw.d>
int offset = elem1f ? 0 : ndof1;
for (int i = 0; i < temp_elvect.Size(); i++)
{
elvect(i+offset) = temp_elvect(i);
}
}
for (int i = 0; i < dkphi_dxk.Size(); i++)
@@ -927,9 +919,9 @@ void SBM2NeumannIntegrator::AssembleFaceMatrix(
wrk *= ip.weight * n_dot_ntilde;
AddMult_a_VWt(1., shape, wrk, temp_elmat);
int offset = elem1f ? 0 : ndof1;
elmat.CopyMN(temp_elmat, offset, offset);
} //p < ir->GetNPoints()
int offset = elem1f ? 0 : ndof1;
elmat.CopyMN(temp_elmat, offset, offset);
for (int i = 0; i < dkphi_dxk.Size(); i++)
{
@@ -1036,8 +1028,8 @@ void SBM2NeumannLFIntegrator::AssembleRHSElementVect(
}
}
temp_elvect.SetSize(ndof);
temp_elvect = 0.0;
int offset = elem1f ? 0 : ndof1;
temp_elvect.SetDataAndSize(elvect.GetData()+offset, ndof);
nor.SetSize(dim);
shape.SetSize(ndof);
@@ -1094,12 +1086,6 @@ void SBM2NeumannLFIntegrator::AssembleRHSElementVect(
wrk.Set(n_dot_ntilde*w, shape);
//<w, (nhat.n)t_n)
temp_elvect.Add(1., wrk);
int offset = elem1f ? 0 : ndof1;
for (int i = 0; i < temp_elvect.Size(); i++)
{
elvect(i+offset) = temp_elvect(i);
}
}
}
+2 -2
View File
@@ -78,7 +78,7 @@ public:
/// method.
/// A(u, w) = -<nabla u.n, w>
/// -<u + nabla u.d + h.o.t, nabla w.n>
/// -<alpha h^{-1} (u + nabla u.d + h.o.t), w + nabla w.d + h.o.t>
/// +<alpha h^{-1} (u + nabla u.d + h.o.t), w + nabla w.d + h.o.t>
/// where h.o.t include higher-order derivatives (nabla^k u) due to Taylor
/// expansion. Since this interior face integrator is applied to the surrogate
/// boundary (see marking.hpp for notes on how the surrogate faces are
@@ -133,7 +133,7 @@ public:
/// LinearFormIntegrator for the high-order extension of shifted boundary
/// method.
/// (u, w) = -<u_D, nabla w.n >
/// -<alpha h^{-1} u_D, w + nabla w.d + h.o.t>
/// +<alpha h^{-1} u_D, w + nabla w.d + h.o.t>
/// where h.o.t include higher-order derivatives (nabla^k u) due to Taylor
/// expansion. Since this interior face integrator is applied to the surrogate
/// boundary (see marking.hpp for notes on how the surrogate faces are
+18 -18
View File
@@ -157,15 +157,15 @@ int main(int argc, char *argv[])
}
args.PrintOptions(mfem::out);
DataCollection *src = create_data_collection(std::string(src_coll_name),
std::string(src_coll_type));
DataCollection *src_dc = create_data_collection(std::string(src_coll_name),
std::string(src_coll_type));
DataCollection *out = create_data_collection(std::string(out_coll_name),
std::string(out_coll_type));
DataCollection *out_dc = create_data_collection(std::string(out_coll_name),
std::string(out_coll_type));
src->Load(src_cycle);
src_dc->Load(src_cycle);
if (src->Error() != DataCollection::NO_ERROR)
if (src_dc->Error() != DataCollection::NO_ERROR)
{
mfem::out << "Error loading data collection: "
<< src_coll_name
@@ -176,33 +176,33 @@ int main(int argc, char *argv[])
return 1;
}
out->SetOwnData(false);
out_dc->SetOwnData(false);
// add mesh from source dc to output dc
#ifdef MFEM_USE_MPI
out->SetMesh(MPI_COMM_WORLD,src->GetMesh());
out_dc->SetMesh(MPI_COMM_WORLD,src_dc->GetMesh());
#else
out->SetMesh(src->GetMesh());
out_dc->SetMesh(src_dc->GetMesh());
#endif
// propagate the basics
out->SetCycle(src->GetCycle());
out->SetTime(src->GetTime());
out->SetTimeStep(src->GetTimeStep());
out_dc->SetCycle(src_dc->GetCycle());
out_dc->SetTime(src_dc->GetTime());
out_dc->SetTimeStep(src_dc->GetTimeStep());
// loop over all fields in the source dc, and add them to the output dc
const DataCollection::FieldMapType &src_fields = src->GetFieldMap();
const DataCollection::FieldMapType &src_fields = src_dc->GetFieldMap();
for (DataCollection::FieldMapType::const_iterator it = src_fields.begin();
it != src_fields.end();
++it)
{
out->RegisterField(it->first,it->second);
out_dc->RegisterField(it->first,it->second);
}
out->Save();
out_dc->Save();
if (out->Error() != DataCollection::NO_ERROR)
if (out_dc->Error() != DataCollection::NO_ERROR)
{
mfem::out << "Error saving data collection: "
<< out_coll_name
@@ -214,8 +214,8 @@ int main(int argc, char *argv[])
}
// cleanup
delete src;
delete out;
delete src_dc;
delete out_dc;
return 0;
}
+9 -9
View File
@@ -148,7 +148,7 @@ double u_function(const Vector &x)
// Tubular Lissajous curve with the given parameters (a, b, theta)
void lissajous_trans(const Vector &x, Vector &p,
double a, double b, double delta)
double a_, double b_, double delta_)
{
p.SetSize(3);
@@ -156,13 +156,13 @@ void lissajous_trans(const Vector &x, Vector &p,
double theta = x[1];
double t = phi;
double A = b; // Scaling of the curve along the x-axis
double B = a; // Scaling of the curve along the y-axis
double A = b_; // Scaling of the curve along the x-axis
double B = a_; // Scaling of the curve along the y-axis
// Lissajous curve on a 3D cylinder
p[0] = B*cos(b*t);
p[1] = B*sin(b*t); // Y
p[2] = A*sin(a*t + delta); // X
p[0] = B*cos(b_*t);
p[1] = B*sin(b_*t); // Y
p[2] = A*sin(a_*t + delta_); // X
// Turn the curve into a tubular surface
{
@@ -170,14 +170,14 @@ void lissajous_trans(const Vector &x, Vector &p,
double R = 0.02*(A+B);
// normal to the cylinder at p(t)
double normal[3] = { cos(b*t), sin(b*t), 0 };
double normal[3] = { cos(b_*t), sin(b_*t), 0 };
// tangent to the curve, dp/dt(t)
// double tangent[3] = { -b*B*sin(b*t), b*B*cos(b*t), A*a*cos(a*t+delta) };
// double tangent[3] = { -b_*B*sin(b_*t), b_*B*cos(b_*t), A*a_*cos(a_*t+delta_) };
// normalized cross product of tangent and normal at p(t)
double cn = 1e-128;
double cross[3] = { A*a*sin(b*t)*cos(a*t+delta), -A*a*cos(b*t)*cos(a*t+delta), b*B };
double cross[3] = { A*a_*sin(b_*t)*cos(a_*t+delta_), -A*a_*cos(b_*t)*cos(a_*t+delta_), b_*B };
for (int i = 0; i < 3; i++) { cn += cross[i]*cross[i]; }
for (int i = 0; i < 3; i++) { cross[i] /= sqrt(cn); }
+11 -11
View File
@@ -36,15 +36,15 @@ using namespace std;
//
// In this particular miniapp, the material value is based on the number of
// iterations for the point from the definition of the Mandelbrot set.
int material(Vector &x, Vector &xmin, Vector &xmax)
int material(Vector &p, Vector &pmin, Vector &pmax)
{
// Rescaling to [0,1]^sdim
for (int i = 0; i < x.Size(); i++)
for (int i = 0; i < p.Size(); i++)
{
x(i) = (x(i)-xmin(i))/(xmax(i)-xmin(i));
p(i) = (p(i)-pmin(i))/(pmax(i)-pmin(i));
}
x(0) -= 0.1;
double col = x(0), row = x(1);
p(0) -= 0.1;
double col = p(0), row = p(1);
{
int width = 1080, height = 1080;
col *= width;
@@ -131,14 +131,14 @@ int main(int argc, char *argv[])
for (int iter = 0; 1; iter++)
{
Array<Refinement> refs;
for (int i = 0; i < mesh.GetNE(); i++)
for (int e = 0; e < mesh.GetNE(); e++)
{
bool refine = false;
// Sample materials in each element using "sd" sub-divisions
Vector pt;
Geometry::Type geom = mesh.GetElementBaseGeometry(i);
ElementTransformation *T = mesh.GetElementTransformation(i);
Geometry::Type geom = mesh.GetElementBaseGeometry(e);
ElementTransformation *T = mesh.GetElementTransformation(e);
RefinedGeometry *RefG = GlobGeometryRefiner.Refine(geom, sd, 1);
IntegrationRule &ir = RefG->RefPts;
@@ -160,8 +160,8 @@ int main(int argc, char *argv[])
}
// Set the element attribute as the "average". Other choices are
// possible here too, e.g. attr(i) = mat;
attr(i) = round(matsum/ir.GetNPoints());
// possible here too, e.g. attr(e) = mat;
attr(e) = round(matsum/ir.GetNPoints());
// Mark the element for refinement
if (refine)
@@ -200,7 +200,7 @@ int main(int argc, char *argv[])
if (!type) { type = 7; } // because of tol
}
refs.Append(Refinement(i, type));
refs.Append(Refinement(e, type));
}
}
+10 -10
View File
@@ -180,22 +180,22 @@ int main(int argc, char *argv[])
const int s = sd+1;
if (dim == 2)
{
for (int j = 0; j <= sd; j++)
for (int i = 0; i < sd; i++)
for (int jj = 0; jj <= sd; jj++)
for (int ii = 0; ii < sd; ii++)
{
dx += abs(mat[j*s + i+1] - mat[j*s + i]);
dy += abs(mat[(i+1)*s + j] - mat[i*s + j]);
dx += abs(mat[jj*s + ii+1] - mat[jj*s + ii]);
dy += abs(mat[(ii+1)*s + jj] - mat[ii*s + jj]);
}
}
else if (dim == 3)
{
for (int k = 0; k <= sd; k++)
for (int j = 0; j <= sd; j++)
for (int i = 0; i < sd; i++)
for (int kk = 0; kk <= sd; kk++)
for (int jj = 0; jj <= sd; jj++)
for (int ii = 0; ii < sd; ii++)
{
dx += abs(mat[(k*s + j)*s + i+1] - mat[(k*s + j)*s + i]);
dy += abs(mat[(k*s + i+1)*s + j] - mat[(k*s + i)*s + j]);
dz += abs(mat[((i+1)*s + j)*s + k] - mat[(i*s + j)*s + k]);
dx += abs(mat[(kk*s + jj)*s + ii+1] - mat[(kk*s + jj)*s + ii]);
dy += abs(mat[(kk*s + ii+1)*s + jj] - mat[(kk*s + ii)*s + jj]);
dz += abs(mat[((ii+1)*s + jj)*s + kk] - mat[(ii*s + jj)*s + kk]);
}
}
type = 0;
+14 -14
View File
@@ -873,30 +873,30 @@ update_state(char axis, int tier, int incr)
}
void
print_state(ostream & out)
print_state(ostream & out_stream)
{
out << "Rubik's Cube State:\n";
out << " Centers: ";
out_stream << "Rubik's Cube State:\n";
out_stream << " Centers: ";
for (int i=0; i<6; i++)
{
out << " " << rubik.cent_[i];
out_stream << " " << rubik.cent_[i];
}
out << "\n";
out << " Edges: ";
out_stream << "\n";
out_stream << " Edges: ";
for (int i=0; i<12; i++)
{
out << " " << rubik.edge_[2 * i + 0]
<< ":" << rubik.edge_[2 * i + 1];
out_stream << " " << rubik.edge_[2 * i + 0]
<< ":" << rubik.edge_[2 * i + 1];
}
out << "\n";
out << " Corners: ";
out_stream << "\n";
out_stream << " Corners: ";
for (int i=0; i<8; i++)
{
out << " " << rubik.corn_[3 * i + 0]
<< ":" << rubik.corn_[3 * i + 1]
<< ":" << rubik.corn_[3 * i + 2];
out_stream << " " << rubik.corn_[3 * i + 0]
<< ":" << rubik.corn_[3 * i + 1]
<< ":" << rubik.corn_[3 * i + 2];
}
out << "\n";
out_stream << "\n";
}
void repaint_cube(Mesh & mesh, GridFunction & color, socketstream & sock)
+4 -4
View File
@@ -366,12 +366,12 @@ rotate(double * x)
}
void
trans(const int * conf, Mesh & mesh)
trans(const int * new_conf, Mesh & mesh)
{
for (int i=0; i<23; i++)
{
joint_ = i;
notch_ = conf[i];
notch_ = new_conf[i];
if (notch_ != 0)
{
@@ -444,12 +444,12 @@ rotate_step(double * x)
}
bool
anim_step(const int * conf, Mesh & mesh)
anim_step(const int * new_conf, Mesh & mesh)
{
if (notch_ == 2 && step_ == 2 * nstep_) { joint_++; step_ = 0; }
if (notch_ != 2 && step_ == nstep_) { joint_++; step_ = 0; }
if (joint_ == 23) { return false; }
notch_ = conf[joint_];
notch_ = new_conf[joint_];
if (notch_ == 0)
{
+1
View File
@@ -70,6 +70,7 @@ set(UNIT_TESTS_SRCS
fem/test_lexicographic_ordering.cpp
fem/test_lin_interp.cpp
fem/test_linear_fes.cpp
fem/test_lor.cpp
fem/test_operatorjacobismoother.cpp
fem/test_pa_coeff.cpp
fem/test_pa_grad.cpp

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