Compare commits

..
239 Commits
Author SHA1 Message Date
IdoAkkerman b09b5dbab5 Fix test error 2024-06-12 16:42:22 +02:00
IdoAkkerman ece1b1fd3d More merge fix stuff 2024-06-12 16:42:06 +02:00
IdoAkkerman 86f72cd22e Merge remote-tracking branch 'origin/master' into dev-stab-mini 2024-06-12 16:41:21 +02:00
IdoAkkerman 97c4aed444 Add nullspace unit test 2024-06-12 14:48:42 +02:00
IdoAkkerman 03199fe1fd Small parallel printing fix 2024-06-12 14:46:26 +02:00
IdoAkkerman aed9945c40 Clean up 2024-06-12 14:46:02 +02:00
IdoAkkerman 25d65f4275 Make style 2024-06-12 14:44:51 +02:00
IdoAkkerman 05989d5d29 Stab Navsto miniapps tweaks 2024-06-12 14:41:32 +02:00
IdoAkkerman 5d762f7cb5 Use EV routines in Dense=Matrix for InverseEstimate coefficients + make style 2024-06-12 14:37:11 +02:00
IdoAkkerman bf5c6ebd23 More eigen problem related routines to densemat 2024-06-12 14:36:08 +02:00
Tzanio Kolev 8153d11274 Merge pull request #3999 from mfem/hdiv-nurbs
Adding H(div) and H(curl) conforming NURBS FiniteElements
2024-06-11 22:37:08 +01:00
Tzanio Kolev 827ed64113 Merge branch 'master' into hdiv-nurbs 2024-06-11 22:36:58 +01:00
Tzanio Kolev ef9f02ba53 Merge pull request #2854 from mfem/var-order-href-op
Variable order space: h-(de)refinement transfer operator
2024-06-11 20:25:12 +01:00
Tzanio Kolev e9a0b0620a Update tests/unit/fem/test_hp_transfer.cpp 2024-06-11 12:24:39 -07:00
Tzanio Kolev 4d9d444248 Merge pull request #4343 from mfem/sample-runs-update
Sample runs update
2024-06-11 20:23:41 +01:00
Tzanio Kolev 6e2badecca Merge pull request #4337 from mfem/lapack-cleanup
Deduplicate single/double precision LAPACK
2024-06-11 20:22:01 +01:00
Tzanio Kolev 99b45fcb02 Merge pull request #4327 from mfem/sjg/mesh-vertex-bdr-table
Add `Mesh::GetVertexToBdrElementTable`
2024-06-11 20:20:12 +01:00
Will Pazner 9a327eeca6 Merge pull request #4332 from mfem/sjg/cuda-atomicadd-fix
Fix compiler error for `real_t` and old CUDA architectures < 60
2024-06-10 17:07:12 -04:00
IdoAkkerman a1d003aec0 Add parallel navsto 2024-06-10 15:31:07 +02:00
IdoAkkerman fa87595f9a Add elastic inverse estimate - a.o. 2024-06-10 15:30:44 +02:00
IdoAkkerman c4697ba253 Tweaks in powermethod 2024-06-10 15:29:19 +02:00
IdoAkkerman 5e01a5433d IMPORTANT: Add HESS as derivType 2024-06-10 09:16:46 +02:00
IdoAkkerman 4833b17636 IMPORTANT: reordering hessian 2024-06-10 09:12:02 +02:00
IdoAkkerman 34378ffc5b Stab navsto kind of works 2024-06-06 17:03:11 +02:00
IdoAkkerman a6e3e8e695 Begin of stab nav sto implementation 2024-06-06 14:47:27 +02:00
IdoAkkerman 8af34d985e Add delta 2024-06-06 11:59:31 +02:00
IdoAkkerman 0f55696c69 Remove print statement 2024-06-06 11:58:52 +02:00
IdoAkkerman f4a6f33284 Fix small bug -- add interface 2024-06-06 11:56:42 +02:00
IdoAkkerman 781efd2d50 Taus in seperate file + put tau in place for stab nav sto 2024-06-06 09:40:57 +02:00
IdoAkkerman 9035279bcb Reinstate scaling in inverse estimate computation 2024-06-06 09:39:20 +02:00
Will Pazner 262fa6173d Remove unneeded '#ifdef MFEM_USE_SINGLE' 2024-06-05 21:20:59 -07:00
Will Pazner e4b8584a16 Formatting 2024-06-05 21:20:59 -07:00
Socratis Petrides 7912d6915d silly mistake 2024-06-05 18:16:45 -07:00
Socratis Petrides 293d9009ae replace abort with skip so that make test passes with lapack 2024-06-05 17:25:00 -07:00
Socratis Petrides 51bde67bb1 fixing default tol in eltrans 2024-06-05 17:24:24 -07:00
Sebastian Grimberg 45e2636921 Address PR feedback: Add const 2024-06-05 14:19:49 -07:00
IdoAkkerman 613a55d318 Add convection to navsto 2024-06-05 10:58:06 +02:00
Veselin Dobrev 35225e045e Updated the script 'config/sample-runs.sh' to
* run examples 40-99
* run autodiff, dpg, hdiv-linear-solver, and moonolith miniapps
* run additional meshing miniapps
* add 'todo' comments for other missing miniapps

Updated the formatting of sample runs in miniapps/dpg.
2024-06-04 14:17:13 -07:00
Socratis Petrides 22c1087503 VariableOrderRefinementMatrix_main -> VariableOrderRefinementMatrix 2024-06-04 11:32:24 -07:00
IdoAkkerman 732e3c33f4 Galerkin Stokes -- > needs checking 2024-06-04 17:58:50 +02:00
IdoAkkerman 0586c0feee Tweak examples 2024-06-04 12:42:18 +02:00
IdoAkkerman 7e1186afd2 Tweaks 2024-06-04 12:24:10 +02:00
IdoAkkerman ffd3088722 Cleanup stuff 2024-06-04 11:47:54 +02:00
Socratis Petrides cd5d2f7c04 minor tweaks 2024-06-03 22:21:20 -07:00
Will Pazner cbae29ad06 Suppress Doxygen warnings in LAPACK header
Otherwise Doxygen complains:

warning: documented symbol 'void mfem::MFEM_LAPACK_PREFIX' was not declared or defined.
2024-06-02 13:21:37 -07:00
Will Pazner 4c1d842c72 Adjust tolerances depending on single or double precision
ex38 was not converging in single precision with previous tolerances
2024-06-02 13:21:37 -07:00
Will Pazner 4aa0ed52af Don't duplicate single and double precision LAPACK code
Introduce MFEM_LAPACK_PREFIX and MFEM_LAPACK_COMPLEX to prepend 's', 'd', 'c',
or 'z' to the BLAS/LAPACK function name according to the precision.

Add new header lapack.hpp with declarations of the LAPACK functions.
2024-06-02 13:06:51 -07:00
Socratis Petrides 8712d02570 remove leftover RT space from enum 2024-05-31 11:17:00 -07:00
Socratis Petrides e5fec6279b minor fix 2024-05-31 11:11:24 -07:00
Socratis Petrides e90e96f9a5 add unit L2 test 2024-05-31 11:04:51 -07:00
Sebastian Grimberg cc00ef7d90 Fix compiler error for real_t and old CUDA architectures pre-6.0 2024-05-30 13:52:27 -07:00
IdoAkkerman 62c535d0ee Merge branch 'hdiv-nurbs' of github.com:mfem/mfem into hdiv-nurbs 2024-05-29 17:56:33 +02:00
IdoAkkerman 17829d1c38 Seperate NURBS examples in dox - small typo 2024-05-29 17:56:15 +02:00
IdoAkkerman dd198ce3f9 Seperate NURBS examples in dox 2024-05-29 17:54:43 +02:00
IdoAkkerman b9f36468ba Move changes to v 4.7.1 2024-05-29 17:45:30 +02:00
IdoAkkerman d5b127caff Remove tad files from CMake 2024-05-29 17:24:53 +02:00
Tzanio Kolev 76bcd044d0 Merge branch 'master' into hdiv-nurbs 2024-05-29 07:49:33 -07:00
IdoAkkerman a2132dac0c Add biharm example 2024-05-28 09:56:47 +02:00
IdoAkkerman 28916b23a4 Merge branch 'master' into hdiv-nurbs 2024-05-27 10:24:58 +02:00
IdoAkkerman 7476c00f2b Solenoidal convergence check SINGLE/DOUBLE 2024-05-27 10:23:03 +02:00
Socratis Petrides 7a0137c496 generalize unit test 2024-05-24 12:49:18 -07:00
Socratis Petrides 4267b2af05 fix for using Rhp in the deref case and addressing reviewer comments 2024-05-24 12:48:51 -07:00
Socratis Petrides e37daad5eb fix from Dylan 2024-05-24 12:48:10 -07:00
IdoAkkerman 289a241f81 Add an alpha term 2024-05-24 15:43:29 +02:00
IdoAkkerman d0850268e3 Removed files 2024-05-24 15:42:27 +02:00
IdoAkkerman 133bf60546 make style 2024-05-24 15:41:50 +02:00
IdoAkkerman 9f13192930 InverseEstimateFix 2024-05-24 15:41:10 +02:00
Socratis Petrides 20b4b72071 Merge branch 'master' into var-order-href-op 2024-05-23 19:25:48 -07:00
Sebastian Grimberg ddf80492c5 Add Mesh::GetVertexToBdrElementTable 2024-05-23 11:13:16 -07:00
IdoAkkerman 60d70b7d3d Make style 2024-05-23 13:53:32 +02:00
IdoAkkerman 7f946e0920 Revert "Add MixedLaplaceIntegrator class"
This reverts commit 9dbc125598.
2024-05-23 13:48:11 +02:00
IdoAkkerman 0456014a32 Merge branch 'dev-stab-mini' of /home/ido/Data/mfem/mfem into dev-stab-mini 2024-05-23 13:39:48 +02:00
IdoAkkerman 77d98d68c3 Make style + bug fix 2024-05-23 13:39:45 +02:00
IdoAkkerman f8d18cd4be Merge branch 'master' into hdiv-nurbs 2024-05-22 17:45:58 +02:00
IdoAkkerman 994d83dd80 Modify tolerance for single precision - more relaxed 2024-05-22 17:44:17 +02:00
IdoAkkerman f218efae09 Modify tolerance for single precision 2024-05-22 16:06:11 +02:00
IdoAkkerman 9bea5c01b7 Merge remote-tracking branch 'origin/hdiv-nurbs' into dev-stab-mini 2024-05-22 10:43:37 +02:00
michi002 9dbc125598 Add MixedLaplaceIntegrator class
This commit introduces the MixedLaplaceIntegrator class in bilininteg.hpp and implements its methods in bilininteg.cpp. This class is for integrating the bilinear form $(Q\Delta u,v)$ where $Q$ is a scalar coefficient, $u$ is in a $C^1$ nurbs space and $v$ is defined on the same nurbs mesh. It is a reimplementation of "LaplaceIntegrator" for mixed spaces. Attention: Don't we need a "CalcPhysLaplacian" in the original routine?
2024-05-21 12:42:03 +02:00
Ido Akkerman af24eaea27 Merge branch 'master' into hdiv-nurbs 2024-05-21 10:57:13 +02:00
IdoAkkerman 8adb7461b0 Comment on array of NURBSexts 2024-05-15 10:38:14 +02:00
IdoAkkerman 716e370d35 Fix merge 2024-05-14 14:21:58 +02:00
IdoAkkerman 37c0768fe3 Merge branch 'master' into hdiv-nurbs 2024-05-14 14:12:44 +02:00
IdoAkkerman 51860e9192 Add auto diff and inverse estimate 2024-04-19 11:06:41 +02:00
IdoAkkerman e81ad14586 Add inverse estimate coefficient 2024-04-19 11:05:03 +02:00
IdoAkkerman ef1d5f86bf Add mixed scalar laplace integrators 2024-04-19 11:03:57 +02:00
IdoAkkerman 6c5cfbfc65 Rough sketch of miniapss 2024-04-11 12:00:40 +02:00
IdoAkkerman 2bd8bb4c3b Add scalar laplace bilinear integrators 2024-04-08 12:29:03 +02:00
IdoAkkerman 1c38648d5f Add laplace linear form 2024-04-08 10:08:33 +02:00
Ido Akkerman 875b5f3f52 Update nurbs_naca_cmesh.cpp 2024-04-05 22:34:26 +02:00
IdoAkkerman be1f36a523 Merge branch 'master' into hdiv-nurbs 2024-04-05 21:54:43 +02:00
IdoAkkerman d4c7dd3490 Double -> Real 2024-04-05 21:53:48 +02:00
IdoAkkerman 637854fd90 Works 2024-04-05 17:44:30 +02:00
IdoAkkerman e55fb21538 Merge branch 'master' into mod-ex23 2024-04-05 14:36:47 +02:00
IdoAkkerman a966b0502f Rewrite BC enforcement 2024-04-05 12:59:41 +02:00
IdoAkkerman 1bac61ad1c Typos 2024-04-05 09:04:06 +02:00
IdoAkkerman c7451115d8 Typos 2024-04-05 09:00:12 +02:00
IdoAkkerman 72ae003a00 double -> real_t 2024-04-05 08:51:50 +02:00
IdoAkkerman d67098b8f8 remove unused variable 2024-04-04 22:06:01 +02:00
IdoAkkerman 0e6dbaf050 remove 999 statement 2024-04-04 21:52:34 +02:00
IdoAkkerman 32afc8565c remove 9999 statement 2024-04-04 21:48:24 +02:00
IdoAkkerman 48ace60875 order[2] big fix + small cosmetic changes 2024-04-04 21:46:38 +02:00
IdoAkkerman 9b6ee6fcad Add papers -- comment flipped with previous commit 2024-04-04 14:44:54 +02:00
IdoAkkerman 1a1639b87e Add neumann example 2024-04-04 14:44:14 +02:00
IdoAkkerman 3735aa504b Comments dec 2023 2024-04-04 12:50:03 +02:00
Ido Akkerman 367dda6794 Merge branch 'master' into hdiv-nurbs 2024-04-04 11:59:43 +02:00
IdoAkkerman e4a85f79cd Remove multipatch examples in ex24 2024-04-03 22:30:00 +02:00
IdoAkkerman 678101938b Merge branch 'master' into hdiv-nurbs 2024-04-03 13:37:00 +02:00
IdoAkkerman 9a3aa18c62 Fix 3D Hcurl 2024-04-03 13:24:20 +02:00
IdoAkkerman 5a3ba1424a Update comments 2024-04-02 13:29:48 +02:00
IdoAkkerman 3bb8419a96 Add miniapp source to doc 2024-04-02 13:07:45 +02:00
IdoAkkerman ce29282f63 Add Hdiv and Hcurl NURBS to changelog 2024-04-02 12:51:37 +02:00
IdoAkkerman 9575299ae3 Merge branch 'master' into hdiv-nurbs 2024-04-02 09:04:07 +02:00
IdoAkkerman 995ceca6c2 Cosmetic fix of 2D Hcurl dof count 2024-04-02 09:03:04 +02:00
IdoAkkerman 6abd0e6002 Fix 2d Curl 2024-03-28 13:29:15 +01:00
IdoAkkerman 656e3062b4 Fix mesh name in example 2024-03-28 13:14:40 +01:00
IdoAkkerman 9c9c519175 Add exso.mesh to gitignore -- prevent regression test error 2024-03-27 14:23:14 +01:00
IdoAkkerman 8300809562 Fix double real_t conversion 2024-03-27 13:57:51 +01:00
IdoAkkerman cce7296ffe Tweak example runs in miniapps; add comments; remove comments 2024-03-27 13:39:50 +01:00
IdoAkkerman a445ad00da Update clean statement in makefile 2024-03-27 13:38:26 +01:00
IdoAkkerman 4db7e1a107 Add comments to NURB extension mode 2024-03-27 13:37:36 +01:00
IdoAkkerman c51a1c4aa9 Remove comment in nurbs, tweak error statement 2024-03-27 13:37:09 +01:00
IdoAkkerman d489908e50 Merge branch 'master' into hdiv-nurbs 2024-03-26 16:55:17 +01:00
IdoAkkerman c4eda188d5 Tweak nurbs ex24 2024-03-26 16:31:27 +01:00
IdoAkkerman 677eb4c876 Change solver params for nurbs ex5 2024-03-26 16:30:57 +01:00
IdoAkkerman 69a4aa70b9 Fix mapping in NURBS Hdiv 3D 2024-03-26 15:37:49 +01:00
IdoAkkerman f07c2f460d Update copyright statement 2024-03-26 10:29:49 +01:00
Socratis Petrides 09c557bdd7 Merge branch 'master' into var-order-href-op 2024-03-21 19:45:57 -07:00
Socratis Petrides e487da01c5 adding unit tests 2024-03-21 19:44:43 -07:00
IdoAkkerman b6b6843ad2 Merge branch 'master' into hdiv-nurbs 2024-03-21 15:46:53 +01:00
Mittal, Ketan 66a1379947 Merge branch 'var-order-href-op' of https://github.com/mfem/mfem into var-order-href-op 2024-03-13 13:10:41 -07:00
Mittal, Ketan 546ba6c11e add support for h-derefinement 2024-03-13 13:10:24 -07:00
Mittal, Ketan 67ba63c2f4 Merge branch 'master' of https://github.com/mfem/mfem into var-order-href-op 2024-03-13 13:08:02 -07:00
Socratis Petrides 99c2967920 Merge branch 'master' into var-order-href-op 2024-03-08 12:07:52 -08:00
Socratis Petrides 2dc419f1ae Merge branch 'master' into var-order-href-op 2024-03-04 11:36:38 -08:00
Mittal, Ketan 450d6cea6d Merge branch 'master' of https://github.com/mfem/mfem into var-order-href-op 2024-03-04 09:51:05 -08:00
Socratis Petrides 75df4ad3e6 replace umfpack with PCG 2024-02-16 12:18:21 -08:00
Socratis Petrides 4048d46443 Merge branch 'master' into var-order-href-op 2024-02-16 12:02:58 -08:00
IdoAkkerman b03cf507be Fix debug stuff 2023-12-21 17:04:02 +01:00
IdoAkkerman 066dc9b078 Us prev. unused variable 2023-12-21 15:16:29 +01:00
IdoAkkerman 70854254e7 Report Dofs in boundary for ex5 2023-12-21 14:45:42 +01:00
IdoAkkerman 646df28ac8 Add sign to Hdiv bdr dof indices 2023-12-21 14:45:09 +01:00
IdoAkkerman 73d4f987e4 Add direction to 2D Hdiv bdr indices 2023-12-21 14:14:39 +01:00
IdoAkkerman c59d519c89 Allow for negative dof indices 2023-12-21 14:12:21 +01:00
IdoAkkerman 1ec2cba9e8 Allow for negative dof indices in Table merge constructor 2023-12-21 14:11:11 +01:00
IdoAkkerman 26cc1f8387 Fix 2D curl 2023-12-21 09:40:38 +01:00
IdoAkkerman b57fa2b127 Add neumann/periodic test case 2023-12-20 12:53:32 +01:00
IdoAkkerman 596909138a Cleaner bc selection/reporting in ex1 2023-12-20 12:53:07 +01:00
IdoAkkerman c11a76f2c1 Update make clean call 2023-12-19 16:52:34 +01:00
IdoAkkerman 51d32ad293 merge master - manual 2023-12-19 16:16:00 +01:00
IdoAkkerman a433e9e0b4 Fix small numbering issue 2023-12-19 14:33:07 +01:00
IdoAkkerman abac61f5b5 Add Hcurl boundary + allow GF read to set dim with seperate call 2023-12-19 14:32:26 +01:00
IdoAkkerman a121a9d186 Small order fix 2023-12-19 14:31:20 +01:00
IdoAkkerman 58ecbf6150 Use new ext and table modes 2023-12-19 14:30:23 +01:00
IdoAkkerman bad5ae41d1 Add bdr dof selection option 2023-12-19 14:29:35 +01:00
IdoAkkerman e773e07373 Make Table merge generic 2023-12-19 14:28:17 +01:00
IdoAkkerman c3ded3c003 Add dim for fe_coll and ess bc output 2023-12-19 14:27:47 +01:00
IdoAkkerman 76e04c4606 Make style 2023-12-15 17:24:11 +01:00
IdoAkkerman 83ccf77d2f Fixing gitignore 2023-12-15 17:00:57 +01:00
IdoAkkerman a0d53975d8 Adding boundary elements to Hdiv collection pt2 2023-12-15 16:17:49 +01:00
IdoAkkerman 1252c0fbb9 Merge branch 'hdiv-nurbs' of /home/ido/Data/mfem/mfem into hdiv-nurbs 2023-12-15 16:14:34 +01:00
IdoAkkerman 04acf613ae Adding boundary elements to Hdiv collection 2023-12-15 16:14:20 +01:00
IdoAkkerman c8bddb8035 Merge branch 'master' into hdiv-nurbs 2023-12-15 14:38:11 +01:00
IdoAkkerman 467e83da31 Fixed nurbs miniapps 2023-12-15 14:36:31 +01:00
IdoAkkerman 8b29ef1335 style fix in fe_nurbs 2023-12-15 14:26:34 +01:00
IdoAkkerman 1076700714 Cmake fixes 2023-12-15 14:26:03 +01:00
IdoAkkerman 978f1155c5 Update Makefile 2023-12-15 14:25:34 +01:00
IdoAkkerman 3096d9d9cb Fixed some sloppiness 2023-12-15 13:51:27 +01:00
IdoAkkerman ffea75abb2 Fixed Table comments 2023-12-15 13:47:04 +01:00
IdoAkkerman a44a8b8789 Made booleans const 2023-12-15 13:43:09 +01:00
IdoAkkerman 05106096c3 Symmetrice delete call 2023-12-15 13:41:43 +01:00
IdoAkkerman ba7fd7a9a9 Remove superfluous hdiv check 2023-12-15 13:38:44 +01:00
IdoAkkerman 9b0e4e0085 Fix nurbs miniapp cmake 2023-12-15 13:38:25 +01:00
IdoAkkerman 3cb64f7f7e Merge branch 'hdiv-nurbs' of /home/ido/Data/mfem/mfem into hdiv-nurbs 2023-12-15 13:25:28 +01:00
IdoAkkerman 6642857437 Fix uninit error 2023-11-29 17:19:52 +01:00
IdoAkkerman 91f00d643a Fix shadow varaibel in fespace 2023-11-29 17:12:17 +01:00
IdoAkkerman ce8b62cfe7 Add override keyword for macosx 2 2023-11-29 16:51:03 +01:00
IdoAkkerman 4064bda60d Add override keyword for macosx 2023-11-29 16:50:15 +01:00
IdoAkkerman 4a21554986 Remove unused variables from table 2023-11-29 16:43:10 +01:00
IdoAkkerman 165968dc26 Make style 2023-11-29 16:40:48 +01:00
IdoAkkerman 9eb70f7be0 Add tests 2023-11-29 16:38:01 +01:00
IdoAkkerman 8797a9cb00 Small ex24 tweaks 2023-11-29 16:37:42 +01:00
IdoAkkerman 8366a5a6d6 Fix documentation error 2023-11-29 12:17:15 +01:00
IdoAkkerman 63a9d5749b Delete parallel miniapp 2023-11-29 12:16:58 +01:00
IdoAkkerman 0e6aa41245 Update nurbs miniapps 2023-11-29 12:11:37 +01:00
IdoAkkerman bbcb054814 example update 2023-11-29 12:08:38 +01:00
IdoAkkerman 2e5a86db7a Merge branch 'master' into hdiv-nurbs 2023-11-29 09:24:21 +01:00
IdoAkkerman 057b15cefb miniapps/nurbs/nurbs_ex24p.cpp 2023-11-28 16:52:13 +01:00
IdoAkkerman 7c06741f36 Remove debug print statement 2023-11-28 15:37:41 +01:00
IdoAkkerman 3a0c42aea5 Add L2 projection for NURBS 2023-11-28 15:37:16 +01:00
IdoAkkerman 75d5555a5f Component output not necessary anymore 2023-11-28 10:35:37 +01:00
IdoAkkerman 10c1ac9a66 Add nurbs hdiv hcurl examples/tests 2023-11-28 10:34:06 +01:00
IdoAkkerman 692e15c088 Make style 2023-11-28 09:57:11 +01:00
IdoAkkerman 6be9665bfb Add mappings to VShape Trans calls 2023-11-27 17:24:23 +01:00
IdoAkkerman 9be617d754 Add Hdiv and Hcurl NURBS to fe coll selection mechanism 2023-11-27 16:58:10 +01:00
IdoAkkerman ec4f37fe25 Make style 2023-11-27 16:57:28 +01:00
IdoAkkerman 6bb4ae9d50 Small correction in solenoidal test app 2023-11-27 16:57:00 +01:00
IdoAkkerman c7a3f188c0 Add output 2023-11-21 17:28:15 +01:00
IdoAkkerman 8e44509585 Make style 2023-11-21 17:27:26 +01:00
IdoAkkerman 787954715b Make style and small compile order fix nurbs fe 2023-11-21 17:26:30 +01:00
IdoAkkerman 9f03260dd2 Fix Hcurl boundary dof table 2 2023-11-21 17:24:23 +01:00
IdoAkkerman 5c3a3f7fdf Add Curl miniapp 2023-11-21 13:08:20 +01:00
IdoAkkerman 6693b22c83 Small compile fixes 2023-11-21 12:55:01 +01:00
IdoAkkerman 49c7f60a57 Add routines to make a Hcurl fespace 2023-11-21 12:49:37 +01:00
IdoAkkerman ace4608f10 Add H curl NURBS collection 2023-11-21 12:41:06 +01:00
IdoAkkerman 3899dfcc64 Remove interfaces -- will implement in follow-up PR 2023-11-21 12:40:39 +01:00
IdoAkkerman 2dc98e9153 Add H curl NURBS elements 2023-11-21 12:39:47 +01:00
IdoAkkerman 90f8a2409f Add divergence free test case 2023-11-21 11:59:37 +01:00
IdoAkkerman 92dc0db889 Fix patch check 2023-11-21 10:23:42 +01:00
IdoAkkerman d8fc48e608 Clean up of projection miniapp 2023-11-20 14:21:05 +01:00
IdoAkkerman 611802f990 Rename extension routine 2023-11-20 14:18:27 +01:00
IdoAkkerman 606df86b0a Component Extension generator 2023-11-20 14:08:27 +01:00
IdoAkkerman 2f7d38e6f6 Fix typo 2023-11-20 14:00:19 +01:00
IdoAkkerman b90d665ced Clean fe collection 2023-11-20 14:00:04 +01:00
IdoAkkerman 50dd77ffd4 Make style 2023-11-20 13:53:10 +01:00
IdoAkkerman 5e5b79783c Other comment -- make style 2023-11-20 13:51:37 +01:00
IdoAkkerman c815114661 Add explaination to new table constructors 2023-11-20 13:48:53 +01:00
IdoAkkerman 93f6a53201 FES cleaning, renaming and memleak fix 2023-11-20 13:35:55 +01:00
IdoAkkerman a3ee0cfe79 Add 3D gradient and hessian -- compile fixes 2023-11-20 12:06:55 +01:00
IdoAkkerman 95b0178514 Add 3D gradient and hessian 2023-11-20 11:40:34 +01:00
IdoAkkerman afacf3db45 Add 3D function 2023-11-17 17:58:20 +01:00
IdoAkkerman 4a80321420 Add 3D output 2023-11-17 17:52:35 +01:00
IdoAkkerman 9295c69249 Hdiv 3D fixes 2023-11-17 17:44:58 +01:00
IdoAkkerman 893f04967c add geom option to NURBS HDiv fecoll 2023-11-17 17:16:05 +01:00
IdoAkkerman fa410a6e02 Correct type in fespace 2023-11-17 17:15:19 +01:00
IdoAkkerman aed2687743 Add 3D HDiv elements 2023-11-17 17:03:08 +01:00
IdoAkkerman 978c0d10bc Add 3D to fespace 2023-11-17 16:41:43 +01:00
IdoAkkerman 25b540e804 Add 3D table merge 2023-11-17 16:41:06 +01:00
IdoAkkerman 9aa58cd5c2 Modify fe space to accomodate Hdiv NURBS 2023-11-17 15:38:39 +01:00
IdoAkkerman 691be01bcc Add constructors to table that merge existing tables 2023-11-17 15:38:10 +01:00
IdoAkkerman 402ed45ee4 Add Hdiv fe collection 2023-11-17 15:37:31 +01:00
IdoAkkerman 07dfcd83b9 Add 2D Hdiv NURBS basis 2023-11-17 15:37:10 +01:00
IdoAkkerman 9845dfda2c Add VectorBasis derivative interfaces 2023-11-17 15:36:42 +01:00
IdoAkkerman da5ee77e61 Add div free option 2023-11-17 14:07:06 +01:00
IdoAkkerman e1d2966e42 Add neumann bcs to nurbs_ex1 miniapp 2023-11-17 14:05:09 +01:00
IdoAkkerman 17428ce198 Add div-free option 2023-11-17 13:21:40 +01:00
IdoAkkerman e87e790215 add nurbs solenoidal miniapp for checking Hdif elemenet 2023-11-16 16:46:41 +01:00
Socratis Petrides a6d4e17911 Transfer Operator as a SparseMatrix 2022-02-25 13:50:07 -08:00
Socratis Petrides bde7846b5a style 2022-02-24 17:43:11 -08:00
Socratis Petrides 01283767a6 variable order href transfer for the 'ANY_TYPE' transfer operator 2022-02-24 17:42:41 -08:00
124 changed files with 9384 additions and 16294 deletions
+11
View File
@@ -272,16 +272,27 @@ miniapps/navier/*_output
miniapps/nurbs/nurbs_ex1
miniapps/nurbs/nurbs_ex1p
miniapps/nurbs/nurbs_ex3
miniapps/nurbs/nurbs_ex5
miniapps/nurbs/nurbs_ex11p
miniapps/nurbs/nurbs_ex24
miniapps/nurbs/nurbs_solenoidal
miniapps/nurbs/nurbs_printfunc
miniapps/nurbs/nurbs_patch_ex1
miniapps/nurbs/nurbs_curveint
miniapps/nurbs/refined.mesh
miniapps/nurbs/mesh.*
miniapps/nurbs/sol_?.gf
miniapps/nurbs/sol.*
miniapps/nurbs/mode_*
miniapps/nurbs/Example1*
miniapps/nurbs/Example3*
miniapps/nurbs/Example5*
miniapps/nurbs/Solenoidal*
miniapps/nurbs/ParaView
miniapps/nurbs/sin-fit.mesh
miniapps/nurbs/ex5.mesh
miniapps/nurbs/exsol.mesh
miniapps/nurbs/CurveInt
miniapps/nurbs/nurbs_naca_cmesh
miniapps/nurbs/naca-cmesh.mesh
+5
View File
@@ -11,6 +11,11 @@
Version 4.7.1 (development)
===========================
- Added NURBS-based H(div) and H(curl) elements in 2D and 3D. Only on single
patch meshes. Only implemented for serial computations.
- Added miniapps to demonstrate the H(div) and H(curl) NURBS elements.
- Added an MFEM example for the eikonal equation. This new solver is based on
the proximal Galerkin method introduced by Keith and Surowiec.
+83 -13
View File
@@ -32,7 +32,7 @@ groups_serial=(
'"examples"
"Examples:"
"examples"
"ex{,1,2,3}[0-9].cpp"'
"ex{,[1-9]}[0-9].cpp"'
# "ex1.cpp"'
'"sundials"
"SUNDIALS examples:"
@@ -58,6 +58,10 @@ groups_serial=(
"HiOp examples:"
"examples/hiop"
"ex9.cpp"'
'"moonolith"
"Moonolith examples:"
"examples/moonolith"
"ex1.cpp"'
'"pumi"
"PUMI examples:"
"examples/pumi"
@@ -66,25 +70,38 @@ groups_serial=(
'"meshing"
"Meshing miniapps:"
"miniapps/meshing"
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp mesh-quality.cpp
polar-nc.cpp reflector.cpp shaper.cpp trimmer.cpp twist.cpp
mesh-optimizer.cpp minimal-surface.cpp"'
'"adjoint"
"Adjoint miniapps:"
"miniapps/adjoint"
"cvsRoberts_ASAi_dns.cpp"'
'"autodiff"
"Autodiff miniapps:"
"miniapps/autodiff"
"seq_example.cpp seq_test.cpp"' # 'seq_test.cpp' has no sample runs
'"dpg"
"DPG miniapps:"
"miniapps/dpg"
"{acoustics,convection-diffusion,diffusion,maxwell}.cpp"'
'"gslib"
"GSLIB miniapps:"
"miniapps/gslib"
"field-diff.cpp field-interp.cpp findpts.cpp schwarz_ex1.cpp "'
# todo: miniapps/mtop
'"nurbs"
"NURBS miniapps:"
"miniapps/nurbs"
"nurbs_ex1.cpp"'
# todo: add other nurbs miniapps
# todo: miniapps/solvers (serial)
'"tools"
"Tools miniapps:"
"miniapps/tools"
"convert-dc.cpp display-basis.cpp get-values.cpp load-dc.cpp
lor-transfer.cpp"'
# todo: add other tools miniapps
'"toys"
"Toys miniapps:"
"miniapps/toys"
@@ -100,7 +117,7 @@ groups_parallel=(
'"examples"
"Examples:"
"examples"
"ex{,1,2,3}[0-9]p.cpp"'
"ex{,[1-9]}[0-9]p.cpp"'
# "ex1p.cpp"'
'"sundials"
"SUNDIALS examples:"
@@ -126,6 +143,10 @@ groups_parallel=(
"HiOp examples:"
"examples/hiop"
"ex9p.cpp"'
'"moonolith"
"Moonolith examples:"
"examples/moonolith"
"ex{1,2}p.cpp"'
'"pumi"
"PUMI examples:"
"examples/pumi"
@@ -138,24 +159,41 @@ groups_parallel=(
'"meshing"
"Meshing miniapps:"
"miniapps/meshing"
"pmesh-optimizer.cpp pmesh-fitting.cpp pminimal-surface.cpp"'
"pmesh-optimizer.cpp pmesh-fitting.cpp pminimal-surface.cpp
fit-node-position.cpp"'
'"electromagnetics"
"Electromagnetics miniapps:"
"miniapps/electromagnetics"
"joule.cpp"'
# "{volta,tesla,joule}.cpp"' # todo: multiline sample runs
# "{joule,maxwell,tesla,volta}.cpp"' # todo: multiline sample runs
'"adjoint"
"Adjoint miniapps:"
"miniapps/adjoint"
"adjoint_advection_diffusion.cpp"'
'"autodiff"
"Autodiff miniapps:"
"miniapps/autodiff"
"par_example.cpp"'
'"dpg"
"DPG miniapps:"
"miniapps/dpg"
"p{acoustics,convection-diffusion,diffusion,maxwell}.cpp"'
'"gslib"
"GSLIB miniapps:"
"miniapps/gslib"
"pfindpts.cpp schwarz_ex1p.cpp"'
'"hdiv-linear-solver"
"H(div) linear solver miniapps:"
"miniapps/hdiv-linear-solver"
"grad_div.cpp darcy.cpp"'
# 'miniapps/hooke/hooke.cpp' has no sample runs
# todo: miniapps/mtop
# todo: miniapps/multidomain
'"navier"
"Navier miniapps:"
"miniapps/navier"
"navier_cht.cpp"'
# todo: add other navier miniapps
'"nurbs"
"NURBS miniapps:"
"miniapps/nurbs"
@@ -164,14 +202,18 @@ groups_parallel=(
"Shifted miniapps:"
"miniapps/shifted"
"distance.cpp"'
# todo: add other shifted miniapps
'"solvers"
"Solvers miniapps:"
"miniapps/solvers"
"block-solvers.cpp"'
# todo: add other solvers miniapps
# todo: miniapps/spde
'"tools"
"Tools miniapps:"
"miniapps/tools"
"convert-cd.cpp get-values.cpp load-dc.cpp"'
"convert-dc.cpp get-values.cpp load-dc.cpp"'
# todo: add other tools miniapps
'"convergence"
"Convergence tests:"
"tests/convergence"
@@ -186,7 +228,7 @@ groups_all=(
'"examples"
"Examples:"
"examples"
"ex\"{,1,2,3}[0-9]\"{,p}.cpp"'
"ex\"{,[1-9]}[0-9]\"{,p}.cpp"'
'"sundials"
"SUNDIALS examples:"
"examples/sundials"
@@ -215,10 +257,14 @@ groups_all=(
"HiOp examples:"
"examples/hiop"
"ex9.cpp ex9p.cpp"'
'"moonolith"
"Moonolith examples:"
"examples/moonolith"
"ex1.cpp ex{1,2}p.cpp"'
'"pumi"
"PUMI examples:"
"examples/pumi"
"ex1.cpp ex1p.cpp ex2.cpp ex6p.cpp"'
"ex1.cpp ex2.cpp ex1p.cpp ex6p.cpp"'
'"superlu"
"Superlu examples:"
"examples/superlu"
@@ -226,43 +272,67 @@ groups_all=(
'"meshing"
"Meshing miniapps:"
"miniapps/meshing"
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp
{,p}mesh-optimizer.cpp pmesh-fitting.cpp {,p}minimal-surface.cpp"'
"mobius-strip.cpp klein-bottle.cpp extruder.cpp toroid.cpp mesh-quality.cpp
polar-nc.cpp reflector.cpp shaper.cpp trimmer.cpp twist.cpp
{,p}mesh-optimizer.cpp pmesh-fitting.cpp {,p}minimal-surface.cpp
fit-node-position.cpp"'
'"electromagnetics"
"Electromagnetics miniapps:"
"miniapps/electromagnetics"
"joule.cpp"'
# "{volta,tesla,joule}.cpp"' # todo: multiline sample runs
# "{joule,maxwell,tesla,volta}.cpp"' # todo: multiline sample runs
'"adjoint"
"Adjoint miniapps:"
"miniapps/adjoint"
"adjoint_advection_diffusion.cpp cvsRoberts_ASAi_dns.cpp"'
"cvsRoberts_ASAi_dns.cpp adjoint_advection_diffusion.cpp"'
'"autodiff"
"Autodiff miniapps:"
"miniapps/autodiff"
"seq_example.cpp seq_test.cpp par_example.cpp"'
# 'seq_test.cpp' has no sample runs
'"dpg"
"DPG miniapps:"
"miniapps/dpg"
"{,p}{acoustics,convection-diffusion,diffusion,maxwell}.cpp"'
'"gslib"
"GSLIB miniapps:"
"miniapps/gslib"
"field-diff.cpp field-interp.cpp findpts.cpp schwarz_ex1.cpp pfindpts.cpp
schwarz_ex1p.cpp"'
'"hdiv-linear-solver"
"H(div) linear solver miniapps:"
"miniapps/hdiv-linear-solver"
"grad_div.cpp darcy.cpp"'
# 'miniapps/hooke/hooke.cpp' has no sample runs
# todo: miniapps/mtop
# todo: miniapps/multidomain
'"navier"
"Navier miniapps:"
"miniapps/navier"
"navier_cht.cpp"'
# todo: add other navier miniapps
'"nurbs"
"NURBS miniapps:"
"miniapps/nurbs"
"nurbs_ex1.cpp nurbs_ex1p.cpp nurbs_ex11p.cpp"'
# todo: add other nurbs miniapps
'"shifted"
"Shifted miniapps:"
"miniapps/shifted"
"distance.cpp"'
# todo: add other shifted miniapps
'"solvers"
"Solvers miniapps:"
"miniapps/solvers"
"block-solvers.cpp"'
# todo: add other solvers miniapps
# todo: miniapps/spde
'"tools"
"Tools miniapps:"
"miniapps/tools"
"convert-dc.cpp display-basis.cpp get-values.cpp load-dc.cpp
lor-transfer.cpp"'
# todo: add other tools miniapps
'"toys"
"Toys miniapps:"
"miniapps/toys"
@@ -386,7 +456,7 @@ function help_message()
mfem_config [${mfem_config}]
Set MFEM configuration options
make [${make}], mpiexec [${mpiexec}], mpiexec_np [${mpiexec_np}]
Their values can also set using the respective uppercase environment
Their values can also be set using the respective uppercase environment
variable
mfem_build_dir [${mfem_build_dir}]
Same as '-d': set this variable to something different from <mfem_dir>
-102
View File
@@ -1,102 +0,0 @@
MFEM mesh v1.0
dimension
4
elements
24
1 7 4 5 8 11 13
1 7 1 4 5 7 8
1 7 1 4 5 8 11
1 7 1 5 8 11 13
1 7 1 5 7 8 13
1 7 4 5 7 8 13
1 7 1 3 4 8 11
1 7 1 3 4 5 11
1 7 1 5 10 11 13
1 7 1 8 10 11 13
1 7 1 3 5 10 11
1 7 1 2 3 5 10
1 7 0 1 3 4 8
1 7 0 1 4 7 8
1 7 1 5 6 7 13
1 7 1 6 7 8 13
1 7 6 7 8 13 15
1 7 4 7 8 13 15
1 7 4 8 12 13 15
1 7 4 8 11 12 13
1 7 6 8 13 14 15
1 7 1 6 8 13 14
1 7 1 8 9 10 13
1 7 1 8 9 13 14
boundary
48
1 4 0 1 3 4
1 4 0 1 3 8
1 4 0 3 4 8
1 4 0 1 4 7
1 4 0 1 7 8
1 4 0 4 7 8
1 4 1 4 5 7
1 4 1 3 8 11
1 4 1 3 4 5
1 4 1 5 10 13
1 4 1 8 10 11
1 4 1 3 10 11
1 4 1 2 3 5
1 4 1 2 3 10
1 4 1 2 5 10
1 4 1 5 6 7
1 4 1 5 6 13
1 4 1 6 7 8
1 4 1 6 8 14
1 4 1 6 13 14
1 4 1 8 9 10
1 4 1 9 10 13
1 4 1 8 9 14
1 4 1 9 13 14
1 4 2 3 5 10
1 4 3 4 8 11
1 4 3 4 5 11
1 4 3 5 10 11
1 4 4 5 11 13
1 4 4 5 7 13
1 4 4 7 8 15
1 4 4 7 13 15
1 4 4 8 12 15
1 4 4 12 13 15
1 4 4 8 11 12
1 4 4 11 12 13
1 4 5 10 11 13
1 4 5 6 7 13
1 4 6 7 8 15
1 4 6 7 13 15
1 4 6 8 14 15
1 4 6 13 14 15
2 4 8 10 11 13
2 4 8 12 13 15
2 4 8 11 12 13
2 4 8 13 14 15
2 4 8 9 10 13
2 4 8 9 13 14
vertices
16
4
0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
1.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
1.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000
1.0000000000000000 0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 0.0000000000000000 1.0000000000000000
1.0000000000000000 0.0000000000000000 0.0000000000000000 1.0000000000000000
1.0000000000000000 1.0000000000000000 0.0000000000000000 1.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000 1.0000000000000000
0.0000000000000000 1.0000000000000000 1.0000000000000000 1.0000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000 1.0000000000000000
1.0000000000000000 0.0000000000000000 1.0000000000000000 1.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0000000000000000
-102
View File
@@ -1,102 +0,0 @@
MFEM mesh v1.0
dimension
4
elements
24
17 8 4 5 8 11 13
11 8 1 4 5 7 8
15 8 1 4 5 8 11
16 8 1 5 8 11 13
12 8 1 5 7 8 13
13 8 4 5 7 8 13
7 8 1 3 4 8 11
2 8 1 3 4 5 11
4 8 1 5 10 11 13
10 8 1 8 10 11 13
3 8 1 3 5 10 11
1 8 1 2 3 5 10
6 8 0 1 3 4 8
8 8 0 1 4 7 8
5 8 1 5 6 7 13
20 8 1 6 7 8 13
19 8 6 7 8 13 15
14 8 4 7 8 13 15
21 8 4 8 12 13 15
22 8 4 8 11 12 13
23 8 6 8 13 14 15
24 8 1 6 8 13 14
9 8 1 8 9 10 13
18 8 1 8 9 13 14
boundary
48
1 4 0 1 3 4
3 4 0 1 3 8
3 4 0 3 4 8
1 4 0 1 4 7
3 4 0 1 7 8
3 4 0 4 7 8
1 4 1 4 5 7
3 4 1 3 8 11
1 4 1 3 4 5
3 4 1 5 10 13
3 4 1 8 10 11
3 4 1 3 10 11
1 4 1 2 3 5
3 4 1 2 3 10
3 4 1 2 5 10
1 4 1 5 6 7
3 4 1 5 6 13
3 4 1 6 7 8
3 4 1 6 8 14
3 4 1 6 13 14
3 4 1 8 9 10
3 4 1 9 10 13
3 4 1 8 9 14
3 4 1 9 13 14
3 4 2 3 5 10
3 4 3 4 8 11
3 4 3 4 5 11
3 4 3 5 10 11
3 4 4 5 11 13
3 4 4 5 7 13
3 4 4 7 8 15
3 4 4 7 13 15
3 4 4 8 12 15
3 4 4 12 13 15
3 4 4 8 11 12
3 4 4 11 12 13
3 4 5 10 11 13
3 4 5 6 7 13
3 4 6 7 8 15
3 4 6 7 13 15
3 4 6 8 14 15
3 4 6 13 14 15
5 4 8 10 11 13
5 4 8 12 13 15
5 4 8 11 12 13
5 4 8 13 14 15
5 4 8 9 10 13
5 4 8 9 13 14
vertices
16
4
0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
1.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
1.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000
1.0000000000000000 0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 0.0000000000000000 1.0000000000000000
1.0000000000000000 0.0000000000000000 0.0000000000000000 1.0000000000000000
1.0000000000000000 1.0000000000000000 0.0000000000000000 1.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000 1.0000000000000000
0.0000000000000000 1.0000000000000000 1.0000000000000000 1.0000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000 1.0000000000000000
1.0000000000000000 0.0000000000000000 1.0000000000000000 1.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0000000000000000
-231
View File
@@ -1,231 +0,0 @@
MFEM mesh v1.0
dimension
4
elements
96
1 8 0 1 7 8 9
1 8 1 6 7 8 9
1 8 4 5 6 8 9
1 8 4 6 7 8 9
1 8 0 1 3 8 9
1 8 1 2 3 8 9
1 8 0 4 7 8 9
1 8 0 3 4 8 9
1 8 1 2 6 8 9
1 8 2 5 6 8 9
1 8 3 4 5 8 9
1 8 2 3 5 8 9
1 8 9 10 11 17 18
1 8 9 11 16 17 18
1 8 9 14 15 16 18
1 8 9 14 16 17 18
1 8 9 10 11 13 18
1 8 9 11 12 13 18
1 8 9 10 14 17 18
1 8 9 10 13 14 18
1 8 9 11 12 16 18
1 8 9 12 15 16 18
1 8 9 13 14 15 18
1 8 9 12 13 15 18
1 8 9 12 15 16 19
1 8 9 11 12 16 19
1 8 1 6 9 11 19
1 8 6 9 11 16 19
1 8 1 2 6 9 19
1 8 2 5 6 9 19
1 8 2 5 9 15 19
1 8 2 9 12 15 19
1 8 5 6 9 16 19
1 8 5 9 15 16 19
1 8 1 9 11 12 19
1 8 1 2 9 12 19
1 8 9 10 13 14 20
1 8 9 10 14 17 20
1 8 0 9 10 17 20
1 8 0 7 9 17 20
1 8 0 3 4 9 20
1 8 0 4 7 9 20
1 8 3 4 9 13 20
1 8 4 9 13 14 20
1 8 4 7 9 14 20
1 8 7 9 14 17 20
1 8 0 3 9 10 20
1 8 3 9 10 13 20
1 8 2 5 9 15 21
1 8 2 9 12 15 21
1 8 2 3 5 9 21
1 8 3 4 5 9 21
1 8 9 13 14 15 21
1 8 9 12 13 15 21
1 8 4 5 9 14 21
1 8 5 9 14 15 21
1 8 2 3 9 12 21
1 8 3 9 12 13 21
1 8 3 4 9 13 21
1 8 4 9 13 14 21
1 8 1 6 9 11 22
1 8 6 9 11 16 22
1 8 6 7 9 16 22
1 8 7 9 16 17 22
1 8 0 7 9 17 22
1 8 0 9 10 17 22
1 8 0 1 9 10 22
1 8 1 9 10 11 22
1 8 0 1 7 9 22
1 8 1 6 7 9 22
1 8 9 10 11 17 22
1 8 9 11 16 17 22
1 8 5 9 15 16 23
1 8 5 6 9 16 23
1 8 6 7 9 16 23
1 8 7 9 16 17 23
1 8 7 9 14 17 23
1 8 4 7 9 14 23
1 8 4 5 9 14 23
1 8 5 9 14 15 23
1 8 4 6 7 9 23
1 8 4 5 6 9 23
1 8 9 14 15 16 23
1 8 9 14 16 17 23
1 8 1 2 9 12 24
1 8 1 9 11 12 24
1 8 0 1 9 10 24
1 8 1 9 10 11 24
1 8 0 3 9 10 24
1 8 3 9 10 13 24
1 8 2 3 9 12 24
1 8 3 9 12 13 24
1 8 1 2 3 9 24
1 8 0 1 3 9 24
1 8 9 10 11 13 24
1 8 9 11 12 13 24
boundary
96
1 4 0 1 7 8
1 4 0 1 3 8
1 4 0 4 7 8
1 4 0 3 4 8
2 4 0 10 17 20
2 4 0 7 17 20
2 4 0 3 4 20
2 4 0 4 7 20
2 4 0 3 10 20
2 4 0 7 17 22
2 4 0 10 17 22
2 4 0 1 10 22
2 4 0 1 7 22
2 4 0 1 10 24
2 4 0 3 10 24
2 4 0 1 3 24
1 4 1 6 7 8
1 4 1 2 3 8
1 4 1 2 6 8
2 4 1 6 11 19
2 4 1 2 6 19
2 4 1 11 12 19
2 4 1 2 12 19
2 4 1 6 11 22
2 4 1 10 11 22
2 4 1 6 7 22
2 4 1 2 12 24
2 4 1 11 12 24
2 4 1 10 11 24
2 4 1 2 3 24
1 4 2 5 6 8
1 4 2 3 5 8
2 4 2 5 6 19
2 4 2 5 15 19
2 4 2 12 15 19
2 4 2 5 15 21
2 4 2 12 15 21
2 4 2 3 5 21
2 4 2 3 12 21
2 4 2 3 12 24
1 4 3 4 5 8
2 4 3 4 13 20
2 4 3 10 13 20
2 4 3 4 5 21
2 4 3 12 13 21
2 4 3 4 13 21
2 4 3 10 13 24
2 4 3 12 13 24
1 4 4 5 6 8
1 4 4 6 7 8
2 4 4 13 14 20
2 4 4 7 14 20
2 4 4 5 14 21
2 4 4 13 14 21
2 4 4 7 14 23
2 4 4 5 14 23
2 4 4 6 7 23
2 4 4 5 6 23
2 4 5 6 16 19
2 4 5 15 16 19
2 4 5 14 15 21
2 4 5 15 16 23
2 4 5 6 16 23
2 4 5 14 15 23
2 4 6 11 16 19
2 4 6 11 16 22
2 4 6 7 16 22
2 4 6 7 16 23
2 4 7 14 17 20
2 4 7 16 17 22
2 4 7 16 17 23
2 4 7 14 17 23
3 4 10 11 17 18
3 4 10 11 13 18
3 4 10 14 17 18
3 4 10 13 14 18
2 4 10 13 14 20
2 4 10 14 17 20
2 4 10 11 17 22
2 4 10 11 13 24
3 4 11 16 17 18
3 4 11 12 13 18
3 4 11 12 16 18
2 4 11 12 16 19
2 4 11 16 17 22
2 4 11 12 13 24
3 4 12 15 16 18
3 4 12 13 15 18
2 4 12 15 16 19
2 4 12 13 15 21
3 4 13 14 15 18
2 4 13 14 15 21
3 4 14 15 16 18
3 4 14 16 17 18
2 4 14 15 16 23
2 4 14 16 17 23
vertices
25
4
0.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
1.0000000000000000 0.0000000000000000 0.0000000000000000 0.0000000000000000
1.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000 0.0000000000000000
0.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000 0.0000000000000000
1.0000000000000000 0.0000000000000000 1.0000000000000000 0.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000 0.0000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000 0.0000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000 0.5000000000000000
0.0000000000000000 0.0000000000000000 0.0000000000000000 1.0000000000000000
1.0000000000000000 0.0000000000000000 0.0000000000000000 1.0000000000000000
1.0000000000000000 1.0000000000000000 0.0000000000000000 1.0000000000000000
0.0000000000000000 1.0000000000000000 0.0000000000000000 1.0000000000000000
0.0000000000000000 1.0000000000000000 1.0000000000000000 1.0000000000000000
1.0000000000000000 1.0000000000000000 1.0000000000000000 1.0000000000000000
1.0000000000000000 0.0000000000000000 1.0000000000000000 1.0000000000000000
0.0000000000000000 0.0000000000000000 1.0000000000000000 1.0000000000000000
0.5000000000000000 0.5000000000000000 0.5000000000000000 1.0000000000000000
1.0000000000000000 0.5000000000000000 0.5000000000000000 0.5000000000000000
0.0000000000000000 0.5000000000000000 0.5000000000000000 0.5000000000000000
0.5000000000000000 1.0000000000000000 0.5000000000000000 0.5000000000000000
0.5000000000000000 0.0000000000000000 0.5000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 1.0000000000000000 0.5000000000000000
0.5000000000000000 0.5000000000000000 0.0000000000000000 0.5000000000000000
-36
View File
@@ -1,36 +0,0 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
2
elements
2
1 2 2 0 1
1 2 0 2 3
boundary
4
1 1 0 1
1 1 1 2
2 1 2 3
1 1 3 0
vertices
4
2
0 0
1 0
1 1
0 1
+3 -3
View File
@@ -18,9 +18,9 @@ elements
boundary
4
1 1 0 1
1 1 2 3
1 1 3 0
1 1 1 2
2 1 2 3
3 1 3 0
4 1 1 2
edges
4
-52
View File
@@ -1,52 +0,0 @@
MFEM mesh v1.0
#
# MFEM Geometry Types (see mesh/geom.hpp):
#
# POINT = 0
# SEGMENT = 1
# TRIANGLE = 2
# SQUARE = 3
# TETRAHEDRON = 4
# CUBE = 5
# PRISM = 6
#
dimension
3
elements
6
1 4 3 1 7 5
1 4 1 6 7 4
1 4 6 1 0 2
1 4 1 6 4 2
1 4 6 1 3 0
1 4 1 6 3 7
boundary
12
1 2 6 0 3
1 2 0 6 2
1 2 1 3 0
1 2 3 1 5
1 2 3 7 6
1 2 7 3 5
1 2 4 6 7
1 2 6 4 2
2 2 1 7 5
2 2 7 1 4
1 2 1 2 4
1 2 2 1 0
vertices
8
3
0 0 0
0 0 1
1 0 0
0 1 0
1 0 1
0 1 1
1 1 0
1 1 1
+5 -3
View File
@@ -980,6 +980,7 @@ INPUT = @MFEM_SOURCE_DIR@/doc/CodeDocumentation.dox \
@MFEM_SOURCE_DIR@/miniapps/mtop \
@MFEM_SOURCE_DIR@/miniapps/multidomain \
@MFEM_SOURCE_DIR@/miniapps/navier \
@MFEM_SOURCE_DIR@/miniapps/stabilized \
@MFEM_SOURCE_DIR@/miniapps/nurbs \
@MFEM_SOURCE_DIR@/miniapps/parelag \
@MFEM_SOURCE_DIR@/miniapps/performance \
@@ -1049,7 +1050,8 @@ RECURSIVE = NO
EXCLUDE = @MFEM_SOURCE_DIR@/config/_config.hpp \
@MFEM_SOURCE_DIR@/config/get_hypre_version.cpp \
@MFEM_SOURCE_DIR@/general/tinyxml2.h \
@MFEM_SOURCE_DIR@/general/tinyxml2.cpp
@MFEM_SOURCE_DIR@/general/tinyxml2.cpp \
@MFEM_SOURCE_DIR@/linalg/lapack.hpp
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@@ -1208,13 +1210,13 @@ STRIP_CODE_COMMENTS = NO
# entity all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = YES
REFERENCED_BY_RELATION = NO
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = YES
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
+15
View File
@@ -182,6 +182,21 @@ namespace mfem {
* <a class="el" href="examples_2superlu_2ex1p_8cpp_source.html">1p</a>,
* demonstrating the use of MFEM's \link superlu.hpp SuperLU integration\endlink.
*
* <H4>NURBS Examples</H4>
* - Variants of Examples
* <a class="el" href="nurbs__ex1_8cpp_source.html">1</a>,
* <a class="el" href="nurbs__ex1p_8cpp_source.html">1p</a>,
* <a class="el" href="nurbs__ex3_8cpp_source.html">3</a>,
* <a class="el" href="nurbs__ex5_8cpp_source.html">5</a>,
* <a class="el" href="nurbs__ex11p_8cpp_source.html">11p</a>, and
* <a class="el" href="nurbs__ex24_8cpp_source.html">24</a>,
* demonstrating howto perform NURBS-based Isogeometric Analysis.
* - Variant of Example <a class="el" href="nurbs__patch__ex1_8cpp_source.html">1</a>: demonstrates the use of patch integration
* - <a class="el" href="nurbs__solenoidal_8cpp_source.html">NURBS Divergence-free</a>: solve a solenoidal vector projection with NURBS-based H(div) elements
* - <a class="el" href="nurbs__curveint_8cpp_source.html">NURBS Interpolation</a>: NURBS interpolation of given geometry
* - <a class="el" href="nurbs__naca__cmesh_8cpp_source.html">NURBS NACA Mesher</a>: generate NURBS based mesh around a NACA foil
* - <a class="el" href="nurbs__printfunc_8cpp_source.html">NURBS Printer</a>: print the NURBS-basis
*
* <H3>Miniapps</H3>
* - <a class="el" href="volta_8cpp_source.html">Volta</a>: simple electrostatics simulation code
* - <a class="el" href="tesla_8cpp_source.html">Tesla</a>: simple magnetostatics simulation code
-3
View File
@@ -73,9 +73,6 @@ if (MFEM_USE_MPI)
ex20p.cpp
ex21p.cpp
ex22p.cpp
ex1p_4d.cpp
ex3p_4d.cpp
ex4D_DivSkew.cpp
ex24p.cpp
ex25p.cpp
ex26p.cpp
+9 -27
View File
@@ -20,7 +20,6 @@
// ex14 -m ../data/fichera-amr.mesh
// ex14 -pa -r 1 -o 3
// ex14 -pa -r 1 -o 3 -m ../data/fichera.mesh
// ex14 -m ../data/inline-tet.mesh -o 0 -nt 4 -s 1
//
// Device sample runs:
// ex14 -pa -r 2 -d cuda -o 3
@@ -56,16 +55,10 @@ int main(int argc, char *argv[])
bool pa = false;
bool visualization = 1;
const char *device_config = "cpu";
int nt = 0;
double st = 1.0;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&nt, "-nt", "--number-of-timeslices",
"Number of slices through the hyper-prism in the 4th coordinate.");
args.AddOption(&st, "-st", "--size-time",
"Length of hyper-prims in 4th coordinate (e.g. time).");
args.AddOption(&ref_levels, "-r", "--refine",
"Number of times to refine the mesh uniformly, -1 for auto.");
args.AddOption(&order, "-o", "--order",
@@ -104,17 +97,8 @@ int main(int argc, char *argv[])
// 3. Read the mesh from the given mesh file. We can handle triangular,
// quadrilateral, tetrahedral and hexahedral meshes with the same code.
// NURBS meshes are projected to second order meshes.
Mesh *mesh = new Mesh(mesh_file, 1, 1);
int dim = mesh->Dimension();
if (dim == 3 && nt > 0)
{
Mesh* spat_mesh = mesh;
mesh = new Mesh(spat_mesh, nt, Element::PENTATOPE, true, st);
delete spat_mesh;
ref_levels = 0;
dim = 4;
}
Mesh mesh(mesh_file);
const int dim = mesh.Dimension();
// 4. Refine the mesh to increase the resolution. In this example we do
// 'ref_levels' of uniform refinement. By default, or if ref_levels < 0,
@@ -123,23 +107,23 @@ int main(int argc, char *argv[])
{
if (ref_levels < 0)
{
ref_levels = (int)floor(log(50000./mesh->GetNE())/log(2.)/(dim < 4 ? dim : 1.));
ref_levels = (int)floor(log(50000./mesh.GetNE())/log(2.)/dim);
}
for (int l = 0; l < ref_levels; l++)
{
mesh->UniformRefinement();
mesh.UniformRefinement();
}
}
if (mesh->NURBSext)
if (mesh.NURBSext)
{
mesh->SetCurvature(max(order, 1));
mesh.SetCurvature(max(order, 1));
}
// 5. Define a finite element space on the mesh. Here we use discontinuous
// finite elements of the specified order >= 0.
const auto bt = pa ? BasisType::GaussLobatto : BasisType::GaussLegendre;
DG_FECollection fec(order, dim, bt);
FiniteElementSpace fespace(mesh, &fec);
FiniteElementSpace fespace(&mesh, &fec);
cout << "Number of unknowns: " << fespace.GetVSize() << endl;
// 6. Set up the linear form b(.) which corresponds to the right-hand side of
@@ -214,7 +198,7 @@ int main(int argc, char *argv[])
// later using GLVis: "glvis -m refined.mesh -g sol.gf".
ofstream mesh_ofs("refined.mesh");
mesh_ofs.precision(8);
mesh->Print(mesh_ofs);
mesh.Print(mesh_ofs);
ofstream sol_ofs("sol.gf");
sol_ofs.precision(8);
x.Save(sol_ofs);
@@ -226,10 +210,8 @@ int main(int argc, char *argv[])
int visport = 19916;
socketstream sol_sock(vishost, visport);
sol_sock.precision(8);
sol_sock << "solution\n" << *mesh << x << flush;
sol_sock << "solution\n" << mesh << x << flush;
}
delete mesh;
return 0;
}
+8 -24
View File
@@ -19,7 +19,6 @@
// mpirun -np 4 ex14p -m ../data/amr-hex.mesh
// mpirun -np 4 ex14p -pa -rs 1 -rp 0 -o 3
// mpirun -np 4 ex14p -pa -rs 1 -rp 0 -m ../data/fichera.mesh -o 3
// mpirun -np 4 ex14p -m ../data/inline-tet.mesh -o 0 -nt 4 -s 1
//
// Device sample runs:
// mpirun -np 4 ex14p -pa -rs 2 -rp 0 -d cuda -o 3
@@ -91,16 +90,10 @@ int main(int argc, char *argv[])
bool pa = false;
bool visualization = 1;
const char *device_config = "cpu";
int nt = 0;
double st = 1.0;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&nt, "-nt", "--number-of-timeslices",
"Number of slices through the hyper-prism in the 4th coordinate.");
args.AddOption(&st, "-st", "--size-time",
"Length of hyper-prims in 4th coordinate (e.g. time).");
args.AddOption(&ser_ref_levels, "-rs", "--refine-serial",
"Number of times to refine the mesh uniformly in serial,"
" -1 for auto.");
@@ -146,17 +139,8 @@ int main(int argc, char *argv[])
// 3. Read the (serial) mesh from the given mesh file on all processors. We
// can handle triangular, quadrilateral, tetrahedral and hexahedral meshes
// with the same code. NURBS meshes are projected to second order meshes.
Mesh *mesh = new Mesh(mesh_file, 1, 1);
int dim = mesh->Dimension();
if (dim == 3 && nt > 0)
{
Mesh* spat_mesh = mesh;
mesh = new Mesh(spat_mesh, nt, Element::PENTATOPE, true, st);
delete spat_mesh;
dim = 4;
}
if (dim == 4)
ser_ref_levels = 0;
Mesh mesh(mesh_file);
int dim = mesh.Dimension();
// 4. Refine the serial mesh on all processors to increase the resolution. In
// this example we do 'ser_ref_levels' of uniform refinement. By default,
@@ -165,23 +149,23 @@ int main(int argc, char *argv[])
{
if (ser_ref_levels < 0)
{
ser_ref_levels = (int)floor(log(10000./mesh->GetNE())/log(2.)/dim);
ser_ref_levels = (int)floor(log(10000./mesh.GetNE())/log(2.)/dim);
}
for (int l = 0; l < ser_ref_levels; l++)
{
mesh->UniformRefinement();
mesh.UniformRefinement();
}
}
if (mesh->NURBSext)
if (mesh.NURBSext)
{
mesh->SetCurvature(max(order, 1));
mesh.SetCurvature(max(order, 1));
}
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
// this mesh further in parallel to increase the resolution. Once the
// parallel mesh is defined, the serial mesh can be deleted.
ParMesh pmesh(MPI_COMM_WORLD, *mesh);
delete mesh;
ParMesh pmesh(MPI_COMM_WORLD, mesh);
mesh.Clear();
{
for (int l = 0; l < par_ref_levels; l++)
{
-412
View File
@@ -1,412 +0,0 @@
// MFEM Example 1 - Parallel Version
//
// Compile with: make ex1p
//
// Sample runs: mpirun -np 4 ex1p -m ../data/square-disc.mesh
// mpirun -np 4 ex1p -m ../data/star.mesh
// mpirun -np 4 ex1p -m ../data/escher.mesh
// mpirun -np 4 ex1p -m ../data/fichera.mesh
// mpirun -np 4 ex1p -m ../data/square-disc-p2.vtk -o 2
// mpirun -np 4 ex1p -m ../data/square-disc-p3.mesh -o 3
// mpirun -np 4 ex1p -m ../data/square-disc-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/disc-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/pipe-nurbs.mesh -o -1
// mpirun -np 4 ex1p -m ../data/ball-nurbs.mesh -o 2
// mpirun -np 4 ex1p -m ../data/star-surf.mesh
// mpirun -np 4 ex1p -m ../data/square-disc-surf.mesh
// mpirun -np 4 ex1p -m ../data/inline-segment.mesh
// mpirun -np 4 ex1p -m ../data/amr-quad.mesh
// mpirun -np 4 ex1p -m ../data/amr-hex.mesh
// mpirun -np 4 ex1p -m ../data/mobius-strip.mesh
// mpirun -np 4 ex1p -m ../data/mobius-strip.mesh -o -1 -sc
//
// Description: This example code demonstrates the use of MFEM to define a
// simple finite element discretization of the Laplace problem
// -Delta u = 1 with homogeneous Dirichlet boundary conditions.
// Specifically, we discretize using a FE space of the specified
// order, or if order < 1 using an isoparametric/isogeometric
// space (i.e. quadratic for quadratic curvilinear mesh, NURBS for
// NURBS mesh, etc.)
//
// The example highlights the use of mesh refinement, finite
// element grid functions, as well as linear and bilinear forms
// corresponding to the left-hand side and right-hand side of the
// discrete linear system. We also cover the explicit elimination
// of essential boundary conditions, static condensation, and the
// optional connection to the GLVis tool for visualization.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
#include "./spe10_coeff.cpp"
int* LoadIterations(int NRows, int NCol)
{
ifstream in("iter_grad.txt");
//initialize
int *iters = new int[NCol*NRows];
for (int col = 0; col < NCol; col++)
{
for (int row = 0; row < NRows; row++)
{
iters[row*NCol+col] = -1;
}
}
if (!in)
{
cout << "Cannot open file.\n";
return iters;
}
for (int row = 0; row < NRows; row++)
for (int col = 0; col < NCol; col++)
{
if (in.eof())
{
in.close();
return iters;
}
in >> iters[row*NCol+col];
}
in.close();
return iters;
}
void putIterationsInArray(int iter, int row, int col, int NCol, int* iters)
{
iters[row*NCol+col] = iter;
}
void WriteIterations(int *iters, int NRows, int NCol)
{
ofstream out;
out.open("iter_grad.txt",fstream::out);
if (!out)
{
cout << "Cannot open file.\n";
delete[] iters;
return;
}
for (int row = 0; row < NRows; row++)
{
for (int col = 0; col < NCol; col++)
{
out << iters[row*NCol+col] << "\t";
}
out << endl;
}
out.close();
delete[] iters;
}
using namespace std;
using namespace mfem;
double kappa = 1.0;
double u_exact(const Vector &x)
{
int dim = x.Size();
if (dim==4)
{
return cos(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*cos(M_PI*x(3));
}
else { return 0.0; }
}
double f_exact(const Vector &x)
{
int dim = x.Size();
if (dim==4)
{
return (kappa + 4.0 * M_PI*M_PI) * cos(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(
2))*cos(M_PI*x(3));
}
else { return 0.0; }
}
int main(int argc, char *argv[])
{
// 1. Initialize MPI.
int num_procs, myid;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
bool verbose = (myid==0);
// 2. Parse command-line options.
const char *mesh_file = "../data/cube4d_96.MFEM";
int order = 1;
bool static_cond = false;
bool visualization = 1;
int sequ_ref_levels = 0;
int par_ref_levels = 0;
double tol = 1e-6;
bool set_bc = true;
bool standardCG = true;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&sequ_ref_levels, "-sr", "--seqrefinement",
"Number of sequential refinement steps.");
args.AddOption(&par_ref_levels, "-pr", "--parrefinement",
"Number of parallel refinement steps.");
args.AddOption(&order, "-o", "--order",
"Polynomial order of the finite element space.");
args.AddOption(&tol, "-tol", "--tol",
"A parameter.");
args.AddOption(&set_bc, "-bc", "--impose-bc", "-no-bc", "--dont-impose-bc",
"Impose or not essential boundary conditions.");
args.AddOption(&standardCG, "-sCG", "--stdCG", "-rCG", "--resCG",
"Switch between standard PCG or recompute residuals in every step and use the residuals itself for the stopping criteria.");
args.Parse();
if (!args.Good())
{
args.PrintUsage(cout);
return 1;
}
if (verbose) { args.PrintOptions(cout); }
Mesh *mesh;
ifstream imesh(mesh_file);
if (!imesh)
{
cerr << "\nCan not open mesh file: " << mesh_file << '\n' << endl;
return 2;
}
mesh = new Mesh(imesh, 1, 1);
imesh.close();
int dim = mesh->Dimension();
int sdim = mesh->SpaceDimension();
// if(dim !=4 || sdim != 4)
// {
// MPI_Finalize();
// return 0;
// }
for (int i=0; i<sequ_ref_levels; i++) { mesh->UniformRefinement(); }
if (verbose) { mesh->PrintCharacteristics(); }
if (verbose) { cout << "now we partition the mesh..." << endl << endl; }
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
for (int i=0; i<par_ref_levels; i++) { pmesh->UniformRefinement(); }
pmesh->PrintInfo(std::cout);
if (verbose) { cout << endl; }
// 6. Define a parallel finite element space on the parallel mesh. Here we
// use continuous Lagrange finite elements of the specified order. If
// order < 1, we instead use an isoparametric/isogeometric space.
FiniteElementCollection *fec;
if (order > 0)
{
if (dim==4)
{
if (order==1) { fec = new LinearFECollection; }
else { fec = new QuadraticFECollection; }
}
else { fec = new H1_FECollection(order, dim); }
}
else if (pmesh->GetNodes())
{
fec = pmesh->GetNodes()->OwnFEC();
if (myid == 0)
{
cout << "Using isoparametric FEs: " << fec->Name() << endl;
}
}
else
{
fec = new H1_FECollection(order = 1, dim);
}
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
HYPRE_Int size = fespace->GlobalTrueVSize();
if (myid == 0)
{
cout << "Number of finite element unknowns: " << size << endl;
}
// 7. Determine the list of true (i.e. parallel conforming) essential
// boundary dofs. In this example, the boundary conditions are defined
// by marking all the boundary attributes from the mesh as essential
// (Dirichlet) and converting them to a list of true dofs.
Array<int> ess_tdof_list;
if (pmesh->bdr_attributes.Size())
{
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
ess_bdr = set_bc ? 1 : 0;
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
FunctionCoefficient uExact(u_exact);
ParGridFunction x(fespace);
int NExpo =8;
for (int expo=-NExpo; expo<=NExpo; expo++)
{
double weight = pow(10.0,expo);
kappa = weight;
x.ProjectCoefficient(uExact);
ParLinearForm *b = new ParLinearForm(fespace);
FunctionCoefficient ffunc(f_exact);
b->AddDomainIntegrator(new DomainLFIntegrator(ffunc));
b->Assemble();
x = 0.0;
// 10. Set up the parallel bilinear form a(.,.) on the finite element space
// corresponding to the Laplacian operator -Delta, by adding the Diffusion
// domain integrator.
// std::string permFile = "spe_perm.dat";
// InversePermeabilityFunction::ReadPermeabilityFile(permFile, MPI_COMM_WORLD);
// FunctionCoefficient *cspe10 = new FunctionCoefficient(InversePermeabilityFunction::Norm2Permeability);
Coefficient *beta = new ConstantCoefficient(weight);
ParBilinearForm *a = new ParBilinearForm(fespace);
a->AddDomainIntegrator(new DiffusionIntegrator);
a->AddDomainIntegrator(new MassIntegrator(*beta));
// 11. Assemble the parallel bilinear form and the corresponding linear
// system, applying any necessary transformations such as: parallel
// assembly, eliminating boundary conditions, applying conforming
// constraints for non-conforming AMR, static condensation, etc.
if (static_cond) { a->EnableStaticCondensation(); }
a->Assemble();
HypreParMatrix A;
Vector B, X;
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
if (myid == 0)
{
cout << "Size of linear system: " << A.GetGlobalNumRows() << endl;
}
// 12. Define and apply a parallel PCG solver for AX=B with the BoomerAMG
// preconditioner from hypre.
HypreSolver *amg = new HypreBoomerAMG(A);
int iter = -1;
if (standardCG)
{
IterativeSolver *pcg = new CGSolver(MPI_COMM_WORLD);
pcg->SetOperator(A);
pcg->SetRelTol(tol);
pcg->SetMaxIter(5000);
pcg->SetPrintLevel(1);
pcg->SetPreconditioner(*amg);
pcg->Mult(B, X);
iter = pcg->GetNumIterations();
delete pcg;
}
else
{
HyprePCG *pcg = new HyprePCG(A);
pcg->SetTol(tol);
pcg->SetMaxIter(5000);
pcg->SetResidualConvergenceOptions(1,tol);
pcg->SetPrintLevel(2);
pcg->SetPreconditioner(*amg);
pcg->Mult(B, X);
pcg->GetNumIterations(iter);
delete pcg;
}
if (myid==0)
{
cout << "Weigth: " << weight << " " << iter << endl;
int *iters = LoadIterations(10, 2*NExpo+1);
putIterationsInArray(iter, sequ_ref_levels+par_ref_levels, expo+NExpo,
2*NExpo+1, iters);
WriteIterations(iters, 10, 2*NExpo+1);
}
// 13. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
a->RecoverFEMSolution(X, *b, x);
{
double err = x.ComputeL2Error(uExact);
if (myid == 0)
{
cout << "\n|| u - u_h ||_{L^2} = " << err << '\n' << endl;
}
}
// 14. Save the refined mesh and the solution in parallel. This output can
// be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
// {
// ostringstream mesh_name, sol_name;
// mesh_name << "mesh." << setfill('0') << setw(6) << myid;
// sol_name << "sol." << setfill('0') << setw(6) << myid;
//
// ofstream mesh_ofs(mesh_name.str().c_str());
// mesh_ofs.precision(8);
// pmesh->Print(mesh_ofs);
//
// ofstream sol_ofs(sol_name.str().c_str());
// sol_ofs.precision(8);
// x.Save(sol_ofs);
// }
// 15. Send the solution by socket to a GLVis server.
// if (visualization)
// {
// char vishost[] = "localhost";
// int visport = 19916;
// socketstream sol_sock(vishost, visport);
// sol_sock << "parallel " << num_procs << " " << myid << "\n";
// sol_sock.precision(8);
// sol_sock << "solution\n" << *pmesh << x << flush;
// }
delete amg;
delete a;
delete beta;
delete b;
}
// 16. Free the used memory.
delete fespace;
if (order > 0) { delete fec; }
delete pmesh;
MPI_Finalize();
return 0;
}
+16 -20
View File
@@ -44,7 +44,7 @@ protected:
BilinearForm *M;
BilinearForm *K;
SparseMatrix Mmat, Kmat, Kmat0;
SparseMatrix Mmat, Kmat;
SparseMatrix *T; // T = M + dt K
real_t current_dt;
@@ -83,25 +83,24 @@ WaveOperator::WaveOperator(FiniteElementSpace &f,
: SecondOrderTimeDependentOperator(f.GetTrueVSize(), (real_t) 0.0),
fespace(f), M(NULL), K(NULL), T(NULL), current_dt(0.0), z(height)
{
const real_t rel_tol = 1e-8;
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
// Assemble Laplace matrix
c2 = new ConstantCoefficient(speed*speed);
K = new BilinearForm(&fespace);
K->AddDomainIntegrator(new DiffusionIntegrator(*c2));
K->Assemble();
Array<int> dummy;
K->FormSystemMatrix(dummy, Kmat0);
K->FormSystemMatrix(ess_tdof_list, Kmat);
// Assemble Mass matrix
M = new BilinearForm(&fespace);
M->AddDomainIntegrator(new MassIntegrator());
M->Assemble();
// Apply Bcs
fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
K->FormSystemMatrix(ess_tdof_list, Kmat);
M->FormSystemMatrix(ess_tdof_list, Mmat);
// Configure preconditioner
const real_t rel_tol = 1e-8;
M_solver.iterative_mode = false;
M_solver.SetRelTol(rel_tol);
M_solver.SetAbsTol(0.0);
@@ -110,14 +109,13 @@ WaveOperator::WaveOperator(FiniteElementSpace &f,
M_solver.SetPreconditioner(M_prec);
M_solver.SetOperator(Mmat);
// Configure solver
T_solver.iterative_mode = false;
T_solver.SetRelTol(rel_tol);
T_solver.SetAbsTol(0.0);
T_solver.SetMaxIter(100);
T_solver.SetPrintLevel(0);
T_solver.SetPreconditioner(T_prec);
T = NULL;
}
void WaveOperator::Mult(const Vector &u, const Vector &du_dt,
@@ -126,9 +124,11 @@ void WaveOperator::Mult(const Vector &u, const Vector &du_dt,
// Compute:
// d2udt2 = M^{-1}*-K(u)
// for d2udt2
Kmat.Mult(u, z);
K->FullMult(u, z);
z.Neg(); // z = -z
z.SetSubVector(ess_tdof_list, 0.0);
M_solver.Mult(z, d2udt2);
d2udt2.SetSubVector(ess_tdof_list, 0.0);
}
void WaveOperator::ImplicitSolve(const real_t fac0, const real_t fac1,
@@ -142,14 +142,11 @@ void WaveOperator::ImplicitSolve(const real_t fac0, const real_t fac1,
T = Add(1.0, Mmat, fac0, Kmat);
T_solver.SetOperator(*T);
}
Kmat0.Mult(u, z);
K->FullMult(u, z);
z.Neg();
for (int i = 0; i < ess_tdof_list.Size(); i++)
{
z[ess_tdof_list[i]] = 0.0;
}
z.SetSubVector(ess_tdof_list, 0.0);
T_solver.Mult(z, d2udt2);
d2udt2.SetSubVector(ess_tdof_list, 0.0);
}
void WaveOperator::SetParameters(const Vector &u)
@@ -314,7 +311,6 @@ int main(int argc, char *argv[])
ess_bdr = 0;
}
}
WaveOperator oper(fespace, ess_bdr, speed);
u_gf.SetFromTrueDofs(u);
+9 -222
View File
@@ -58,180 +58,6 @@ void f_exact(const Vector &, Vector &);
real_t freq = 1.0, kappa;
int dim;
class Curl4dPrec : public Solver
{
private:
HypreParMatrix *A;
ParFiniteElementSpace *fespace;
HypreParMatrix *idMat;
HypreParMatrix *H1VecLaplaceMat;
HypreBoomerAMG *amgVecH1;
HypreParMatrix *gradMat;
HypreParMatrix *H1LaplaceMat;
HypreBoomerAMG *amgH1;
HypreSmoother * smoother;
CGSolver *pcgGrad;
CGSolver *pcgH1Vec;
Vector *f;
Vector *fGrad, *uGrad;
Vector *fH1Vec, *uH1Vec;
bool exactSolves;
public:
Curl4dPrec(HypreParMatrix *AUser, ParFiniteElementSpace *fespaceUser,
const Array<int> &essBnd, int orderKernel=1, bool exactSolvesUser=false)
{
A = AUser;
fespace = fespaceUser;
ParMesh *pmesh = fespace->GetParMesh();
int dim = pmesh->Dimension();
exactSolves = exactSolvesUser;
int orderIm=1; //vecH1 --> H(curl)
int orderKer=orderKernel; //grad V --> H(curl)
smoother = new HypreSmoother(*A, 16, 3);
// //for the pure dirichlet case
// Array<int> essBnd(pmesh->bdr_attributes.Max()); essBnd = 1;
Array<int> HCurl_essDof(fespace->GetVSize()); HCurl_essDof = 0;
fespace->GetEssentialVDofs(essBnd, HCurl_essDof);
//setup the H1 FESpace
FiniteElementCollection* fecH1;
if (orderKer==1) { fecH1 = new LinearFECollection; }
else { fecH1 = new QuadraticFECollection; }
ParFiniteElementSpace *H1FESpace = new ParFiniteElementSpace(pmesh, fecH1);
Array<int> H1_essDof(H1FESpace->GetVSize()); H1_essDof = 0;
H1FESpace->GetEssentialVDofs(essBnd, H1_essDof);
//setup the discrete gradient
ParDiscreteLinearOperator *disGrad = new ParDiscreteLinearOperator(H1FESpace,
fespace);
disGrad->AddDomainInterpolator(new GradientInterpolator);
disGrad->Assemble();
disGrad->Finalize();
SparseMatrix* smat = &(disGrad->SpMat());
smat->EliminateCols(H1_essDof);
for (int dof=0; dof<HCurl_essDof.Size(); dof++) if (HCurl_essDof[dof]<0) { smat->EliminateRow(dof); }
gradMat = disGrad->ParallelAssemble();
delete disGrad;
//setup the H1 preconditioner
ParBilinearForm* H1Varf = new ParBilinearForm(H1FESpace);
H1Varf->AddDomainIntegrator(new DiffusionIntegrator);
H1Varf->AddDomainIntegrator(new MassIntegrator);
H1Varf->Assemble();
H1Varf->Finalize();
SparseMatrix &matH1(H1Varf->SpMat());
for (int dof=0; dof<H1_essDof.Size(); dof++) if (H1_essDof[dof]<0) { matH1.EliminateRowCol(dof); }
H1LaplaceMat = H1Varf->ParallelAssemble();
delete H1Varf;
amgH1 = new HypreBoomerAMG(*H1LaplaceMat);
//setup the H1 injection
FiniteElementCollection* fecH1Vec;
if (orderIm==1) { fecH1Vec = new LinearFECollection; }
else { fecH1Vec = new QuadraticFECollection; }
ParFiniteElementSpace *H1VecFESpace = new ParFiniteElementSpace(pmesh, fecH1Vec,
dim, Ordering::byVDIM);
Array<int> H1Vec_essDof(H1VecFESpace->GetVSize()); H1Vec_essDof = 0;
H1VecFESpace->GetEssentialVDofs(essBnd, H1Vec_essDof);
//setup the discrete gradient
ParDiscreteLinearOperator *disInterpol = new ParDiscreteLinearOperator(
H1VecFESpace, fespace);
disInterpol->AddDomainInterpolator(new IdentityInterpolator);
disInterpol->Assemble();
disInterpol->Finalize();
SparseMatrix* smatID = &(disInterpol->SpMat());
smatID->EliminateCols(H1Vec_essDof);
for (int dof=0; dof<HCurl_essDof.Size(); dof++) if (HCurl_essDof[dof]<0) { smatID->EliminateRow(dof); }
idMat = disInterpol->ParallelAssemble();
delete disInterpol;
//setup the H1-vec preconditioner
ParBilinearForm* H1VecVarf = new ParBilinearForm(H1VecFESpace);
H1VecVarf->AddDomainIntegrator(new VectorDiffusionIntegrator);
H1VecVarf->AddDomainIntegrator(new VectorMassIntegrator);
H1VecVarf->Assemble();
H1VecVarf->Finalize();
SparseMatrix &matH1Vec(H1VecVarf->SpMat());
for (int dof=0; dof<H1Vec_essDof.Size(); dof++) if (H1Vec_essDof[dof]<0) { matH1Vec.EliminateRowCol(dof); }
H1VecLaplaceMat = H1VecVarf->ParallelAssemble();
delete H1VecVarf;
amgVecH1 = new HypreBoomerAMG(*H1VecLaplaceMat);
amgVecH1->SetSystemsOptions(dim);
f = new Vector(fespace->GetTrueVSize());
fGrad = new Vector(H1FESpace->GetTrueVSize());
uGrad = new Vector(H1FESpace->GetTrueVSize());
fH1Vec = new Vector(H1VecFESpace->GetTrueVSize());
uH1Vec = new Vector(H1VecFESpace->GetTrueVSize());;
amgH1->Mult(*fGrad, *uGrad);
amgVecH1->Mult(*fH1Vec, *uH1Vec);
pcgGrad = new CGSolver(MPI_COMM_WORLD);
pcgGrad->SetOperator(*H1LaplaceMat);
pcgGrad->SetPreconditioner(*amgH1);
pcgGrad->SetRelTol(1e-16);
pcgGrad->SetMaxIter(100000000);
pcgGrad->SetPrintLevel(-2);
pcgH1Vec = new CGSolver(MPI_COMM_WORLD);
pcgH1Vec->SetOperator(*H1VecLaplaceMat);
pcgH1Vec->SetPreconditioner(*amgVecH1);
pcgH1Vec->SetRelTol(1e-16);
pcgH1Vec->SetMaxIter(100000000);
pcgH1Vec->SetPrintLevel(-2);
}
void setExactSolve(bool exSol)
{
exactSolves = exSol;
}
virtual void Mult(const Vector &x, Vector &y) const
{
smoother->Mult(x,y);
idMat->MultTranspose(x,*fH1Vec);
*uH1Vec = 0.0;
if (exactSolves) { pcgH1Vec->Mult(*fH1Vec, *uH1Vec); }
else { amgVecH1->Mult(*fH1Vec, *uH1Vec); }
idMat->Mult(1.0, *uH1Vec, 1.0, y);
gradMat->MultTranspose(x,*fGrad);
*uGrad = 0.0;
if (exactSolves) { pcgGrad->Mult(*fGrad, *uGrad); }
else { amgH1->Mult(*fGrad, *uGrad); }
gradMat->Mult(1.0, *uGrad, 1.0, y);
}
virtual void SetOperator(const Operator &op) {};
};
int main(int argc, char *argv[])
{
// 1. Initialize MPI and HYPRE.
@@ -336,13 +162,7 @@ int main(int argc, char *argv[])
// 7. Define a parallel finite element space on the parallel mesh. Here we
// use the Nedelec finite elements of the specified order.
FiniteElementCollection *fec;
if (dim==4)
{
if (order==1) { fec = new ND1_4DFECollection; }
else { fec = new ND2_4DFECollection; }
}
else { fec = new ND_FECollection(order, dim); }
FiniteElementCollection *fec = new ND_FECollection(order, dim);
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
HYPRE_BigInt size = fespace->GlobalTrueVSize();
if (myid == 0)
@@ -428,29 +248,15 @@ int main(int argc, char *argv[])
ParFiniteElementSpace *prec_fespace =
(a->StaticCondensationIsEnabled() ? a->SCParFESpace() : fespace);
Solver *prec;
HypreAMS ams(*A.As<HypreParMatrix>(), prec_fespace);
if (dim <= 3)
{
prec = new HypreAMS(*A.As<HypreParMatrix>(), prec_fespace);
}
else if (dim == 4)
{
prec = new Curl4dPrec(A.As<HypreParMatrix>(), fespace, ess_bdr, order, false);
}
IterativeSolver *pcg = new CGSolver(MPI_COMM_WORLD);
pcg->SetOperator(*A.As<HypreParMatrix>());
pcg->SetTol(1e-12);
pcg->SetMaxIter(500);
pcg->SetPrintLevel(2);
pcg->SetPreconditioner(*prec);
pcg->Mult(B, X);
delete pcg;
delete prec;
HyprePCG pcg(*A.As<HypreParMatrix>());
pcg.SetTol(1e-12);
pcg.SetMaxIter(500);
pcg.SetPrintLevel(2);
pcg.SetPreconditioner(ams);
pcg.Mult(B, X);
}
// 13. Recover the parallel grid function corresponding to X. This is the
// 14. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
a->RecoverFEMSolution(X, *b, x);
@@ -506,14 +312,7 @@ int main(int argc, char *argv[])
void E_exact(const Vector &x, Vector &E)
{
if (dim==4)
{
E(0) = sin(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*cos(M_PI*x(3));
E(1) = -cos(M_PI*x(0))*sin(M_PI*x(1))*cos(M_PI*x(2))*cos(M_PI*x(3));
E(2) = cos(M_PI*x(0))*cos(M_PI*x(1))*sin(M_PI*x(2))*cos(M_PI*x(3));
E(3) = -cos(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*sin(M_PI*x(3));
}
else if (dim == 3)
if (dim == 3)
{
E(0) = sin(kappa * x(1));
E(1) = sin(kappa * x(2));
@@ -529,19 +328,7 @@ void E_exact(const Vector &x, Vector &E)
void f_exact(const Vector &x, Vector &f)
{
//f_exact = E + DivSkew P( curl E ), where P is the 4d permutation operator
if (dim==4)
{
f(0) = (1.0+4.0*M_PI*M_PI)*sin(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*cos(
M_PI*x(3));
f(1) = -(1.0+4.0*M_PI*M_PI)*cos(M_PI*x(0))*sin(M_PI*x(1))*cos(M_PI*x(2))*cos(
M_PI*x(3));
f(2) = (1.0+4.0*M_PI*M_PI)*cos(M_PI*x(0))*cos(M_PI*x(1))*sin(M_PI*x(2))*cos(
M_PI*x(3));
f(3) = -(1.0+4.0*M_PI*M_PI)*cos(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*sin(
M_PI*x(3));
}
else if (dim == 3)
if (dim == 3)
{
f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
f(1) = (1. + kappa * kappa) * sin(kappa * x(2));
-650
View File
@@ -1,650 +0,0 @@
// MFEM Example 3 - Parallel Version
//
// Compile with: make ex3p
//
// Sample runs: mpirun -np 4 ex3p -m ../data/star.mesh
// mpirun -np 4 ex3p -m ../data/square-disc.mesh -o 2
// mpirun -np 4 ex3p -m ../data/beam-tet.mesh
// mpirun -np 4 ex3p -m ../data/beam-hex.mesh
// mpirun -np 4 ex3p -m ../data/escher.mesh
// mpirun -np 4 ex3p -m ../data/fichera.mesh
// mpirun -np 4 ex3p -m ../data/fichera-q2.vtk
// mpirun -np 4 ex3p -m ../data/fichera-q3.mesh
// mpirun -np 4 ex3p -m ../data/square-disc-nurbs.mesh
// mpirun -np 4 ex3p -m ../data/beam-hex-nurbs.mesh
// mpirun -np 4 ex3p -m ../data/amr-quad.mesh -o 2
// mpirun -np 4 ex3p -m ../data/amr-hex.mesh
// mpirun -np 4 ex3p -m ../data/star-surf.mesh -o 2
// mpirun -np 4 ex3p -m ../data/mobius-strip.mesh -o 2 -f 0.1
// mpirun -np 4 ex3p -m ../data/klein-bottle.mesh -o 2 -f 0.1
//
// Description: This example code solves a simple electromagnetic diffusion
// problem corresponding to the second order definite Maxwell
// equation curl curl E + E = f with boundary condition
// E x n = <given tangential field>. Here, we use a given exact
// solution E and compute the corresponding r.h.s. f.
// We discretize with Nedelec finite elements in 2D or 3D.
//
// The example demonstrates the use of H(curl) finite element
// spaces with the curl-curl and the (vector finite element) mass
// bilinear form, as well as the computation of discretization
// error when the exact solution is known. Static condensation is
// also illustrated.
//
// We recommend viewing examples 1-2 before viewing this example.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
#include "./spe10_coeff.cpp"
using namespace std;
using namespace mfem;
int* LoadIterations(int NRows, int NCol)
{
ifstream in("iter_curl.txt");
//initialize
int *iters = new int[NCol*NRows];
for (int col = 0; col < NCol; col++)
{
for (int row = 0; row < NRows; row++)
{
iters[row*NCol+col] = -1;
}
}
if (!in)
{
cout << "Cannot open file.\n";
return iters;
}
for (int row = 0; row < NRows; row++)
for (int col = 0; col < NCol; col++)
{
if (in.eof())
{
in.close();
return iters;
}
in >> iters[row*NCol+col];
}
in.close();
return iters;
}
void putIterationsInArray(int iter, int row, int col, int NCol, int* iters)
{
iters[row*NCol+col] = iter;
}
void WriteIterations(int *iters, int NRows, int NCol)
{
ofstream out;
out.open("iter_curl.txt",fstream::out);
if (!out)
{
cout << "Cannot open file.\n";
delete[] iters;
return;
}
for (int row = 0; row < NRows; row++)
{
for (int col = 0; col < NCol; col++)
{
out << iters[row*NCol+col] << "\t";
}
out << endl;
}
out.close();
delete[] iters;
}
// Exact solution, E, and r.h.s., f. See below for implementation.
void E_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa = 1.0;
int dim;
double osziCoeff(const Vector &x)
{
return 1.0001 + sin(100*x(0))*sin(200*x(1))*sin(300*x(2))*sin(400*x(3));
}
class Curl4dPrec : public Solver
{
private:
HypreParMatrix *A;
ParFiniteElementSpace *fespace;
Coefficient *alpha_, *beta_, *neg_beta_;
HypreParMatrix *idMat;
HypreParMatrix *H1VecLaplaceMat;
HypreBoomerAMG *amgVecH1;
HypreParMatrix *gradMat;
HypreParMatrix *H1LaplaceMat;
HypreBoomerAMG *amgH1;
HypreSmoother * smoother;
CGSolver *pcgGrad;
CGSolver *pcgH1Vec;
Vector *f;
Vector *fGrad, *uGrad;
Vector *fH1Vec, *uH1Vec;
bool exactSolves;
public:
~Curl4dPrec()
{
delete pcgH1Vec;
delete pcgGrad;
delete f, fGrad, uGrad, fH1Vec, uH1Vec;
delete smoother;
delete amgVecH1, H1VecLaplaceMat;
delete idMat;
delete amgH1, H1LaplaceMat;
delete gradMat;
}
Curl4dPrec(HypreParMatrix *AUser, ParFiniteElementSpace *fespaceUser,
Coefficient *alpha, Coefficient *beta, Coefficient *neg_beta,
const Array<int> &essBnd, int orderKernel=1, bool exactSolvesUser=false)
{
A = AUser;
fespace = fespaceUser;
alpha_ = alpha;
beta_ = beta;
neg_beta_=neg_beta;
ParMesh *pmesh = fespace->GetParMesh();
int dim = pmesh->Dimension();
exactSolves = exactSolvesUser;
int orderIm=1; //vecH1 --> H(curl)
int orderKer=orderKernel; //grad V --> H(curl)
smoother = new HypreSmoother(*A, 16, 3);
// //for the pure dirichlet case
// Array<int> essBnd(pmesh->bdr_attributes.Max()); essBnd = 1;
Array<int> HCurl_essDof(fespace->GetVSize()); HCurl_essDof = 0;
fespace->GetEssentialVDofs(essBnd, HCurl_essDof);
//setup the H1 FESpace
FiniteElementCollection* fecH1;
if (orderKer==1) { fecH1 = new LinearFECollection; }
else { fecH1 = new QuadraticFECollection; }
ParFiniteElementSpace *H1FESpace = new ParFiniteElementSpace(pmesh, fecH1);
Array<int> H1_essDof(H1FESpace->GetVSize()); H1_essDof = 0;
H1FESpace->GetEssentialVDofs(essBnd, H1_essDof);
//setup the discrete gradient
ParDiscreteLinearOperator *disGrad = new ParDiscreteLinearOperator(H1FESpace,
fespace);
disGrad->AddDomainInterpolator(new GradientInterpolator);
disGrad->Assemble();
disGrad->Finalize();
SparseMatrix* smat = &(disGrad->SpMat());
smat->EliminateCols(H1_essDof);
for (int dof=0; dof<HCurl_essDof.Size(); dof++) if (HCurl_essDof[dof]<0) { smat->EliminateRow(dof); }
gradMat = disGrad->ParallelAssemble();
delete disGrad;
//setup the H1 preconditioner
ParBilinearForm* H1Varf = new ParBilinearForm(H1FESpace);
H1Varf->AddDomainIntegrator(new DiffusionIntegrator(*beta_));
// H1Varf->AddDomainIntegrator(new MassIntegrator);
H1Varf->Assemble();
H1Varf->Finalize();
SparseMatrix &matH1(H1Varf->SpMat());
for (int dof=0; dof<H1_essDof.Size(); dof++) if (H1_essDof[dof]<0) { matH1.EliminateRowCol(dof); }
H1LaplaceMat = H1Varf->ParallelAssemble();
delete H1Varf;
amgH1 = new HypreBoomerAMG(*H1LaplaceMat);
//setup the H1 injection
FiniteElementCollection* fecH1Vec;
if (orderIm==1) { fecH1Vec = new LinearFECollection; }
else { fecH1Vec = new QuadraticFECollection; }
ParFiniteElementSpace *H1VecFESpace = new ParFiniteElementSpace(pmesh, fecH1Vec,
dim, Ordering::byVDIM);
Array<int> H1Vec_essDof(H1VecFESpace->GetVSize()); H1Vec_essDof = 0;
H1VecFESpace->GetEssentialVDofs(essBnd, H1Vec_essDof);
//setup the discrete gradient
ParDiscreteLinearOperator *disInterpol = new ParDiscreteLinearOperator(
H1VecFESpace, fespace);
disInterpol->AddDomainInterpolator(new IdentityInterpolator);
disInterpol->Assemble();
disInterpol->Finalize();
SparseMatrix* smatID = &(disInterpol->SpMat());
smatID->EliminateCols(H1Vec_essDof);
for (int dof=0; dof<HCurl_essDof.Size(); dof++) if (HCurl_essDof[dof]<0) { smatID->EliminateRow(dof); }
idMat = disInterpol->ParallelAssemble();
delete disInterpol;
//setup the H1-vec preconditioner
ParBilinearForm* H1VecVarf = new ParBilinearForm(H1VecFESpace);
H1VecVarf->AddDomainIntegrator(new VectorDiffusionIntegrator(*alpha_));
H1VecVarf->AddDomainIntegrator(new VectorMassIntegrator(*neg_beta_));
H1VecVarf->Assemble();
H1VecVarf->Finalize();
SparseMatrix &matH1Vec(H1VecVarf->SpMat());
for (int dof=0; dof<H1Vec_essDof.Size(); dof++) if (H1Vec_essDof[dof]<0) { matH1Vec.EliminateRowCol(dof); }
H1VecLaplaceMat = H1VecVarf->ParallelAssemble();
delete H1VecVarf;
amgVecH1 = new HypreBoomerAMG(*H1VecLaplaceMat);
amgVecH1->SetSystemsOptions(dim);
f = new Vector(fespace->GetTrueVSize());
fGrad = new Vector(H1FESpace->GetTrueVSize());
uGrad = new Vector(H1FESpace->GetTrueVSize());
fH1Vec = new Vector(H1VecFESpace->GetTrueVSize());
uH1Vec = new Vector(H1VecFESpace->GetTrueVSize());
amgH1->Mult(*fGrad, *uGrad);
amgVecH1->Mult(*fH1Vec, *uH1Vec);
pcgGrad = new CGSolver(MPI_COMM_WORLD);
pcgGrad->SetOperator(*H1LaplaceMat);
pcgGrad->SetPreconditioner(*amgH1);
pcgGrad->SetRelTol(1e-16);
pcgGrad->SetMaxIter(100000000);
pcgGrad->SetPrintLevel(-2);
pcgH1Vec = new CGSolver(MPI_COMM_WORLD);
pcgH1Vec->SetOperator(*H1VecLaplaceMat);
pcgH1Vec->SetPreconditioner(*amgVecH1);
pcgH1Vec->SetRelTol(1e-16);
pcgH1Vec->SetMaxIter(100000000);
pcgH1Vec->SetPrintLevel(-2);
delete H1FESpace; delete fecH1;
delete H1VecFESpace; delete fecH1Vec;
}
void setExactSolve(bool exSol)
{
exactSolves = exSol;
}
virtual void Mult(const Vector &x, Vector &y) const
{
smoother->Mult(x,y);
idMat->MultTranspose(x,*fH1Vec);
*uH1Vec = 0.0;
if (exactSolves) { pcgH1Vec->Mult(*fH1Vec, *uH1Vec); }
else { amgVecH1->Mult(*fH1Vec, *uH1Vec); }
idMat->Mult(1.0, *uH1Vec, 1.0, y);
gradMat->MultTranspose(x,*fGrad);
*uGrad = 0.0;
if (exactSolves) { pcgGrad->Mult(*fGrad, *uGrad); }
else { amgH1->Mult(*fGrad, *uGrad); }
gradMat->Mult(1.0, *uGrad, 1.0, y);
}
virtual void SetOperator(const Operator &op) {};
};
int main(int argc, char *argv[])
{
// 1. Initialize MPI.
int num_procs, myid;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
bool verbose = (myid==0);
// 2. Parse command-line options.
const char *mesh_file = "../data/cube4d_96.MFEM";
int order = 1;
bool set_bc = true;
bool static_cond = false;
bool visualization = 1;
int sequ_ref_levels = 0;
int par_ref_levels = 0;
double tol = 1e-6;
double coeffWeight = 1.0;
bool exactH1Solver = false;
bool spe10Coeff = false;
bool standardCG = true;
int NExpo = 8;
int weightStart = -NExpo;
int weightEnd = NExpo;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&sequ_ref_levels, "-sr", "--seqrefinement",
"Number of sequential refinement steps.");
args.AddOption(&par_ref_levels, "-pr", "--parrefinement",
"Number of parallel refinement steps.");
args.AddOption(&order, "-o", "--order",
"Polynomial order of the finite element space.");
args.AddOption(&set_bc, "-bc", "--impose-bc", "-no-bc", "--dont-impose-bc",
"Impose or not essential boundary conditions.");
args.AddOption(&tol, "-tol", "--tol",
"A parameter.");
args.AddOption(&freq, "-f", "--frequency", "Set the frequency for the exact"
" solution.");
args.AddOption(&coeffWeight, "-c", "--coeffMass",
"the weight for the mass term.");
args.AddOption(&exactH1Solver, "-exH1Sol", "--exactH1Solver", "-H1prec",
"--H1preconditioner",
"Use exact H1 solvers for the preconditioner.");
args.AddOption(&spe10Coeff, "-spe10", "--useSPE10Coeff", "-constCoeff",
"--constCoeff",
"Switch between the coefficients for the mass bilinear form.");
args.AddOption(&standardCG, "-sCG", "--stdCG", "-rCG", "--resCG",
"Switch between standard PCG or recompute residuals in every step and use the residuals itself for the stopping criteria.");
args.AddOption(&weightStart, "-ws", "--weightStart",
"the exponent for the starting weight (for the mass term).");
args.AddOption(&weightEnd, "-we", "--weightEnd",
"the exponent for the weight at the end (for the mass term).");
args.Parse();
if (!args.Good())
{
args.PrintUsage(cout);
return 1;
}
if (verbose) { args.PrintOptions(cout); }
kappa = freq * M_PI;
Mesh *mesh;
ifstream imesh(mesh_file);
if (!imesh)
{
cerr << "\nCan not open mesh file: " << mesh_file << '\n' << endl;
return 2;
}
mesh = new Mesh(imesh, 1, 1);
imesh.close();
dim = mesh->Dimension();
int sdim = mesh->SpaceDimension();
if (dim !=4 || sdim != 4)
{
MPI_Finalize();
return 0;
}
for (int i=0; i<sequ_ref_levels; i++) { mesh->UniformRefinement(); }
if (verbose) { mesh->PrintCharacteristics(); }
if (verbose) { cout << "now we partition the mesh..." << endl << endl; }
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
for (int i=0; i<par_ref_levels; i++) { pmesh->UniformRefinement(); }
pmesh->ReorientTetMesh();
pmesh->PrintInfo(std::cout);
if (verbose) { cout << endl; }
// 6. Define a parallel finite element space on the parallel mesh. Here we
// use the Nedelec finite elements of the specified order.
FiniteElementCollection *fec;
if (dim==4)
{
if (order==1) { fec = new ND1_4DFECollection; }
else { fec = new ND2_4DFECollection; }
}
else { fec = new ND_FECollection(order, dim); }
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
HYPRE_Int size = fespace->GlobalTrueVSize();
if (myid == 0)
{
cout << "Number of finite element unknowns: " << size << endl;
}
// 7. Determine the list of true (i.e. parallel conforming) essential
// boundary dofs. In this example, the boundary conditions are defined
// by marking all the boundary attributes from the mesh as essential
// (Dirichlet) and converting them to a list of true dofs.
Array<int> ess_tdof_list;
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
ess_bdr = set_bc ? 1 : 0;
if (pmesh->bdr_attributes.Size())
{
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
// 8. Set up the parallel linear form b(.) which corresponds to the
// right-hand side of the FEM linear system, which in this case is
// (f,phi_i) where f is given by the function f_exact and phi_i are the
// basis functions in the finite element fespace.
// 9. Define the solution vector x as a parallel finite element grid function
// corresponding to fespace. Initialize x by projecting the exact
// solution. Note that only values from the boundary edges will be used
// when eliminating the non-homogeneous boundary condition to modify the
// r.h.s. vector b.
ParGridFunction x(fespace);
VectorFunctionCoefficient E(sdim, E_exact);
for (int expo=weightStart; expo<=weightEnd; expo++)
{
double weight = pow(10.0,expo);
kappa = weight;
VectorFunctionCoefficient f(sdim, f_exact);
ParLinearForm *b = new ParLinearForm(fespace);
b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
b->Assemble();
x.ProjectCoefficient(E);
// 10. Set up the parallel bilinear form corresponding to the EM diffusion
// operator curl muinv curl + sigma I, by adding the curl-curl and the
// mass domain integrators.
// std::string permFile = "spe_perm.dat";
// InversePermeabilityFunction::ReadPermeabilityFile(permFile, MPI_COMM_WORLD);
Coefficient *alpha = new ConstantCoefficient(1.0);
Coefficient *beta;
// if(spe10Coeff) beta = new FunctionCoefficient(InversePermeabilityFunction::Norm2Permeability);
// else
beta = new ConstantCoefficient(weight);
Coefficient *neg_beta = new ConstantCoefficient(-weight);
ParBilinearForm *a = new ParBilinearForm(fespace);
a->AddDomainIntegrator(new CurlCurlIntegrator(*alpha));
a->AddDomainIntegrator(new VectorFEMassIntegrator(*beta));
// 11. Assemble the parallel bilinear form and the corresponding linear
// system, applying any necessary transformations such as: parallel
// assembly, eliminating boundary conditions, applying conforming
// constraints for non-conforming AMR, static condensation, etc.
if (static_cond) { a->EnableStaticCondensation(); }
a->Assemble();
HypreParMatrix A;
Vector B, X;
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
if (myid == 0)
{
cout << "Size of linear system: " << A.GetGlobalNumRows() << endl;
}
// 12. Define and apply a parallel PCG solver for AX=B with the AMS
// preconditioner from hypre.
ParFiniteElementSpace *prec_fespace =
(a->StaticCondensationIsEnabled() ? a->SCParFESpace() : fespace);
Solver *prec;
if (dim<=3) { prec = new HypreAMS(A, prec_fespace); }
else if (dim==4) { prec = new Curl4dPrec(&A, fespace, alpha, beta, neg_beta, ess_bdr, order, false); }
IterativeSolver *pcg = new CGSolver(MPI_COMM_WORLD);
pcg->SetOperator(A);
pcg->SetRelTol(tol);
pcg->SetMaxIter(5000);
pcg->SetPrintLevel(1);
pcg->SetPreconditioner(*prec);
pcg->Mult(B, X);
int iter = pcg->GetNumIterations();
if (myid==0)
{
cout << "Weigth: " << weight << " " << iter << endl;
int *iters = LoadIterations(10, 2*NExpo+1);
putIterationsInArray(iter, sequ_ref_levels+par_ref_levels, expo+NExpo,
2*NExpo+1, iters);
WriteIterations(iters, 10, 2*NExpo+1);
}
// 13. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
a->RecoverFEMSolution(X, *b, x);
// 14. Compute and print the L^2 norm of the error.
{
double err = x.ComputeL2Error(E);
if (myid == 0)
{
cout << "\n|| E_h - E ||_{L^2} = " << err << '\n' << endl;
}
}
// 15. Save the refined mesh and the solution in parallel. This output can
// be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
// {
// ostringstream mesh_name, sol_name;
// mesh_name << "mesh." << setfill('0') << setw(6) << myid;
// sol_name << "sol." << setfill('0') << setw(6) << myid;
//
// ofstream mesh_ofs(mesh_name.str().c_str());
// mesh_ofs.precision(8);
// pmesh->Print(mesh_ofs);
//
// ofstream sol_ofs(sol_name.str().c_str());
// sol_ofs.precision(8);
// x.Save(sol_ofs);
// }
// // 16. Send the solution by socket to a GLVis server.
// if (visualization)
// {
// char vishost[] = "localhost";
// int visport = 19916;
// socketstream sol_sock(vishost, visport);
// sol_sock << "parallel " << num_procs << " " << myid << "\n";
// sol_sock.precision(8);
// sol_sock << "solution\n" << *pmesh << x << flush;
// }
delete pcg;
delete prec;
delete a;
delete alpha;
delete beta;
delete b;
}
// 17. Free the used memory.
delete fespace;
delete fec;
delete pmesh;
MPI_Finalize();
return 0;
}
void E_exact(const Vector &x, Vector &E)
{
if (dim==4)
{
E(0) = sin(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*cos(M_PI*x(3));
E(1) = -cos(M_PI*x(0))*sin(M_PI*x(1))*cos(M_PI*x(2))*cos(M_PI*x(3));
E(2) = cos(M_PI*x(0))*cos(M_PI*x(1))*sin(M_PI*x(2))*cos(M_PI*x(3));
E(3) = -cos(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*sin(M_PI*x(3));
}
else if (dim == 3)
{
E(0) = sin(kappa * x(1));
E(1) = sin(kappa * x(2));
E(2) = sin(kappa * x(0));
}
else
{
E(0) = sin(kappa * x(1));
E(1) = sin(kappa * x(0));
if (x.Size() == 3) { E(2) = 0.0; }
}
}
void f_exact(const Vector &x, Vector &f)
{
//f_exact = E + DivSkew P( curl E ), where P is the 4d permutation operator
if (dim==4)
{
f(0) = (kappa+4.0*M_PI*M_PI)*sin(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*cos(
M_PI*x(3));
f(1) = -(kappa+4.0*M_PI*M_PI)*cos(M_PI*x(0))*sin(M_PI*x(1))*cos(M_PI*x(2))*cos(
M_PI*x(3));
f(2) = (kappa+4.0*M_PI*M_PI)*cos(M_PI*x(0))*cos(M_PI*x(1))*sin(M_PI*x(2))*cos(
M_PI*x(3));
f(3) = -(kappa+4.0*M_PI*M_PI)*cos(M_PI*x(0))*cos(M_PI*x(1))*cos(M_PI*x(2))*sin(
M_PI*x(3));
}
else if (dim == 3)
{
f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
f(1) = (1. + kappa * kappa) * sin(kappa * x(2));
f(2) = (1. + kappa * kappa) * sin(kappa * x(0));
}
else
{
f(0) = (1. + kappa * kappa) * sin(kappa * x(1));
f(1) = (1. + kappa * kappa) * sin(kappa * x(0));
if (x.Size() == 3) { f(2) = 0.0; }
}
}
-782
View File
@@ -1,782 +0,0 @@
// MFEM Example 3 - Parallel Version
//
// Compile with: make ex3p
//
// Sample runs: mpirun -np 4 ex3p -m ../data/star.mesh
// mpirun -np 4 ex3p -m ../data/square-disc.mesh -o 2
// mpirun -np 4 ex3p -m ../data/beam-tet.mesh
// mpirun -np 4 ex3p -m ../data/beam-hex.mesh
// mpirun -np 4 ex3p -m ../data/escher.mesh
// mpirun -np 4 ex3p -m ../data/fichera.mesh
// mpirun -np 4 ex3p -m ../data/fichera-q2.vtk
// mpirun -np 4 ex3p -m ../data/fichera-q3.mesh
// mpirun -np 4 ex3p -m ../data/square-disc-nurbs.mesh
// mpirun -np 4 ex3p -m ../data/beam-hex-nurbs.mesh
// mpirun -np 4 ex3p -m ../data/amr-quad.mesh -o 2
// mpirun -np 4 ex3p -m ../data/amr-hex.mesh
// mpirun -np 4 ex3p -m ../data/star-surf.mesh -o 2
// mpirun -np 4 ex3p -m ../data/mobius-strip.mesh -o 2 -f 0.1
// mpirun -np 4 ex3p -m ../data/klein-bottle.mesh -o 2 -f 0.1
//
// Description: This example code solves a simple electromagnetic diffusion
// problem corresponding to the second order definite Maxwell
// equation curl curl E + E = f with boundary condition
// E x n = <given tangential field>. Here, we use a given exact
// solution E and compute the corresponding r.h.s. f.
// We discretize with Nedelec finite elements in 2D or 3D.
//
// The example demonstrates the use of H(curl) finite element
// spaces with the curl-curl and the (vector finite element) mass
// bilinear form, as well as the computation of discretization
// error when the exact solution is known. Static condensation is
// also illustrated.
//
// We recommend viewing examples 1-2 before viewing this example.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
#include "./spe10_coeff.cpp"
using namespace std;
using namespace mfem;
int* LoadIterations(int NRows, int NCol)
{
ifstream in("iter_DivSkew.txt");
//initialize
int *iters = new int[NCol*NRows];
for (int col = 0; col < NCol; col++)
{
for (int row = 0; row < NRows; row++)
{
iters[row*NCol+col] = -1;
}
}
if (!in)
{
cout << "Cannot open file.\n";
return iters;
}
for (int row = 0; row < NRows; row++)
for (int col = 0; col < NCol; col++)
{
if (in.eof())
{
in.close();
return iters;
}
in >> iters[row*NCol+col];
}
in.close();
return iters;
}
void putIterationsInArray(int iter, int row, int col, int NCol, int* iters)
{
iters[row*NCol+col] = iter;
}
void WriteIterations(int *iters, int NRows, int NCol)
{
ofstream out;
out.open("iter_DivSkew.txt",fstream::out);
if (!out)
{
cout << "Cannot open file.\n";
delete[] iters;
return;
}
for (int row = 0; row < NRows; row++)
{
for (int col = 0; col < NCol; col++)
{
out << iters[row*NCol+col] << "\t";
}
out << endl;
}
out.close();
delete[] iters;
}
// Exact solution, E, and r.h.s., f. See below for implementation.
void E_exact_vec(const Vector &x, Vector &E);
void E_exact(const Vector &, DenseMatrix &);
void f_exact(const Vector &, DenseMatrix &);
class DivSkew4dPrec : public Solver
{
private:
HypreParMatrix *A;
ParFiniteElementSpace *fespace;
Coefficient *alpha_, *beta_;
//kernel operators
HypreParMatrix *P_d_HCurl_HDivSkew;
HypreParMatrix *P_H1_HCurl;
HypreParMatrix *H1_KernelMat;
HypreBoomerAMG *amgH1_Kernel;
//"image" operators
HypreParMatrix *P_H1_HDivSkew;
HypreParMatrix *H1_ImageMat;
HypreBoomerAMG *amgH1_Image;
HypreParMatrix *HCurlMat;
HypreSmoother * smootherDivSkew;
HypreSmoother * smootherCurl;
CGSolver *pcgKernel;
CGSolver *pcgImage;
Vector *f;
Vector *fKernel, *uKernel;
Vector *fImage, *uImage;
Vector *fCurl, *uCurl;
bool exactSolves;
FiniteElementCollection* fecHCurlKernel;
ParFiniteElementSpace *HCurlKernelFESpace;
public:
~DivSkew4dPrec()
{
delete pcgImage, pcgKernel;
delete f, fKernel, uKernel, fImage, uImage, fCurl, uCurl;
delete smootherCurl, HCurlMat;
delete P_d_HCurl_HDivSkew, P_H1_HDivSkew, P_H1_HCurl;
delete amgH1_Image, H1_ImageMat;
delete amgH1_Kernel, H1_KernelMat;
delete smootherDivSkew;
delete HCurlKernelFESpace, fecHCurlKernel;
}
DivSkew4dPrec(HypreParMatrix *AUser, ParFiniteElementSpace *fespaceUser,
Coefficient *alpha, Coefficient *beta,
const Array<int> &essBnd, int orderKernel=1, bool exactSolvesUser=false)
{
A = AUser;
fespace = fespaceUser;
alpha_ = alpha;
beta_ = beta;
ParMesh *pmesh = fespace->GetParMesh();
int dim = pmesh->Dimension();
exactSolves = exactSolvesUser;
int orderIm=1; //H1 --> H(divSkew)
int orderKer=orderKernel; //curl V --> H(divSkew)
smootherDivSkew = new HypreSmoother(*A, 16, 3);
Array<int> HDivSkew_essDof(fespace->GetVSize()); HDivSkew_essDof = 0;
fespace->GetEssentialVDofs(essBnd, HDivSkew_essDof);
//setup the H1 FESpace for the kernel
FiniteElementCollection* fecH1Kernel = new H1_FECollection(orderKer, 4);
ParFiniteElementSpace *H1KernelFESpace = new ParFiniteElementSpace(pmesh,
fecH1Kernel, dim, Ordering::byVDIM);
Array<int> H1Kernel_essDof(H1KernelFESpace->GetVSize()); H1Kernel_essDof = 0;
H1KernelFESpace->GetEssentialVDofs(essBnd, H1Kernel_essDof);
//setup the H(curl) FESpace for the kernel
if (orderKer==1) { fecHCurlKernel = new ND1_4DFECollection; }
else { fecHCurlKernel = new ND2_4DFECollection; }
HCurlKernelFESpace = new ParFiniteElementSpace(pmesh,
fecHCurlKernel);
Array<int> HCurlKernel_essDof(HCurlKernelFESpace->GetVSize());
HCurlKernel_essDof = 0;
HCurlKernelFESpace->GetEssentialVDofs(essBnd, HCurlKernel_essDof);
//setup the FESpace for the H1 injection
FiniteElementCollection* fecH1Vec;
if (orderIm==1) { fecH1Vec = new LinearFECollection; }
else { fecH1Vec = new QuadraticFECollection; }
ParFiniteElementSpace *H1_ImageFESpace = new ParFiniteElementSpace(pmesh,
fecH1Vec, 6, Ordering::byVDIM);
Array<int> H1Image_essDof(H1_ImageFESpace->GetVSize()); H1Image_essDof = 0;
H1_ImageFESpace->GetEssentialVDofs(essBnd, H1Image_essDof);
//setup the H1 preconditioner for the kernel
ParBilinearForm* H1Varf = new ParBilinearForm(H1KernelFESpace);
H1Varf->AddDomainIntegrator(new VectorDiffusionIntegrator(*beta_));
// H1Varf->AddDomainIntegrator(new VectorMassIntegrator);
H1Varf->Assemble();
H1Varf->Finalize();
SparseMatrix &matH1(H1Varf->SpMat());
for (int dof = 0; dof < H1Kernel_essDof.Size(); dof++)
if (H1Kernel_essDof[dof] < 0)
{
matH1.EliminateRowCol(dof);
}
H1_KernelMat = H1Varf->ParallelAssemble();
delete H1Varf;
amgH1_Kernel = new HypreBoomerAMG(*H1_KernelMat);
amgH1_Kernel->SetSystemsOptions(dim);
amgH1_Kernel->SetPrintLevel(0);
//setup the H1 preconditioner for the image
ParBilinearForm* H1VecVarf = new ParBilinearForm(H1_ImageFESpace);
VectorDiffusionIntegrator *alpha_integ = new VectorDiffusionIntegrator(*alpha_);
alpha_integ->SetVDim(6);
H1VecVarf->AddDomainIntegrator(alpha_integ);
VectorMassIntegrator *beta_integ = new VectorMassIntegrator(*beta);
beta_integ->SetVDim(6);
H1VecVarf->AddDomainIntegrator(beta_integ);
H1VecVarf->Assemble();
H1VecVarf->Finalize();
SparseMatrix &matH1Vec(H1VecVarf->SpMat());
for (int dof=0; dof<H1Image_essDof.Size(); dof++) if (H1Image_essDof[dof]<0) { matH1Vec.EliminateRowCol(dof); }
H1_ImageMat = H1VecVarf->ParallelAssemble();
delete H1VecVarf;
amgH1_Image = new HypreBoomerAMG(*H1_ImageMat);
amgH1_Image->SetSystemsOptions(6);
amgH1_Image->SetPrintLevel(0);
//setup the injection of H1 into H(curl)
ParDiscreteLinearOperator *disInterpol = new ParDiscreteLinearOperator(
H1KernelFESpace, HCurlKernelFESpace);
disInterpol->AddDomainInterpolator(new IdentityInterpolator);
disInterpol->Assemble();
disInterpol->Finalize();
SparseMatrix* smatID = &(disInterpol->SpMat());
smatID->EliminateCols(H1Kernel_essDof);
for (int dof=0; dof<HCurlKernel_essDof.Size();
dof++) if (HCurlKernel_essDof[dof]<0) { smatID->EliminateRow(dof); }
P_H1_HCurl = disInterpol->ParallelAssemble();
delete disInterpol;
//setup the injection of H1 into H(DivSkew)
ParDiscreteLinearOperator *disInterpolIm = new ParDiscreteLinearOperator(
H1_ImageFESpace, fespace);
disInterpolIm->AddDomainInterpolator(new IdentityInterpolator);
disInterpolIm->Assemble();
disInterpolIm->Finalize();
SparseMatrix* smatIDIm = &(disInterpolIm->SpMat());
smatIDIm->EliminateCols(H1Image_essDof);
for (int dof=0; dof<HDivSkew_essDof.Size(); dof++) if (HDivSkew_essDof[dof]<0) { smatIDIm->EliminateRow(dof); }
P_H1_HDivSkew = disInterpolIm->ParallelAssemble();
delete disInterpolIm;
//setup the injection of the curl(H(curl)) into H(DivSkew)
ParDiscreteLinearOperator *disCurl = new ParDiscreteLinearOperator(
HCurlKernelFESpace, fespace);
disCurl->AddDomainInterpolator(new CurlInterpolator);
disCurl->Assemble();
disCurl->Finalize();
SparseMatrix* smatCurl = &(disCurl->SpMat());
smatCurl->EliminateCols(HCurlKernel_essDof);
for (int dof=0; dof<HDivSkew_essDof.Size(); dof++) if (HDivSkew_essDof[dof]<0) { smatCurl->EliminateRow(dof); }
P_d_HCurl_HDivSkew = disCurl->ParallelAssemble();
delete disCurl;
//setup the smoother for H(curl)
// Coefficient *massC = new ConstantCoefficient(1.0);
// Coefficient *CurlCurlC = new ConstantCoefficient(1.0);
ParBilinearForm *a_HCurl = new ParBilinearForm(HCurlKernelFESpace);
a_HCurl->AddDomainIntegrator(new CurlCurlIntegrator(*beta_));
// a_HCurl->AddDomainIntegrator(new CurlCurlIntegrator(*CurlCurlC));
// a_HCurl->AddDomainIntegrator(new VectorFEMassIntegrator(*massC));
a_HCurl->Assemble();
a_HCurl->Finalize();
SparseMatrix &matHCurl(a_HCurl->SpMat());
for (int dof=0; dof<HCurlKernel_essDof.Size();
dof++) if (HCurlKernel_essDof[dof]<0) { matHCurl.EliminateRowCol(dof); }
HCurlMat = a_HCurl->ParallelAssemble();
delete a_HCurl;
smootherCurl = new HypreSmoother(*HCurlMat, 16, 3);
f = new Vector(fespace->GetTrueVSize());
fKernel = new Vector(H1KernelFESpace->GetTrueVSize());
uKernel = new Vector(H1KernelFESpace->GetTrueVSize());
fImage = new Vector(H1_ImageFESpace->GetTrueVSize());
uImage = new Vector(H1_ImageFESpace->GetTrueVSize());
fCurl = new Vector(HCurlKernelFESpace->GetTrueVSize());
uCurl = new Vector(HCurlKernelFESpace->GetTrueVSize());
amgH1_Kernel->Mult(*fKernel, *uKernel);
amgH1_Image->Mult(*fImage, *uImage);
pcgKernel = new CGSolver(MPI_COMM_WORLD);
pcgKernel->SetOperator(*H1_KernelMat);
pcgKernel->SetPreconditioner(*amgH1_Kernel);
pcgKernel->SetRelTol(1e-16);
pcgKernel->SetMaxIter(100000000);
pcgKernel->SetPrintLevel(-2);
pcgImage = new CGSolver(MPI_COMM_WORLD);
pcgImage->SetOperator(*H1_ImageMat);
pcgImage->SetPreconditioner(*amgH1_Image);
pcgImage->SetRelTol(1e-16);
pcgImage->SetMaxIter(100000000);
pcgImage->SetPrintLevel(-2);
delete H1KernelFESpace, fecH1Kernel;
delete H1_ImageFESpace, fecH1Vec;
}
void setExactSolve(bool exSol)
{
exactSolves = exSol;
}
virtual void Mult(const Vector &x, Vector &y) const
{
smootherDivSkew->Mult(x,y);
P_H1_HDivSkew->MultTranspose(x,*fImage);
*uImage = 0.0;
if (exactSolves) { pcgImage->Mult(*fImage, *uImage); }
else { amgH1_Image->Mult(*fImage, *uImage); }
P_H1_HDivSkew->Mult(1.0, *uImage, 1.0, y);
*uCurl = 0.0;
P_d_HCurl_HDivSkew->MultTranspose(x,*fCurl);
smootherCurl->Mult(*fCurl, *uCurl);
P_H1_HCurl->MultTranspose(*fCurl,*fKernel);
*uKernel = 0.0;
if (exactSolves) { pcgKernel->Mult(*fKernel, *uKernel); }
else { amgH1_Kernel->Mult(*fKernel, *uKernel); }
P_H1_HCurl->Mult(1.0, *uKernel, 1.0, *uCurl);
P_d_HCurl_HDivSkew->Mult(1.0, *uCurl, 1.0, y);
}
virtual void SetOperator(const Operator &op) {};
};
int main(int argc, char *argv[])
{
// 1. Initialize MPI.
int num_procs, myid;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
bool verbose = (myid==0);
// 2. Parse command-line options.
const char *mesh_file = "../data/cube4d_96.MFEM";
int order = 1;
bool set_bc = true;
bool static_cond = false;
bool visualization = 1;
int sequ_ref_levels = 0;
int par_ref_levels = 0;
double tol = 1e-6;
double coeffWeight = 1.0;
bool exactH1Solver = false;
bool spe10Coeff = false;
bool standardCG = true;
int NExpo = 8;
int weightStart = -NExpo;
int weightEnd = NExpo;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&sequ_ref_levels, "-sr", "--seqrefinement",
"Number of sequential refinement steps.");
args.AddOption(&par_ref_levels, "-pr", "--parrefinement",
"Number of parallel refinement steps.");
args.AddOption(&order, "-o", "--order",
"Polynomial order of the finite element space.");
args.AddOption(&set_bc, "-bc", "--impose-bc", "-no-bc", "--dont-impose-bc",
"Impose or not essential boundary conditions.");
args.AddOption(&tol, "-tol", "--tol",
"A parameter.");
args.AddOption(&coeffWeight, "-c", "--coeffMass",
"the weight for the mass term.");
args.AddOption(&exactH1Solver, "-exH1Sol", "--exactH1Solver", "-H1prec",
"--H1preconditioner",
"Use exact H1 solvers for the preconditioner.");
args.AddOption(&spe10Coeff, "-spe10", "--useSPE10Coeff", "-constCoeff",
"--constCoeff",
"Switch between the coefficients for the mass bilinear form.");
args.AddOption(&standardCG, "-sCG", "--stdCG", "-rCG", "--resCG",
"Switch between standard PCG or recompute residuals in every step and use the residuals itself for the stopping criteria.");
args.AddOption(&weightStart, "-ws", "--weightStart",
"the exponent for the starting weight (for the mass term).");
args.AddOption(&weightEnd, "-we", "--weightEnd",
"the exponent for the weight at the end (for the mass term).");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.Parse();
if (!args.Good())
{
args.PrintUsage(cout);
return 1;
}
if (verbose) { args.PrintOptions(cout); }
Mesh *mesh;
ifstream imesh(mesh_file);
if (!imesh)
{
cerr << "\nCan not open mesh file: " << mesh_file << '\n' << endl;
return 2;
}
mesh = new Mesh(imesh, 1, 1);
imesh.close();
int dim = mesh->Dimension();
int sdim = mesh->SpaceDimension();
if (dim !=4 || sdim != 4)
{
MPI_Finalize();
return 0;
}
for (int i=0; i<sequ_ref_levels; i++) { mesh->UniformRefinement(); }
if (verbose) { mesh->PrintCharacteristics(); }
if (verbose) { cout << "now we partition the mesh..." << endl << endl; }
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
for (int i=0; i<par_ref_levels; i++) { pmesh->UniformRefinement(); }
pmesh->PrintInfo(std::cout);
if (verbose) { cout << endl; }
// 6. Define a parallel finite element space on the parallel mesh. Here we
// use the Nedelec finite elements of the specified order.
FiniteElementCollection *fec;
if (order==1) { fec = new DivSkew1_4DFECollection; }
// else fec = new F2K1_4DFECollection;
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
fespace->SetUpdateOperatorType(Operator::Hypre_ParCSR);
HYPRE_Int size = fespace->GlobalTrueVSize();
// 7. Determine the list of true (i.e. parallel conforming) essential
// boundary dofs. In this example, the boundary conditions are defined
// by marking all the boundary attributes from the mesh as essential
// (Dirichlet) and converting them to a list of true dofs.
Array<int> ess_tdof_list;
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
ess_bdr = set_bc ? 1 : 0;
if (pmesh->bdr_attributes.Size())
{
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
if (myid == 0)
{
cout << "Number of finite element unknowns: " << size << endl;
}
// 8. Set up the parallel linear form b(.) which corresponds to the
// right-hand side of the FEM linear system, which in this case is
// (f,phi_i) where f is given by the function f_exact and phi_i are the
// basis functions in the finite element fespace.
MatrixFunctionCoefficient f(sdim, f_exact);
MatrixFunctionCoefficient solMat(sdim, E_exact);
VectorFunctionCoefficient solVec(6, E_exact_vec);
// 9. Define the solution vector x as a parallel finite element grid function
// corresponding to fespace. Initialize x by projecting the exact
// solution. Note that only values from the boundary edges will be used
// when eliminating the non-homogeneous boundary condition to modify the
// r.h.s. vector b.
ParGridFunction x(fespace);
for (int expo=weightStart; expo<=weightEnd; expo++)
{
double weight = pow(10.0,expo);
x.ProjectCoefficient(solVec);
ParLinearForm *b = new ParLinearForm(fespace);
b->AddDomainIntegrator(new MatFEDomainLFIntegrator(f));
b->Assemble();
// cout << x << endl;
// x = 0.0;
// 10. Set up the parallel bilinear form corresponding to the EM diffusion
// operator curl muinv curl + sigma I, by adding the curl-curl and the
// mass domain integrators.
// std::string permFile = "spe_perm.dat";
// InversePermeabilityFunction::ReadPermeabilityFile(permFile, MPI_COMM_WORLD);
Coefficient *alpha = new ConstantCoefficient(1.0);
Coefficient *beta;
// if(spe10Coeff) beta = new FunctionCoefficient(InversePermeabilityFunction::Norm2Permeability);
// else
beta = new ConstantCoefficient(weight);
ParBilinearForm *a = new ParBilinearForm(fespace);
a->AddDomainIntegrator(new DivSkewDivSkewIntegrator(*alpha));
a->AddDomainIntegrator(new VectorFE_DivSkewMassIntegrator(*beta));
// 11. Assemble the parallel bilinear form and the corresponding linear
// system, applying any necessary transformations such as: parallel
// assembly, eliminating boundary conditions, applying conforming
// constraints for non-conforming AMR, static condensation, etc.
if (static_cond) { a->EnableStaticCondensation(); }
a->Assemble();
HypreParMatrix A;
Vector B, X;
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
if (myid == 0)
{
cout << "Size of linear system: " << A.GetGlobalNumRows() << endl;
}
//Define the preconditioner
if (myid == 0) { cout << "Set up the preconditioner" << endl; }
Solver *prec;
if (dim==4) { prec = new DivSkew4dPrec(&A, fespace, alpha, beta, ess_bdr, order, exactH1Solver); }
IterativeSolver *pcg = new CGSolver(MPI_COMM_WORLD);
pcg->SetOperator(A);
pcg->SetRelTol(tol);
pcg->SetMaxIter(500);
pcg->SetPrintLevel(1);
pcg->SetPreconditioner(*prec);
pcg->Mult(B, X);
delete prec;
int iter = pcg->GetNumIterations();
if (myid==0)
{
cout << "Weigth: " << weight << " " << iter << endl;
int *iters = LoadIterations(10, 2*NExpo+1);
putIterationsInArray(iter, sequ_ref_levels+par_ref_levels, expo+NExpo,
2*NExpo+1, iters);
WriteIterations(iters, 10, 2*NExpo+1);
}
// 13. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
a->RecoverFEMSolution(X, *b, x);
// 14. Compute and print the L^2 norm of the error.
{
double error = 0.0;
for (int i = 0; i < fespace->GetNE(); i++)
{
const FiniteElement* fe = fespace->GetFE(i);
int fdof = fe->GetDof();
ElementTransformation* transf = fespace->GetElementTransformation(i);
DenseMatrix shape(fdof,dim*dim);
int intorder = 2*fe->GetOrder() + 1; // <----------
const IntegrationRule *ir;
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
Vector elSol(dim*dim);
DenseMatrix elSolMat(dim,dim);
DenseMatrix exactSol(dim,dim);
Vector exactSolVec(dim*dim);
Array<int> vdofs;
fespace->GetElementVDofs(i, vdofs);
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
transf->SetIntPoint(&ip);
fe->CalcVShape(*transf, shape);
elSol = 0.0;
for (int k = 0; k < fdof; k++)
{
if (vdofs[k] >= 0)
{
for (int l=0; l<dim*dim; l++) { elSol(l) += shape(k,l)*x(vdofs[k]); }
}
else
{
for (int l=0; l<dim*dim; l++) { elSol(l) -= shape(k,l)*x(-1-vdofs[k]); }
}
}
for (int k=0; k<dim; k++)
for (int l=0; l<dim; l++)
{
elSolMat(k,l) = elSol(dim*k+l);
}
solMat.Eval(exactSol,*transf, ip);
for (int k=0; k<dim; k++)
for (int l=0; l<dim; l++)
{
exactSolVec(dim*k+l) = exactSol(k,l);
}
elSol.Add(-1.0, exactSolVec);
error += ip.weight * fabs(transf->Weight()) * (elSol * elSol);
}
}
double globalError = 0.0;
MPI_Allreduce(&error, &globalError, 1, MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD);
if (myid==0) { std::cout << "L2 error: " << sqrt(globalError) << std::endl; }
}
delete pcg;
delete a;
delete alpha;
delete beta;
delete b;
}
// 17. Free the used memory.
delete fespace;
delete fec;
delete pmesh;
MPI_Finalize();
return 0;
}
void E_exact_vec(const Vector &x, Vector &E)
{
int dim = x.Size();
if (dim==4)
{
E.SetSize(6);
double s0 = sin(M_PI*x(0)), s1 = sin(M_PI*x(1)), s2 = sin(M_PI*x(2)),
s3 = sin(M_PI*x(3));
double c0 = cos(M_PI*x(0)), c1 = cos(M_PI*x(1)), c2 = cos(M_PI*x(2)),
c3 = cos(M_PI*x(3));
E(0) = c0*c1*s2*s3;
E(1) = -c0*s1*c2*s3;
E(2) = c0*s1*s2*c3;
E(3) = s0*c1*c2*s3;
E(4) = -s0*c1*s2*c3;
E(5) = s0*s1*c2*c3;
}
}
void E_exact(const Vector &x, DenseMatrix &E)
{
int dim = x.Size();
E.SetSize(dim*dim);
if (dim==4)
{
Vector vecE; E_exact_vec(x, vecE);
E = 0.0;
E(0,1) = vecE(0);
E(0,2) = vecE(1);
E(0,3) = vecE(2);
E(1,2) = vecE(3);
E(1,3) = vecE(4);
E(2,3) = vecE(5);
E(1,0) = -E(0,1);
E(2,0) = -E(0,2);
E(3,0) = -E(0,3);
E(2,1) = -E(1,2);
E(3,1) = -E(1,3);
E(3,2) = -E(2,3);
}
}
//f_exact = E + 0.5 * P( curl DivSkew E ), where P is the 4d permutation operator
void f_exact(const Vector &x, DenseMatrix &f)
{
int dim = x.Size();
f.SetSize(dim,dim);
if (dim==4)
{
f = 0.0;
double s0 = sin(M_PI*x(0)), s1 = sin(M_PI*x(1)), s2 = sin(M_PI*x(2)),
s3 = sin(M_PI*x(3));
double c0 = cos(M_PI*x(0)), c1 = cos(M_PI*x(1)), c2 = cos(M_PI*x(2)),
c3 = cos(M_PI*x(3));
f(0,1) = (1.0 + 1.0 * M_PI*M_PI)*c0*c1*s2*s3;
f(0,2) = -(1.0 + 0.0 * M_PI*M_PI)*c0*s1*c2*s3;
f(0,3) = (1.0 + 1.0 * M_PI*M_PI)*c0*s1*s2*c3;
f(1,2) = (1.0 - 1.0 * M_PI*M_PI)*s0*c1*c2*s3;
f(1,3) = -(1.0 + 0.0 * M_PI*M_PI)*s0*c1*s2*c3;
f(2,3) = (1.0 + 1.0 * M_PI*M_PI)*s0*s1*c2*c3;
f(1,0) = -f(0,1);
f(2,0) = -f(0,2);
f(3,0) = -f(0,3);
f(2,1) = -f(1,2);
f(3,1) = -f(1,3);
f(3,2) = -f(2,3);
}
}
-800
View File
@@ -1,800 +0,0 @@
// MFEM Example 4 - Parallel Version
//
// Compile with: make ex4p
//
// Sample runs: mpirun -np 4 ex4p -m ../data/square-disc.mesh
// mpirun -np 4 ex4p -m ../data/star.mesh
// mpirun -np 4 ex4p -m ../data/beam-tet.mesh
// mpirun -np 4 ex4p -m ../data/beam-hex.mesh
// mpirun -np 4 ex4p -m ../data/escher.mesh -o 2 -sc
// mpirun -np 4 ex4p -m ../data/fichera.mesh -o 2 -hb
// mpirun -np 4 ex4p -m ../data/fichera-q2.vtk
// mpirun -np 4 ex4p -m ../data/fichera-q3.mesh -o 2 -sc
// mpirun -np 4 ex4p -m ../data/square-disc-nurbs.mesh -o 3
// mpirun -np 4 ex4p -m ../data/beam-hex-nurbs.mesh -o 3
// mpirun -np 4 ex4p -m ../data/periodic-square.mesh -no-bc
// mpirun -np 4 ex4p -m ../data/periodic-cube.mesh -no-bc
// mpirun -np 4 ex4p -m ../data/amr-quad.mesh
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -sc
// mpirun -np 4 ex4p -m ../data/amr-hex.mesh -o 2 -hb
// mpirun -np 4 ex4p -m ../data/star-surf.mesh -o 3 -hb
//
// Description: This example code solves a simple 2D/3D H(div) diffusion
// problem corresponding to the second order definite equation
// -grad(alpha div F) + beta F = f with boundary condition F dot n
// = <given normal field>. Here, we use a given exact solution F
// and compute the corresponding r.h.s. f. We discretize with
// Raviart-Thomas finite elements.
//
// The example demonstrates the use of H(div) finite element
// spaces with the grad-div and H(div) vector finite element mass
// bilinear form, as well as the computation of discretization
// error when the exact solution is known. Bilinear form
// hybridization and static condensation are also illustrated.
//
// We recommend viewing examples 1-3 before viewing this example.
#include "mfem.hpp"
#include <fstream>
#include <iostream>
#include "./spe10_coeff.cpp"
using namespace std;
using namespace mfem;
int* LoadIterations(int NRows, int NCol)
{
ifstream in("iter_div.txt");
//initialize
int *iters = new int[NCol*NRows];
for (int col = 0; col < NCol; col++)
{
for (int row = 0; row < NRows; row++)
{
iters[row*NCol+col] = -1;
}
}
if (!in)
{
cout << "Cannot open file.\n";
return iters;
}
for (int row = 0; row < NRows; row++)
for (int col = 0; col < NCol; col++)
{
if (in.eof())
{
in.close();
return iters;
}
in >> iters[row*NCol+col];
}
in.close();
return iters;
}
void putIterationsInArray(int iter, int row, int col, int NCol, int* iters)
{
iters[row*NCol+col] = iter;
}
void WriteIterations(int *iters, int NRows, int NCol)
{
ofstream out;
out.open("iter_div.txt",fstream::out);
if (!out)
{
cout << "Cannot open file.\n";
delete[] iters;
return;
}
for (int row = 0; row < NRows; row++)
{
for (int col = 0; col < NCol; col++)
{
out << iters[row*NCol+col] << "\t";
}
out << endl;
}
out.close();
delete[] iters;
}
// Exact solution, F, and r.h.s., f. See below for implementation.
void F_exact(const Vector &, Vector &);
void f_exact(const Vector &, Vector &);
double freq = 1.0, kappa;
class div4dPrec : public Solver
{
private:
HypreParMatrix *A;
ParFiniteElementSpace *fespace;
Coefficient *alpha_, *beta_;
//kernel operators
HypreParMatrix *P_d_HSkewDiv_Hdiv;
HypreParMatrix *P_H1_HDivSkew;
HypreParMatrix *H1_KernelMat;
HypreBoomerAMG *amgH1_Kernel;
//"image" operators
HypreParMatrix *P_H1_Hdiv;
HypreParMatrix *H1_ImageMat;
HypreBoomerAMG *amgH1_Image;
HypreParMatrix *HDivSkewMat;
HypreSmoother * smootherdiv;
HypreSmoother * smootherDivSkew;
CGSolver *pcgKernel;
CGSolver *pcgImage;
Vector *f;
Vector *fKernel, *uKernel;
Vector *fImage, *uImage;
Vector *fDivSkew, *uDivSkew;
FiniteElementCollection* fecHDivSkewKernel;
ParFiniteElementSpace *HDivSkewKernelFESpace;
bool exactSolves;
public:
~div4dPrec()
{
delete pcgImage;
delete pcgKernel;
delete uDivSkew, fDivSkew, uImage, fImage, uKernel, fKernel, f;
delete smootherDivSkew;
delete HDivSkewMat;
delete P_d_HSkewDiv_Hdiv;
delete P_H1_Hdiv;
delete P_H1_HDivSkew;
delete amgH1_Image, H1_ImageMat;
delete amgH1_Kernel, H1_KernelMat;
delete smootherdiv;
delete HDivSkewKernelFESpace;
delete fecHDivSkewKernel;
}
div4dPrec(HypreParMatrix *AUser, ParFiniteElementSpace *fespaceUser,
Coefficient *alpha, Coefficient *beta, const Array<int> &essBnd,
int orderKernel=1, bool exactSolvesUser=false)
{
A = AUser;
fespace = fespaceUser;
alpha_ = alpha;
beta_ = beta;
ParMesh *pmesh = fespace->GetParMesh();
int dim = pmesh->Dimension();
exactSolves = exactSolvesUser;
int orderIm=1; //H1 --> H(div)
int orderKer=orderKernel; //DivSkew V --> H(div)
smootherdiv = new HypreSmoother(*A, 16, 3);
Array<int> Hdiv_essDof(fespace->GetVSize()); Hdiv_essDof = 0;
fespace->GetEssentialVDofs(essBnd, Hdiv_essDof);
//setup the H1 FESpace for the kernel
FiniteElementCollection* fecH1Kernel;
if (orderKer==1) { fecH1Kernel = new LinearFECollection; }
else { fecH1Kernel = new QuadraticFECollection; }
ParFiniteElementSpace *H1KernelFESpace = new ParFiniteElementSpace(pmesh,
fecH1Kernel, 6, Ordering::byVDIM);
Array<int> H1Kernel_essDof(H1KernelFESpace->GetVSize()); H1Kernel_essDof = 0;
H1KernelFESpace->GetEssentialVDofs(essBnd, H1Kernel_essDof);
//setup the H(DivSkew) FESpace for the kernel
if (orderKer==1) { fecHDivSkewKernel = new DivSkew1_4DFECollection; }
// else fecHDivSkewKernel = new DivSkewFull1_4DFECollection;
HDivSkewKernelFESpace = new ParFiniteElementSpace(pmesh, fecHDivSkewKernel);
Array<int> HDivSkewKernel_essDof(HDivSkewKernelFESpace->GetVSize());
HDivSkewKernel_essDof = 0;
HDivSkewKernelFESpace->GetEssentialVDofs(essBnd, HDivSkewKernel_essDof);
//setup the FESpace for the H1 injection
FiniteElementCollection* fecH1Vec;
if (orderIm==1) { fecH1Vec = new LinearFECollection; }
else { fecH1Vec = new QuadraticFECollection; }
ParFiniteElementSpace *H1_ImageFESpace = new ParFiniteElementSpace(pmesh,
fecH1Vec, dim, Ordering::byVDIM);
Array<int> H1Image_essDof(H1_ImageFESpace->GetVSize()); H1Image_essDof = 0;
H1_ImageFESpace->GetEssentialVDofs(essBnd, H1Image_essDof);
//setup the H1 preconditioner for the kernel
ParBilinearForm* H1Varf = new ParBilinearForm(H1KernelFESpace);
// H1Varf->AddDomainIntegrator(new VectorDiffusionIntegrator(*alpha_, 6));
// H1Varf->AddDomainIntegrator(new VectorMassIntegrator(6, beta_));
H1Varf->AddDomainIntegrator(new VectorDiffusionIntegrator(*beta_, 6));
H1Varf->Assemble();
H1Varf->Finalize();
SparseMatrix &matH1(H1Varf->SpMat());
for (int dof=0; dof<H1Kernel_essDof.Size(); dof++) if (H1Kernel_essDof[dof]<0) { matH1.EliminateRowCol(dof); }
H1_KernelMat = H1Varf->ParallelAssemble();
delete H1Varf;
amgH1_Kernel = new HypreBoomerAMG(*H1_KernelMat);
amgH1_Kernel->SetSystemsOptions(6);
//setup the H1 preconditioner for the image
ParBilinearForm* H1VecVarf = new ParBilinearForm(H1_ImageFESpace);
H1VecVarf->AddDomainIntegrator(new VectorDiffusionIntegrator(*alpha_));
H1VecVarf->AddDomainIntegrator(new VectorMassIntegrator(-1, beta_));
H1VecVarf->Assemble();
H1VecVarf->Finalize();
SparseMatrix &matH1Vec(H1VecVarf->SpMat());
for (int dof=0; dof<H1Image_essDof.Size(); dof++) if (H1Image_essDof[dof]<0) { matH1Vec.EliminateRowCol(dof); }
H1_ImageMat = H1VecVarf->ParallelAssemble();
delete H1VecVarf;
amgH1_Image = new HypreBoomerAMG(*H1_ImageMat);
amgH1_Image->SetSystemsOptions(dim);
//setup the injection of H1 into H(DivSkew)
ParDiscreteLinearOperator *disInterpolIm = new ParDiscreteLinearOperator(
H1KernelFESpace, HDivSkewKernelFESpace);
disInterpolIm->AddDomainInterpolator(new IdentityInterpolator);
disInterpolIm->Assemble();
disInterpolIm->Finalize();
SparseMatrix* smatIDIm = &(disInterpolIm->SpMat());
smatIDIm->EliminateCols(H1Kernel_essDof);
for (int dof=0; dof<HDivSkewKernel_essDof.Size();
dof++) if (HDivSkewKernel_essDof[dof]<0) { smatIDIm->EliminateRow(dof); }
P_H1_HDivSkew = disInterpolIm->ParallelAssemble();
delete disInterpolIm;
//setup the injection of H1 into H(div)
ParDiscreteLinearOperator *disInterpol = new ParDiscreteLinearOperator(
H1_ImageFESpace, fespace);
disInterpol->AddDomainInterpolator(new IdentityInterpolator);
disInterpol->Assemble();
disInterpol->Finalize();
SparseMatrix* smatID = &(disInterpol->SpMat());
smatID->EliminateCols(H1Image_essDof);
for (int dof=0; dof<Hdiv_essDof.Size(); dof++) if (Hdiv_essDof[dof]<0) { smatID->EliminateRow(dof); }
P_H1_Hdiv = disInterpol->ParallelAssemble();
delete disInterpol;
//setup the injection of the DivSkew(H(DivSkew)) into H(div)
ParDiscreteLinearOperator *disDivSkew = new ParDiscreteLinearOperator(
HDivSkewKernelFESpace, fespace);
disDivSkew->AddDomainInterpolator(new DivSkewInterpolator);
disDivSkew->Assemble();
disDivSkew->Finalize();
SparseMatrix* smatDivSkew= &(disDivSkew->SpMat());
smatDivSkew->EliminateCols(HDivSkewKernel_essDof);
for (int dof=0; dof<Hdiv_essDof.Size(); dof++) if (Hdiv_essDof[dof]<0) { smatDivSkew->EliminateRow(dof); }
P_d_HSkewDiv_Hdiv = disDivSkew->ParallelAssemble();
delete disDivSkew;
//setup the smoother for H(DivSkew)
ParBilinearForm *a_HDivSkew = new ParBilinearForm(HDivSkewKernelFESpace);
// a_HDivSkew->AddDomainIntegrator(new DivSkewDivSkewIntegrator(*alpha_));
// a_HDivSkew->AddDomainIntegrator(new VectorFE_DivSkewMassIntegrator(*beta_));
a_HDivSkew->AddDomainIntegrator(new DivSkewDivSkewIntegrator(*beta_));
a_HDivSkew->Assemble();
a_HDivSkew->Finalize();
SparseMatrix &matHDivSkew(a_HDivSkew->SpMat());
for (int dof=0; dof<HDivSkewKernel_essDof.Size();
dof++) if (HDivSkewKernel_essDof[dof]<0) { matHDivSkew.EliminateRowCol(dof); }
HDivSkewMat = a_HDivSkew->ParallelAssemble();
delete a_HDivSkew;
smootherDivSkew = new HypreSmoother(*HDivSkewMat, 16, 3);
f = new Vector(fespace->GetTrueVSize());
fKernel = new Vector(H1KernelFESpace->GetTrueVSize());
uKernel = new Vector(H1KernelFESpace->GetTrueVSize());
fImage = new Vector(H1_ImageFESpace->GetTrueVSize());
uImage = new Vector(H1_ImageFESpace->GetTrueVSize());
fDivSkew = new Vector(HDivSkewKernelFESpace->GetTrueVSize());
uDivSkew = new Vector(HDivSkewKernelFESpace->GetTrueVSize());
amgH1_Kernel->Mult(*fKernel, *uKernel);
amgH1_Image->Mult(*fImage, *uImage);
pcgKernel = new CGSolver(MPI_COMM_WORLD);
pcgKernel->SetOperator(*H1_KernelMat);
pcgKernel->SetPreconditioner(*amgH1_Kernel);
pcgKernel->SetRelTol(1e-16);
pcgKernel->SetMaxIter(100000000);
pcgKernel->SetPrintLevel(-2);
pcgImage = new CGSolver(MPI_COMM_WORLD);
pcgImage->SetOperator(*H1_ImageMat);
pcgImage->SetPreconditioner(*amgH1_Image);
pcgImage->SetRelTol(1e-16);
pcgImage->SetMaxIter(100000000);
pcgImage->SetPrintLevel(-2);
delete H1_ImageFESpace;
delete H1KernelFESpace;
delete fecH1Kernel;
delete fecH1Vec;
}
void setExactSolve(bool exSol)
{
exactSolves = exSol;
}
virtual void Mult(const Vector &x, Vector &y) const
{
smootherdiv->Mult(x,y);
P_H1_Hdiv->MultTranspose(x,*fImage);
*uImage = 0.0;
if (exactSolves) { pcgImage->Mult(*fImage, *uImage); }
else { amgH1_Image->Mult(*fImage, *uImage); }
P_H1_Hdiv->Mult(1.0, *uImage, 1.0, y);
*uDivSkew = 0.0;
P_d_HSkewDiv_Hdiv->MultTranspose(x,*fDivSkew);
smootherDivSkew->Mult(*fDivSkew, *uDivSkew);
P_H1_HDivSkew->MultTranspose(*fDivSkew,*fKernel);
*uKernel = 0.0;
if (exactSolves) { pcgKernel->Mult(*fKernel, *uKernel); }
else { amgH1_Kernel->Mult(*fKernel, *uKernel); }
P_H1_HDivSkew->Mult(1.0, *uKernel, 1.0, *uDivSkew);
P_d_HSkewDiv_Hdiv->Mult(1.0, *uDivSkew, 1.0, y);
}
virtual void SetOperator(const Operator &op) {};
};
int main(int argc, char *argv[])
{
// 1. Initialize MPI.
int num_procs, myid;
MPI_Init(&argc, &argv);
MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
MPI_Comm_rank(MPI_COMM_WORLD, &myid);
bool verbose = (myid==0);
// 2. Parse command-line options.
const char *mesh_file = "../data/star.mesh";
int order = 1;
bool set_bc = true;
bool static_cond = false;
bool hybridization = false;
bool visualization = 1;
int sequ_ref_levels = 0;
int par_ref_levels = 0;
double tol = 1e-6;
double coeffWeight = 1.0;
bool spe10Coeff = false;
bool exactH1Solver = false;
bool standardCG = true;
int NExpo = 8;
int weightStart = -NExpo;
int weightEnd = NExpo;
OptionsParser args(argc, argv);
args.AddOption(&mesh_file, "-m", "--mesh",
"Mesh file to use.");
args.AddOption(&order, "-o", "--order",
"Finite element order (polynomial degree).");
args.AddOption(&sequ_ref_levels, "-sr", "--seqrefinement",
"Number of sequential refinement steps.");
args.AddOption(&par_ref_levels, "-pr", "--parrefinement",
"Number of parallel refinement steps.");
args.AddOption(&set_bc, "-bc", "--impose-bc", "-no-bc", "--dont-impose-bc",
"Impose or not essential boundary conditions.");
args.AddOption(&freq, "-f", "--frequency", "Set the frequency for the exact"
" solution.");
args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
"--no-static-condensation", "Enable static condensation.");
args.AddOption(&hybridization, "-hb", "--hybridization", "-no-hb",
"--no-hybridization", "Enable hybridization.");
args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
"--no-visualization",
"Enable or disable GLVis visualization.");
args.AddOption(&tol, "-tol", "--tol",
"A parameter.");
args.AddOption(&coeffWeight, "-c", "--coeffMass",
"the weight for the mass term.");
args.AddOption(&exactH1Solver, "-exH1Sol", "--exactH1Solver", "-H1prec",
"--H1preconditioner",
"Use exact H1 solvers for the preconditioner.");
args.AddOption(&spe10Coeff, "-spe10", "--useSPE10Coeff", "-constCoeff",
"--constCoeff",
"Switch between the coefficients for the mass bilinear form.");
args.AddOption(&standardCG, "-sCG", "--stdCG", "-rCG", "--resCG",
"Switch between standard PCG or recompute residuals in every step and use the residuals itself for the stopping criteria.");
args.AddOption(&weightStart, "-ws", "--weightStart",
"the exponent for the starting weight (for the mass term).");
args.AddOption(&weightEnd, "-we", "--weightEnd",
"the exponent for the weight at the end (for the mass term).");
args.Parse();
if (!args.Good())
{
if (myid == 0)
{
args.PrintUsage(cout);
}
MPI_Finalize();
return 1;
}
if (myid == 0)
{
args.PrintOptions(cout);
}
kappa = freq * M_PI;
// 3. Read the (serial) mesh from the given mesh file on all processors. We
// can handle triangular, quadrilateral, tetrahedral, hexahedral, surface
// and volume, as well as periodic meshes with the same code.
Mesh *mesh = new Mesh(mesh_file, 1, 1);
int dim = mesh->Dimension();
int sdim = mesh->SpaceDimension();
// 4. Refine the serial mesh on all processors to increase the resolution. In
// this example we do 'ref_levels' of uniform refinement. We choose
// 'ref_levels' to be the largest number that gives a final mesh with no
// more than 1,000 elements.
{
for (int l = 0; l < sequ_ref_levels; l++)
{
mesh->UniformRefinement();
}
}
// 5. Define a parallel mesh by a partitioning of the serial mesh. Refine
// this mesh further in parallel to increase the resolution. Once the
// parallel mesh is defined, the serial mesh can be deleted. Tetrahedral
// meshes need to be reoriented before we can define high-order Nedelec
// spaces on them (this is needed in the ADS solver below).
ParMesh *pmesh = new ParMesh(MPI_COMM_WORLD, *mesh);
delete mesh;
{
for (int l = 0; l < par_ref_levels; l++)
{
pmesh->UniformRefinement();
}
}
pmesh->ReorientTetMesh();
// 6. Define a parallel finite element space on the parallel mesh. Here we
// use the Raviart-Thomas finite elements of the specified order.
FiniteElementCollection *fec;
if (dim==4) { fec = new RT0_4DFECollection; }
else { fec = new RT_FECollection(order-1, dim); }
ParFiniteElementSpace *fespace = new ParFiniteElementSpace(pmesh, fec);
HYPRE_Int size = fespace->GlobalTrueVSize();
if (myid == 0)
{
cout << "Number of finite element unknowns: " << size << endl;
}
// 7. Determine the list of true (i.e. parallel conforming) essential
// boundary dofs. In this example, the boundary conditions are defined
// by marking all the boundary attributes from the mesh as essential
// (Dirichlet) and converting them to a list of true dofs.
Array<int> ess_tdof_list;
Array<int> ess_bdr(pmesh->bdr_attributes.Max());
ess_bdr = set_bc ? 1 : 0;
if (pmesh->bdr_attributes.Size())
{
fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
}
// 8. Set up the parallel linear form b(.) which corresponds to the
// right-hand side of the FEM linear system, which in this case is
// (f,phi_i) where f is given by the function f_exact and phi_i are the
// basis functions in the finite element fespace.
// 9. Define the solution vector x as a parallel finite element grid function
// corresponding to fespace. Initialize x by projecting the exact
// solution. Note that only values from the boundary faces will be used
// when eliminating the non-homogeneous boundary condition to modify the
// r.h.s. vector b.
ParGridFunction x(fespace);
VectorFunctionCoefficient F(sdim, F_exact);
for (int expo=weightStart; expo<=weightEnd; expo++)
{
double weight = pow(10.0,expo);
kappa = weight;
x.ProjectCoefficient(F);
VectorFunctionCoefficient f(sdim, f_exact);
ParLinearForm *b = new ParLinearForm(fespace);
b->AddDomainIntegrator(new VectorFEDomainLFIntegrator(f));
b->Assemble();
// 10. Set up the parallel bilinear form corresponding to the H(div)
// diffusion operator grad alpha div + beta I, by adding the div-div and
// the mass domain integrators.
// std::string permFile = "spe_perm.dat";
// InversePermeabilityFunction::ReadPermeabilityFile(permFile, MPI_COMM_WORLD);
Coefficient *alpha = new ConstantCoefficient(1.0);
Coefficient *beta;
// if(spe10Coeff) beta = new FunctionCoefficient(InversePermeabilityFunction::Norm2Permeability);
// else
beta = new ConstantCoefficient(weight);
ParBilinearForm *a = new ParBilinearForm(fespace);
a->AddDomainIntegrator(new DivDivIntegrator(*alpha));
a->AddDomainIntegrator(new VectorFEMassIntegrator(*beta));
// 11. Assemble the parallel bilinear form and the corresponding linear
// system, applying any necessary transformations such as: parallel
// assembly, eliminating boundary conditions, applying conforming
// constraints for non-conforming AMR, static condensation,
// hybridization, etc.
FiniteElementCollection *hfec = NULL;
ParFiniteElementSpace *hfes = NULL;
if (static_cond)
{
a->EnableStaticCondensation();
}
else if (hybridization)
{
hfec = new DG_Interface_FECollection(order-1, dim);
hfes = new ParFiniteElementSpace(pmesh, hfec);
a->EnableHybridization(hfes, new NormalTraceJumpIntegrator(),
ess_tdof_list);
}
a->Assemble();
HypreParMatrix A;
Vector B, X;
a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);
HYPRE_Int glob_size = A.GetGlobalNumRows();
if (myid == 0)
{
cout << "Size of linear system: " << glob_size << endl;
}
// 12. Define and apply a parallel PCG solver for A X = B with the 2D AMS or
// the 3D ADS preconditioners from hypre. If using hybridization, the
// system is preconditioned with hypre's BoomerAMG.
Solver *prec = NULL;
if (hybridization) { prec = new HypreBoomerAMG(A); }
else
{
ParFiniteElementSpace *prec_fespace =
(a->StaticCondensationIsEnabled() ? a->SCParFESpace() : fespace);
if (dim == 2) { prec = new HypreAMS(A, prec_fespace); }
else if (dim==3) { prec = new HypreADS(A, prec_fespace); }
else if (dim==4) { prec = new div4dPrec(&A, fespace, alpha, beta, ess_bdr, order, exactH1Solver); }
else { prec = NULL; }
}
int iter = -1;
if (standardCG)
{
IterativeSolver *pcg = new CGSolver(MPI_COMM_WORLD);
pcg->SetOperator(A);
pcg->SetRelTol(tol);
pcg->SetMaxIter(500);
pcg->SetPrintLevel(1);
pcg->SetPreconditioner(*prec);
pcg->Mult(B, X);
iter = pcg->GetNumIterations();
delete pcg;
}
else
{
HyprePCG *pcg = new HyprePCG(A);
pcg->SetTol(tol);
pcg->SetMaxIter(5000);
pcg->SetResidualConvergenceOptions(1,tol);
pcg->SetPrintLevel(2);
// pcg->SetPreconditioner(*prec);
pcg->Mult(B, X);
pcg->GetNumIterations(iter);
delete pcg;
}
if (myid==0)
{
cout << "Weigth: " << weight << " " << iter << endl;
int *iters = LoadIterations(10, 2*NExpo+1);
putIterationsInArray(iter, sequ_ref_levels+par_ref_levels, expo+NExpo,
2*NExpo+1, iters);
WriteIterations(iters, 10, 2*NExpo+1);
}
// 13. Recover the parallel grid function corresponding to X. This is the
// local finite element solution on each processor.
a->RecoverFEMSolution(X, *b, x);
// 14. Compute and print the L^2 norm of the error.
{
double err = x.ComputeL2Error(F);
if (myid == 0)
{
cout << "\n|| F_h - F ||_{L^2} = " << err << '\n' << endl;
}
}
// 15. Save the refined mesh and the solution in parallel. This output can
// be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
// {
// ostringstream mesh_name, sol_name;
// mesh_name << "mesh." << setfill('0') << setw(6) << myid;
// sol_name << "sol." << setfill('0') << setw(6) << myid;
//
// ofstream mesh_ofs(mesh_name.str().c_str());
// mesh_ofs.precision(8);
// pmesh->Print(mesh_ofs);
//
// ofstream sol_ofs(sol_name.str().c_str());
// sol_ofs.precision(8);
// x.Save(sol_ofs);
// }
// 16. Send the solution by socket to a GLVis server.
// if (visualization)
// {
// char vishost[] = "localhost";
// int visport = 19916;
// socketstream sol_sock(vishost, visport);
// sol_sock << "parallel " << num_procs << " " << myid << "\n";
// sol_sock.precision(8);
// sol_sock << "solution\n" << *pmesh << x << flush;
// }
if (prec!=NULL) { delete prec; }
delete hfes;
delete hfec;
delete a;
delete alpha;
delete beta;
delete b;
}
// 17. Free the used memory.
delete fespace;
delete fec;
delete pmesh;
MPI_Finalize();
return 0;
}
// The exact solution (for non-surface meshes)
void F_exact(const Vector &p, Vector &F)
{
int dim = p.Size();
if (dim==4)
{
double s0 = sin(M_PI*p(0)), s1 = sin(M_PI*p(1)), s2 = sin(M_PI*p(2)),
s3 = sin(M_PI*p(3));
double c0 = cos(M_PI*p(0)), c1 = cos(M_PI*p(1)), c2 = cos(M_PI*p(2)),
c3 = cos(M_PI*p(3));
F(0) = c0 * s1 * s2 * s3;
F(1) = s0 * c1 * s2 * s3;
F(2) = s0 * s1 * c2 * s3;
F(3) = s0 * s1 * s2 * c3;
}
else
{
double x = p(0);
double y = p(1);
// double z = (dim == 3) ? p(2) : 0.0;
F(0) = cos(kappa*x)*sin(kappa*y);
F(1) = cos(kappa*y)*sin(kappa*x);
if (dim == 3)
{
F(2) = 0.0;
}
}
}
// The right hand side
void f_exact(const Vector &p, Vector &f)
{
int dim = p.Size();
if (dim==4)
{
double s0 = sin(M_PI*p(0)), s1 = sin(M_PI*p(1)), s2 = sin(M_PI*p(2)),
s3 = sin(M_PI*p(3));
double c0 = cos(M_PI*p(0)), c1 = cos(M_PI*p(1)), c2 = cos(M_PI*p(2)),
c3 = cos(M_PI*p(3));
f(0) = c0 * s1 * s2 * s3;
f(1) = s0 * c1 * s2 * s3;
f(2) = s0 * s1 * c2 * s3;
f(3) = s0 * s1 * s2 * c3;
f *= (kappa + 4.0 * M_PI*M_PI);
}
else
{
double x = p(0);
double y = p(1);
// double z = (dim == 3) ? p(2) : 0.0;
double temp = 1 + 2*kappa*kappa;
f(0) = temp*cos(kappa*x)*sin(kappa*y);
f(1) = temp*cos(kappa*y)*sin(kappa*x);
if (dim == 3)
{
f(2) = 0;
}
}
}
+1 -2
View File
@@ -27,8 +27,7 @@ SEQ_EXAMPLES = ex0 ex1 ex2 ex3 ex4 ex5 ex6 ex7 ex8 ex9 ex10 ex14 ex15 ex16 \
PAR_EXAMPLES = ex0p ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex8p ex9p ex10p ex11p \
ex12p ex13p ex14p ex15p ex16p ex17p ex18p ex19p ex20p ex21p ex22p ex24p \
ex25p ex26p ex27p ex28p ex29p ex30p ex31p ex32p ex33p ex34p ex35p ex36p \
ex37p ex39p ex40p \
ex1p_4d ex3p_4d ex4D_DivSkew
ex37p ex39p ex40p
SEQ_DEVICE_EXAMPLES = ex1 ex3 ex4 ex5 ex6 ex9 ex14 ex22 ex24 ex25 ex26 ex34
PAR_DEVICE_EXAMPLES = ex1p ex2p ex3p ex4p ex5p ex6p ex7p ex9p ex13p ex14p \
ex22p ex24p ex25p ex26p ex34p ex35p
-352
View File
@@ -1,352 +0,0 @@
/*
* spe10_coeff.cpp
*
* Created on: Aug 23, 2017
* Author: neumueller
*/
#include "mfem.hpp"
#include <fstream>
#include <iostream>
using namespace std;
using namespace mfem;
class InversePermeabilityFunction
{
public:
enum SliceOrientation {NONE, XY, XZ, YZ};
static void SetNumberCells(int Nx_, int Ny_, int Nz_);
static void SetMeshSizes(double hx, double hy, double hz);
static void Set2DSlice(SliceOrientation o, int npos );
static void ReadPermeabilityFile(const std::string fileName);
#ifdef MFEM_USE_MPI
static void ReadPermeabilityFile(const std::string fileName, MPI_Comm comm);
#endif
static void SetConstantInversePermeability(double ipx, double ipy, double ipz);
template<class F>
static void Transform(const F & f)
{
for (int i = 0; i < 3*Nx*Ny*Nz; ++i)
{
inversePermeability[i] = f(inversePermeability[i]);
}
}
static void InversePermeability(const Vector & x, Vector & val);
static double PermeabilityXY(Vector &x);
static void NegativeInversePermeability(const Vector & x, Vector & val);
static void Permeability(const Vector & x, Vector & val);
static double Norm2Permeability(const Vector & x);
static double Norm2InversePermeability(const Vector & x);
static double Norm1InversePermeability(const Vector & x);
static double NormInfInversePermeability(const Vector & x);
static double InvNorm2(const Vector & x);
static double InvNorm1(const Vector & x);
static double InvNormInf(const Vector & x);
static void ClearMemory();
private:
static int Nx;
static int Ny;
static int Nz;
static double hx;
static double hy;
static double hz;
static double * inversePermeability;
static SliceOrientation orientation;
static int npos;
};
void InversePermeabilityFunction::SetNumberCells(int Nx_, int Ny_, int Nz_)
{
Nx = Nx_;
Ny = Ny_;
Nz = Nz_;
}
void InversePermeabilityFunction::SetMeshSizes(double hx_, double hy_,
double hz_)
{
hx = hx_;
hy = hy_;
hz = hz_;
}
void InversePermeabilityFunction::Set2DSlice(SliceOrientation o, int npos_ )
{
orientation = o;
npos = npos_;
}
void InversePermeabilityFunction::SetConstantInversePermeability(double ipx,
double ipy, double ipz)
{
int compSize = Nx*Ny*Nz;
int size = 3*compSize;
inversePermeability = new double [size];
double *ip = inversePermeability;
for (int i(0); i < compSize; ++i)
{
ip[i] = ipx;
ip[i+compSize] = ipy;
ip[i+2*compSize] = ipz;
}
}
#ifdef MFEM_USE_MPI
void InversePermeabilityFunction::ReadPermeabilityFile(const std::string
fileName, MPI_Comm comm)
{
int num_procs, myid;
MPI_Comm_size(comm, &num_procs);
MPI_Comm_rank(comm, &myid);
StopWatch chrono;
chrono.Start();
if (myid == 0)
{
ReadPermeabilityFile(fileName);
}
else
{
inversePermeability = new double [3*Nx*Ny*Nz];
}
chrono.Stop();
if (myid==0)
{
std::cout<<"Permeability file read in " << chrono.RealTime() << ".s \n";
}
chrono.Clear();
chrono.Start();
MPI_Bcast(inversePermeability, 3*Nx*Ny*Nz, MPI_DOUBLE, 0, comm);
chrono.Stop();
if (myid==0)
{
std::cout<<"Permeability field distributed in " << chrono.RealTime() <<
".s \n";
}
}
#endif
void InversePermeabilityFunction::ReadPermeabilityFile(const std::string
fileName)
{
std::ifstream permfile(fileName.c_str());
if (!permfile.is_open())
{
std::cout << "Error in opening file " << fileName << "\n";
mfem_error("File do not exists");
}
inversePermeability = new double [3*Nx*Ny*Nz];
double *ip = inversePermeability;
double tmp;
for (int l = 0; l < 3; l++)
{
for (int k = 0; k < Nz; k++)
{
for (int j = 0; j < Ny; j++)
{
for (int i = 0; i < Nx; i++)
{
permfile >> *ip;
*ip = 1./(*ip);
ip++;
}
for (int i = 0; i < 60-Nx; i++)
{
permfile >> tmp; // skip unneeded part
}
}
for (int j = 0; j < 220-Ny; j++)
for (int i = 0; i < 60; i++)
{
permfile >> tmp; // skip unneeded part
}
}
if (l < 2) // if not processing Kz, skip unneeded part
for (int k = 0; k < 85-Nz; k++)
for (int j = 0; j < 220; j++)
for (int i = 0; i < 60; i++)
{
permfile >> tmp;
}
}
}
void InversePermeabilityFunction::InversePermeability(const Vector & x,
Vector & val)
{
val.SetSize(3);
unsigned int i,j,k;
switch (orientation)
{
case NONE:
i = Nx-1-(int)floor(x[0]/hx/(1.+3e-16));
j = (int)floor(x[1]/hy/(1.+3e-16));
k = Nz-1-(int)floor(x[2]/hz/(1.+3e-16));
break;
case XY:
i = Nx-1-(int)floor(x[0]/hx/(1.+3e-16));
j = (int)floor(x[1]/hy/(1.+3e-16));
k = npos;
break;
case XZ:
i = Nx-1-(int)floor(x[0]/hx/(1.+3e-16));
j = npos;
k = Nz-1-(int)floor(x[2]/hz/(1.+3e-16));
break;
case YZ:
i = npos;
j = (int)floor(x[1]/hy/(1.+3e-16));
k = Nz-1-(int)floor(x[2]/hz/(1.+3e-16));
break;
default:
{
mfem_error("InversePermeabilityFunction::InversePermeability");
}
}
int NMax = 3*Nx*Ny*Nz-1;
if (Ny*Nx*k + Nx*j + i>NMax || Ny*Nx*k + Nx*j + i + Nx*Ny*Nz>NMax ||
Ny*Nx*k + Nx*j + i + 2*Nx*Ny*Nz>NMax)
{
cout << " the indicies are wrong!" << endl;
cout << i << " " << j << " " << k << endl;
}
val[0] = inversePermeability[Ny*Nx*k + Nx*j + i];
val[1] = inversePermeability[Ny*Nx*k + Nx*j + i + Nx*Ny*Nz];
if (orientation == NONE)
{
val[2] = inversePermeability[Ny*Nx*k + Nx*j + i + 2*Nx*Ny*Nz];
}
}
double InversePermeabilityFunction::PermeabilityXY(Vector &x)
{
unsigned int i,j,k;
i = Nx-1-(int)floor(x[0]/hx/(1.+3e-16));
j = (int)floor(x[1]/hy/(1.+3e-16));
k = npos;
return 1./inversePermeability[Ny*Nx*k + Nx*j + i];
}
void InversePermeabilityFunction::NegativeInversePermeability(const Vector & x,
Vector & val)
{
InversePermeability(x,val);
val *= -1.;
}
void InversePermeabilityFunction::Permeability(const Vector & x, Vector & val)
{
InversePermeability(x,val);
for (double * it = val.GetData(), *end = val.GetData()+val.Size(); it != end;
++it )
{
(*it) = 1./ (*it);
}
}
double InversePermeabilityFunction::Norm2Permeability(const Vector & x)
{
Vector val(3);
Permeability(x,val);
return val.Norml2();
}
double InversePermeabilityFunction::Norm2InversePermeability(const Vector & x)
{
Vector val(3);
InversePermeability(x,val);
return val.Norml2();
}
double InversePermeabilityFunction::Norm1InversePermeability(const Vector & x)
{
Vector val(3);
InversePermeability(x,val);
return val.Norml1();
}
double InversePermeabilityFunction::NormInfInversePermeability(const Vector & x)
{
Vector val(3);
InversePermeability(x,val);
return val.Normlinf();
}
double InversePermeabilityFunction::InvNorm2(const Vector & x)
{
Vector val(3);
InversePermeability(x,val);
return 1./val.Norml2();
}
double InversePermeabilityFunction::InvNorm1(const Vector & x)
{
Vector val(3);
InversePermeability(x,val);
return 1./val.Norml1();
}
double InversePermeabilityFunction::InvNormInf(const Vector & x)
{
Vector val(3);
InversePermeability(x,val);
return 1./val.Normlinf();
}
void InversePermeabilityFunction::ClearMemory()
{
delete[] inversePermeability;
}
int InversePermeabilityFunction::Nx(60);
int InversePermeabilityFunction::Ny(220);
int InversePermeabilityFunction::Nz(85);
double InversePermeabilityFunction::hx(20);
double InversePermeabilityFunction::hy(10);
double InversePermeabilityFunction::hz(2);
double * InversePermeabilityFunction::inversePermeability(NULL);
InversePermeabilityFunction::SliceOrientation
InversePermeabilityFunction::orientation( InversePermeabilityFunction::NONE );
int InversePermeabilityFunction::npos(-1);
+2 -7
View File
@@ -1833,6 +1833,7 @@ void MixedBilinearForm::FormRectangularSystemMatrix(
const Array<int> &trial_tdof_list,
const Array<int> &test_tdof_list,
OperatorHandle &A)
{
if (ext)
{
@@ -1911,14 +1912,8 @@ void MixedBilinearForm::FormRectangularLinearSystem(
B.SetSubVector(test_tdof_list, 0.0);
}
void MixedBilinearForm::Update(FiniteElementSpace *ntr_fes,
FiniteElementSpace *nte_fes)
void MixedBilinearForm::Update()
{
if ((ntr_fes && nte_fes) && (ntr_fes != trial_fes || nte_fes != test_fes))
{
trial_fes = ntr_fes;
test_fes = nte_fes;
}
delete mat;
mat = NULL;
delete mat_e;
+2 -11
View File
@@ -706,10 +706,6 @@ public:
*/
void SetDiagonalPolicy(DiagonalPolicy policy);
void SetIntegratorOwnership(int _extern_bfs)
{
extern_bfs = _extern_bfs;
}
/// Indicate that integrators are not owned by the BilinearForm
void UseExternalIntegrators() { extern_bfs = 1; }
@@ -1072,13 +1068,8 @@ public:
A.MakeRef(*A_ptr);
}
virtual void Update(FiniteElementSpace *ntr_fes = NULL,
FiniteElementSpace *nte_fes = NULL);
void SetIntegratorOwnership(int _extern_bfs)
{
extern_bfs = _extern_bfs;
}
/// Must be called after making changes to #trial_fes or #test_fes.
void Update();
/// Return the trial FE space associated with the BilinearForm.
FiniteElementSpace *TrialFESpace() { return trial_fes; }
+347 -123
View File
@@ -1539,6 +1539,351 @@ const IntegrationRule &ConvectionIntegrator::GetRule(
return GetRule(el,el,Trans);
}
void LaplaceIntegrator::AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
DenseMatrix &elmat )
{
int nd = el.GetDof();
real_t w;
elmat.SetSize(nd);
shape.SetSize(nd);
laplace.SetSize(nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el, Trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Trans.SetIntPoint (&ip);
el.CalcPhysShape(Trans, shape);
el.CalcPhysLaplacian(Trans, laplace);
w = Trans.Weight() * ip.weight * alpha;
if (Q)
{
w *= Q -> Eval(Trans, ip);
}
shape *= w;
AddMultVWt(shape, laplace, elmat);
}
}
void LaplaceIntegrator::AssembleElementMatrix2(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans,
DenseMatrix &elmat)
{
int tr_nd = trial_fe.GetDof();
int te_nd = test_fe.GetDof();
elmat.SetSize(te_nd, tr_nd);
laplace.SetSize(tr_nd);
shape.SetSize(te_nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(trial_fe, test_fe,
Trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Trans.SetIntPoint (&ip);
test_fe.CalcPhysShape(Trans, shape);
trial_fe.CalcPhysLaplacian(Trans, laplace);
real_t w = Trans.Weight() * ip.weight * alpha;
if (Q)
{
w *= Q -> Eval(Trans, ip);
}
AddMult_a_VWt(w, shape, laplace, elmat);
}
}
const IntegrationRule &LaplaceIntegrator::GetRule(
const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans)
{
int order = trial_fe.GetOrder() + test_fe.GetOrder();
return IntRules.Get(trial_fe.GetGeomType(), order);
}
void LaplaceGradIntegrator::AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
DenseMatrix &elmat )
{
int nd = el.GetDof();
dim = el.GetDim();
elmat.SetSize(nd);
dshape.SetSize(nd,dim);
adjJ.SetSize(dim);
laplace.SetSize(nd);
vec2.SetSize(dim);
BdFidxT.SetSize(nd);
Vector vec1;
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el, Trans);
Q->Eval(Q_ir, Trans, *ir);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
el.CalcDShape(ip, dshape);
el.CalcPhysLaplacian(Trans, laplace);
Trans.SetIntPoint(&ip);
CalcAdjugate(Trans.Jacobian(), adjJ);
Q_ir.GetColumnReference(i, vec1);
vec1 *= alpha * ip.weight;
adjJ.Mult(vec1, vec2);
dshape.Mult(vec2, BdFidxT);
AddMultVWt(BdFidxT, laplace, elmat);
}
}
void LaplaceGradIntegrator::AssembleElementMatrix2(const FiniteElement
&trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans,
DenseMatrix &elmat)
{
dim = trial_fe.GetDim();
int tr_nd = trial_fe.GetDof();
int te_nd = test_fe.GetDof();
elmat.SetSize(te_nd, tr_nd);
laplace.SetSize(tr_nd);
dshape.SetSize(te_nd,dim);
adjJ.SetSize(dim);
vec2.SetSize(dim);
BdFidxT.SetSize(te_nd);
Vector vec1;
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(trial_fe, test_fe,
Trans);
Q->Eval(Q_ir, Trans, *ir);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
test_fe.CalcDShape(ip, dshape);
trial_fe.CalcPhysLaplacian(Trans, laplace);
Trans.SetIntPoint(&ip);
CalcAdjugate(Trans.Jacobian(), adjJ);
Q_ir.GetColumnReference(i, vec1);
vec1 *= alpha * ip.weight;
adjJ.Mult(vec1, vec2);
dshape.Mult(vec2, BdFidxT);
AddMultVWt(BdFidxT, laplace,elmat);
}
}
const IntegrationRule &LaplaceGradIntegrator::GetRule(
const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans)
{
int order = trial_fe.GetOrder() + test_fe.GetOrder();
return IntRules.Get(trial_fe.GetGeomType(), order);
}
void LaplaceLaplaceIntegrator::AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
DenseMatrix &elmat )
{
int nd = el.GetDof();
real_t w;
elmat.SetSize(nd);
laplace.SetSize(nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(el, el, Trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Trans.SetIntPoint (&ip);
el.CalcPhysLaplacian(Trans, laplace);
w = Trans.Weight() * ip.weight * alpha;
if (Q)
{
w *= Q -> Eval(Trans, ip);
}
AddMult_a_VVt(w, laplace, elmat);
}
}
void LaplaceLaplaceIntegrator::AssembleElementMatrix2(const FiniteElement
&trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans,
DenseMatrix &elmat)
{
int
dim = trial_fe.GetDim();
int tr_nd = trial_fe.GetDof();
int te_nd = test_fe.GetDof();
real_t w;
elmat.SetSize(te_nd, tr_nd);
laplace.SetSize(tr_nd);
te_laplace.SetSize(te_nd);
const IntegrationRule *ir = IntRule ? IntRule : &GetRule(trial_fe, test_fe,
Trans);
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Trans.SetIntPoint (&ip);
trial_fe.CalcPhysLaplacian(Trans, laplace);
test_fe.CalcPhysLaplacian(Trans, te_laplace);
w = Trans.Weight() * ip.weight * alpha;
if (Q)
{
w *= Q -> Eval(Trans, ip);
}
AddMult_a_VWt(w, te_laplace, laplace, elmat);
}
}
const IntegrationRule &LaplaceLaplaceIntegrator::GetRule(
const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans)
{
int order = trial_fe.GetOrder() + test_fe.GetOrder();
return IntRules.Get(trial_fe.GetGeomType(), order);
}
void InverseEstimateIntegrator::AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
DenseMatrix &elmat )
{
elmat = 0.0;
int nd = el.GetDof();
int dim = el.GetDim();
shape.SetSize(nd);
dshape.SetSize(nd,dim);
laplace.SetSize(nd);
lapmat.SetSize(nd,nd);
bimat.SetSize(nd,nd);
ovec.SetSize(nd);
real_t w,q;
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int order = Trans.OrderGrad(&el) + Trans.Order() + el.GetOrder();
ir = &IntRules.Get(el.GetGeomType(), order);
}
bimat = 0.0;
lapmat = 0.0;
ovec = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Trans.SetIntPoint(&ip);
w = Trans.Weight()*ip.weight;
if (Q)
{
q = Q->Eval(Trans, ip);
}
el.CalcPhysDShape(Trans, dshape);
AddMult_a_AAt(w*q, dshape, lapmat);
el.CalcPhysLaplacian(Trans, laplace);
AddMult_a_VVt(w*q*q, laplace, bimat);
el.CalcPhysShape(Trans, shape);
ovec.Add(w, shape);
}
// Power method
Vector x(nd);
x.Randomize(696383532);
// Correct nullspace + inverse
AddMult_a_VVt(1.0, ovec, lapmat);
DenseMatrixInverse L_inv(lapmat);
// DenseMatrix M_i, Q_i;
real_t alpha= 0.0, eval_i = 0.0, eval_prev = 0.0;
// Inverse power method
Vector x_tmp(nd);
int iter = 0;
const real_t rel_tol = 1e-4;
alpha = ovec*ovec;
ovec *= 1.0/sqrt(alpha);
do
{
// Othogonalize
alpha = x*ovec;
x.Add(-alpha, ovec);
// MatVec (2x)
bimat.Mult(x, x_tmp);
L_inv.Mult(x_tmp, x);
eval_prev = eval_i;
eval_i = x.Norml2();
x *= 1.0/eval_i;
++iter;
}
while ((iter < 10000) && (fabs(eval_i - eval_prev)/fabs(eval_i) > rel_tol));
MFEM_VERIFY(fabs(eval_i - eval_prev)/fabs(eval_i) <= rel_tol,
"Inverse power method did not converge."
<< "\n\t iter = " << iter
<< "\n\t eval_i = " << eval_i
<< "\n\t eval_prev = " << eval_prev
<< "\n\t fabs(eval_i - eval_prev)/fabs(eval_i) = "
<< fabs(eval_i - eval_prev)/fabs(eval_i));
cout<<"evev = "<<eval_i<<" "<<iter<<endl;
}
const IntegrationRule &InverseEstimateIntegrator::GetRule(
const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans)
{
// int order = Trans.OrderGrad(&trial_fe) + Trans.Order() + test_fe.GetOrder() - 2;
int order = trial_fe.GetOrder() + test_fe.GetOrder();
return IntRules.Get(trial_fe.GetGeomType(), order);
}
void VectorMassIntegrator::AssembleElementMatrix
( const FiniteElement &el, ElementTransformation &Trans,
DenseMatrix &elmat )
@@ -1999,11 +2344,7 @@ void CurlCurlIntegrator::AssembleElementMatrix
{
int nd = el.GetDof();
dim = el.GetDim();
// in main
// int dimc = el.GetCurlDim();
// Taken from 4d_dev:
int dimc = (dim == 3) ? 3 : 1;
if (dim==4) { dimc = 6; }
int dimc = el.GetCurlDim();
real_t w;
#ifdef MFEM_THREAD_SAFE
@@ -2040,43 +2381,8 @@ void CurlCurlIntegrator::AssembleElementMatrix
Trans.SetIntPoint (&ip);
if (dim ==4)
{
DenseMatrix tSh(4,4);
DenseMatrix trShTemp(4,4);
DenseMatrix J = Trans.Jacobian();
DenseMatrix invJ(4,4); CalcInverse(J, invJ);
DenseMatrix invJtr(invJ); invJtr.Transpose();
el.CalcCurlShape(ip, curlshape);
for (int dof=0; dof<nd; dof++)
{
tSh = 0.; trShTemp = 0.;
tSh(0,1) = curlshape(dof,0); tSh(0,2) = curlshape(dof,1);
tSh(0,3) = curlshape(dof,2);
tSh(1,0) = -curlshape(dof,0);
tSh(1,2) = curlshape(dof,3); tSh(1,3) = curlshape(dof,4);
tSh(2,0) = -curlshape(dof,1); tSh(2,1) = -curlshape(dof,3);
tSh(2,3) = curlshape(dof,5);
tSh(3,0) = -curlshape(dof,2); tSh(3,1) = -curlshape(dof,4);
tSh(3,2) = -curlshape(dof,5);
Mult(tSh, invJ, trShTemp);
Mult(invJtr, trShTemp, tSh);
curlshape_dFt(dof,0) = tSh(0,1);
curlshape_dFt(dof,1) = tSh(0,2);
curlshape_dFt(dof,2) = tSh(0,3);
curlshape_dFt(dof,3) = tSh(1,2);
curlshape_dFt(dof,4) = tSh(1,3);
curlshape_dFt(dof,5) = tSh(2,3);
}
}
else
el.CalcPhysCurlShape(Trans, curlshape_dFt);
w = ip.weight * Trans.Weight();
el.CalcPhysCurlShape(Trans, curlshape_dFt);
if (MQ)
{
@@ -3454,7 +3760,6 @@ void DGTraceIntegrator::AssembleFaceMatrix(const FiniteElement &el1,
}
}
}
// elmat.PrintMatlab(std::cout);
}
@@ -4595,85 +4900,4 @@ VectorInnerProductInterpolator::AssembleElementMatrix2(
ran_fe.Project(dom_shape_coeff, Trans, elmat_as_vec);
}
void HeatEquationIntegrator::AssembleElementMatrix
( const FiniteElement &el, ElementTransformation &Trans,
DenseMatrix &elmat )
{
int nd = el.GetDof();
int dim = el.GetDim();
int spaceDim = Trans.GetSpaceDim();
double w;
#ifdef MFEM_THREAD_SAFE
DenseMatrix dshape(nd,dim), dshapedxt(nd,spaceDim), invdfdx(dim,spaceDim);
Vector shape(nd), vec(nd);
#else
dshape.SetSize(nd,dim);
dshapedxt.SetSize(nd,spaceDim);
invdfdx.SetSize(dim,spaceDim);
shape.SetSize(nd);
dtshape.SetSize(nd);
#endif
elmat.SetSize(nd);
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int order;
if (el.Space() == FunctionSpace::Pk)
{
order = 2*el.GetOrder() - 2;
}
else
// order = 2*el.GetOrder() - 2; // <-- this seems to work fine too
{
order = 2*el.GetOrder() + dim - 1;
}
if (el.Space() == FunctionSpace::rQk)
{
ir = &RefinedIntRules.Get(el.GetGeomType(), order);
}
else
{
ir = &IntRules.Get(el.GetGeomType(), order);
}
}
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
el.CalcShape(ip,shape);
el.CalcDShape(ip, dshape);
Trans.SetIntPoint(&ip);
w = Trans.Weight();
w *= ip.weight;
CalcInverse(Trans.Jacobian(), invdfdx);
Mult(dshape, invdfdx, dshapedxt);
dshapedxt.GetColumn(spaceDim - 1, dtshape); // d_t u
dshapedxt.SetCol(spaceDim - 1, 0.);
AddMult_a_VWt(w,shape,dtshape,elmat); // d_t u * v
if (!MQ)
{
if (Q)
{
w *= Q->Eval(Trans, ip);
}
AddMult_a_AAt(w, dshapedxt, elmat);
}
else
{
MQ->Eval(invdfdx, Trans, ip);
invdfdx *= w;
Mult(dshapedxt, invdfdx, dshape);
AddMultABt(dshape, dshapedxt, elmat);
}
}
}
}
+130 -187
View File
@@ -266,9 +266,6 @@ public:
Vector &flux, Vector *d_energy = NULL)
{ return 0.0; }
// I think this got deleted
// void SetIntRule(const IntegrationRule *ir) { IntRule = ir; }
/** @brief For bilinear forms on element faces, specifies if the normal
derivatives are needed on the faces or just the face restriction.
@@ -301,6 +298,7 @@ public:
*/
virtual void AddMultPAFaceNormalDerivatives(const Vector &x, const Vector &dxdn,
Vector &y, Vector &dydn) const;
virtual ~BilinearFormIntegrator() { }
};
@@ -2452,6 +2450,135 @@ public:
DenseMatrix &);
};
/// $\alpha (Q \Delta u, v)$
class LaplaceIntegrator : public BilinearFormIntegrator
{
protected:
Coefficient *Q;
real_t alpha;
private:
Vector laplace, shape;
public:
LaplaceIntegrator(Coefficient &q, real_t a = 1.0)
: Q(&q) { alpha = a; }
virtual void AssembleElementMatrix(const FiniteElement &,
ElementTransformation &,
DenseMatrix &);
virtual void AssembleElementMatrix2(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans,
DenseMatrix &elmat);
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
};
/// $\alpha (u, Q \Delta v)$
class TransposeLaplaceIntegrator : public TransposeIntegrator
{
public:
TransposeLaplaceIntegrator (Coefficient &q, real_t a = 1.0)
: TransposeIntegrator(new LaplaceIntegrator(q, a)) { }
};
/// $\alpha (\Delta u, Q \cdot \nabla v)$
class LaplaceGradIntegrator : public BilinearFormIntegrator
{
protected:
VectorCoefficient *Q;
real_t alpha;
int dim;
private:
Vector laplace, vec2, BdFidxT;
DenseMatrix dshape, adjJ, Q_ir;
public:
LaplaceGradIntegrator(VectorCoefficient &q, real_t a = 1.0)
: Q(&q) { alpha = a; }
virtual void AssembleElementMatrix(const FiniteElement &,
ElementTransformation &,
DenseMatrix &);
virtual void AssembleElementMatrix2(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans,
DenseMatrix &elmat);
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
};
/// $\alpha (Q \cdot \nabla u, \Delta v)$
class GradLaplaceIntegrator : public TransposeIntegrator
{
public:
GradLaplaceIntegrator(VectorCoefficient &q, real_t a = 1.0)
: TransposeIntegrator(new LaplaceGradIntegrator(q, a)) { }
};
/// $\alpha (Q \Delta u, \Delta v)$
class LaplaceLaplaceIntegrator : public BilinearFormIntegrator
{
protected:
Coefficient *Q;
real_t alpha;
private:
Vector laplace, te_laplace;
public:
LaplaceLaplaceIntegrator(Coefficient &q, real_t a = 1.0)
: Q(&q) { alpha = a; }
virtual void AssembleElementMatrix(const FiniteElement &,
ElementTransformation &,
DenseMatrix &);
virtual void AssembleElementMatrix2(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans,
DenseMatrix &elmat);
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
};
// Alias for @LaplaceLaplaceIntegrator.
using BiHarmonicIntegrator = LaplaceLaplaceIntegrator;
/// Get the inverse estimate
class InverseEstimateIntegrator : public BilinearFormIntegrator
{
protected:
Coefficient *Q;
private:
Vector laplace, shape, ovec;//, vec2, BdFidxT;
DenseMatrix dshape, lapmat, bimat;//, adjJ, Q_ir;
public:
InverseEstimateIntegrator(Coefficient &q)
: Q(&q) { }
virtual void AssembleElementMatrix(const FiniteElement &,
ElementTransformation &,
DenseMatrix &);
static const IntegrationRule &GetRule(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans);
};
/** Class for integrating the bilinear form $a(u,v) := (Q u, v)$,
where $u=(u_1,\dots,u_n)$ and $v=(v_1,\dots,v_n)$, $u_i$ and $v_i$ are defined
by scalar FE through standard transformation. */
@@ -3682,16 +3809,6 @@ public:
};
class DivSkewInterpolator : public DiscreteInterpolator
{
public:
virtual void AssembleElementMatrix2(const FiniteElement &dom_fe,
const FiniteElement &ran_fe,
ElementTransformation &Trans,
DenseMatrix &elmat)
{ ran_fe.ProjectDivSkew(dom_fe, Trans, elmat); }
};
/** Class for constructing the (local) discrete divergence matrix which can
be used as an integrator in a DiscreteLinearOperator object to assemble
the global discrete divergence matrix.
@@ -3823,179 +3940,5 @@ protected:
VectorCoefficient *VQ;
};
class DivSkewDivSkewIntegrator: public BilinearFormIntegrator
{
private:
DenseMatrix DivSkewshape, DivSkew_dFt;
Coefficient *Q;
public:
DivSkewDivSkewIntegrator() { Q = NULL; }
/// Construct a bilinear form integrator for Nedelec elements
DivSkewDivSkewIntegrator(Coefficient &q) : Q(&q) { }
/* Given a particular Finite Element, compute the
element DivSkew-DivSkew matrix elmat */
virtual void AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
DenseMatrix &elmat)
{
int nd = el.GetDof();
int dim = el.GetDim();
real_t w;
DivSkewshape.SetSize(nd,dim);
DivSkew_dFt.SetSize(nd,dim);
elmat.SetSize(nd);
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int order = 2*el.GetOrder()+2;
ir = &IntRules.Get(el.GetGeomType(), order);
}
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Trans.SetIntPoint (&ip);
el.CalcDivSkewShape(ip, DivSkewshape);
MultABt(DivSkewshape, Trans.Jacobian(), DivSkew_dFt);
DivSkew_dFt *= (1.0 / Trans.Weight());
w = ip.weight * fabs(Trans.Weight());
if (Q)
{
w *= Q->Eval(Trans, ip);
}
AddMult_a_AAt(w, DivSkew_dFt, elmat);
}
}
};
class VectorFE_DivSkewMassIntegrator: public BilinearFormIntegrator
{
private:
DenseMatrix shape;
Coefficient *Q;
public:
VectorFE_DivSkewMassIntegrator() { Q = NULL; }
/// Construct a bilinear form integrator for Nedelec elements
VectorFE_DivSkewMassIntegrator(Coefficient &q) : Q(&q) { }
/* Given a particular Finite Element, compute the
element curl-curl matrix elmat */
virtual void AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
DenseMatrix &elmat)
{
int nd = el.GetDof();
int dim = el.GetDim();
real_t w;
shape.SetSize(nd,dim*dim);
elmat.SetSize(nd);
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
int order = Trans.OrderW() + 2 * el.GetOrder();
ir = &IntRules.Get(el.GetGeomType(), order);
}
elmat = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Trans.SetIntPoint (&ip);
w = ip.weight * fabs(Trans.Weight());
el.CalcVShape(Trans, shape);
if (Q)
{
w *= Q->Eval(Trans, ip);
}
AddMult_a_AAt(w, shape, elmat);
}
}
};
/** Class for integrating the bilinear form a(u,v) := (d_t u, v) + (Q grad_x u, grad_x v) where Q
can be a scalar or a matrix coefficient and grad_x is the gradient wrt to the spatial variables.
Here we use the space-time f.e. scheme by [Steinbach2015]. */
class HeatEquationIntegrator: public BilinearFormIntegrator
{
private:
Vector vec, pointflux, shape, dtshape;
#ifndef MFEM_THREAD_SAFE
DenseMatrix dshape, dshapedxt, invdfdx, mq;
DenseMatrix te_dshape, te_dshapedxt;
#endif
Coefficient *Q;
MatrixCoefficient *MQ;
public:
/// Construct a diffusion integrator with coefficient Q = 1
HeatEquationIntegrator() { Q = NULL; MQ = NULL; }
/// Construct a diffusion integrator with a scalar coefficient q
HeatEquationIntegrator (Coefficient &q) : Q(&q) { MQ = NULL; }
/// Construct a diffusion integrator with a matrix coefficient q
HeatEquationIntegrator (MatrixCoefficient &q) : MQ(&q) { Q = NULL; }
/** Given a particular Finite Element
computes the element stiffness matrix elmat. */
virtual void AssembleElementMatrix(const FiniteElement &el,
ElementTransformation &Trans,
DenseMatrix &elmat);
/** Given a trial and test Finite Element computes the element stiffness
matrix elmat. */
virtual void AssembleElementMatrix2(const FiniteElement &trial_fe,
const FiniteElement &test_fe,
ElementTransformation &Trans,
DenseMatrix &elmat)
{ mfem_error("HeatEquationIntegrator::AssembleElementMatrix2: not implemented!"); }
/// Perform the local action of the BilinearFormIntegrator
virtual void AssembleElementVector(const FiniteElement &el,
ElementTransformation &Tr,
const Vector &elfun, Vector &elvect)
{ mfem_error("HeatEquationIntegrator::AssembleElementVector: not implemented!"); }
virtual void ComputeElementFlux(const FiniteElement &el,
ElementTransformation &Trans,
Vector &u, const FiniteElement &fluxelem,
Vector &flux, int with_coef = 1)
{ mfem_error("HeatEquationIntegrator::ComputeElementFlux: not implemented!"); }
virtual double ComputeFluxEnergy(const FiniteElement &fluxelem,
ElementTransformation &Trans,
Vector &flux, Vector *d_energy = NULL)
{ mfem_error("HeatEquationIntegrator::ComputeFluxEnergy: not implemented!"); return -1;}
};
}
#endif
+293 -8
View File
@@ -129,10 +129,8 @@ real_t PWCoefficient::Eval(ElementTransformation &T,
real_t FunctionCoefficient::Eval(ElementTransformation & T,
const IntegrationPoint & ip)
{
// real_t x[Geometry::MaxDim];
// Vector transip(x, Geometry::MaxDim);
real_t x[4];
Vector transip(x, 4);
real_t x[3];
Vector transip(x, 3);
T.Transform(ip, transip);
@@ -368,10 +366,8 @@ void PositionVectorCoefficient::Eval(Vector &V, ElementTransformation &T,
void VectorFunctionCoefficient::Eval(Vector &V, ElementTransformation &T,
const IntegrationPoint &ip)
{
// real_t x[Geometry::MaxDim];
// Vector transip(x, Geometry::MaxDim);
real_t x[4];
Vector transip(x, 4);
real_t x[3];
Vector transip(x, 3);
T.Transform(ip, transip);
@@ -1508,6 +1504,295 @@ void CrossCrossCoefficient::Eval(DenseMatrix &M, ElementTransformation &T,
M *= ((a == NULL ) ? aConst : a->Eval(T, ip) );
}
InverseEstimateCoefficient::InverseEstimateCoefficient(FiniteElementSpace *f)
: fes(f), Q(NULL), ir(NULL)
{
ComputeInverseEstimates();
}
InverseEstimateCoefficient::InverseEstimateCoefficient(FiniteElementSpace *f,
Coefficient &q)
: fes(f), Q(&q), ir(NULL)
{
ComputeInverseEstimates();
}
GridFunction *InverseEstimateCoefficient::GetGridFunction()
{
FiniteElementCollection* fec_ec = new L2_FECollection(0,
fes ->GetMesh()->Dimension());
FiniteElementSpace *fes_ec = new FiniteElementSpace(fes ->GetMesh(), fec_ec);
GridFunction *gf = new GridFunction(fes_ec, elemInvEst.GetData());
gf->MakeOwner(fec_ec);
return gf;
}
void InverseEstimateCoefficient::ComputeInverseEstimates()
{
elemInvEst.SetSize(fes -> GetNE());
SetIntRule(*fes->GetFE(0));
for (int i = 0; i < fes -> GetNE(); i++)
{
elemInvEst[i] = ElementInverseEstimate(*fes->GetFE(i),
*fes->GetElementTransformation(i));
}
}
void InverseEstimateCoefficient::SetIntRule(const FiniteElement &el)
{
ir = &IntRules.Get(el.GetGeomType(), 2*el.GetOrder());
}
real_t InverseEstimateCoefficient::ElementInverseEstimate(
const FiniteElement &el,
ElementTransformation &Trans)
{
if (el.GetOrder() < 2)
{
return std::numeric_limits<real_t>::min();
}
int nd = el.GetDof();
int dim = el.GetDim();
shape.SetSize(nd);
dshape.SetSize(nd,dim);
laplace.SetSize(nd);
lapmat.SetSize(nd,nd);
bimat.SetSize(nd,nd);
ovec.SetSize(nd);
real_t w,q = 1.0;
bimat = 0.0;
lapmat = 0.0;
ovec = 0.0;
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Trans.SetIntPoint(&ip);
w = Trans.Weight()*ip.weight;
if (Q)
{
q = Q->Eval(Trans, ip);
}
el.CalcPhysDShape(Trans, dshape);
AddMult_a_AAt(w*q, dshape, lapmat);
el.CalcPhysLaplacian(Trans, laplace);
AddMult_a_VVt(w*q*q, laplace, bimat);
el.CalcPhysShape(Trans, shape);
ovec.Add(w, shape);
}
ovec *= 1.0/ovec.Norml2();
// Correct nullspace
AddMultVVt(ovec, lapmat);
// Return largest eigenvalue
return bimat.Eigenvalue(lapmat);
}
ElasticInverseEstimateCoefficient
::ElasticInverseEstimateCoefficient(FiniteElementSpace *f)
: fes(f), Q(NULL), ir(NULL)
{
ComputeInverseEstimates();
}
ElasticInverseEstimateCoefficient
::ElasticInverseEstimateCoefficient(FiniteElementSpace *f,
Coefficient &q)
: fes(f), Q(&q), ir(NULL)
{
ComputeInverseEstimates();
}
GridFunction *ElasticInverseEstimateCoefficient::GetGridFunction()
{
FiniteElementCollection* fec_ec = new L2_FECollection(0,
fes ->GetMesh()->Dimension());
FiniteElementSpace *fes_ec = new FiniteElementSpace(fes ->GetMesh(), fec_ec);
GridFunction *gf = new GridFunction(fes_ec, elemInvEst.GetData());
gf->MakeOwner(fec_ec);
return gf;
}
void ElasticInverseEstimateCoefficient::ComputeInverseEstimates()
{
elemInvEst.SetSize(fes -> GetNE());
SetIntRule(*fes->GetFE(0));
int dim = fes->GetFE(0)->GetDim();
emat.SetSize(dim,dim);
divmat.SetSize(dim,dim);
for (int i = 0; i < dim; i++)
{
for (int j = 0; j < dim; j++)
{
emat(i,j)= new DenseMatrix();
divmat(i,j)= new DenseMatrix();
}
}
hmap.SetSize(dim,dim);
if (dim == 2)
{
hmap(0,0) = 0;
hmap(0,1) = hmap(1,0) = 1;
hmap(1,1) = 2;
}
else if (dim == 2)
{
hmap(0,0) = 0;
hmap(0,1) = hmap(1,0) = 1;
hmap(0,2) = hmap(2,0) = 2;
hmap(1,1) = 3;
hmap(1,2) = hmap(2,1) = 4;
hmap(2,2) = 5;
}
else
{
mfem_error("Only implemented for 2D and 3D");
}
for (int i = 0; i < fes -> GetNE(); i++)
{
elemInvEst[i] = ElementInverseEstimate(*fes->GetFE(i),
*fes->GetElementTransformation(i));
}
}
void ElasticInverseEstimateCoefficient::SetIntRule(const FiniteElement &el)
{
ir = &IntRules.Get(el.GetGeomType(), 2*el.GetOrder());
}
real_t ElasticInverseEstimateCoefficient::ElementInverseEstimate(
const FiniteElement &el,
ElementTransformation &Trans)
{
// if (el.GetDerivType() != (int) FiniteElement::HESS)
// {
// return std::numeric_limits<real_t>::min();
// }
int nd = el.GetDof();
int dim = el.GetDim();
shape.SetSize(nd);
dshape.SetSize(nd,dim);
hshape.SetSize(nd,dim*(dim+1)/2);
for (int i = 0; i < dim; i++)
{
for (int j = 0; j < dim; j++)
{
emat(i,j)->SetSize(nd,nd);
*emat(i,j) = 0.0;
divmat(i,j)->SetSize(nd,nd);
*divmat(i,j) = 0.0;
}
}
real_t w,q = 1.0;
for (int ii = 0; ii < ir->GetNPoints(); ii++)
{
const IntegrationPoint &ip = ir->IntPoint(ii);
Trans.SetIntPoint(&ip);
w = Trans.Weight()*ip.weight;
if (Q)
{
q = Q->Eval(Trans, ip);
}
el.CalcPhysDShape(Trans, dshape);
for (int i = 0; i < dim; i++)
{
for (int j = 0; j < dim; j++)
{
AddMult_a_VVt(w*q, Vector(dshape.GetColumn(i),nd), *emat(j,j));
AddMult_a_VWt(w*q, Vector(dshape.GetColumn(i),nd),
Vector(dshape.GetColumn(j),nd), *emat(j,i));
AddMult_a_VWt(w*q, Vector(dshape.GetColumn(j),nd),
Vector(dshape.GetColumn(i),nd), *emat(i,j));
AddMult_a_VVt(w*q, Vector(dshape.GetColumn(j),nd), *emat(i,i));
}
}
el.CalcPhysHessian(Trans, hshape);
for (int i = 0; i < dim; i++)
{
for (int j = 0; j < dim; j++)
{
for (int k = 0; k < dim; k++)
{
AddMult_a_VWt(w*q*q, Vector(hshape.GetColumn(hmap(i,i)),nd),
Vector(hshape.GetColumn(hmap(k,k)),nd), *divmat(j,j));
AddMult_a_VWt(w*q*q, Vector(hshape.GetColumn(hmap(i,i)),nd),
Vector(hshape.GetColumn(hmap(k,j)),nd), *divmat(j,k));
AddMult_a_VWt(w*q*q, Vector(hshape.GetColumn(hmap(i,j)),nd),
Vector(hshape.GetColumn(hmap(k,k)),nd), *divmat(i,j));
AddMult_a_VWt(w*q*q, Vector(hshape.GetColumn(hmap(i,j)),nd),
Vector(hshape.GetColumn(hmap(k,j)),nd), *divmat(i,k));
}
}
}
}
// Collect matrices
emat_tot.SetSize(nd*dim,nd*dim);
divmat_tot.SetSize(nd*dim,nd*dim);
for (int i = 0; i < dim; i++)
{
for (int j = 0; j < dim; j++)
{
emat_tot .SetSubMatrix(i*nd, j*nd, *emat(i,j));
divmat_tot.SetSubMatrix(i*nd, j*nd, *divmat(i,j));
}
}
// Correct nullspace
DenseMatrix ns;
emat_tot.NullSpace(ns, 1e-10);
for (int i = 0; i < ns.Width(); i++)
{
AddMultVVt(Vector(ns.GetColumn(i),nd*dim), emat_tot);
}
// Return largest eigenvalue
return divmat_tot.Eigenvalue(emat_tot);
}
ElasticInverseEstimateCoefficient::~ElasticInverseEstimateCoefficient()
{
for (int i = 0; i < emat.NumRows(); i++)
{
for (int j = 0; j < emat.NumCols(); j++)
{
delete emat(i,j);
}
}
for (int i = 0; i < divmat.NumRows(); i++)
{
for (int j = 0; j < divmat.NumCols(); j++)
{
delete divmat(i,j);
}
}
}
real_t LpNormLoop(real_t p, Coefficient &coeff, Mesh &mesh,
const IntegrationRule *irs[])
{
+121
View File
@@ -2328,6 +2328,127 @@ public:
};
///@}
/** @brief
*/
class InverseEstimateCoefficient : public Coefficient
{
private:
///
Vector elemInvEst;
/// FE space on which the grid function lives. Owned if #fec is not NULL.
FiniteElementSpace *fes;
///
const IntegrationRule *ir;
///
Coefficient *Q;
Vector laplace, shape, ovec, evec;
DenseMatrix dshape, lapmat, bimat;
///
void SetIntRule(const FiniteElement &el);
///
void ComputeInverseEstimates();
real_t ElementInverseEstimate(const FiniteElement &el,
ElementTransformation &Trans);
public:
///
InverseEstimateCoefficient(FiniteElementSpace *f);
InverseEstimateCoefficient(FiniteElementSpace *f, Coefficient &q);
/// Caller gets owner ship of GridFunction and
GridFunction *GetGridFunction();
/// Reset the scalar factor
void SetDiffusion(Coefficient &q)
{
if (Q != &q)
{
Q = &q;
ComputeInverseEstimates();
}
}
/// Return the scalar factor
Coefficient * GetDiffusion() const { return Q; }
/// Evaluate the coefficient at @a ip.
virtual real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{ return elemInvEst[T.ElementNo]; }
};
class ElasticInverseEstimateCoefficient : public Coefficient
{
private:
///
Vector elemInvEst;
/// FE space on which the grid function lives. Owned if #fec is not NULL.
FiniteElementSpace *fes;
///
const IntegrationRule *ir;
///
Coefficient *Q;
Vector shape, ovec, evec;
DenseMatrix dshape, hshape, emat_tot, divmat_tot;
Array2D<DenseMatrix*> emat,divmat;
Array2D<int> hmap;
///
void SetIntRule(const FiniteElement &el);
///
void ComputeInverseEstimates();
///
real_t ElementInverseEstimate(const FiniteElement &el,
ElementTransformation &Trans);
public:
///
ElasticInverseEstimateCoefficient(FiniteElementSpace *f);
ElasticInverseEstimateCoefficient(FiniteElementSpace *f, Coefficient &q);
/// Caller gets owner ship of GridFunction and
GridFunction *GetGridFunction();
/// Reset the scalar factor
void SetDiffusion(Coefficient &q)
{
if (Q != &q)
{
Q = &q;
ComputeInverseEstimates();
}
}
void SetShearModulus(Coefficient &q) { SetDiffusion(q);}
/// Return the scalar factor
Coefficient * GetDiffusion() const { return Q; }
Coefficient * GetModulus() const { return GetDiffusion(); }
/// Evaluate the coefficient at @a ip.
virtual real_t Eval(ElementTransformation &T,
const IntegrationPoint &ip)
{ return elemInvEst[T.ElementNo]; }
// Destructor
~ElasticInverseEstimateCoefficient();
};
///@}
/** @brief Vector quadrature function coefficient which requires that the
quadrature rules used for this vector coefficient be the same as those that
live within the supplied QuadratureFunction. */
+2 -6
View File
@@ -180,7 +180,7 @@ int InverseElementTransformation::NewtonSolve(const Vector &pt,
const int dim = T->GetDimension();
const int sdim = T->GetSpaceDim();
IntegrationPoint xip, prev_xip;
double xd[4], yd[4], dxd[4], dx_norm = -1.0, err_phys, real_dx_norm = -1.0;
real_t xd[3], yd[3], dxd[3], dx_norm = -1.0, err_phys, real_dx_norm = -1.0;
Vector x(xd, dim), y(yd, sdim), dx(dxd, dim);
bool hit_bdr = false, prev_hit_bdr = false;
@@ -389,8 +389,6 @@ void IsoparametricTransformation::SetIdentityTransformation(
case Geometry::CUBE : FElem = &HexahedronFE; break;
case Geometry::PRISM : FElem = &WedgeFE; break;
case Geometry::PYRAMID : FElem = &PyramidFE; break;
case Geometry::PENTATOPE: FElem = &PentatopeFE; break;
case Geometry::TESSERACT: FElem = &TesseractFE; break;
default:
MFEM_ABORT("unknown Geometry::Type!");
}
@@ -545,9 +543,7 @@ void IsoparametricTransformation::Transform (const DenseMatrix &matrix,
void IntegrationPointTransformation::Transform (const IntegrationPoint &ip1,
IntegrationPoint &ip2)
{
// real_t vec[Geometry::MaxDim];
real_t vec[4];
real_t vec[3];
Vector v (vec, Transf.GetPointMat().Height());
Transf.Transform (ip1, v);
+17 -2
View File
@@ -52,6 +52,15 @@ protected:
const DenseMatrix &EvalTransAdjugateJ();
const DenseMatrix &EvalInverseJ();
/// @name Tolerance used for point comparisons
///@{
#ifdef MFEM_USE_DOUBLE
static constexpr real_t tol_0 = 1e-15;
#elif defined(MFEM_USE_SINGLE)
static constexpr real_t tol_0 = 1e-7;
#endif
///@}
public:
/** This enumeration declares the values stored in
@@ -176,7 +185,7 @@ public:
returned. This method is not 100 percent reliable for non-linear
transformations. */
virtual int TransformBack(const Vector &pt, IntegrationPoint &ip,
const real_t phys_tol = 1e-15) = 0;
const real_t phys_tol = tol_0) = 0;
virtual ~ElementTransformation() { }
};
@@ -281,9 +290,15 @@ public:
rel_qpts_order(-1),
solver_type(NewtonElementProject),
max_iter(16),
#ifdef MFEM_USE_DOUBLE
ref_tol(1e-15),
phys_rtol(1e-15),
ip_tol(1e-8),
#elif defined(MFEM_USE_SINGLE)
ref_tol(1e-7),
phys_rtol(1e-7),
ip_tol(1e-4),
#endif
print_level(-1)
{ }
@@ -449,7 +464,7 @@ public:
returned. This method is not 100 percent reliable for non-linear
transformations. */
virtual int TransformBack(const Vector & v, IntegrationPoint & ip,
const real_t phys_rel_tol = 1e-15)
const real_t phys_rel_tol = tol_0)
{
InverseElementTransformation inv_tr(this);
inv_tr.SetPhysicalRelTol(phys_rel_tol);
-4
View File
@@ -43,10 +43,6 @@ LinearWedgeFiniteElement WedgeFE;
// Defined here to ensure it is constructed before 'Geometries'.
LinearPyramidFiniteElement PyramidFE;
// Object declared in mesh/pentatope.hpp.
// Defined here to ensure it is constructed before 'Geometries'.
Linear4DFiniteElement PentatopeFE;
// Object declared in geom.hpp.
// Construct 'Geometries' after 'TriangleFE', 'TetrahedronFE', 'WedgeFE', and
// PyramidFE.
+8 -101
View File
@@ -93,13 +93,6 @@ void FiniteElement::CalcPhysCurlShape(ElementTransformation &Trans,
}
}
void FiniteElement::CalcDivSkewShape(const IntegrationPoint &ip,
DenseMatrix &curl_shape) const
{
mfem_error ("FiniteElement::CalcDivSkewShape (ip, ...)\n"
" is not implemented for this class!");
}
void FiniteElement::GetFaceDofs(int face, int **dofs, int *ndofs) const
{
MFEM_ABORT("method is not overloaded");
@@ -186,14 +179,6 @@ void FiniteElement::ProjectDiv(
MFEM_ABORT("method is not implemented for this element");
}
void FiniteElement::ProjectDivSkew(
const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &DivSkew) const
{
mfem_error("FiniteElement::ProjectDivSkew(...) is not implemented for "
"this element!");
}
void FiniteElement::CalcPhysShape(ElementTransformation &Trans,
Vector &shape) const
{
@@ -236,7 +221,7 @@ void FiniteElement::CalcPhysLaplacian(ElementTransformation &Trans,
{
for (int nd = 0; nd < dof; nd++)
{
Laplacian[nd] = hess(nd,0) + hess(nd,4) + hess(nd,5);
Laplacian[nd] = hess(nd,0) + hess(nd,3) + hess(nd,5);
}
}
else if (dim == 2)
@@ -274,10 +259,10 @@ void FiniteElement::CalcPhysLinLaplacian(ElementTransformation &Trans,
scale[1] = 2*Gij(0,1);
scale[2] = 2*Gij(0,2);
scale[3] = 2*Gij(1,2);
scale[4] = Gij(2,2);
scale[3] = Gij(1,1);
scale[4] = 2*Gij(1,2);
scale[5] = Gij(1,1);
scale[5] = Gij(2,2);
}
else if (dim == 2)
{
@@ -314,12 +299,12 @@ void FiniteElement::CalcPhysHessian(ElementTransformation &Trans,
map[2] = 2;
map[3] = 1;
map[4] = 5;
map[5] = 3;
map[4] = 3;
map[5] = 4;
map[6] = 2;
map[7] = 3;
map[8] = 4;
map[7] = 4;
map[8] = 5;
}
else if (dim == 2)
{
@@ -1027,19 +1012,9 @@ void VectorFiniteElement::SetDerivMembers()
deriv_range_type = SCALAR;
deriv_map_type = INTEGRAL;
break;
case H_DIV_SKEW:
deriv_type = DIV_SKEW;
deriv_range_type = VECTOR;
deriv_map_type = H_DIV;
break;
case H_CURL:
switch (dim)
{
case 4: // curl: 4D H_CURL -> 4D H_DIV(skew)
deriv_type = CURL;
deriv_range_type = MAT_SKEW;
deriv_map_type = H_DIV_SKEW;
break;
case 3: // curl: 3D H_CURL -> 3D H_DIV
deriv_type = CURL;
deriv_range_type = VECTOR;
@@ -1088,74 +1063,6 @@ void VectorFiniteElement::CalcVShape_ND(
Mult(vshape, Trans.InverseJacobian(), shape);
}
void VectorFiniteElement::CalcVShape_DivSkew (
ElementTransformation &Trans, DenseMatrix &shape) const
{
if (dim!=4) { return; }
MFEM_ASSERT(map_type == H_DIV_SKEW, "");
const DenseMatrix &J = Trans.Jacobian();
#ifdef MFEM_THREAD_SAFE
DenseMatrix vshape(dof, dim*dim);
DenseMatrix Jinv(J.Width(), J.Height());
#else
Jinv.SetSize(J.Width(), J.Height());
#endif
if (vshape.Width()!=dim*dim) { vshape.SetSize(dof,dim*dim); }
CalcVShape(Trans.GetIntPoint(), vshape);
CalcInverse(J, Jinv);
DenseMatrix invJtr(Jinv); invJtr.Transpose();
CalcVShape(Trans.GetIntPoint(), vshape);
DenseMatrix mat(dim,dim); mat = 0.0;
DenseMatrix tempMat(dim,dim);
for (int o=0; o<dof; o++)
{
// for(int ik=0; ik<dim; ik++)
// for(int jk=0; jk<dim; jk++)
// {
// mat(ik,jk) = vshape(o,dim*ik+jk);
// }
//
// Mult(mat, Jinv, tempMat);
// Mult(invJtr, tempMat, mat);
//
// for(int ik=0; ik<dim; ik++)
// for(int jk=0; jk<dim; jk++)
// {
// shape(o,dim*ik+jk) = mat(ik,jk);
// }
mat(0,0) = 0.0; mat(0,1) = vshape(o,11);
mat(0,2) = vshape(o,13); mat(0,3) = vshape(o,6);
mat(1,0) = vshape(o,14); mat(1,1) = 0.0;
mat(1,2) = vshape(o,3); mat(1,3) = vshape(o,8);
mat(2,0) = vshape(o,7); mat(2,1) = vshape(o,12); mat(2,2) = 0.0;
mat(2,3) = vshape(o,1);
mat(3,0) = vshape(o,9); mat(3,1) = vshape(o,2);
mat(3,2) = vshape(o,4); mat(3,3) = 0.0;
Mult(mat, Jinv, tempMat);
Mult(invJtr, tempMat, mat);
shape(o,0) = 0.0; shape(o,1) = mat(2,3); shape(o,2) = mat(3,1);
shape(o,3) = mat(1,2);
shape(o,4) = mat(3,2); shape(o,5) = 0.0; shape(o,6) = mat(0,3);
shape(o,7) = mat(2,0);
shape(o,8) = mat(1,3); shape(o,9) = mat(3,0); shape(o,10) = 0.0;
shape(o,11) = mat(0,1);
shape(o,12) = mat(2,1); shape(o,13) = mat(0,2); shape(o,14) = mat(1,0);
shape(o,15) = 0.0;
}
}
void VectorFiniteElement::Project_RT(
const real_t *nk, const Array<int> &d2n,
VectorCoefficient &vc, ElementTransformation &Trans, Vector &dofs) const
+31 -43
View File
@@ -259,7 +259,7 @@ protected:
public:
/// Enumeration for range_type and deriv_range_type
enum RangeType { UNKNOWN_RANGE_TYPE = -1, SCALAR, VECTOR, MAT_SKEW };
enum RangeType { UNKNOWN_RANGE_TYPE = -1, SCALAR, VECTOR };
/** @brief Enumeration for MapType: defines how reference functions are
mapped to physical space.
@@ -281,11 +281,10 @@ public:
$ u(x) = (1/w) \hat u(\hat x) $ */
H_DIV, /**< For vector fields; preserves surface integrals of the
normal component $ u(x) = (J/w) \hat u(\hat x) $ */
H_CURL, /**< For vector fields; preserves line integrals of the
H_CURL /**< For vector fields; preserves line integrals of the
tangential component
$ u(x) = J^{-t} \hat u(\hat x) $ (square J),
$ u(x) = J(J^t J)^{-1} \hat u(\hat x) $ (general J) */
H_DIV_SKEW
};
/** @brief Enumeration for DerivType: defines which derivative method
@@ -301,7 +300,7 @@ public:
GRAD, ///< Implements CalcDShape methods
DIV, ///< Implements CalcDivShape methods
CURL, ///< Implements CalcCurlShape methods
DIV_SKEW
HESS ///< Implements CalcHessian & CalcDShape methods
};
/** @brief Construct FiniteElement with given
@@ -358,7 +357,7 @@ public:
/** @brief Returns the FiniteElement::DerivType of the element describing the
spatial derivative method implemented, one of {NONE, GRAD,
DIV, CURL}. */
DIV, CURL, HESS}. */
int GetDerivType() const { return deriv_type; }
/** @brief Returns the FiniteElement::DerivType of the element describing how
@@ -396,7 +395,32 @@ public:
/// Get a const reference to the nodes of the element
const IntegrationRule & GetNodes() const { return Nodes; }
// virtual functions for finite elements on vector spaces
/** @brief Evaluate the Hessians of all shape functions of a scalar finite
element in reference space at the given point @a ip. */
/** Each row of the result DenseMatrix @a Hessian contains upper triangular
part of the Hessian of one shape function.
The order in 2D is {u_xx, u_xy, u_yy}.
The size (#dof x (#dim (#dim+1)/2) of @a Hessian must be set in advance.*/
virtual void CalcHessian(const IntegrationPoint &ip,
DenseMatrix &Hessian) const;
/** @brief Evaluate the Hessian of all shape functions of a scalar finite
element in physical space at the given point @a ip. */
/** The size (#dof, #dim*(#dim+1)/2) of @a Hessian must be set in advance. */
void CalcPhysHessian(ElementTransformation &Trans,
DenseMatrix& Hessian) const;
/** @brief Evaluate the Laplacian of all shape functions of a scalar finite
element in physical space at the given point @a ip. */
/** The size (#dof) of @a Laplacian must be set in advance. */
void CalcPhysLaplacian(ElementTransformation &Trans,
Vector& Laplacian) const;
/** @brief Evaluate the Laplacian of all shape functions of a scalar finite
element in physical space at the given point @a ip. */
/** The size (#dof) of @a Laplacian must be set in advance. */
void CalcPhysLinLaplacian(ElementTransformation &Trans,
Vector& Laplacian) const;
/** @brief Evaluate the values of all shape functions of a *vector* finite
element in reference space at the given point @a ip. */
@@ -450,40 +474,12 @@ public:
virtual void CalcPhysCurlShape(ElementTransformation &Trans,
DenseMatrix &curl_shape) const;
virtual void CalcDivSkewShape(const IntegrationPoint &ip,
DenseMatrix &curl_shape) const;
/** @brief Get the dofs associated with the given @a face.
@a *dofs is set to an internal array of the local dofc on the
face, while *ndofs is set to the number of dofs on that face.
*/
virtual void GetFaceDofs(int face, int **dofs, int *ndofs) const;
/** @brief Evaluate the Hessians of all shape functions of a scalar finite
element in reference space at the given point @a ip. */
/** Each row of the result DenseMatrix @a Hessian contains upper triangular
part of the Hessian of one shape function.
The order in 2D is {u_xx, u_xy, u_yy}.
The size (#dof x (#dim (#dim+1)/2) of @a Hessian must be set in advance.*/
virtual void CalcHessian(const IntegrationPoint &ip,
DenseMatrix &Hessian) const;
/** @brief Evaluate the Hessian of all shape functions of a scalar finite
element in reference space at the given point @a ip. */
/** The size (#dof, #dim*(#dim+1)/2) of @a Hessian must be set in advance. */
virtual void CalcPhysHessian(ElementTransformation &Trans,
DenseMatrix& Hessian) const;
/** @brief Evaluate the Laplacian of all shape functions of a scalar finite
element in reference space at the given point @a ip. */
/** The size (#dof) of @a Laplacian must be set in advance. */
virtual void CalcPhysLaplacian(ElementTransformation &Trans,
Vector& Laplacian) const;
virtual void CalcPhysLinLaplacian(ElementTransformation &Trans,
Vector& Laplacian) const;
/** @brief Return the local interpolation matrix @a I (Dof x Dof) where the
fine element is the image of the base geometry under the given
transformation. */
@@ -583,10 +579,6 @@ public:
ElementTransformation &Trans,
DenseMatrix &div) const;
virtual void ProjectDivSkew(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &DivSkew) const;
/** @brief Return a DofToQuad structure corresponding to the given
IntegrationRule using the given DofToQuad::Mode. */
/** See the documentation for DofToQuad for more details. */
@@ -822,7 +814,7 @@ private:
protected:
bool is_nodal;
#ifndef MFEM_THREAD_SAFE
mutable DenseMatrix JtJ, J, Jinv;
mutable DenseMatrix JtJ;
mutable DenseMatrix curlshape, curlshape_J;
#endif
void SetDerivMembers();
@@ -833,10 +825,6 @@ protected:
void CalcVShape_ND(ElementTransformation &Trans,
DenseMatrix &shape) const;
void CalcVShape_DivSkew(ElementTransformation &Trans,
DenseMatrix &shape) const;
/** @brief Project a vector coefficient onto the RT basis functions
@param nk Face normal vectors for this element type
@param d2n Offset into nk for each degree of freedom
File diff suppressed because it is too large Load Diff
-187
View File
@@ -450,74 +450,6 @@ public:
{ dofs = 0.0; dofs(vertex) = 1.0; }
};
/// Class for quad-linear FE on tesseract (4d element)
class QuadLinear4DFiniteElement : public NodalFiniteElement
{
public:
/// Construct a quad-linear FE on tesseract
QuadLinear4DFiniteElement();
/** virtual function which evaluates the values of all
shape functions at a given point ip and stores
them in the vector shape of dimension Dof (16) */
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
/** virtual function which evaluates the values of all
partial derivatives of all shape functions at a given
point ip and stores them in the matrix dshape (Dof x Dim) (16 x 4)
so that each row contains the derivatives of one shape function */
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
virtual void CalcHessian (const IntegrationPoint &ip,
DenseMatrix &h) const;
virtual void ProjectDelta(int vertex, Vector &dofs) const
{ dofs = 0.0; dofs(vertex) = 1.0; }
};
/// Class for linear FE on a pentatope
class Linear4DFiniteElement : public NodalFiniteElement
{
public:
/// Construct a linear FE on tetrahedron
Linear4DFiniteElement();
/** virtual function which evaluates the values of all
shape functions at a given point ip and stores
them in the vector shape of dimension Dof (4) */
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
/** virtual function which evaluates the values of all
partial derivatives of all shape functions at a given
point ip and stores them in the matrix dshape (Dof x Dim) (4 x 3)
so that each row contains the derivatives of one shape function */
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
virtual void ProjectDelta(int vertex, Vector &dofs) const
{ dofs = 0.0; dofs(vertex) = 1.0; }
virtual void GetFaceDofs(int face, int **dofs, int *ndofs) const;
virtual void CalcHessian(const IntegrationPoint &ip, DenseMatrix &h) const;
};
/// Class for quadratic FE on pentatope
class Quadratic4DFiniteElement : public NodalFiniteElement
{
public:
/// Construct a quadratic FE on pentatope
Quadratic4DFiniteElement();
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
virtual void CalcHessian(const IntegrationPoint &ip,
DenseMatrix &h) const;
};
/// A 2D Crouzeix-Raviart element on triangle
class CrouzeixRaviartFiniteElement : public NodalFiniteElement
@@ -1257,126 +1189,7 @@ public:
DenseMatrix &dshape) const;
};
//lowest order first kind nedelec element for a pentatope
class Nedelec1PentFiniteElement : public VectorFiniteElement
{
private:
static const double tk[10][4];
public:
Nedelec1PentFiniteElement();
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{ CalcVShape_ND(Trans, shape); }
virtual void CalcCurlShape(const IntegrationPoint &ip,
DenseMatrix &curl_shape) const;
virtual void GetLocalInterpolation (ElementTransformation &Trans,
DenseMatrix &I) const;
using FiniteElement::Project;
virtual void Project (VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const;
virtual void Project(const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const;
virtual void ProjectGrad(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &grad) const;
};
//lowest order second kind nedelec element for a pentatope
class Nedelec1FullPentFiniteElement : public VectorFiniteElement
{
private:
static const double tk[10][4];
public:
Nedelec1FullPentFiniteElement();
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{ CalcVShape_ND(Trans, shape); }
virtual void CalcCurlShape(const IntegrationPoint &ip,
DenseMatrix &curl_shape) const;
virtual void GetLocalInterpolation (ElementTransformation &Trans,
DenseMatrix &I) const {};
using FiniteElement::Project;
virtual void Project (VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const;
virtual void Project(const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const;
virtual void ProjectGrad(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &grad) const;
};
class DivSkew1PentFiniteElement : public VectorFiniteElement
{
private:
static const double tk1[10][4];
static const double tk2[10][4];
public:
DivSkew1PentFiniteElement();
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{ CalcVShape_DivSkew(Trans, shape); }
virtual void CalcDivSkewShape(const IntegrationPoint &ip,
DenseMatrix &divSkew_shape) const;
virtual void GetLocalInterpolation (ElementTransformation &Trans,
DenseMatrix &I) const;
using FiniteElement::Project;
virtual void Project (VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const;
virtual void Project(const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const;
virtual void ProjectCurl(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &curl) const;
};
class RT0PentFiniteElement : public VectorFiniteElement
{
private:
static const double nk[5][4];
public:
RT0PentFiniteElement();
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{ CalcVShape_RT(Trans, shape); };
virtual void CalcDivShape(const IntegrationPoint &ip,
Vector &divshape) const;
virtual void GetLocalInterpolation (ElementTransformation &Trans,
DenseMatrix &I) const;
using FiniteElement::Project;
virtual void Project (VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const;
virtual void Project(const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const;
virtual void ProjectDivSkew(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &DivSkew) const;
};
} // namespace mfem
#endif
-341
View File
@@ -1040,345 +1040,4 @@ void H1_WedgeElement::CalcDShape(const IntegrationPoint &ip,
}
}
H1_PentatopeElement::H1_PentatopeElement(const int p, const int type)
: NodalFiniteElement(4, Geometry::PENTATOPE,
((p + 1)*(p + 2)*(p + 3)*(p + 4))/24,
p, FunctionSpace::Pk)
{
const double *cp = poly1d.ClosedPoints(p, VerifyClosed(type));
#ifndef MFEM_THREAD_SAFE
shape_x.SetSize(p + 1);
shape_y.SetSize(p + 1);
shape_z.SetSize(p + 1);
shape_t.SetSize(p + 1);
shape_l.SetSize(p + 1);
dshape_x.SetSize(p + 1);
dshape_y.SetSize(p + 1);
dshape_z.SetSize(p + 1);
dshape_t.SetSize(p + 1);
dshape_l.SetSize(p + 1);
ddshape_x.SetSize(p + 1);
ddshape_y.SetSize(p + 1);
ddshape_z.SetSize(p + 1);
ddshape_t.SetSize(p + 1);
ddshape_l.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), shape_t(p+1),
shape_l(p + 1);
#endif
// vertices
Nodes.IntPoint(0).Set4(cp[0], cp[0], cp[0], cp[0]);
Nodes.IntPoint(1).Set4(cp[p], cp[0], cp[0], cp[0]);
Nodes.IntPoint(2).Set4(cp[0], cp[p], cp[0], cp[0]);
Nodes.IntPoint(3).Set4(cp[0], cp[0], cp[p], cp[0]);
Nodes.IntPoint(4).Set4(cp[0], cp[0], cp[0], cp[p]);
// edges (see Tetrahedron::edges in mesh/tetrahedron.cpp)
int o = 5;
for (int i = 1; i < p; i++) // (0,1)
{
Nodes.IntPoint(o++).Set4(cp[i], cp[0], cp[0], cp[0]);
}
for (int i = 1; i < p; i++) // (0,2)
{
Nodes.IntPoint(o++).Set4(cp[0], cp[i], cp[0], cp[0]);
}
for (int i = 1; i < p; i++) // (0,3)
{
Nodes.IntPoint(o++).Set4(cp[0], cp[0], cp[i], cp[0]);
}
for (int i = 1; i < p; i++) // (0,4)
{
Nodes.IntPoint(o++).Set4(cp[0], cp[0], cp[0], cp[i]);
}
for (int i = 1; i < p; i++) // (1,2)
{
Nodes.IntPoint(o++).Set4(cp[p-i], cp[i], cp[0], cp[0]);
}
for (int i = 1; i < p; i++) // (1,3)
{
Nodes.IntPoint(o++).Set4(cp[p-i], cp[0], cp[i], cp[0]);
}
for (int i = 1; i < p; i++) // (1,4)
{
Nodes.IntPoint(o++).Set4(cp[p-i], cp[0], cp[0], cp[i]);
}
for (int i = 1; i < p; i++) // (2,3)
{
Nodes.IntPoint(o++).Set4(cp[0], cp[p-i], cp[i], cp[0]);
}
for (int i = 1; i < p; i++) // (2,4)
{
Nodes.IntPoint(o++).Set4(cp[0], cp[p-i], cp[0], cp[i]);
}
for (int i = 1; i < p; i++) // (3,4)
{
Nodes.IntPoint(o++).Set4(cp[0], cp[0], cp[p-i], cp[i]);
}
// planars (see Mesh::GeneratePlanars in mesh/mesh.cpp)
for (int j = 1; j < p; j++)
for (int i=1; i + j < p; i++) // (0,1,2)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set4(cp[i]/w, cp[j]/w, cp[0], cp[0]);
}
for (int j = 1; j < p; j++)
for (int i=1; i + j < p; i++) // (0,1,3)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set4(cp[i]/w, cp[0], cp[j]/w, cp[0]);
}
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++).Set4(cp[i]/w, cp[0], cp[0], cp[j]/w);
}
for (int j = 1; j < p; j++)
for (int i=1; i + j < p; i++) // (0,2,3)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set4(cp[0], cp[i]/w, cp[j]/w, cp[0]);
}
for (int j = 1; j < p; j++)
for (int i=1; i + j < p; i++) // (0,2,4)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set4(cp[0], cp[i]/w, cp[0], cp[j]/w);
}
for (int j = 1; j < p; j++)
for (int i=1; i + j < p; i++) // (0,3,4)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set4(cp[0], cp[0], cp[i]/w, cp[j]/w);
}
for (int j = 1; j < p; j++)
for (int i=1; i + j < p; i++) // (1,2,3)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set4(cp[p-i-j]/w, cp[i]/w, cp[j]/w, cp[0]);
}
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++).Set4(cp[p-i-j]/w, cp[i]/w, cp[0], cp[j]/w);
}
for (int j = 1; j < p; j++)
for (int i=1; i + j < p; i++) // (1,3,4)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set4(cp[p-i-j]/w, cp[0], cp[i]/w, cp[j]/w);
}
for (int j = 1; j < p; j++)
for (int i=1; i + j < p; i++) // (2,3,4)
{
double w = cp[i] + cp[j] + cp[p-i-j];
Nodes.IntPoint(o++).Set4(cp[0], cp[p-i-j]/w, cp[i]/w, cp[j]/w);
}
// face(volumes)s (see Mesh::GenerateFaces in mesh/mesh.cpp)
for (int k = 1; k < p; k++)
for (int j = 1; j + k < p; j++)
for (int i = 1; i + j + k < p; i++) // (0,1,2,3)
{
double w = cp[i] + cp[j] + cp[k] + cp[p-i-j-k];
Nodes.IntPoint(o++).Set4(cp[i]/w, cp[j]/w, cp[k]/w, cp[0]);
}
for (int k = 1; k < p; k++)
for (int j = 1; j + k < p; j++)
for (int i = 1; i + j + k < p; i++) // (0,2,1,4)
{
double w = cp[i] + cp[j] + cp[k] + cp[p-i-j-k];
Nodes.IntPoint(o++).Set4(cp[j]/w, cp[i]/w, cp[0], cp[k]/w);
}
for (int k = 1; k < p; k++)
for (int j = 1; j + k < p; j++)
for (int i = 1; i + j + k < p; i++) // (0,1,3,4)
{
double w = cp[i] + cp[j] + cp[k] + cp[p-i-j-k];
Nodes.IntPoint(o++).Set4(cp[i]/w, cp[0], cp[j]/w, cp[k]/w);
}
for (int k = 1; k < p; k++)
for (int j = 1; j + k < p; j++)
for (int i = 1; i + j + k < p; i++) // (0,3,2,4)
{
double w = cp[i] + cp[j] + cp[k] + cp[p-i-j-k];
Nodes.IntPoint(o++).Set4(cp[0], cp[j]/w, cp[i]/w, cp[k]/w);
}
for (int k = 1; k < p; k++)
for (int j = 1; j + k < p; j++)
for (int i = 1; i + j + k < p; i++) // (1,2,3,4)
{
double w = cp[i] + cp[j] + cp[k] + cp[p-i-j-k];
Nodes.IntPoint(o++).Set4(cp[p-i-j-k]/w, cp[i]/w, cp[j]/w, cp[k]/w);
}
// interior
for (int l = 1; l < p; l++)
for (int k = 1; k + l < p; k++)
for (int j = 1; j + k + l < p; j++)
for (int i = 1; i + j + k + l < p; i++)
{
double w = cp[i] + cp[j] + cp[k] + cp[l] + cp[p-i-j-k-l];
Nodes.IntPoint(o++).Set4(cp[i]/w, cp[j]/w, cp[k]/w, cp[l]/w);
}
DenseMatrix T(dof);
for (int m = 0; m < dof; m++)
{
IntegrationPoint &ip = Nodes.IntPoint(m);
poly1d.CalcBasis(p, ip.x, shape_x);
poly1d.CalcBasis(p, ip.y, shape_y);
poly1d.CalcBasis(p, ip.z, shape_z);
poly1d.CalcBasis(p, ip.t, shape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l);
o = 0;
for (int l = 0; l <= p; l++)
for (int k = 0; k + l <= p; k++)
for (int j = 0; j + k +l <= p; j++)
for (int i = 0; i + j + k + l <= p; i++)
{
T(o++, m) = shape_x(i)*shape_y(j)*shape_z(k)*shape_t(l)*shape_l(p-i-j-k-l);
}
}
Ti.Factor(T);
// cout << "H1_PentatopeElement(" << p << ") : "; Ti.TestInversion();
}
void H1_PentatopeElement::CalcShape(const IntegrationPoint &ip,
Vector &shape) const
{
const int p = order;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_t(p+1),
shape_l(p + 1);
Vector u(Dof);
#endif
poly1d.CalcBasis(p, ip.x, shape_x);
poly1d.CalcBasis(p, ip.y, shape_y);
poly1d.CalcBasis(p, ip.z, shape_z);
poly1d.CalcBasis(p, ip.t, shape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l);
for (int o = 0, l = 0; l <= p; l++)
for (int k = 0; k + l <= p; k++)
for (int j = 0; j + k + l <= p; j++)
for (int i = 0; i + j + k + l <= p; i++)
{
u(o++) = shape_x(i)*shape_y(j)*shape_z(k)*shape_t(l)*shape_l(p-i-j-k-l);
}
Ti.Mult(u, shape);
}
void H1_PentatopeElement::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), shape_t(p+1),
shape_l(p + 1);
Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_t(p+1),
dshape_l(p + 1);
DenseMatrix du(Dof, Dim);
#endif
poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
poly1d.CalcBasis(p, ip.t, shape_t, dshape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l, dshape_l);
for (int o = 0, l = 0; l <= p; l++)
for (int k = 0; k + l <= p; k++)
for (int j = 0; j + k + l <= p; j++)
for (int i = 0; i + j + k + l <= p; i++)
{
int m = p - i - j - k - l;
du(o,0) = ((dshape_x(i)* shape_l(m)) -
( shape_x(i)*dshape_l(m)))*shape_y(j)*shape_z(k)*shape_t(l);
du(o,1) = ((dshape_y(j)* shape_l(m)) -
( shape_y(j)*dshape_l(m)))*shape_x(i)*shape_z(k)*shape_t(l);
du(o,2) = ((dshape_z(k)* shape_l(m)) -
( shape_z(k)*dshape_l(m)))*shape_x(i)*shape_y(j)*shape_t(l);
du(o,3) = ((dshape_t(l)* shape_l(m)) -
( shape_t(l)*dshape_l(m)))*shape_x(i)*shape_y(j)*shape_z(k);
o++;
}
Ti.Mult(du, dshape);
}
void H1_PentatopeElement::CalcHessian(const IntegrationPoint &ip,
DenseMatrix &ddshape) const
{
const int p = order;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_t(p+1),
shape_l(p + 1);
Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_t(p+1),
dshape_l(p + 1);
Vector ddshape_x(p + 1), ddshape_y(p + 1), ddshape_z(p + 1), ddshape_t(p+1),
ddshape_l(p + 1);
DenseMatrix ddu(Dof, ((Dim+1)*Dim)/2);
#endif
poly1d.CalcBasis(p, ip.x, shape_x, dshape_x, ddshape_x);
poly1d.CalcBasis(p, ip.y, shape_y, dshape_y, ddshape_y);
poly1d.CalcBasis(p, ip.z, shape_z, dshape_z, ddshape_z);
poly1d.CalcBasis(p, ip.t, shape_t, dshape_t, ddshape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l, dshape_l,
ddshape_l);
for (int o = 0, l = 0; l <= p; l++)
for (int k = 0; k + l <= p; k++)
for (int j = 0; j + k + l <= p; j++)
for (int i = 0; i + j + k + l <= p; i++)
{
// u_xx, u_xy, u_xz, u_xt, u_yy, u_yz, u_yt, u_zz, u_zt, u_tt
int m = p - i - j - k - l;
ddu(o,0) = ((ddshape_x(i)*shape_l(m)) - 2.* (dshape_x(i)*dshape_l(m)) +
(shape_x(i)*ddshape_l(m))) * shape_y(j) * shape_z(k) * shape_t(l);
ddu(o,1) = ((dshape_y(j)* ( (dshape_x(i)*shape_l(m)) - (shape_x(i)*dshape_l(
m))) ) + (shape_y(j)* ((ddshape_l(m)*shape_x(i)) - (dshape_x(i) * dshape_l(
m)) ) ) )* shape_z(k) * shape_t(l);
ddu(o,2) = ((dshape_z(k)* ( (dshape_x(i)*shape_l(m)) - (shape_x(i)*dshape_l(
m))) ) + (shape_z(k)* ((ddshape_l(m)*shape_x(i)) - (dshape_x(i) * dshape_l(
m)) ) ) )* shape_y(j) * shape_t(l);
ddu(o,3) = ((dshape_t(l)* ( (dshape_x(i)*shape_l(m)) - (shape_x(i)*dshape_l(
m))) ) + (shape_t(l)* ((ddshape_l(m)*shape_x(i)) - (dshape_x(i) * dshape_l(
m)) ) ) )* shape_y(j) * shape_z(k);
ddu(o,4) = ((ddshape_y(j)*shape_l(m)) - 2.* (dshape_y(j)*dshape_l(m)) +
(shape_y(j)*ddshape_l(m))) * shape_x(i) * shape_z(k) * shape_t(l);
ddu(o,5) = ((dshape_z(k)* ( (dshape_y(j)*shape_l(m)) - (shape_y(j)*dshape_l(
m))) ) + (shape_z(k)* ((ddshape_l(m)*shape_y(j)) - (dshape_y(j) * dshape_l(
m)) ) ) )* shape_x(i) * shape_t(l);
ddu(o,6) = ((dshape_t(l)* ( (dshape_y(j)*shape_l(m)) - (shape_y(j)*dshape_l(
m))) ) + (shape_t(l)* ((ddshape_l(m)*shape_y(j)) - (dshape_y(j) * dshape_l(
m)) ) ) )* shape_x(i) * shape_z(k);
ddu(o,7) = ((ddshape_z(k)*shape_l(m)) - 2.* (dshape_z(k)*dshape_l(m)) +
(shape_z(k)*ddshape_l(m))) * shape_y(j) * shape_x(i) * shape_t(l);
ddu(o,8) = ((dshape_t(l)* ( (dshape_z(k)*shape_l(m)) - (shape_z(k)*dshape_l(
m))) ) + (shape_t(l)* ((ddshape_l(m)*shape_z(k)) - (dshape_z(k) * dshape_l(
m)) ) ) )* shape_x(i) * shape_y(j);
ddu(o,9) = ((ddshape_t(l)*shape_l(m)) - 2.* (dshape_t(l)*dshape_l(m)) +
(shape_t(l)*ddshape_l(m))) * shape_y(j) * shape_x(i) * shape_z(k);
o++;
}
Ti.Mult(ddu, ddshape);
}
}
-22
View File
@@ -148,28 +148,6 @@ public:
DenseMatrix &dshape) const;
};
class H1_PentatopeElement : public NodalFiniteElement
{
private:
#ifndef MFEM_THREAD_SAFE
mutable Vector shape_x, shape_y, shape_z, shape_t, shape_l;
mutable Vector dshape_x, dshape_y, dshape_z, dshape_t, dshape_l, u;
mutable Vector ddshape_x, ddshape_y, ddshape_z, ddshape_t, ddshape_l;
mutable DenseMatrix du, ddu;
#endif
DenseMatrixInverse Ti;
public:
H1_PentatopeElement(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;
virtual void CalcHessian(const IntegrationPoint &ip,
DenseMatrix &ddshape) const;
};
} // namespace mfem
#endif
-171
View File
@@ -923,175 +923,4 @@ void L2_WedgeElement::CalcDShape(const IntegrationPoint &ip,
}
}
L2_PentatopeElement::L2_PentatopeElement(const int p, const int _type)
: NodalFiniteElement(4, Geometry::PENTATOPE,
((p + 1)*(p + 2)*(p + 3)*(p + 4))/24,
p, FunctionSpace::Pk), T(dof)
{
const double *op;
type = _type;
switch (type)
{
case 0: op = poly1d.OpenPoints(p); break;
case 1:
default: op = poly1d.ClosedPoints(p);
}
#ifndef MFEM_THREAD_SAFE
shape_x.SetSize(p + 1);
shape_y.SetSize(p + 1);
shape_z.SetSize(p + 1);
shape_t.SetSize(p + 1);
shape_l.SetSize(p + 1);
dshape_x.SetSize(p + 1);
dshape_y.SetSize(p + 1);
dshape_z.SetSize(p + 1);
dshape_t.SetSize(p + 1);
dshape_l.SetSize(p + 1);
u.SetSize(dof);
du.SetSize(dof, dim);
#else
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_t(p + 1),
shape_l(p + 1);
#endif
for (int o = 0, l = 0; l <= p; l++)
for (int k = 0; l + k <= p; k++)
for (int j = 0; j + l + k <= p; j++)
for (int i = 0; i + j + l + k <= p; i++)
{
double w = op[i] + op[j] + op[k] + op[l] + op[p-i-j-k-l];
Nodes.IntPoint(o++).Set4(op[i]/w, op[j]/w, op[k]/w, op[l]/w);
}
for (int m = 0; m < dof; m++)
{
IntegrationPoint &ip = Nodes.IntPoint(m);
poly1d.CalcBasis(p, ip.x, shape_x);
poly1d.CalcBasis(p, ip.y, shape_y);
poly1d.CalcBasis(p, ip.z, shape_z);
poly1d.CalcBasis(p, ip.t, shape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l);
for (int o = 0, l = 0; l <= p; l++)
for (int k = 0; l + k <= p; k++)
for (int j = 0; j + l + k <= p; j++)
for (int i = 0; i + j + l + k <= p; i++)
{
T(o++, m) = shape_x(i)*shape_y(j)*shape_z(k)*shape_t(l)*shape_l(p-i-j-k-l);
}
}
T.Invert();
}
void L2_PentatopeElement::CalcShape(const IntegrationPoint &ip,
Vector &shape) const
{
const int p = order;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
Vector u(Dof);
#endif
poly1d.CalcBasis(p, ip.x, shape_x);
poly1d.CalcBasis(p, ip.y, shape_y);
poly1d.CalcBasis(p, ip.z, shape_z);
poly1d.CalcBasis(p, ip.t, shape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l);
for (int o = 0, l = 0; l <= p; l++)
for (int k = 0; l + k <= p; k++)
for (int j = 0; j + l + k <= p; j++)
for (int i = 0; i + j + l + k <= p; i++)
{
u(o++) = shape_x(i)*shape_y(j)*shape_z(k)*shape_t(l)*shape_l(p-i-j-k-l);
}
T.Mult(u, shape);
}
void L2_PentatopeElement::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), shape_t(p + 1),
shape_l(p + 1);
Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_t(p + 1),
dshape_l(p + 1);
DenseMatrix du(Dof, Dim);
#endif
poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
poly1d.CalcBasis(p, ip.t, shape_t, dshape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l, dshape_l);
for (int o = 0, m = 0; m <= p; m++)
for (int k = 0; k + m <= p; k++)
for (int j = 0; j + k + m <= p; j++)
for (int i = 0; i + j + k + m <= p; i++)
{
int l = p - i - j - k - m;
du(o,0) = ((dshape_x(i)* shape_l(l)) -
( shape_x(i)*dshape_l(l)))*shape_y(j)*shape_z(k)*shape_t(m);
du(o,1) = ((dshape_y(j)* shape_l(l)) -
( shape_y(j)*dshape_l(l)))*shape_x(i)*shape_z(k)*shape_t(m);
du(o,2) = ((dshape_z(k)* shape_l(l)) -
( shape_z(k)*dshape_l(l)))*shape_x(i)*shape_y(j)*shape_t(m);
du(o,3) = ((dshape_t(m)* shape_l(l)) -
( shape_t(m)*dshape_l(l)))*shape_x(i)*shape_y(j)*shape_z(k);
o++;
}
Mult(T, du, dshape);
}
void L2_PentatopeElement::ProjectDelta(int vertex, Vector &dofs) const
{
switch (vertex)
{
case 0:
for (int i = 0; i < dof; i++)
{
const IntegrationPoint &ip = Nodes.IntPoint(i);
dofs[i] = pow(1.0 - ip.x - ip.y - ip.z - ip.t, order);
}
break;
case 1:
for (int i = 0; i < dof; i++)
{
const IntegrationPoint &ip = Nodes.IntPoint(i);
dofs[i] = pow(ip.x, order);
}
break;
case 2:
for (int i = 0; i < dof; i++)
{
const IntegrationPoint &ip = Nodes.IntPoint(i);
dofs[i] = pow(ip.y, order);
}
break;
case 3:
for (int i = 0; i < dof; i++)
{
const IntegrationPoint &ip = Nodes.IntPoint(i);
dofs[i] = pow(ip.z, order);
}
break;
case 4:
for (int i = 0; i < dof; i++)
{
const IntegrationPoint &ip = Nodes.IntPoint(i);
dofs[i] = pow(ip.t, order);
}
break;
}
}
}
-19
View File
@@ -183,25 +183,6 @@ public:
DenseMatrix &dshape) const;
};
class L2_PentatopeElement : public NodalFiniteElement
{
private:
int type;
#ifndef MFEM_THREAD_SAFE
mutable Vector shape_x, shape_y, shape_z, shape_t, shape_l;
mutable Vector dshape_x, dshape_y, dshape_z, dshape_t, dshape_l, u;
mutable DenseMatrix du;
#endif
DenseMatrix T;
public:
L2_PentatopeElement(const int p, const int _type = 0);
virtual void CalcShape(const IntegrationPoint &ip, Vector &shape) const;
virtual void CalcDShape(const IntegrationPoint &ip,
DenseMatrix &dshape) const;
virtual void ProjectDelta(int vertex, Vector &dofs) const;
};
} // namespace mfem
#endif
+624 -11
View File
@@ -349,10 +349,10 @@ void NURBS3DFiniteElement::CalcHessian (const IntegrationPoint &ip,
d2sum[1] += ( hessian(o,1) = dsx*dsy*sz*weights(o) );
d2sum[2] += ( hessian(o,2) = dsx*sy*dsz*weights(o) );
d2sum[3] += ( hessian(o,3) = sx*dsy*dsz*weights(o) );
d2sum[3] += ( hessian(o,3) = sx*d2sy*sz*weights(o) );
d2sum[4] += ( hessian(o,4) = sx*dsy*dsz*weights(o) );
d2sum[4] += ( hessian(o,4) = sx*sy*d2sz*weights(o) );
d2sum[5] += ( hessian(o,5) = sx*d2sy*sz*weights(o) );
d2sum[5] += ( hessian(o,5) = sx*sy*d2sz*weights(o) );
}
}
}
@@ -387,19 +387,632 @@ void NURBS3DFiniteElement::CalcHessian (const IntegrationPoint &ip,
+ u[o]*sum*(2*dsum[0]*dsum[2] - d2sum[2]);
hessian(o,3) = hessian(o,3)*sum
- du(o,1)*sum*dsum[2]
- du(o,2)*sum*dsum[1]
+ u[o]*sum*(2*dsum[1]*dsum[2] - d2sum[3]);
- 2*du(o,1)*sum*dsum[1]
+ u[o]*sum*(2*dsum[1]*dsum[1] - d2sum[3]);
hessian(o,4) = hessian(o,4)*sum
- 2*du(o,2)*sum*dsum[2]
+ u[o]*sum*(2*dsum[2]*dsum[2] - d2sum[4]);
- du(o,1)*sum*dsum[2]
- du(o,2)*sum*dsum[1]
+ u[o]*sum*(2*dsum[1]*dsum[2] - d2sum[4]);
hessian(o,5) = hessian(o,5)*sum
- 2*du(o,1)*sum*dsum[1]
+ u[o]*sum*(2*dsum[1]*dsum[1] - d2sum[5]);
- 2*du(o,2)*sum*dsum[2]
+ u[o]*sum*(2*dsum[2]*dsum[2] - d2sum[5]);
}
}
void NURBS_HDiv2DFiniteElement::SetOrder() const
{
orders[0] = kv[0]->GetOrder();
orders[1] = kv[1]->GetOrder();
if (kv1[0]) { delete kv1[0]; }
if (kv1[1]) { delete kv1[1]; }
kv1[0] = kv[0]->DegreeElevate(1);
kv1[1] = kv[1]->DegreeElevate(1);
shape_x.SetSize(orders[0]+1);
shape_y.SetSize(orders[1]+1);
dshape_x.SetSize(orders[0]+1);
dshape_y.SetSize(orders[1]+1);
d2shape_x.SetSize(orders[0]+1);
d2shape_y.SetSize(orders[1]+1);
shape1_x.SetSize(orders[0]+2);
shape1_y.SetSize(orders[1]+2);
dshape1_x.SetSize(orders[0]+2);
dshape1_y.SetSize(orders[1]+2);
d2shape1_x.SetSize(orders[0]+2);
d2shape1_y.SetSize(orders[1]+2);
order = max(orders[0]+1, orders[1]+1);
dof = (orders[0] + 2)*(orders[1] + 1)
+ (orders[1] + 1)*(orders[1] + 2);
u.SetSize(dof);
du.SetSize(dof);
weights.SetSize(dof);
}
void NURBS_HDiv2DFiniteElement::CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const
{
kv[0]->CalcShape(shape_x, ijk[0], ip.x);
kv[1]->CalcShape(shape_y, ijk[1], ip.y);
kv1[0]->CalcShape(shape1_x, ijk[0], ip.x);
kv1[1]->CalcShape(shape1_y, ijk[1], ip.y);
int o = 0;
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy = shape_y(j);
for (int i = 0; i <= orders[0]+1; i++, o++)
{
shape(o,0) = shape1_x(i)*sy;
shape(o,1) = 0.0;
}
}
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t sy1 = shape1_y(j);
for (int i = 0; i <= orders[0]; i++, o++)
{
shape(o,0) = 0.0;
shape(o,1) = shape_x(i)*sy1;
}
}
}
void NURBS_HDiv2DFiniteElement::CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{
CalcVShape(Trans.GetIntPoint(), shape);
const DenseMatrix & J = Trans.Jacobian();
MFEM_ASSERT(J.Width() == 2 && J.Height() == 2,
"NURBS_HDiv2DFiniteElement cannot be embedded in "
"3 dimensional spaces");
for (int i=0; i<dof; i++)
{
real_t sx = shape(i, 0);
real_t sy = shape(i, 1);
shape(i, 0) = sx * J(0, 0) + sy * J(0, 1);
shape(i, 1) = sx * J(1, 0) + sy * J(1, 1);
}
shape *= (1.0 / Trans.Weight());
}
void NURBS_HDiv2DFiniteElement::CalcDivShape(const IntegrationPoint &ip,
Vector &divshape) const
{
kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
kv1[0]->CalcDShape(dshape1_x, ijk[0], ip.x);
kv1[1]->CalcDShape(dshape1_y, ijk[1], ip.y);
int o = 0;
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy = shape_y(j);
for (int i = 0; i <= orders[0]+1; i++, o++)
{
divshape(o) = dshape1_x(i)*sy;
}
}
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t dsy1 = dshape1_y(j);
for (int i = 0; i <= orders[0]; i++, o++)
{
divshape(o) = shape_x(i)*dsy1;
}
}
}
NURBS_HDiv2DFiniteElement::~NURBS_HDiv2DFiniteElement()
{
if (kv1[0]) { delete kv1[0]; }
if (kv1[1]) { delete kv1[1]; }
}
void NURBS_HDiv3DFiniteElement::SetOrder() const
{
orders[0] = kv[0]->GetOrder();
orders[1] = kv[1]->GetOrder();
orders[2] = kv[2]->GetOrder();
if (kv1[0]) { delete kv1[0]; }
if (kv1[1]) { delete kv1[1]; }
if (kv1[2]) { delete kv1[2]; }
kv1[0] = kv[0]->DegreeElevate(1);
kv1[1] = kv[1]->DegreeElevate(1);
kv1[2] = kv[2]->DegreeElevate(1);
shape_x.SetSize(orders[0]+1);
shape_y.SetSize(orders[1]+1);
shape_z.SetSize(orders[2]+1);
dshape_x.SetSize(orders[0]+1);
dshape_y.SetSize(orders[1]+1);
dshape_z.SetSize(orders[2]+1);
d2shape_x.SetSize(orders[0]+1);
d2shape_y.SetSize(orders[1]+1);
d2shape_z.SetSize(orders[2]+1);
shape1_x.SetSize(orders[0]+2);
shape1_y.SetSize(orders[1]+2);
shape1_z.SetSize(orders[2]+2);
dshape1_x.SetSize(orders[0]+2);
dshape1_y.SetSize(orders[1]+2);
dshape1_z.SetSize(orders[2]+2);
d2shape1_x.SetSize(orders[0]+2);
d2shape1_y.SetSize(orders[1]+2);
d2shape1_z.SetSize(orders[2]+2);
order = max(orders[0]+1, max( orders[1]+1, orders[2]+1));
dof = (orders[0] + 2)*(orders[1] + 1)*(orders[2] + 1) +
(orders[0] + 1)*(orders[1] + 2)*(orders[2] + 1) +
(orders[0] + 1)*(orders[1] + 1)*(orders[2] + 2);
u.SetSize(dof);
du.SetSize(dof);
weights.SetSize(dof);
}
void NURBS_HDiv3DFiniteElement::CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const
{
kv[0]->CalcShape(shape_x, ijk[0], ip.x);
kv[1]->CalcShape(shape_y, ijk[1], ip.y);
kv[2]->CalcShape(shape_z, ijk[2], ip.z);
kv1[0]->CalcShape(shape1_x, ijk[0], ip.x);
kv1[1]->CalcShape(shape1_y, ijk[1], ip.y);
kv1[2]->CalcShape(shape1_z, ijk[2], ip.z);
shape = 0.0;
int o = 0;
for (int k = 0; k <= orders[2]; k++)
{
const real_t sz = shape_z(k);
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy_sz = shape_y(j)*sz;
for (int i = 0; i <= orders[0]+1; i++, o++)
{
shape(o,0) = shape1_x(i)*sy_sz;
}
}
}
for (int k = 0; k <= orders[2]; k++)
{
const real_t sz = shape_z(k);
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t sy1_sz = shape1_y(j)*sz;
for (int i = 0; i <= orders[0]; i++, o++)
{
shape(o,1) = shape_x(i)*sy1_sz;
}
}
}
for (int k = 0; k <= orders[2]+1; k++)
{
const real_t sz1 = shape1_z(k);
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy_sz1 = shape_y(j)*sz1;
for (int i = 0; i <= orders[0]; i++, o++)
{
shape(o,2) = shape_x(i)*sy_sz1;
}
}
}
}
void NURBS_HDiv3DFiniteElement::CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{
CalcVShape(Trans.GetIntPoint(), shape);
const DenseMatrix & J = Trans.Jacobian();
MFEM_ASSERT(J.Width() == 3 && J.Height() == 3,
"RT_R2D_FiniteElement cannot be embedded in "
"3 dimensional spaces");
for (int i=0; i<dof; i++)
{
real_t sx = shape(i, 0);
real_t sy = shape(i, 1);
real_t sz = shape(i, 2);
shape(i, 0) = sx * J(0, 0) + sy * J(0, 1) + sz * J(0, 2);
shape(i, 1) = sx * J(1, 0) + sy * J(1, 1) + sz * J(1, 2);
shape(i, 2) = sx * J(2, 0) + sy * J(2, 1) + sz * J(2, 2);
}
shape *= (1.0 / Trans.Weight());
}
void NURBS_HDiv3DFiniteElement::CalcDivShape(const IntegrationPoint &ip,
Vector &divshape) const
{
kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
kv[2]->CalcShape ( shape_z, ijk[2], ip.z);
kv1[0]->CalcDShape(dshape1_x, ijk[0], ip.x);
kv1[1]->CalcDShape(dshape1_y, ijk[1], ip.y);
kv1[2]->CalcDShape(dshape1_z, ijk[2], ip.z);
int o = 0;
for (int k = 0; k <= orders[2]; k++)
{
const real_t sz = shape_z(k);
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy_sz = shape_y(j)*sz;
for (int i = 0; i <= orders[0]+1; i++, o++)
{
divshape(o) = dshape1_x(i)*sy_sz;
}
}
}
for (int k = 0; k <= orders[2]; k++)
{
const real_t sz = shape_z(k);
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t dy1_sz = dshape1_y(j)*sz;
for (int i = 0; i <= orders[0]; i++, o++)
{
divshape(o) = shape_x(i)*dy1_sz;
}
}
}
for (int k = 0; k <= orders[2]+1; k++)
{
const real_t dz1 = dshape1_z(k);
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy_dz1 = shape_y(j)*dz1;
for (int i = 0; i <= orders[0]; i++, o++)
{
divshape(o) = shape_x(i)*sy_dz1;
}
}
}
}
NURBS_HDiv3DFiniteElement::~NURBS_HDiv3DFiniteElement()
{
if (kv1[0]) { delete kv1[0]; }
if (kv1[1]) { delete kv1[1]; }
if (kv1[2]) { delete kv1[2]; }
}
void NURBS_HCurl2DFiniteElement::SetOrder() const
{
orders[0] = kv[0]->GetOrder();
orders[1] = kv[1]->GetOrder();
if (kv1[0]) { delete kv1[0]; }
if (kv1[1]) { delete kv1[1]; }
kv1[0] = kv[0]->DegreeElevate(1);
kv1[1] = kv[1]->DegreeElevate(1);
shape_x.SetSize(orders[0]+1);
shape_y.SetSize(orders[1]+1);
dshape_x.SetSize(orders[0]+1);
dshape_y.SetSize(orders[1]+1);
d2shape_x.SetSize(orders[0]+1);
d2shape_y.SetSize(orders[1]+1);
shape1_x.SetSize(orders[0]+2);
shape1_y.SetSize(orders[1]+2);
dshape1_x.SetSize(orders[0]+2);
dshape1_y.SetSize(orders[1]+2);
d2shape1_x.SetSize(orders[0]+2);
d2shape1_y.SetSize(orders[1]+2);
order = max(orders[0]+1, orders[1]+1);
dof = (orders[0] + 1)*(orders[1] + 2)
+ (orders[1] + 2)*(orders[1] + 1);
u.SetSize(dof);
du.SetSize(dof);
weights.SetSize(dof);
}
void NURBS_HCurl2DFiniteElement::CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const
{
kv[0]->CalcShape(shape_x, ijk[0], ip.x);
kv[1]->CalcShape(shape_y, ijk[1], ip.y);
kv1[0]->CalcShape(shape1_x, ijk[0], ip.x);
kv1[1]->CalcShape(shape1_y, ijk[1], ip.y);
int o = 0;
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t sy1 = shape1_y(j);
for (int i = 0; i <= orders[0]; i++, o++)
{
shape(o,0) = shape_x(i)*sy1;
shape(o,1) = 0.0;
}
}
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy = shape_y(j);
for (int i = 0; i <= orders[0]+1; i++, o++)
{
shape(o,0) = 0.0;
shape(o,1) = shape1_x(i)*sy;
}
}
}
void NURBS_HCurl2DFiniteElement::CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{
CalcVShape(Trans.GetIntPoint(), shape);
const DenseMatrix & JI = Trans.InverseJacobian();
MFEM_ASSERT(JI.Width() == 2 && JI.Height() == 2,
"NURBS_HCurl2DFiniteElement cannot be embedded in "
"3 dimensional spaces");
for (int i=0; i<dof; i++)
{
real_t sx = shape(i, 0);
real_t sy = shape(i, 1);
shape(i, 0) = sx * JI(0, 0) + sy * JI(1, 0);
shape(i, 1) = sx * JI(0, 1) + sy * JI(1, 1);
}
}
void NURBS_HCurl2DFiniteElement::CalcCurlShape(const IntegrationPoint &ip,
DenseMatrix &curl_shape) const
{
kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
kv1[0]->CalcDShape(dshape1_x, ijk[0], ip.x);
kv1[1]->CalcDShape(dshape1_y, ijk[1], ip.y);
int o = 0;
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t dsy1 = dshape1_y(j);
for (int i = 0; i <= orders[0]; i++, o++)
{
curl_shape(o,0) = -shape_x(i)*dsy1;
}
}
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy = shape_y(j);
for (int i = 0; i <= orders[0]+1; i++, o++)
{
curl_shape(o,0) = dshape1_x(i)*sy;
}
}
}
NURBS_HCurl2DFiniteElement::~NURBS_HCurl2DFiniteElement()
{
if (kv1[0]) { delete kv1[0]; }
if (kv1[1]) { delete kv1[1]; }
}
void NURBS_HCurl3DFiniteElement::SetOrder() const
{
orders[0] = kv[0]->GetOrder();
orders[1] = kv[1]->GetOrder();
orders[2] = kv[2]->GetOrder();
if (kv1[0]) { delete kv1[0]; }
if (kv1[1]) { delete kv1[1]; }
if (kv1[2]) { delete kv1[2]; }
kv1[0] = kv[0]->DegreeElevate(1);
kv1[1] = kv[1]->DegreeElevate(1);
kv1[2] = kv[2]->DegreeElevate(1);
shape_x.SetSize(orders[0]+1);
shape_y.SetSize(orders[1]+1);
shape_z.SetSize(orders[2]+1);
dshape_x.SetSize(orders[0]+1);
dshape_y.SetSize(orders[1]+1);
dshape_z.SetSize(orders[2]+1);
d2shape_x.SetSize(orders[0]+1);
d2shape_y.SetSize(orders[1]+1);
d2shape_z.SetSize(orders[2]+1);
shape1_x.SetSize(orders[0]+2);
shape1_y.SetSize(orders[1]+2);
shape1_z.SetSize(orders[2]+2);
dshape1_x.SetSize(orders[0]+2);
dshape1_y.SetSize(orders[1]+2);
dshape1_z.SetSize(orders[2]+2);
d2shape1_x.SetSize(orders[0]+2);
d2shape1_y.SetSize(orders[1]+2);
d2shape1_z.SetSize(orders[2]+2);
order = max(orders[0]+1, max( orders[1]+1, orders[2]+1));
dof = (orders[0] + 1)*(orders[1] + 2)*(orders[2] + 2) +
(orders[0] + 2)*(orders[1] + 1)*(orders[2] + 2) +
(orders[0] + 2)*(orders[1] + 2)*(orders[2] + 1);
u.SetSize(dof);
du.SetSize(dof);
weights.SetSize(dof);
}
void NURBS_HCurl3DFiniteElement::CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const
{
kv[0]->CalcShape(shape_x, ijk[0], ip.x);
kv[1]->CalcShape(shape_y, ijk[1], ip.y);
kv[2]->CalcShape(shape_z, ijk[2], ip.z);
kv1[0]->CalcShape(shape1_x, ijk[0], ip.x);
kv1[1]->CalcShape(shape1_y, ijk[1], ip.y);
kv1[2]->CalcShape(shape1_z, ijk[2], ip.z);
shape = 0.0;
int o = 0;
for (int k = 0; k <= orders[2]+1; k++)
{
const real_t sz1 = shape1_z(k);
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t sy1_sz1 = shape1_y(j)*sz1;
for (int i = 0; i <= orders[0]; i++, o++)
{
shape(o,0) = shape_x(i)*sy1_sz1;
}
}
}
for (int k = 0; k <= orders[2]+1; k++)
{
const real_t sz1 = shape1_z(k);
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy_sz1 = shape_y(j)*sz1;
for (int i = 0; i <= orders[0]+1; i++, o++)
{
shape(o,1) = shape1_x(i)*sy_sz1;
}
}
}
for (int k = 0; k <= orders[2]; k++)
{
const real_t sz = shape_z(k);
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t sy1_sz = shape1_y(j)*sz;
for (int i = 0; i <= orders[0]+1; i++, o++)
{
shape(o,2) = shape1_x(i)*sy1_sz;
}
}
}
}
void NURBS_HCurl3DFiniteElement::CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{
CalcVShape(Trans.GetIntPoint(), shape);
const DenseMatrix & JI = Trans.InverseJacobian();
MFEM_ASSERT(JI.Width() == 3 && JI.Height() == 3,
"NURBS_HCurl3DFiniteElement must be in a"
"3 dimensional spaces");
for (int i=0; i<dof; i++)
{
real_t sx = shape(i, 0);
real_t sy = shape(i, 1);
real_t sz = shape(i, 2);
shape(i, 0) = sx * JI(0, 0) + sy * JI(1, 0) + sz * JI(2, 0);
shape(i, 1) = sx * JI(0, 1) + sy * JI(1, 1) + sz * JI(2, 1);
shape(i, 2) = sx * JI(0, 2) + sy * JI(1, 2) + sz * JI(2, 2);
}
}
void NURBS_HCurl3DFiniteElement::CalcCurlShape(const IntegrationPoint &ip,
DenseMatrix &curl_shape) const
{
kv[0]->CalcShape ( shape_x, ijk[0], ip.x);
kv[1]->CalcShape ( shape_y, ijk[1], ip.y);
kv[2]->CalcShape ( shape_z, ijk[2], ip.z);
kv1[0]->CalcShape(shape1_x, ijk[0], ip.x);
kv1[1]->CalcShape(shape1_y, ijk[1], ip.y);
kv1[2]->CalcShape(shape1_z, ijk[2], ip.z);
kv1[0]->CalcDShape(dshape1_x, ijk[0], ip.x);
kv1[1]->CalcDShape(dshape1_y, ijk[1], ip.y);
kv1[2]->CalcDShape(dshape1_z, ijk[2], ip.z);
int o = 0;
for (int k = 0; k <= orders[2]+1; k++)
{
const real_t sz1 = shape1_z(k), dsz1 = dshape1_z(k);
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t sy1_dsz1 = shape1_y(j)*dsz1,
dsy1_sz1 = dshape1_y(j)*sz1;
for (int i = 0; i <= orders[0]; i++, o++)
{
curl_shape(o,0) = 0.0;
curl_shape(o,1) = shape_x(i)*sy1_dsz1;
curl_shape(o,2) = -shape_x(i)*dsy1_sz1;
}
}
}
for (int k = 0; k <= orders[2]+1; k++)
{
const real_t sz1 = shape1_z(k), dsz1 = dshape1_z(k);
for (int j = 0; j <= orders[1]; j++)
{
const real_t sy_dsz1 = shape_y(j)*dsz1,
sy_sz1 = shape_y(j)*sz1;
for (int i = 0; i <= orders[0]+1; i++, o++)
{
curl_shape(o,0) = -shape1_x(i)*sy_dsz1;
curl_shape(o,1) = 0.0;
curl_shape(o,2) = dshape1_x(i)*sy_sz1;
}
}
}
for (int k = 0; k <= orders[2]; k++)
{
const real_t sz = shape_z(k);
for (int j = 0; j <= orders[1]+1; j++)
{
const real_t sy1_sz = shape1_y(j)*sz,
dsy1_sz = dshape1_y(j)*sz;
for (int i = 0; i <= orders[0]+1; i++, o++)
{
curl_shape(o,0) = shape1_x(i)*dsy1_sz;
curl_shape(o,1) = -dshape1_x(i)*sy1_sz;
curl_shape(o,2) = 0.0;
}
}
}
}
NURBS_HCurl3DFiniteElement::~NURBS_HCurl3DFiniteElement()
{
if (kv1[0]) { delete kv1[0]; }
if (kv1[1]) { delete kv1[1]; }
if (kv1[2]) { delete kv1[2]; }
}
}
+380 -23
View File
@@ -20,7 +20,7 @@ namespace mfem
class KnotVector;
/// An arbitrary order and dimension NURBS element
class NURBSFiniteElement : public ScalarFiniteElement
class NURBSFiniteElement
{
protected:
mutable Array <const KnotVector*> kv;
@@ -30,31 +30,34 @@ protected:
public:
/** @brief Construct NURBSFiniteElement with given
@param D Reference space dimension
@param G Geometry type (of type Geometry::Type)
@param Do Number of degrees of freedom in the FiniteElement
@param O Order/degree of the FiniteElement
@param F FunctionSpace type of the FiniteElement
@param dim Reference space dimension
*/
NURBSFiniteElement(int D, Geometry::Type G, int Do, int O, int F)
: ScalarFiniteElement(D, G, Do, O, F)
NURBSFiniteElement(int dim)
{
ijk = NULL;
patch = elem = -1;
kv.SetSize(dim);
weights.SetSize(dof);
weights = 1.0;
}
/// Resets the patch and element data stored in the element
void Reset () const { patch = elem = -1; }
/// Set which IJK in patch should be evaluated
void SetIJK (const int *IJK) const { ijk = IJK; }
/// Get which patch is currently considered
int GetPatch () const { return patch; }
/// Set which patch should be evaluated
void SetPatch (int p) const { patch = p; }
/// Set which elemenet should be evaluated
int GetElement () const { return elem; }
/// Get which element is currently considered
void SetElement (int e) const { elem = e; }
/// Get the KnotVectors
Array <const KnotVector*> &KnotVectors() const { return kv; }
/// Get the Weights
Vector &Weights () const { return weights; }
/// Update the NURBSFiniteElement according to the currently set knot vectors
/// Update the polynomial order according to the currently set knotvectors
/// Resizes all internal data members to have the correct size
/// related to the polynomial order
virtual void SetOrder () const { }
/// Returns the indices (i,j) in 2D or (i,j,k) in 3D of this element in the
@@ -64,7 +67,8 @@ public:
/// An arbitrary order 1D NURBS element on a segment
class NURBS1DFiniteElement : public NURBSFiniteElement
class NURBS1DFiniteElement : public ScalarFiniteElement,
public NURBSFiniteElement
{
protected:
mutable Vector shape_x;
@@ -72,7 +76,8 @@ protected:
public:
/// Construct the NURBS1DFiniteElement of order @a p
NURBS1DFiniteElement(int p)
: NURBSFiniteElement(1, Geometry::SEGMENT, p + 1, p, FunctionSpace::Qk),
: ScalarFiniteElement(1, Geometry::SEGMENT, p + 1, p, FunctionSpace::Qk),
NURBSFiniteElement(1),
shape_x(p + 1) { }
virtual void SetOrder() const;
@@ -84,7 +89,8 @@ public:
};
/// An arbitrary order 2D NURBS element on a square
class NURBS2DFiniteElement : public NURBSFiniteElement
class NURBS2DFiniteElement : public ScalarFiniteElement,
public NURBSFiniteElement
{
protected:
mutable Vector u, shape_x, shape_y, dshape_x, dshape_y, d2shape_x, d2shape_y;
@@ -93,16 +99,18 @@ protected:
public:
/// Construct the NURBS2DFiniteElement of order @a p
NURBS2DFiniteElement(int p)
: NURBSFiniteElement(2, Geometry::SQUARE, (p + 1)*(p + 1), p,
FunctionSpace::Qk),
: ScalarFiniteElement(2, Geometry::SQUARE, (p + 1)*(p + 1), p,
FunctionSpace::Qk),
NURBSFiniteElement(2),
u(dof), shape_x(p + 1), shape_y(p + 1), dshape_x(p + 1),
dshape_y(p + 1), d2shape_x(p + 1), d2shape_y(p + 1), du(dof,2)
{ orders[0] = orders[1] = p; }
/// Construct the NURBS2DFiniteElement with x-order @a px and y-order @a py
NURBS2DFiniteElement(int px, int py)
: NURBSFiniteElement(2, Geometry::SQUARE, (px + 1)*(py + 1),
std::max(px, py), FunctionSpace::Qk),
: ScalarFiniteElement(2, Geometry::SQUARE, (px + 1)*(py + 1),
std::max(px, py), FunctionSpace::Qk),
NURBSFiniteElement(2),
u(dof), shape_x(px + 1), shape_y(py + 1), dshape_x(px + 1),
dshape_y(py + 1), d2shape_x(px + 1), d2shape_y(py + 1), du(dof,2)
{ orders[0] = px; orders[1] = py; }
@@ -116,7 +124,8 @@ public:
};
/// An arbitrary order 3D NURBS element on a cube
class NURBS3DFiniteElement : public NURBSFiniteElement
class NURBS3DFiniteElement : public ScalarFiniteElement,
public NURBSFiniteElement
{
protected:
mutable Vector u, shape_x, shape_y, shape_z;
@@ -127,8 +136,9 @@ protected:
public:
/// Construct the NURBS3DFiniteElement of order @a p
NURBS3DFiniteElement(int p)
: NURBSFiniteElement(3, Geometry::CUBE, (p + 1)*(p + 1)*(p + 1), p,
FunctionSpace::Qk),
: ScalarFiniteElement(3, Geometry::CUBE, (p + 1)*(p + 1)*(p + 1), p,
FunctionSpace::Qk),
NURBSFiniteElement(3),
u(dof), shape_x(p + 1), shape_y(p + 1), shape_z(p + 1),
dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1),
d2shape_x(p + 1), d2shape_y(p + 1), d2shape_z(p + 1), du(dof,3)
@@ -137,8 +147,9 @@ public:
/// Construct the NURBS3DFiniteElement with x-order @a px and y-order @a py
/// and z-order @a pz
NURBS3DFiniteElement(int px, int py, int pz)
: NURBSFiniteElement(3, Geometry::CUBE, (px + 1)*(py + 1)*(pz + 1),
std::max(std::max(px,py),pz), FunctionSpace::Qk),
: ScalarFiniteElement(3, Geometry::CUBE, (px + 1)*(py + 1)*(pz + 1),
std::max(std::max(px,py),pz), FunctionSpace::Qk),
NURBSFiniteElement(2),
u(dof), shape_x(px + 1), shape_y(py + 1), shape_z(pz + 1),
dshape_x(px + 1), dshape_y(py + 1), dshape_z(pz + 1),
d2shape_x(px + 1), d2shape_y(py + 1), d2shape_z(pz + 1), du(dof,3)
@@ -152,6 +163,352 @@ public:
DenseMatrix &hessian) const;
};
/** An arbitrary order H(div)-conforming 2D NURBS element on a square.
More details in the following papers:
[1] Annalisa Buffa, Carlo De Falco, Giancarlo Sangalli
"Isogeometric analysis: stable elements for the 2D Stokes equation."
International Journal for Numerical Methods in Fluids 65 (1112) 1407-1422
[2] John A Evans, Thomas JR Hughes
"Isogeometric divergence-conforming B-splines for the unsteady NavierStokes equations."
Journal of Computational Physics (241) 141-167
*/
class NURBS_HDiv2DFiniteElement : public VectorFiniteElement,
public NURBSFiniteElement
{
protected:
mutable Vector shape_x, shape_y, dshape_x, dshape_y, d2shape_x, d2shape_y;
mutable Vector shape1_x, shape1_y, dshape1_x, dshape1_y, d2shape1_x, d2shape1_y;
mutable Vector u;
mutable DenseMatrix du;
mutable Array <const KnotVector*> kv1;
public:
/// Construct the NURBS_HDiv2DFiniteElement of order @a p
NURBS_HDiv2DFiniteElement(int p)
: VectorFiniteElement(2, Geometry::SQUARE, 2*(p + 1)*(p + 2), p,
H_DIV,FunctionSpace::Qk),
NURBSFiniteElement(2),
shape_x(p + 1), shape_y(p + 1), dshape_x(p + 1),
dshape_y(p + 1), d2shape_x(p + 1), d2shape_y(p + 1),
shape1_x(p + 2), shape1_y(p + 2), dshape1_x(p + 2),
dshape1_y(p + 2), d2shape1_x(p + 2), d2shape1_y(p + 2),
u(dof), du(dof,2)
{
orders[0] = orders[1] = p;
kv1.SetSize(dim);
kv1[0] = nullptr;
kv1[1] = nullptr;
}
/// Construct the NURBS_HDiv2DFiniteElement with x-order @a px and y-order @a py
NURBS_HDiv2DFiniteElement(int px, int py)
: VectorFiniteElement(2, Geometry::SQUARE,
(px + 2)*(py + 1)+(px + 1)*(py + 2),
std::max(px, py), H_DIV, FunctionSpace::Qk),
NURBSFiniteElement(2),
shape_x(px + 1), shape_y(py + 1), dshape_x(px + 1),
dshape_y(py + 1), d2shape_x(px + 1), d2shape_y(py + 1),
shape1_x(px + 2), shape1_y(py + 2), dshape1_x(px + 2),
dshape1_y(py + 2), d2shape1_x(px + 2), d2shape1_y(py + 2),
u(dof), du(dof,2)
{
orders[0] = px; orders[1] = py;
kv1.SetSize(dim);
kv1[0] = nullptr;
kv1[1] = nullptr;
}
virtual void SetOrder() const;
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
/** @brief Evaluate the values of all shape functions of a *vector* finite
element in physical space at the point described by @a Trans. */
/** Each row of the result DenseMatrix @a shape contains the components of
one vector shape function. The size (#dof x SDim) of @a shape must be set
in advance, where SDim >= #dim is the physical space dimension as
described by @a Trans. */
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const;
/** @brief Evaluate the divergence of all shape functions of a *vector*
finite element in reference space at the given point @a ip. */
/** The size (#dof) of the result Vector @a divshape must be set in advance.
*/
virtual void CalcDivShape(const IntegrationPoint &ip,
Vector &divshape) const;
~NURBS_HDiv2DFiniteElement();
};
/** An arbitrary order H(div)-conforming 3D NURBS element on a cube
More details in the following papers:
[1] Annalisa Buffa, Carlo De Falco, Giancarlo Sangalli
"Isogeometric analysis: stable elements for the 2D Stokes equation."
International Journal for Numerical Methods in Fluids 65 (1112) 1407-1422
[2] John A Evans, Thomas JR Hughes
"Isogeometric divergence-conforming B-splines for the unsteady
NavierStokes equations."
Journal of Computational Physics (241) 141-167 */
class NURBS_HDiv3DFiniteElement : public VectorFiniteElement,
public NURBSFiniteElement
{
protected:
mutable Vector shape_x, shape_y, shape_z;
mutable Vector dshape_x, dshape_y, dshape_z;
mutable Vector d2shape_x, d2shape_y, d2shape_z;
mutable Vector shape1_x, shape1_y, shape1_z;
mutable Vector dshape1_x, dshape1_y, dshape1_z;
mutable Vector d2shape1_x, d2shape1_y, d2shape1_z;
mutable Vector u;
mutable DenseMatrix du;
mutable Array <const KnotVector*> kv1;
public:
/// Construct the NURBS_HDiv3DFiniteElement of order @a p
NURBS_HDiv3DFiniteElement(int p)
: VectorFiniteElement(3, Geometry::CUBE, 3*(p + 1)*(p + 1)*(p + 2),
p, H_DIV,FunctionSpace::Qk),
NURBSFiniteElement(3),
shape_x(p + 1), shape_y(p + 1), shape_z(p + 1),
dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1),
d2shape_x(p + 1), d2shape_y(p + 1), d2shape_z(p + 1),
shape1_x(p + 2), shape1_y(p + 2), shape1_z(p + 2),
dshape1_x(p + 2), dshape1_y(p + 2),dshape1_z(p + 2),
d2shape1_x(p + 2), d2shape1_y(p + 2), d2shape1_z(p + 2),
u(dof), du(dof,3)
{
orders[0] = orders[1] = orders[2] = p;
kv1.SetSize(dim);
kv1[0] = nullptr;
kv1[1] = nullptr;
kv1[2] = nullptr;
}
/// Construct the NURBS_HDiv3DFiniteElement with x-order @a px, y-order @a py and z-order @a pz
NURBS_HDiv3DFiniteElement(int px, int py, int pz)
: VectorFiniteElement(3, Geometry::CUBE,
(px + 2)*(py + 1)*(pz + 1) +
(px + 1)*(py + 2)*(pz + 1) +
(px + 1)*(py + 1)*(pz + 2),
std::max(px, py), H_DIV, FunctionSpace::Qk),
NURBSFiniteElement(3),
shape_x(px + 1), shape_y(py + 1), shape_z(pz + 1),
dshape_x(px + 1), dshape_y(py + 1), dshape_z(pz + 1),
d2shape_x(px + 1), d2shape_y(py + 1), d2shape_z(pz + 1),
shape1_x(px + 2), shape1_y(py + 2), shape1_z(pz + 2),
dshape1_x(px + 2), dshape1_y(py + 2),dshape1_z(pz + 2),
d2shape1_x(px + 2), d2shape1_y(py + 2), d2shape1_z(pz + 2),
u(dof), du(dof,3)
{
orders[0] = px; orders[1] = py; orders[2] = pz;
kv1.SetSize(dim);
kv1[0] = nullptr;
kv1[1] = nullptr;
kv1[2] = nullptr;
}
virtual void SetOrder() const;
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
/** @brief Evaluate the values of all shape functions of a *vector* finite
element in physical space at the point described by @a Trans. */
/** Each row of the result DenseMatrix @a shape contains the components of
one vector shape function. The size (#dof x SDim) of @a shape must be set
in advance, where SDim >= #dim is the physical space dimension as
described by @a Trans. */
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const;
/** @brief Evaluate the divergence of all shape functions of a *vector*
finite element in reference space at the given point @a ip. */
/** The size (#dof) of the result Vector @a divshape must be set in advance.
*/
virtual void CalcDivShape(const IntegrationPoint &ip,
Vector &divshape) const;
~NURBS_HDiv3DFiniteElement();
};
/** An arbitrary order H(curl)-conforming 2D NURBS element on a square
More details in the following paper:
[1] Annalisa Buffa, Giancarlo Sangalli, Rafael Vázquez
"Isogeometric analysis in electromagnetics: B-splines approximation."
Computer Methods in Applied Mechanics and Engineering (199) 1143-1152 */
class NURBS_HCurl2DFiniteElement : public VectorFiniteElement,
public NURBSFiniteElement
{
protected:
mutable Vector shape_x, shape_y, dshape_x, dshape_y, d2shape_x, d2shape_y;
mutable Vector shape1_x, shape1_y, dshape1_x, dshape1_y, d2shape1_x, d2shape1_y;
mutable Vector u;
mutable DenseMatrix du;
mutable Array <const KnotVector*> kv1;
public:
/// Construct the NURBS_HCurl2DFiniteElement of order @a p
NURBS_HCurl2DFiniteElement(int p)
: VectorFiniteElement(2, Geometry::SQUARE, 2*(p + 1)*(p + 2), p,
H_CURL,FunctionSpace::Qk),
NURBSFiniteElement(2),
shape_x(p + 1), shape_y(p + 1), dshape_x(p + 1),
dshape_y(p + 1), d2shape_x(p + 1), d2shape_y(p + 1),
shape1_x(p + 2), shape1_y(p + 2), dshape1_x(p + 2),
dshape1_y(p + 2), d2shape1_x(p + 2), d2shape1_y(p + 2),
u(dof), du(dof,2)
{
orders[0] = orders[1] = p;
kv1.SetSize(dim);
kv1[0] = nullptr;
kv1[1] = nullptr;
}
/// Construct the NURBS_HCurl2DFiniteElement with x-order @a px and y-order @a py
NURBS_HCurl2DFiniteElement(int px, int py)
: VectorFiniteElement(2, Geometry::SQUARE,
(px + 1)*(py + 2)+(px + 2)*(py + 1),
std::max(px, py), H_CURL, FunctionSpace::Qk),
NURBSFiniteElement(2),
shape_x(px + 1), shape_y(py + 1), dshape_x(px + 1),
dshape_y(py + 1), d2shape_x(px + 1), d2shape_y(py + 1),
shape1_x(px + 2), shape1_y(py + 2), dshape1_x(px + 2),
dshape1_y(py + 2), d2shape1_x(px + 2), d2shape1_y(py + 2),
u(dof), du(dof,2)
{
orders[0] = px; orders[1] = py;
kv1.SetSize(dim);
kv1[0] = nullptr;
kv1[1] = nullptr;
}
virtual void SetOrder() const;
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
/** @brief Evaluate the values of all shape functions of a *vector* finite
element in physical space at the point described by @a Trans. */
/** Each row of the result DenseMatrix @a shape contains the components of
one vector shape function. The size (#dof x SDim) of @a shape must be set
in advance, where SDim >= #dim is the physical space dimension as
described by @a Trans. */
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const;
/** @brief Evaluate the curl of all shape functions of a *vector* finite
element in reference space at the given point @a ip. */
/** Each row of the result DenseMatrix @a curl_shape contains the components
of the curl of one vector shape function. The size (#dof x CDim) of
@a curl_shape must be set in advance, where CDim = 3 for #dim = 3 and
CDim = 1 for #dim = 2. */
virtual void CalcCurlShape(const IntegrationPoint &ip,
DenseMatrix &curl_shape) const;
~NURBS_HCurl2DFiniteElement();
};
/** An arbitrary order H(curl)-conforming 3D NURBS element on a cube
More details in the following paper:
[1] Annalisa Buffa, Giancarlo Sangalli, Rafael Vázquez
"Isogeometric analysis in electromagnetics: B-splines approximation."
Computer Methods in Applied Mechanics and Engineering (199) 1143-1152 */
class NURBS_HCurl3DFiniteElement : public VectorFiniteElement,
public NURBSFiniteElement
{
protected:
mutable Vector shape_x, shape_y, shape_z;
mutable Vector dshape_x, dshape_y, dshape_z;
mutable Vector d2shape_x, d2shape_y, d2shape_z;
mutable Vector shape1_x, shape1_y, shape1_z;
mutable Vector dshape1_x, dshape1_y, dshape1_z;
mutable Vector d2shape1_x, d2shape1_y, d2shape1_z;
mutable Vector u;
mutable DenseMatrix du;
mutable Array <const KnotVector*> kv1;
public:
/// Construct the NURBS_HCurl3DFiniteElement of order @a p
NURBS_HCurl3DFiniteElement(int p)
: VectorFiniteElement(3, Geometry::CUBE, 3*(p + 1)*(p + 2)*(p + 2), p,
H_CURL,FunctionSpace::Qk),
NURBSFiniteElement(3),
shape_x(p + 1), shape_y(p + 1), shape_z(p + 1),
dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1),
d2shape_x(p + 1), d2shape_y(p + 1), d2shape_z(p + 1),
shape1_x(p + 2), shape1_y(p + 2), shape1_z(p + 2),
dshape1_x(p + 2), dshape1_y(p + 2),dshape1_z(p + 2),
d2shape1_x(p + 2), d2shape1_y(p + 2), d2shape1_z(p + 2),
u(dof), du(dof,3)
{
orders[0] = orders[1] = orders[2] = p;
kv1.SetSize(dim);
kv1[0] = nullptr;
kv1[1] = nullptr;
kv1[2] = nullptr;
}
/// Construct the NURBS_HCurl3DFiniteElement with x-order @a px, y-order @a py and z-order @a pz
NURBS_HCurl3DFiniteElement(int px, int py, int pz)
: VectorFiniteElement(3, Geometry::CUBE,
(px + 1)*(py + 2)*(pz + 2) +
(px + 2)*(py + 1)*(pz + 2) +
(px + 2)*(py + 2)*(pz + 1),
std::max(std::max(px, py), pz), H_CURL, FunctionSpace::Qk),
NURBSFiniteElement(3),
shape_x(px + 1), shape_y(py + 1), shape_z(pz + 1),
dshape_x(px + 1), dshape_y(py + 1), dshape_z(pz + 1),
d2shape_x(px + 1), d2shape_y(py + 1), d2shape_z(pz + 1),
shape1_x(px + 2), shape1_y(py + 2), shape1_z(pz + 2),
dshape1_x(px + 2), dshape1_y(py + 2),dshape1_z(pz + 2),
d2shape1_x(px + 2), d2shape1_y(py + 2), d2shape1_z(pz + 2),
u(dof), du(dof,3)
{
orders[0] = px; orders[1] = py; orders[2] = pz;
kv1.SetSize(dim);
kv1[0] = nullptr;
kv1[1] = nullptr;
kv1[2] = nullptr;
}
virtual void SetOrder() const;
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
/** @brief Evaluate the values of all shape functions of a *vector* finite
element in physical space at the point described by @a Trans. */
/** Each row of the result DenseMatrix @a shape contains the components of
one vector shape function. The size (#dof x SDim) of @a shape must be set
in advance, where SDim >= #dim is the physical space dimension as
described by @a Trans. */
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const;
/** @brief Evaluate the curl of all shape functions of a *vector* finite
element in reference space at the given point @a ip. */
/** Each row of the result DenseMatrix @a curl_shape contains the components
of the curl of one vector shape function. The size (#dof x CDim) of
@a curl_shape must be set in advance, where CDim = 3 for #dim = 3 and
CDim = 1 for #dim = 2. */
virtual void CalcCurlShape(const IntegrationPoint &ip,
DenseMatrix &curl_shape) const;
~NURBS_HCurl3DFiniteElement();
};
} // namespace mfem
#endif
-264
View File
@@ -2266,268 +2266,4 @@ void RT_R2D_QuadrilateralElement::CalcDivShape(const IntegrationPoint &ip,
}
}
const double RT_PentatopeElement::nk[20] =
{ 0,0,0,-1, 0,0,-1,0, 0,-1,0,0, -1,0,0,0, 1,1,1,1};
// { .5,.5,.5, -.5,0,0, 0,-.5,0, 0,0,-.5}; // n_F |F|
const double RT_PentatopeElement::c = 1./5.;
RT_PentatopeElement::RT_PentatopeElement(const int p)
: VectorFiniteElement(4, Geometry::PENTATOPE, (p + 1)*(p + 2)*(p + 3)*(p + 5)/6,
p + 1, H_DIV, FunctionSpace::Pk),
dof2nk(dof)
{
const double *iop = (p > 0) ? poly1d.OpenPoints(p - 1) : NULL;
const double *bop = poly1d.OpenPoints(p);
#ifndef MFEM_THREAD_SAFE
shape_x.SetSize(p + 1);
shape_y.SetSize(p + 1);
shape_z.SetSize(p + 1);
shape_t.SetSize(p + 1);
shape_l.SetSize(p + 1);
dshape_x.SetSize(p + 1);
dshape_y.SetSize(p + 1);
dshape_z.SetSize(p + 1);
dshape_t.SetSize(p + 1);
dshape_l.SetSize(p + 1);
u.SetSize(dof, dim);
divu.SetSize(dof);
#else
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_t(p + 1),
shape_l(p + 1);
#endif
int o = 0;
// faces (see Mesh::GenerateFaces in mesh/mesh.cpp,
// the constructor of H1_PentatopeElement)
for (int k = 0; k <= p; k++)
for (int j = 0; j + k <= p; j++)
for (int i = 0; i + j + k <= p; i++) // (0,1,2,3)
{
double w = bop[i] + bop[j] + bop[k] + bop[p-i-j-k];
Nodes.IntPoint(o).Set4(bop[i]/w, bop[j]/w, bop[k]/w, 0.);
dof2nk[o++] = 0;
}
for (int k = 0; k <= p; k++)
for (int j = 0; j + k <= p; j++)
for (int i = 0; i + j + k <= p; i++) // (0,2,1,4)
{
double w = bop[i] + bop[j] + bop[k] + bop[p-i-j-k];
Nodes.IntPoint(o).Set4(bop[j]/w, bop[i]/w, 0., bop[k]/w);
dof2nk[o++] = 1;
}
for (int k = 0; k <= p; k++)
for (int j = 0; j + k <= p; j++)
for (int i = 0; i + j + k <= p; i++) // (0,1,3,4)
{
double w = bop[i] + bop[j] + bop[k] + bop[p-i-j-k];
Nodes.IntPoint(o).Set4(bop[i]/w, 0., bop[j]/w, bop[k]/w);
dof2nk[o++] = 2;
}
for (int k = 0; k <= p; k++)
for (int j = 0; j + k <= p; j++)
for (int i = 0; i + j + k <= p; i++) // (0,3,2,4)
{
double w = bop[i] + bop[j] + bop[k] + bop[p-i-j-k];
Nodes.IntPoint(o).Set4(0., bop[j]/w, bop[i]/w, bop[k]/w);
dof2nk[o++] = 3;
}
for (int k = 0; k <= p; k++)
for (int j = 0; j + k <= p; j++)
for (int i = 0; i + j + k <= p; i++) // (1,2,3,4)
{
double w = bop[i] + bop[j] + bop[k] + bop[p-i-j-k];
Nodes.IntPoint(o).Set4(bop[p-i-j-k]/w, bop[i]/w, bop[j]/w, bop[k]/w);
dof2nk[o++] = 4;
}
// interior
for (int l = 0; l < p; l++)
for (int k = 0; k + l < p; k++)
for (int j = 0; j + k + l < p; j++)
for (int i = 0; i + j + k + l < p; i++)
{
double w = iop[i] + iop[j] + iop[k] + iop[l] + iop[p-1-i-j-k-l];
Nodes.IntPoint(o).Set4(iop[i]/w, iop[j]/w, iop[k]/w, iop[l]/w);
dof2nk[o++] = 1;
Nodes.IntPoint(o).Set4(iop[i]/w, iop[j]/w, iop[k]/w, iop[l]/w);
dof2nk[o++] = 2;
Nodes.IntPoint(o).Set4(iop[i]/w, iop[j]/w, iop[k]/w, iop[l]/w);
dof2nk[o++] = 3;
Nodes.IntPoint(o).Set4(iop[i]/w, iop[j]/w, iop[k]/w, iop[l]/w);
dof2nk[o++] = 4;
}
DenseMatrix T(dof);
for (int m = 0; m < dof; m++)
{
const IntegrationPoint &ip = Nodes.IntPoint(m);
poly1d.CalcBasis(p, ip.x, shape_x);
poly1d.CalcBasis(p, ip.y, shape_y);
poly1d.CalcBasis(p, ip.z, shape_z);
poly1d.CalcBasis(p, ip.t, shape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l);
const double *nm = nk + 4*dof2nk[m];
o = 0;
for (int l = 0; l<= p; l++)
for (int k = 0; k + l <= p; k++)
for (int j = 0; j + k + l <= p; j++)
for (int i = 0; i + j + k + l <= p; i++)
{
double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_t(l)*shape_l(p-i-j-k-l);
T(o++, m) = s * nm[0];
T(o++, m) = s * nm[1];
T(o++, m) = s * nm[2];
T(o++, m) = s * nm[3];
}
for (int k = 0; k <= p; k++)
for (int j = 0; j + k <= p; j++)
for (int i = 0; i + j + k <= p; i++)
{
double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_t(p-i-j-k);
T(o++, m) = s*((ip.x - c)*nm[0] + (ip.y - c)*nm[1] +
(ip.z - c)*nm[2] + (ip.t - c)*nm[3]);
}
}
Ti.Factor(T);
// mfem::out << "RT_TetrahedronElement(" << p << ") : "; Ti.TestInversion();
}
void RT_PentatopeElement::CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const
{
const int p = order - 1;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_t(p + 1),
shape_l(p + 1);
DenseMatrix u(Dof, Dim);
#endif
poly1d.CalcBasis(p, ip.x, shape_x);
poly1d.CalcBasis(p, ip.y, shape_y);
poly1d.CalcBasis(p, ip.z, shape_z);
poly1d.CalcBasis(p, ip.t, shape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l);
int o = 0;
for (int l = 0; l <= p; l++)
for (int k = 0; k + l <= p; k++)
for (int j = 0; j + k + l <= p; j++)
for (int i = 0; i + j + k + l <= p; i++)
{
double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_t(l)*shape_l(p-i-j-k-l);
u(o,0) = s; u(o,1) = 0; u(o,2) = 0; u(o,3) = 0; o++;
u(o,0) = 0; u(o,1) = s; u(o,2) = 0; u(o,3) = 0; o++;
u(o,0) = 0; u(o,1) = 0; u(o,2) = s; u(o,3) = 0; o++;
u(o,0) = 0; u(o,1) = 0; u(o,2) = 0; u(o,3) = s; o++;
}
for (int k = 0; k <= p; k++)
for (int j = 0; j + k <= p; j++)
for (int i = 0; i + j + k <= p; i++)
{
double s = shape_x(i)*shape_y(j)*shape_z(k)*shape_t(p-i-j-k);
u(o,0) = (ip.x - c)*s; u(o,1) = (ip.y - c)*s; u(o,2) = (ip.z - c)*s;
u(o,3) = (ip.t - c)*s;
o++;
}
Ti.Mult(u, shape);
}
void RT_PentatopeElement::CalcDivShape(const IntegrationPoint &ip,
Vector &divshape) const
{
const int p = order - 1;
#ifdef MFEM_THREAD_SAFE
Vector shape_x(p + 1), shape_y(p + 1), shape_z(p + 1), shape_l(p + 1);
Vector dshape_x(p + 1), dshape_y(p + 1), dshape_z(p + 1), dshape_l(p + 1);
Vector divu(Dof);
#endif
poly1d.CalcBasis(p, ip.x, shape_x, dshape_x);
poly1d.CalcBasis(p, ip.y, shape_y, dshape_y);
poly1d.CalcBasis(p, ip.z, shape_z, dshape_z);
poly1d.CalcBasis(p, ip.t, shape_t, dshape_t);
poly1d.CalcBasis(p, 1. - ip.x - ip.y - ip.z - ip.t, shape_l, dshape_l);
int o = 0;
for (int m = 0; m <= p; m++)
for (int k = 0; k + m <= p; k++)
for (int j = 0; j + k + m <= p; j++)
for (int i = 0; i + j + k + m <= p; i++)
{
int l = p - i - j - k - m;
divu(o++) = (dshape_x(i)*shape_l(l) -
shape_x(i)*dshape_l(l))*shape_y(j)*shape_z(k)*shape_t(m);
divu(o++) = (dshape_y(j)*shape_l(l) -
shape_y(j)*dshape_l(l))*shape_x(i)*shape_z(k)*shape_t(m);
divu(o++) = (dshape_z(k)*shape_l(l) -
shape_z(k)*dshape_l(l))*shape_x(i)*shape_y(j)*shape_t(m);
divu(o++) = (dshape_t(m)*shape_l(l) -
shape_t(m)*dshape_l(l))*shape_x(i)*shape_y(j)*shape_z(k);
}
for (int l = 0; l <= p; l++)
for (int j = 0; j + l<= p; j++)
for (int i = 0; i + j + l <= p; i++)
{
int k = p - i - j - l;
divu(o++) =
(shape_x(i) + (ip.x - c)*dshape_x(i))*shape_y(j)*shape_z(l)*shape_t(k) +
(shape_y(j) + (ip.y - c)*dshape_y(j))*shape_x(i)*shape_z(l)*shape_t(k) +
(shape_z(l) + (ip.z - c)*dshape_z(l))*shape_x(i)*shape_y(j)*shape_t(k) +
(shape_t(k) + (ip.t - c)*dshape_t(k))*shape_x(i)*shape_y(j)*shape_z(l);
}
Ti.Mult(divu, divshape);
}
void RT_PentatopeElement::ProjectDivSkew(const FiniteElement& fe,
ElementTransformation& Trans, DenseMatrix& DivSkew) const
{
int dof = fe.GetDof();
mfem_warning("RT_PentatopeElement::ProjectDivSkew(...) Implementation not tested!"); // TODO
#ifdef MFEM_THREAD_SAFE
DenseMatrix Jinv(dim, dim);
#endif
DivSkew.SetSize(dof,dof);
DivSkew = 0.0;
double n[4];
Vector ni(n, 4);
Vector vecF(4);
DenseMatrix DivSkewshape(dof,4);
DenseMatrix DivSkew_dFt(dof,4);
for (int k = 0; k < dof; k++)
{
Trans.SetIntPoint(&Nodes.IntPoint(k));
const DenseMatrix &J = Trans.Jacobian();
CalcAdjugateTranspose(J, Jinv);
fe.CalcDivSkewShape(Nodes.IntPoint(k), DivSkewshape);
MultABt(DivSkewshape, J, DivSkew_dFt);
DivSkew_dFt *= (1.0 / Trans.Weight());
Jinv.Mult(nk + dof2nk[k] * dim,n);
for (int j=0; j<dof; j++)
{
vecF(0) = DivSkew_dFt(j,0);
vecF(1) = DivSkew_dFt(j,1);
vecF(2) = DivSkew_dFt(j,2);
vecF(3) = DivSkew_dFt(j,3);
DivSkew(k, j) = vecF * ni;
}
}
}
}
-47
View File
@@ -524,53 +524,6 @@ public:
Vector &divshape) const;
};
class RT_PentatopeElement : public VectorFiniteElement
{
static const double nk[20], c;
#ifndef MFEM_THREAD_SAFE
mutable Vector shape_x, shape_y, shape_z, shape_t, shape_l;
mutable Vector dshape_x, dshape_y, dshape_z, dshape_t, dshape_l;
mutable DenseMatrix u;
mutable Vector divu;
#endif
Array<int> dof2nk;
DenseMatrixInverse Ti;
public:
RT_PentatopeElement(const int p);
virtual void CalcVShape(const IntegrationPoint &ip,
DenseMatrix &shape) const;
virtual void CalcVShape(ElementTransformation &Trans,
DenseMatrix &shape) const
{ CalcVShape_RT(Trans, shape); }
virtual void CalcDivShape(const IntegrationPoint &ip,
Vector &divshape) const;
virtual void GetLocalInterpolation(ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_RT(*this, nk, dof2nk, Trans, I); }
virtual void GetLocalRestriction(ElementTransformation &Trans,
DenseMatrix &R) const
{ LocalRestriction_RT(nk, dof2nk, Trans, R); }
virtual void GetTransferMatrix(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &I) const
{ LocalInterpolation_RT(CheckVectorFE(fe), nk, dof2nk, Trans, I); }
using FiniteElement::Project;
virtual void Project(VectorCoefficient &vc,
ElementTransformation &Trans, Vector &dofs) const
{ Project_RT(nk, dof2nk, vc, Trans, dofs); }
virtual void ProjectMatrixCoefficient(
MatrixCoefficient &mc, ElementTransformation &T, Vector &dofs) const
{ ProjectMatrixCoefficient_RT(nk, dof2nk, mc, T, dofs); }
virtual void Project(const FiniteElement &fe, ElementTransformation &Trans,
DenseMatrix &I) const
{ Project_RT(nk, dof2nk, fe, Trans, I); }
virtual void ProjectDivSkew(const FiniteElement &fe,
ElementTransformation &Trans,
DenseMatrix &DivSkew) const;
};
} // namespace mfem
+216 -345
View File
@@ -111,29 +111,12 @@ int FiniteElementCollection::HasFaceDofs(Geometry::Type geom, int p) const
case Geometry::PYRAMID:
return max(GetNumDof(Geometry::TRIANGLE, p),
GetNumDof(Geometry::SQUARE, p));
case Geometry::PENTATOPE:
return GetNumDof(Geometry::TETRAHEDRON, p);
case Geometry::TESSERACT:
return GetNumDof(Geometry::CUBE, p);
default:
MFEM_ABORT("unknown geometry type");
}
return 0;
}
int FiniteElementCollection::HasPlanarDofs(Geometry::Type GeomType, int p) const
{
switch (GeomType)
{
case Geometry::PENTATOPE: return GetNumDof(Geometry::TRIANGLE, p);
case Geometry::TESSERACT: return GetNumDof(Geometry::SQUARE, p);
default:
mfem_error ("FiniteElementCollection::HasPlanarDofs:"
" unknown geometry type.");
}
return 0;
}
FiniteElementCollection *FiniteElementCollection::GetTraceCollection() const
{
MFEM_ABORT("this method is not implemented in this derived class!");
@@ -361,6 +344,32 @@ FiniteElementCollection *FiniteElementCollection::New(const char *name)
{
fec = new Local_FECollection(name + 6);
}
else if (!strncmp(name, "NURBS_HDiv", 10))
{
if (name[10] != '\0')
{
// "NURBS" + "number" --> fixed order nurbs collection
fec = new NURBS_HDivFECollection(atoi(name + 10));
}
else
{
// "NURBS" --> variable order nurbs collection
fec = new NURBS_HDivFECollection();
}
}
else if (!strncmp(name, "NURBS_HCurl", 11))
{
if (name[11] != '\0')
{
// "NURBS" + "number" --> fixed order nurbs collection
fec = new NURBS_HCurlFECollection(atoi(name + 11));
}
else
{
// "NURBS" --> variable order nurbs collection
fec = new NURBS_HCurlFECollection();
}
}
else if (!strncmp(name, "NURBS", 5))
{
if (name[5] != '\0')
@@ -670,8 +679,6 @@ LinearFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
case Geometry::CUBE: return &ParallelepipedFE;
case Geometry::PRISM: return &WedgeFE;
case Geometry::PYRAMID: return &PyramidFE;
case Geometry::PENTATOPE: return &PentatopeFE;
case Geometry::TESSERACT: return &TesseractFE;
default:
if (error_mode == RETURN_NULL) { return nullptr; }
mfem_error ("LinearFECollection: unknown geometry type.");
@@ -691,8 +698,6 @@ int LinearFECollection::DofForGeometry(Geometry::Type GeomType) const
case Geometry::CUBE: return 0;
case Geometry::PRISM: return 0;
case Geometry::PYRAMID: return 0;
case Geometry::PENTATOPE: return 0;
case Geometry::TESSERACT: return 0;
default:
mfem_error ("LinearFECollection: unknown geometry type.");
}
@@ -718,7 +723,6 @@ QuadraticFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
case Geometry::TETRAHEDRON: return &TetrahedronFE;
case Geometry::CUBE: return &ParallelepipedFE;
case Geometry::PRISM: return &WedgeFE;
case Geometry::PENTATOPE: return &PentatopeFE;
default:
if (error_mode == RETURN_NULL) { return nullptr; }
mfem_error ("QuadraticFECollection: unknown geometry type.");
@@ -737,7 +741,6 @@ int QuadraticFECollection::DofForGeometry(Geometry::Type GeomType) const
case Geometry::TETRAHEDRON: return 0;
case Geometry::CUBE: return 1;
case Geometry::PRISM: return 0;
case Geometry::PENTATOPE: return 0;
default:
mfem_error ("QuadraticFECollection: unknown geometry type.");
}
@@ -1564,135 +1567,6 @@ const int *ND1_3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
return ind_neg;
}
const FiniteElement *
ND1_4DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::PENTATOPE: return &NedPentatopFE;
default:
mfem_error ("ND1_4DFECollection: unknown geometry type.");
}
return &NedPentatopFE; // Make some compilers happy
}
int ND1_4DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::POINT: return 0;
case Geometry::SEGMENT: return 1;
case Geometry::TRIANGLE: return 0;
case Geometry::SQUARE: return 0;
case Geometry::TETRAHEDRON: return 0;
case Geometry::CUBE: return 0;
case Geometry::PENTATOPE: return 0;
default:
mfem_error ("ND1_4DFECollection: unknown geometry type.");
}
return 0; // Make some compilers happy
}
const int * ND1_4DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or)
const
{
static int ind_pos[] = { 0 };
static int ind_neg[] = { -1 };
if (Or > 0)
{
return ind_pos;
}
return ind_neg;
}
const FiniteElement *
ND2_4DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::PENTATOPE: return &NedPentatopFE;
default:
mfem_error ("ND2_4DFECollection: unknown geometry type.");
}
return &NedPentatopFE; // Make some compilers happy
}
int ND2_4DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::POINT: return 0;
case Geometry::SEGMENT: return 2;
case Geometry::TRIANGLE: return 0;
case Geometry::SQUARE: return 0;
case Geometry::TETRAHEDRON: return 0;
case Geometry::CUBE: return 0;
case Geometry::PENTATOPE: return 0;
default:
mfem_error ("ND2_4DFECollection: unknown geometry type.");
}
return 0; // Make some compilers happy
}
const int * ND2_4DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or)
const
{
static int ind_pos[] = { 0, 1 };
static int ind_neg[] = { -2, -1};
if (Or > 0)
{
return ind_pos;
}
return ind_neg;
}
const FiniteElement *
DivSkew1_4DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::PENTATOPE: return &DivSkew0PentatopFE;
default:
mfem_error ("DivSkew1_4DFECollection: unknown geometry type 1.");
}
return &DivSkew0PentatopFE; // Make some compilers happy
}
int DivSkew1_4DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::POINT: return 0;
case Geometry::SEGMENT: return 0;
case Geometry::TRIANGLE: return 1;
case Geometry::SQUARE: return 0;
case Geometry::TETRAHEDRON: return 0;
case Geometry::CUBE: return 0;
case Geometry::PENTATOPE: return 0;
default:
mfem_error ("DivSkew1_4DFECollection: unknown geometry type 2.");
}
return 0; // Make some compilers happy
}
const int * DivSkew1_4DFECollection::DofOrderForOrientation(
Geometry::Type GeomType, int Or)
const
{
static int ind_pos[] = { 0 };
static int ind_neg[] = { -1 };
if (Or %2 == 0)
{
return ind_pos;
}
return ind_neg;
}
const FiniteElement *
RT0_3DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
@@ -1798,57 +1672,13 @@ const int *RT1_3DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
}
}
const FiniteElement *
RT0_4DFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::TETRAHEDRON: return &TetrahedronFE;
case Geometry::PENTATOPE: return &PentatopeFE;
default:
mfem_error ("RT0_4DFECollection: unknown geometry type.");
}
return &PentatopeFE; // Make some compilers happy
}
int RT0_4DFECollection::DofForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::POINT: return 0;
case Geometry::SEGMENT: return 0;
case Geometry::TRIANGLE: return 0;
case Geometry::SQUARE: return 0;
case Geometry::TETRAHEDRON: return 1;
case Geometry::CUBE: return 0;
case Geometry::PENTATOPE: return 0;
default:
mfem_error ("RT0_4DFECollection: unknown geometry type.");
}
return 0; // Make some compilers happy
}
const int * RT0_4DFECollection::DofOrderForOrientation(Geometry::Type GeomType,
int Or)
const
{
static int ind_pos[] = { 0 };
static int ind_neg[] = { -1 };
if (GeomType == Geometry::TETRAHEDRON)
{
if (Or % 2 == 0) { return ind_pos; }
return ind_neg;
}
return NULL;
}
H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
: FiniteElementCollection(p)
, dim(dim)
{
MFEM_VERIFY(p >= 1, "H1_FECollection requires order >= 1.");
MFEM_VERIFY(dim >= 0 && dim <= 4, "H1_FECollection requires 0 <= dim <= 4.");
MFEM_VERIFY(dim >= 0 && dim <= 3, "H1_FECollection requires 0 <= dim <= 3.");
const int pm1 = p - 1, pm2 = pm1 - 1, pm3 = pm2 - 1, pm4 = pm3 - 1;
@@ -2149,20 +1979,6 @@ H1_FECollection::H1_FECollection(const int p, const int dim, const int btype)
}
}
}
if (dim >= 4)
{
H1_dof[Geometry::PENTATOPE] = (TriDof*pm3*pm4)/12;
H1_dof[Geometry::TESSERACT] = QuadDof*pm1*pm1;
if (b_type == BasisType::Positive)
{
mfem_error("H1_FECollection: BasisType::Positive not implemented");
}
else
{
H1_Elements[Geometry::PENTATOPE] = new H1_PentatopeElement(p, pt_type);
}
}
}
}
}
@@ -2540,38 +2356,6 @@ L2_FECollection::L2_FECollection(const int p, const int dim, const int btype,
OtherDofOrd[j] = j; // for Or == 0
}
}
else if (dim == 4)
{
if (b_type == BasisType::Positive)
{
mfem::err <<
"L2_FECollection::L2_FECollection : BasisType::Positive not implemented" <<
endl;
mfem_error();
}
else
{
L2_Elements[Geometry::PENTATOPE] =
new L2_PentatopeElement(p, btype);
// 2025 November: check this
L2_Elements[Geometry::TESSERACT] = new L2_HexahedronElement(p, btype);
}
L2_Elements[Geometry::PENTATOPE]->SetMapType(map_type);
L2_Elements[Geometry::TESSERACT]->SetMapType(map_type);
// All trace element use the default Gauss-Legendre nodal points
Tr_Elements[Geometry::TETRAHEDRON] = new L2_TetrahedronElement(p);
Tr_Elements[Geometry::CUBE] = new L2_HexahedronElement(p);
const int PentDof = L2_Elements[Geometry::PENTATOPE]->GetDof();
const int TessDof = L2_Elements[Geometry::TESSERACT]->GetDof();
const int MaxDof = std::max(PentDof, TessDof);
OtherDofOrd = new int[MaxDof];
for (int j = 0; j < MaxDof; j++)
{
OtherDofOrd[j] = j; // for Or == 0
}
}
else
{
mfem::err << "L2_FECollection::L2_FECollection : dim = "
@@ -2610,9 +2394,6 @@ const int *L2_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
case Geometry::TETRAHEDRON:
return TetDofOrd[Or%24];
case Geometry::PENTATOPE:
return TetDofOrd[Or%120];
default:
return (Or == 0) ? OtherDofOrd : NULL;
}
@@ -2697,13 +2478,6 @@ RT_FECollection::RT_FECollection(const int order, const int dim,
RT_Elements[Geometry::PYRAMID] = new RT0PyrFiniteElement(false);
RT_dof[Geometry::PYRAMID] = 0;
}
else if (dim == 4)
{
RT_Elements[Geometry::PENTATOPE] = new RT_PentatopeElement(p);
RT_dof[Geometry::PENTATOPE] = p*pp1*(p + 2)*(p + 3)/6;
//TODO: tesseracts
}
else
{
MFEM_ABORT("invalid dim = " << dim);
@@ -2736,7 +2510,7 @@ void RT_FECollection::InitFaces(const int p, const int dim_,
MFEM_VERIFY(Quadrature1D::CheckOpen(op_type) != Quadrature1D::Invalid,
"invalid open point type");
const int pp1 = p + 1, pp2 = p + 2, pp3 = p + 3;
const int pp1 = p + 1, pp2 = p + 2;
for (int g = 0; g < Geometry::NumGeom; g++)
{
@@ -2756,10 +2530,6 @@ void RT_FECollection::InitFaces(const int p, const int dim_,
{
QuadDofOrd[i] = NULL;
}
for (int i = 0; i < 24; i++)
{
TetDofOrd[i] = NULL;
}
if (dim_ == 2)
{
@@ -2848,89 +2618,6 @@ void RT_FECollection::InitFaces(const int p, const int dim_,
}
}
}
else if (dim == 4)
{
L2_TetrahedronElement *l2_tet = new L2_TetrahedronElement(p, ob_type);
l2_tet->SetMapType(map_type);
RT_Elements[Geometry::TETRAHEDRON] = l2_tet;
RT_dof[Geometry::TETRAHEDRON] = pp1*pp2*pp3/6;
int TetDof = RT_dof[Geometry::TETRAHEDRON];
int TriDof2 = pp2*pp1/2;
TetDofOrd[0] = new int[24*TetDof];
for (int i = 1; i < 24; i++)
{
TetDofOrd[i] = TetDofOrd[i-1] + TetDof;
}
// see Mesh::GetTriOrientation in mesh/mesh.cpp,
// the constructor of H1_FECollection
for (int k=0; k<=p; k++)
{
for (int j=0; j+k<=p; j++)
{
for (int i=0; i+j+k<=p; i++)
{
int o = TetDof + TriDof2 - ((pp3-k)*(pp2-k)*(pp1-k))/6 - (pp2-j)*
(pp1-j)/2 - k*j + i;
int l = p-k-j-i;
TetDofOrd[0][o] = o;
TetDofOrd[1][o] = -1 - (TetDof + TriDof2 - ((pp3-k)*(pp2-k)*(pp1-k))/6 -
(pp2-j)*(pp1-j)/2 - k*j + l);
TetDofOrd[2][o] = TetDof + TriDof2 - ((pp3-k)*(pp2-k)*(pp1-k))/6 -
(pp2-i)*(pp1-i)/2 - k*i + l;
TetDofOrd[3][o] = -1 - (TetDof + TriDof2 - ((pp3-k)*(pp2-k)*(pp1-k))/6 -
(pp2-l)*(pp1-l)/2 - k*l + i);
TetDofOrd[4][o] = TetDof + TriDof2 - ((pp3-k)*(pp2-k)*(pp1-k))/6 -
(pp2-l)*(pp1-l)/2 - k*l + j;
TetDofOrd[5][o] = -1 - (TetDof + TriDof2 - ((pp3-k)*(pp2-k)*(pp1-k))/6 -
(pp2-i)*(pp1-i)/2 - k*i + j);
TetDofOrd[6][o] = TetDof + TriDof2 - ((pp3-j)*(pp2-j)*(pp1-j))/6 -
(pp2-i)*(pp1-i)/2 - j*i + k;
TetDofOrd[7][o] = -1 - (TetDof + TriDof2 - ((pp3-j)*(pp2-j)*(pp1-j))/6 -
(pp2-l)*(pp1-l)/2 - j*l + k);
TetDofOrd[8][o] = TetDof + TriDof2 - ((pp3-i)*(pp2-i)*(pp1-i))/6 -
(pp2-l)*(pp1-l)/2 - i*l + k;
TetDofOrd[9][o] = -1 - (TetDof + TriDof2 - ((pp3-l)*(pp2-l)*(pp1-l))/6 -
(pp2-i)*(pp1-i)/2 - l*i + k);
TetDofOrd[10][o] = TetDof + TriDof2 - ((pp3-l)*(pp2-l)*(pp1-l))/6 -
(pp2-j)*(pp1-j)/2 - l*j + k;
TetDofOrd[11][o] = -1 - (TetDof + TriDof2 - ((pp3-i)*(pp2-i)*(pp1-i))/6 -
(pp2-j)*(pp1-j)/2 - i*j + k);
TetDofOrd[12][o] = TetDof + TriDof2 - ((pp3-i)*(pp2-i)*(pp1-i))/6 -
(pp2-k)*(pp1-k)/2 - i*k + j;
TetDofOrd[13][o] = -1 - (TetDof + TriDof2 - ((pp3-l)*(pp2-l)*(pp1-l))/6 -
(pp2-k)*(pp1-k)/2 - l*k + j);
TetDofOrd[14][o] = TetDof + TriDof2 - ((pp3-l)*(pp2-l)*(pp1-l))/6 -
(pp2-k)*(pp1-k)/2 - l*k + i;
TetDofOrd[15][o] = -1 - (TetDof + TriDof2 - ((pp3-i)*(pp2-i)*(pp1-i))/6 -
(pp2-k)*(pp1-k)/2 - i*k + l);
TetDofOrd[16][o] = TetDof + TriDof2 - ((pp3-j)*(pp2-j)*(pp1-j))/6 -
(pp2-k)*(pp1-k)/2 - j*k + l;
TetDofOrd[17][o] = -1 - (TetDof + TriDof2 - ((pp3-j)*(pp2-j)*(pp1-j))/6 -
(pp2-k)*(pp1-k)/2 - j*k + i);
TetDofOrd[18][o] = TetDof + TriDof2 - ((pp3-j)*(pp2-j)*(pp1-j))/6 -
(pp2-l)*(pp1-l)/2 - j*l + i;
TetDofOrd[19][o] = -1 - (TetDof + TriDof2 - ((pp3-j)*(pp2-j)*(pp1-j))/6 -
(pp2-i)*(pp1-i)/2 - j*i + l);
TetDofOrd[20][o] = TetDof + TriDof2 - ((pp3-i)*(pp2-i)*(pp1-i))/6 -
(pp2-j)*(pp1-j)/2 - i*j + l;
TetDofOrd[21][o] = -1 - (TetDof + TriDof2 - ((pp3-l)*(pp2-l)*(pp1-l))/6 -
(pp2-j)*(pp1-j)/2 - l*j + i);
TetDofOrd[22][o] = TetDof + TriDof2 - ((pp3-l)*(pp2-l)*(pp1-l))/6 -
(pp2-i)*(pp1-i)/2 - l*i + j;
TetDofOrd[23][o] = -1 - (TetDof + TriDof2 - ((pp3-i)*(pp2-i)*(pp1-i))/6 -
(pp2-l)*(pp1-l)/2 - i*l + j);
if (!signs)
{
for (int m = 0; m < 24; m+=2)
{
TetDofOrd[m][o] = -1 - TetDofOrd[m][o];
}
}
}
}
}
}
}
const FiniteElement *
@@ -2964,10 +2651,6 @@ const int *RT_FECollection::DofOrderForOrientation(Geometry::Type GeomType,
{
return QuadDofOrd[Or%8];
}
else if (GeomType == Geometry::TETRAHEDRON)
{
return TetDofOrd[Or%24];
}
return NULL;
}
@@ -3876,4 +3559,192 @@ FiniteElementCollection *NURBSFECollection::GetTraceCollection() const
return NULL;
}
NURBS_HDivFECollection::NURBS_HDivFECollection(int Order, const int dim)
: NURBSFECollection((Order == VariableOrder) ? 1 : Order)
{
const int order = (Order == VariableOrder) ? 1 : Order;
SegmentFE = new NURBS1DFiniteElement(order);
QuadrilateralFE = new NURBS2DFiniteElement(order);
QuadrilateralVFE = new NURBS_HDiv2DFiniteElement(order);
ParallelepipedVFE = new NURBS_HDiv3DFiniteElement(order);
if (dim != -1) { SetDim(dim); }
SetOrder(Order);
}
void NURBS_HDivFECollection::SetDim(int dim)
{
if (dim == 2)
{
sFE = SegmentFE;
qFE = QuadrilateralVFE;
hFE = nullptr;
}
else if (dim == 3)
{
sFE = nullptr;
qFE = QuadrilateralFE;
hFE = ParallelepipedVFE;
}
else
{
mfem::err<<"Dimension = "<<dim<<endl;
mfem_error ("NURBS_HDivFECollection: wrong dimension!");
}
}
NURBS_HDivFECollection::~NURBS_HDivFECollection()
{
delete SegmentFE;
delete QuadrilateralFE;
delete QuadrilateralVFE;
delete ParallelepipedVFE;
}
const FiniteElement *
NURBS_HDivFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::SEGMENT: return sFE;
case Geometry::SQUARE: return qFE;
case Geometry::CUBE: return hFE;
default:
if (error_mode == RETURN_NULL) { return nullptr; }
mfem_error ("NURBS_HDivFECollection: unknown geometry type.");
}
return QuadrilateralFE; // Make some compilers happy
}
void NURBS_HDivFECollection::SetOrder(int Order) const
{
mOrder = Order;
if (Order != VariableOrder)
{
snprintf(name, 16, "NURBS_HDiv%i", Order);
}
else
{
snprintf(name, 16, "NURBS_HDiv");
}
}
int NURBS_HDivFECollection::DofForGeometry(Geometry::Type GeomType) const
{
mfem_error("NURBS_HDivFECollection::DofForGeometry");
return 0; // Make some compilers happy
}
const int *NURBS_HDivFECollection::DofOrderForOrientation(
Geometry::Type GeomType,
int Or) const
{
mfem_error("NURBS_HDivFECollection::DofOrderForOrientation");
return NULL;
}
FiniteElementCollection *NURBS_HDivFECollection::GetTraceCollection() const
{
MFEM_ABORT("NURBS finite elements can not be statically condensed!");
return NULL;
}
NURBS_HCurlFECollection::NURBS_HCurlFECollection(int Order, const int dim)
: NURBSFECollection((Order == VariableOrder) ? 1 : Order)
{
const int order = (Order == VariableOrder) ? 1 : Order;
SegmentFE = new NURBS1DFiniteElement(order+1);
QuadrilateralFE = new NURBS2DFiniteElement(order+1);
QuadrilateralVFE = new NURBS_HCurl2DFiniteElement(order);
ParallelepipedVFE = new NURBS_HCurl3DFiniteElement(order);
if (dim != -1) { SetDim(dim); }
SetOrder(Order);
}
void NURBS_HCurlFECollection::SetDim(int dim)
{
if (dim == 2)
{
sFE = SegmentFE;
qFE = QuadrilateralVFE;
hFE = nullptr;
}
else if (dim == 3)
{
sFE = nullptr;
qFE = QuadrilateralFE;
hFE = ParallelepipedVFE;
}
else
{
mfem::err<<"Dimension = "<<dim<<endl;
mfem_error ("NURBS_HCurlFECollection: wrong dimension!");
}
}
NURBS_HCurlFECollection::~NURBS_HCurlFECollection()
{
delete SegmentFE;
delete QuadrilateralFE;
delete QuadrilateralVFE;
delete ParallelepipedVFE;
}
const FiniteElement *
NURBS_HCurlFECollection::FiniteElementForGeometry(Geometry::Type GeomType) const
{
switch (GeomType)
{
case Geometry::SEGMENT: return sFE;
case Geometry::SQUARE: return qFE;
case Geometry::CUBE: return hFE;
default:
if (error_mode == RETURN_NULL) { return nullptr; }
mfem_error ("NURBS_HCurlFECollection: unknown geometry type.");
}
return QuadrilateralFE; // Make some compilers happy
}
void NURBS_HCurlFECollection::SetOrder(int Order) const
{
mOrder = Order;
if (Order != VariableOrder)
{
snprintf(name, 16, "NURBS_HCurl%i", Order);
}
else
{
snprintf(name, 16, "NURBS_HCurl");
}
}
int NURBS_HCurlFECollection::DofForGeometry(Geometry::Type GeomType) const
{
mfem_error("NURBS_HCurlFECollection::DofForGeometry");
return 0; // Make some compilers happy
}
const int *NURBS_HCurlFECollection::DofOrderForOrientation(
Geometry::Type GeomType,
int Or) const
{
mfem_error("NURBS_HCurlFECollection::DofOrderForOrientation");
return NULL;
}
FiniteElementCollection *NURBS_HCurlFECollection::GetTraceCollection() const
{
MFEM_ABORT("NURBS finite elements can not be statically condensed!");
return NULL;
}
}
+110 -89
View File
@@ -94,8 +94,6 @@ public:
int HasFaceDofs(Geometry::Type geom, int p) const;
int HasPlanarDofs(Geometry::Type GeomType, int p) const;
virtual const FiniteElement *TraceFiniteElementForGeometry(
Geometry::Type GeomType) const
{
@@ -393,7 +391,7 @@ protected:
char rt_name[32];
FiniteElement *RT_Elements[Geometry::NumGeom];
int RT_dof[Geometry::NumGeom];
int *SegDofOrd[2], *TriDofOrd[6], *QuadDofOrd[8], *TetDofOrd[24];
int *SegDofOrd[2], *TriDofOrd[6], *QuadDofOrd[8];
// Initialize only the face elements
void InitFaces(const int p, const int dim, const int map_type,
@@ -682,8 +680,8 @@ public:
/// Arbitrary order non-uniform rational B-splines (NURBS) finite elements.
class NURBSFECollection : public FiniteElementCollection
{
private:
PointFiniteElement *PointFE;
protected:
PointFiniteElement *PointFE;
NURBS1DFiniteElement *SegmentFE;
NURBS2DFiniteElement *QuadrilateralFE;
NURBS3DFiniteElement *ParallelepipedFE;
@@ -703,13 +701,15 @@ public:
order, or VariableOrder (default). */
explicit NURBSFECollection(int Order = VariableOrder);
void Reset() const
virtual void Reset() const
{
SegmentFE->Reset();
QuadrilateralFE->Reset();
ParallelepipedFE->Reset();
}
virtual void SetDim(const int dim) {};
/** @brief Get the order of the NURBS collection: either a positive number,
when using fixed order, or VariableOrder. */
/** @note Not to be confused with FiniteElementCollection::GetOrder(). */
@@ -717,7 +717,7 @@ public:
/** @brief Set the order and the name, based on the given @a Order: either a
positive number for fixed order, or VariableOrder. */
void SetOrder(int Order) const;
virtual void SetOrder(int Order) const;
const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const override;
@@ -736,6 +736,109 @@ public:
virtual ~NURBSFECollection();
};
/// Arbitrary order H(div) NURBS finite elements.
class NURBS_HDivFECollection : public NURBSFECollection
{
private:
NURBS1DFiniteElement *SegmentFE;
NURBS2DFiniteElement *QuadrilateralFE;
NURBS_HDiv2DFiniteElement *QuadrilateralVFE;
NURBS_HDiv3DFiniteElement *ParallelepipedVFE;
FiniteElement *sFE;
FiniteElement *qFE;
FiniteElement *hFE;
public:
/** @brief The parameter @a Order must be either a positive number, for fixed
order, or VariableOrder (default). */
explicit NURBS_HDivFECollection(int Order = VariableOrder, const int vdim = -1);
virtual void Reset() const override
{
SegmentFE->Reset();
QuadrilateralFE->Reset();
QuadrilateralVFE->Reset();
ParallelepipedVFE->Reset();
}
virtual void SetDim(const int dim) override;
/** @brief Set the order and the name, based on the given @a Order: either a
positive number for fixed order, or VariableOrder. */
virtual void SetOrder(int Order) const override;
const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const override;
int DofForGeometry(Geometry::Type GeomType) const override;
const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const override;
const char *Name() const override { return name; }
int GetContType() const override { return CONTINUOUS; }
FiniteElementCollection *GetTraceCollection() const override;
virtual ~NURBS_HDivFECollection();
};
/// Arbitrary order H(curl) NURBS finite elements.
class NURBS_HCurlFECollection : public NURBSFECollection
{
private:
NURBS1DFiniteElement *SegmentFE;
NURBS2DFiniteElement *QuadrilateralFE;
NURBS_HCurl2DFiniteElement *QuadrilateralVFE;
NURBS_HCurl3DFiniteElement *ParallelepipedVFE;
FiniteElement *sFE;
FiniteElement *qFE;
FiniteElement *hFE;
public:
/** @brief The parameter @a Order must be either a positive number, for fixed
order, or VariableOrder (default). */
explicit NURBS_HCurlFECollection(int Order = VariableOrder,
const int vdim = -1);
virtual void Reset() const override
{
SegmentFE->Reset();
QuadrilateralFE->Reset();
QuadrilateralVFE->Reset();
ParallelepipedVFE->Reset();
}
virtual void SetDim(const int dim) override;
/** @brief Set the order and the name, based on the given @a Order: either a
positive number for fixed order, or VariableOrder. */
virtual void SetOrder(int Order) const override;
const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const override;
int DofForGeometry(Geometry::Type GeomType) const override;
const int *DofOrderForOrientation(Geometry::Type GeomType,
int Or) const override;
const char *Name() const override { return name; }
int GetContType() const override { return CONTINUOUS; }
FiniteElementCollection *GetTraceCollection() const override;
virtual ~NURBS_HCurlFECollection();
};
/// Piecewise-(bi/tri)linear continuous finite elements.
class LinearFECollection : public FiniteElementCollection
{
@@ -748,8 +851,6 @@ private:
const TriLinear3DFiniteElement ParallelepipedFE;
const LinearWedgeFiniteElement WedgeFE;
const LinearPyramidFiniteElement PyramidFE;
const Linear4DFiniteElement PentatopeFE;
const QuadLinear4DFiniteElement TesseractFE;
public:
LinearFECollection() : FiniteElementCollection(1) {}
@@ -777,7 +878,6 @@ private:
const Quadratic3DFiniteElement TetrahedronFE;
const LagrangeHexFiniteElement ParallelepipedFE;
const H1_WedgeElement WedgeFE;
const Quadratic4DFiniteElement PentatopeFE;
public:
QuadraticFECollection()
@@ -1295,65 +1395,6 @@ public:
int GetContType() const override { return TANGENTIAL; }
};
class ND1_4DFECollection : public FiniteElementCollection
{
private:
const Nedelec1PentFiniteElement NedPentatopFE;
public:
ND1_4DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual const int * DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "ND1_4D"; }
};
class ND2_4DFECollection : public FiniteElementCollection
{
private:
const Nedelec1FullPentFiniteElement NedPentatopFE;
public:
ND2_4DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual const int * DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "ND2_4D"; }
};
class DivSkew1_4DFECollection : public FiniteElementCollection
{
private:
const DivSkew1PentFiniteElement DivSkew0PentatopFE;
public:
DivSkew1_4DFECollection() { }
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual const int * DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "F2K0_4D"; }
};
/** @brief First order Raviart-Thomas finite elements in 3D. This class is kept
only for backward compatibility, consider using RT_FECollection instead. */
class RT0_3DFECollection : public FiniteElementCollection
@@ -1405,26 +1446,6 @@ public:
int GetContType() const override { return NORMAL; }
};
/** First order Raviart-Thomas finite elements in 4D. */
class RT0_4DFECollection : public FiniteElementCollection
{
private:
const P0TetFiniteElement TetrahedronFE;
const RT0PentFiniteElement PentatopeFE;
public:
RT0_4DFECollection() { };
virtual const FiniteElement *
FiniteElementForGeometry(Geometry::Type GeomType) const;
virtual int DofForGeometry(Geometry::Type GeomType) const;
virtual const int * DofOrderForOrientation(Geometry::Type GeomType,
int Or) const;
virtual const char * Name() const { return "RT0_4D"; };
};
/// Discontinuous collection defined locally by a given finite element.
class Local_FECollection : public FiniteElementCollection
{
+276 -394
View File
@@ -58,8 +58,8 @@ DofsToVDofs<Ordering::byVDIM>(int ndofs, int vdim, Array<int> &dofs)
FiniteElementSpace::FiniteElementSpace()
: mesh(NULL), fec(NULL), vdim(0), ordering(Ordering::byNODES),
ndofs(0), nvdofs(0), nedofs(0), nfdofs(0), nbdofs(0), npdofs(0),
bdofs(NULL), pdofs(NULL),
ndofs(0), nvdofs(0), nedofs(0), nfdofs(0), nbdofs(0),
bdofs(NULL),
elem_dof(NULL), elem_fos(NULL), bdr_elem_dof(NULL), bdr_elem_fos(NULL),
face_dof(NULL),
NURBSext(NULL), own_ext(false),
@@ -319,12 +319,6 @@ void FiniteElementSpace::GetFaceVDofs(int i, Array<int> &vdofs) const
DofsToVDofs(vdofs);
}
void FiniteElementSpace::GetPlanarVDofs(int i, Array<int> &vdofs) const
{
GetPlanarDofs(i, vdofs);
DofsToVDofs(vdofs);
}
void FiniteElementSpace::GetEdgeVDofs(int i, Array<int> &vdofs) const
{
GetEdgeDofs(i, vdofs);
@@ -546,13 +540,7 @@ void FiniteElementSpace::GetEssentialVDofs(const Array<int> &bdr_attr_is_ess,
// local DOFs affected by boundary elements on other processors
if (Nonconforming())
{
Array<int> bdr_verts, bdr_edges, bdr_faces, bdr_planars;
// if (mesh->Dimension() > 3)
// {
// mesh->ncmesh->GetBoundaryClosure(bdr_attr_is_ess, bdr_verts, bdr_edges,
// bdr_faces, bdr_planars);
// }
// else
Array<int> bdr_verts, bdr_edges, bdr_faces;
mesh->ncmesh->GetBoundaryClosure(bdr_attr_is_ess, bdr_verts, bdr_edges,
bdr_faces);
for (auto v : bdr_verts)
@@ -594,20 +582,6 @@ void FiniteElementSpace::GetEssentialVDofs(const Array<int> &bdr_attr_is_ess,
}
MarkDofs(dofs, ess_vdofs);
}
for (int i = 0; i < bdr_planars.Size(); i++)
{
if (component < 0)
{
GetPlanarVDofs(bdr_planars[i], dofs);
}
else
{
GetPlanarVDofs(bdr_planars[i], dofs);
for (int d = 0; d < dofs.Size(); d++)
{ dofs[d] = DofToVDof(dofs[d], component); }
}
MarkDofs(dofs, ess_vdofs);
}
}
}
@@ -1015,8 +989,6 @@ void FiniteElementSpace::BuildConformingInterpolation() const
"This method should not be used with a ParFiniteElementSpace!");
#endif
if (mesh->Dimension() == 4) { BuildConformingInterpolation4D(); return; }
if (cP_is_set) { return; }
cP_is_set = true;
@@ -1299,178 +1271,6 @@ void FiniteElementSpace::BuildConformingInterpolation() const
}
}
void FiniteElementSpace::BuildConformingInterpolation4D() const
{
#if 0
#ifdef MFEM_USE_MPI
MFEM_VERIFY(dynamic_cast<const ParFiniteElementSpace*>(this) == NULL,
"This method should not be used with a ParFiniteElementSpace!");
#endif
if (cP_is_set) { return; }
cP_is_set = true;
// For each slave DOF, the dependency matrix will contain a row that
// expresses the slave DOF as a linear combination of its immediate master
// DOFs. Rows of independent DOFs will remain empty.
SparseMatrix deps(ndofs);
// collect local edge/planar/face dependencies
for (int entity = 1; entity <= 3; entity++)
{
const NCMesh::NCList &list = (entity > 2) ? mesh->ncmesh->GetFaceList()
/* */ : ( (entity > 1) ? mesh->ncmesh->GetPlanarList() :
mesh->ncmesh->GetEdgeList() );
if (!list.masters.size()) { continue; }
IsoparametricTransformation T;
if (entity > 2) { T.SetFE(&TetrahedronFE); }
else if (entity > 1) { T.SetFE(&TriangleFE); }
else { T.SetFE(&SegmentFE); }
Geometry::Type geom = (entity > 2) ? Geometry::TETRAHEDRON : ( (
entity > 1) ? Geometry::TRIANGLE : Geometry::SEGMENT );
const FiniteElement* fe = fec->FiniteElementForGeometry(geom);
if (!fe) { continue; }
Array<int> master_dofs, slave_dofs;
DenseMatrix I(fe->GetDof());
// loop through all master edges/faces, constrain their slave edges/faces
for (unsigned mi = 0; mi < list.masters.size(); mi++)
{
const NCMesh::Master &master = list.masters[mi];
GetEntityDofs4D(entity, master.index, master_dofs);
if (!master_dofs.Size()) { continue; }
// mfem::out << "--------------------\n";
// master_dofs.Print(mfem::out,master_dofs.Size());
for (int si = master.slaves_begin; si < master.slaves_end; si++)
{
const NCMesh::Slave &slave = list.slaves[si];
GetEntityDofs4D(entity, slave.index, slave_dofs);
if (!slave_dofs.Size()) { continue; }
slave.OrientedPointMatrix(T.GetPointMat());
T.FinalizeTransformation();
fe->GetLocalInterpolation(T, I);
// mfem::out << "********************\n";
// slave_dofs.Print(mfem::out,slave_dofs.Size());
// mfem::out << "++++++++++++++++++++\n";
// I.PrintMatlab(mfem::out);
// mfem::out << "++++++++++++++++++++\n";
// make each slave DOF dependent on all master DOFs
AddDependencies(deps, master_dofs, slave_dofs, I);
}
}
}
deps.Finalize();
// deps.PrintMatlab(mfem::out);
// DOFs that stayed independent are true DOFs
int n_true_dofs = 0;
for (int i = 0; i < ndofs; i++)
{
if (!deps.RowSize(i)) { n_true_dofs++; }
}
// if all dofs are true dofs leave cP and cR NULL
if (n_true_dofs == ndofs)
{
cP = cR = NULL; // will be treated as identities
return;
}
// create the conforming restriction matrix cR
int *cR_J;
{
int *cR_I = new int[n_true_dofs+1];
double *cR_A = new double[n_true_dofs];
cR_J = new int[n_true_dofs];
for (int i = 0; i < n_true_dofs; i++)
{
cR_I[i] = i;
cR_A[i] = 1.0;
}
cR_I[n_true_dofs] = n_true_dofs;
cR = new SparseMatrix(cR_I, cR_J, cR_A, n_true_dofs, ndofs);
}
// create the conforming prolongation matrix cP
cP = new SparseMatrix(ndofs, n_true_dofs);
Array<bool> finalized(ndofs);
finalized = false;
// put identity in the restriction and prolongation matrices for true DOFs
for (int i = 0, true_dof = 0; i < ndofs; i++)
{
if (!deps.RowSize(i))
{
cR_J[true_dof] = i;
cP->Add(i, true_dof++, 1.0);
finalized[i] = true;
}
}
// Now calculate cP rows of slave DOFs as combinations of cP rows of their
// master DOFs. It is possible that some slave DOFs depend on DOFs that are
// themselves slaves. Here we resolve such indirect constraints by first
// calculating rows of the cP matrix for DOFs whose master DOF cP rows are
// already known (in the first iteration these are the true DOFs). In the
// second iteration, slaves of slaves can be 'finalized' (given a row in the
// cP matrix), in the third iteration slaves of slaves of slaves, etc.
bool finished;
int n_finalized = n_true_dofs;
Array<int> cols;
Vector srow;
do
{
finished = true;
for (int dof = 0; dof < ndofs; dof++)
{
if (!finalized[dof] && DofFinalizable(dof, finalized, deps))
{
const int* dep_col = deps.GetRowColumns(dof);
const double* dep_coef = deps.GetRowEntries(dof);
int n_dep = deps.RowSize(dof);
for (int j = 0; j < n_dep; j++)
{
cP->GetRow(dep_col[j], cols, srow);
srow *= dep_coef[j];
cP->AddRow(dof, cols, srow);
}
finalized[dof] = true;
n_finalized++;
finished = false;
}
}
}
while (!finished);
// if everything is consistent (mesh, face orientations, etc.), we should
// be able to finalize all slave DOFs, otherwise it's a serious error
if (n_finalized != ndofs)
{
MFEM_ABORT("Error creating cP matrix.");
}
cP->Finalize();
if (vdim > 1)
{
MakeVDimMatrix(*cP);
MakeVDimMatrix(*cR);
}
#endif
}
void FiniteElementSpace::MakeVDimMatrix(SparseMatrix &mat) const
{
if (vdim == 1) { return; }
@@ -1725,6 +1525,67 @@ SparseMatrix *FiniteElementSpace::RefinementMatrix_main(
return P;
}
SparseMatrix *FiniteElementSpace::VariableOrderRefinementMatrix(
const int coarse_ndofs, const Table &coarse_elem_dof) const
{
MFEM_VERIFY(mesh->GetLastOperation() == Mesh::REFINE, "");
Array<int> dofs, coarse_dofs, coarse_vdofs;
Vector row;
Mesh::GeometryList elem_geoms(*mesh);
SparseMatrix *P = new SparseMatrix(GetVSize(), coarse_ndofs*vdim);
Array<int> mark(P->Height());
mark = 0;
const CoarseFineTransformations &rtrans = mesh->GetRefinementTransforms();
DenseMatrix lP;
IsoparametricTransformation isotr;
for (int k = 0; k < mesh->GetNE(); k++)
{
const Embedding &emb = rtrans.embeddings[k];
const Geometry::Type geom = mesh->GetElementBaseGeometry(k);
const FiniteElement *fe = GetFE(k);
isotr.SetIdentityTransformation(geom);
const int ldof = fe->GetDof();
lP.SetSize(ldof, ldof);
const DenseTensor &pmats = rtrans.point_matrices[geom];
isotr.SetPointMat(pmats(emb.matrix));
fe->GetLocalInterpolation(isotr, lP);
const int fine_ldof = lP.Height();
elem_dof->GetRow(k, dofs);
coarse_elem_dof.GetRow(emb.parent, coarse_dofs);
for (int vd = 0; vd < vdim; vd++)
{
coarse_dofs.Copy(coarse_vdofs);
DofsToVDofs(vd, coarse_vdofs, coarse_ndofs);
for (int i = 0; i < fine_ldof; i++)
{
const int r = DofToVDof(dofs[i], vd);
int m = (r >= 0) ? r : (-1 - r);
if (!mark[m])
{
lP.GetRow(i, row);
P->SetRow(r, coarse_vdofs, row);
mark[m] = 1;
}
}
}
}
MFEM_VERIFY(mark.Sum() == P->Height(), "Not all rows of P set.");
P->Finalize();
return P;
}
void FiniteElementSpace::GetLocalRefinementMatrices(
Geometry::Type geom, DenseTensor &localP) const
{
@@ -1756,15 +1617,20 @@ SparseMatrix* FiniteElementSpace::RefinementMatrix(int old_ndofs,
"Previous mesh is not coarser.");
Mesh::GeometryList elem_geoms(*mesh);
DenseTensor localP[Geometry::NumGeom];
for (int i = 0; i < elem_geoms.Size(); i++)
if (!IsVariableOrder())
{
GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
DenseTensor localP[Geometry::NumGeom];
for (int i = 0; i < elem_geoms.Size(); i++)
{
GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
}
return RefinementMatrix_main(old_ndofs, *old_elem_dof, old_elem_fos,
localP);
}
else
{
return VariableOrderRefinementMatrix(old_ndofs, *old_elem_dof);
}
return RefinementMatrix_main(old_ndofs, *old_elem_dof, old_elem_fos,
localP);
}
FiniteElementSpace::RefinementOperator::RefinementOperator(
@@ -1782,9 +1648,12 @@ FiniteElementSpace::RefinementOperator::RefinementOperator(
Mesh::GeometryList elem_geoms(*fespace->GetMesh());
for (int i = 0; i < elem_geoms.Size(); i++)
if (!fespace->IsVariableOrder())
{
fespace->GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
for (int i = 0; i < elem_geoms.Size(); i++)
{
fespace->GetLocalRefinementMatrices(elem_geoms[i], localP[elem_geoms[i]]);
}
}
ConstructDoFTransArray();
@@ -1797,10 +1666,13 @@ FiniteElementSpace::RefinementOperator::RefinementOperator(
{
Mesh::GeometryList elem_geoms(*fespace->GetMesh());
for (int i = 0; i < elem_geoms.Size(); i++)
if (!fespace->IsVariableOrder())
{
fespace->GetLocalRefinementMatrices(*coarse_fes, elem_geoms[i],
localP[elem_geoms[i]]);
for (int i = 0; i < elem_geoms.Size(); i++)
{
fespace->GetLocalRefinementMatrices(*coarse_fes, elem_geoms[i],
localP[elem_geoms[i]]);
}
}
// Make a copy of the coarse elem_dof Table.
@@ -1876,11 +1748,25 @@ void FiniteElementSpace::RefinementOperator::Mult(const Vector &x,
Vector subY, subX;
DenseMatrix eP;
IsoparametricTransformation isotr;
for (int k = 0; k < mesh_ref->GetNE(); k++)
{
const Embedding &emb = trans_ref.embeddings[k];
const Geometry::Type geom = mesh_ref->GetElementBaseGeometry(k);
const DenseMatrix &lP = localP[geom](emb.matrix);
if (fespace->IsVariableOrder())
{
const FiniteElement *fe = fespace->GetFE(k);
isotr.SetIdentityTransformation(geom);
const int ldof = fe->GetDof();
eP.SetSize(ldof, ldof);
const DenseTensor &pmats = trans_ref.point_matrices[geom];
isotr.SetPointMat(pmats(emb.matrix));
fe->GetLocalInterpolation(isotr, eP);
}
const DenseMatrix &lP = (fespace->IsVariableOrder()) ? eP : localP[geom](
emb.matrix);
subY.SetSize(lP.Height());
@@ -1945,11 +1831,28 @@ void FiniteElementSpace::RefinementOperator::MultTranspose(const Vector &x,
Vector subY, subX, subYt;
DenseMatrix eP;
IsoparametricTransformation isotr;
const FiniteElement *fe = nullptr;
for (int k = 0; k < mesh_ref->GetNE(); k++)
{
const Embedding &emb = trans_ref.embeddings[k];
const Geometry::Type geom = mesh_ref->GetElementBaseGeometry(k);
const DenseMatrix &lP = localP[geom](emb.matrix);
if (fespace->IsVariableOrder())
{
fe = fespace->GetFE(k);
isotr.SetIdentityTransformation(geom);
const int ldof = fe->GetDof();
eP.SetSize(ldof);
const DenseTensor &pmats = trans_ref.point_matrices[geom];
isotr.SetPointMat(pmats(emb.matrix));
fe->GetLocalInterpolation(isotr, eP);
}
const DenseMatrix &lP = (fespace->IsVariableOrder()) ? eP : localP[geom](
emb.matrix);
DofTransformation *doftrans = fespace->GetElementDofs(k, f_dofs);
old_elem_dof->GetRow(emb.parent, c_dofs);
@@ -2308,9 +2211,12 @@ SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
Mesh::GeometryList elem_geoms(*mesh);
DenseTensor localR[Geometry::NumGeom];
for (int i = 0; i < elem_geoms.Size(); i++)
if (!IsVariableOrder())
{
GetLocalDerefinementMatrices(elem_geoms[i], localR[elem_geoms[i]]);
for (int i = 0; i < elem_geoms.Size(); i++)
{
GetLocalDerefinementMatrices(elem_geoms[i], localR[elem_geoms[i]]);
}
}
SparseMatrix *R = new SparseMatrix(ndofs*vdim, old_ndofs*vdim);
@@ -2325,14 +2231,34 @@ SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
bool is_dg = FEColl()->GetContType() == FiniteElementCollection::DISCONTINUOUS;
int num_marked = 0;
const FiniteElement *fe = nullptr;
DenseMatrix localRVO; //for variable order only
for (int k = 0; k < dtrans.embeddings.Size(); k++)
{
const Embedding &emb = dtrans.embeddings[k];
Geometry::Type geom = mesh->GetElementBaseGeometry(emb.parent);
DenseMatrix &lR = localR[geom](emb.matrix);
if (IsVariableOrder())
{
fe = GetFE(emb.parent);
const DenseTensor &pmats = dtrans.point_matrices[geom];
const int ldof = fe->GetDof();
IsoparametricTransformation isotr;
isotr.SetIdentityTransformation(geom);
localRVO.SetSize(ldof, ldof);
isotr.SetPointMat(pmats(emb.matrix));
// Local restriction is size ldofxldof assuming that the parent and
// child are of same polynomial order.
fe->GetLocalRestriction(isotr, localRVO);
}
DenseMatrix &lR = IsVariableOrder() ? localRVO : localR[geom](emb.matrix);
elem_dof->GetRow(emb.parent, dofs);
old_elem_dof->GetRow(k, old_dofs);
MFEM_VERIFY(old_dofs.Size() == dofs.Size(),
"Parent and child must have same #dofs.");
for (int vd = 0; vd < vdim; vd++)
{
@@ -2358,7 +2284,7 @@ SparseMatrix* FiniteElementSpace::DerefinementMatrix(int old_ndofs,
}
}
if (!is_dg)
if (!is_dg && !IsVariableOrder())
{
MFEM_VERIFY(num_marked == R->Height(),
"internal error: not all rows of R were set.");
@@ -2416,6 +2342,7 @@ void FiniteElementSpace::Constructor(Mesh *mesh_, NURBSExtension *NURBSext_,
const NURBSFECollection *nurbs_fec =
dynamic_cast<const NURBSFECollection *>(fec_);
if (nurbs_fec)
{
MFEM_VERIFY(mesh_->NURBSext, "NURBS FE space requires a NURBS mesh.");
@@ -2504,22 +2431,71 @@ void FiniteElementSpace::UpdateNURBS()
nvdofs = 0;
nedofs = 0;
npdofs = 0;
nfdofs = 0;
nbdofs = 0;
pdofs = NULL;
bdofs = NULL;
delete face_dof;
face_dof = NULL;
face_to_be.DeleteAll();
// Depending on the element type create the appropriate extensions
// for the individual components.
dynamic_cast<const NURBSFECollection *>(fec)->Reset();
ndofs = NURBSext->GetNDof();
elem_dof = NURBSext->GetElementDofTable();
bdr_elem_dof = NURBSext->GetBdrElementDofTable();
if (dynamic_cast<const NURBS_HDivFECollection *>(fec))
{
VNURBSext.SetSize(mesh->Dimension());
for (int d = 0; d < mesh->Dimension(); d++)
{
VNURBSext[d] = NURBSext->GetDivExtension(d);
}
}
if (dynamic_cast<const NURBS_HCurlFECollection *>(fec))
{
VNURBSext.SetSize(mesh->Dimension());
for (int d = 0; d < mesh->Dimension(); d++)
{
VNURBSext[d] = NURBSext->GetCurlExtension(d);
}
}
// If required: concatenate the dof tables of the individual components into
// one dof table for the vector fespace.
if (VNURBSext.Size() == 2)
{
int offset1 = VNURBSext[0]->GetNDof();
ndofs = VNURBSext[0]->GetNDof() + VNURBSext[1]->GetNDof();
// Merge Tables
elem_dof = new Table(*VNURBSext[0]->GetElementDofTable(),
*VNURBSext[1]->GetElementDofTable(),offset1 );
bdr_elem_dof = new Table(*VNURBSext[0]->GetBdrElementDofTable(),
*VNURBSext[1]->GetBdrElementDofTable(),offset1);
}
else if (VNURBSext.Size() == 3)
{
int offset1 = VNURBSext[0]->GetNDof();
int offset2 = offset1 + VNURBSext[1]->GetNDof();
ndofs = offset2 + VNURBSext[2]->GetNDof();
// Merge Tables
elem_dof = new Table(*VNURBSext[0]->GetElementDofTable(),
*VNURBSext[1]->GetElementDofTable(),offset1,
*VNURBSext[2]->GetElementDofTable(),offset2);
bdr_elem_dof = new Table(*VNURBSext[0]->GetBdrElementDofTable(),
*VNURBSext[1]->GetBdrElementDofTable(),offset1,
*VNURBSext[2]->GetBdrElementDofTable(),offset2);
}
else
{
ndofs = NURBSext->GetNDof();
elem_dof = NURBSext->GetElementDofTable();
bdr_elem_dof = NURBSext->GetBdrElementDofTable();
}
mesh_sequence = mesh->GetSequence();
sequence++;
}
@@ -2590,8 +2566,6 @@ void FiniteElementSpace::Construct()
face_dof = NULL;
ndofs = 0;
npdofs = 0;
pdofs = NULL;
nvdofs = nedofs = nfdofs = nbdofs = 0;
bdofs = NULL;
@@ -2664,24 +2638,6 @@ void FiniteElementSpace::Construct()
}
}
if (mesh->Dimension() >= 4 && mesh->GetNE())
{
// Here we assume that all planars in the mesh have the same base
// geometry -- the base geometry of the 0-th face element.
int pdof = fec->DofForGeometry(mesh->GetPlanarBaseGeometry(0));
if (pdof > 0)
{
pdofs = new int[mesh->GetNPlanars()+1];
pdofs[0] = 0;
for (int i = 0; i < mesh->GetNPlanars(); i++)
{
npdofs += pdof;
// npdofs += fec->DofForGeometry(mesh->GetPlanarBaseGeometry(i));
pdofs[i+1] = npdofs;
}
}
}
// assign internal ("bubble") DOFs
if (mesh->GetNE() && dim > 0)
{
@@ -2705,7 +2661,7 @@ void FiniteElementSpace::Construct()
}
}
ndofs = nvdofs + nedofs + npdofs + nfdofs + nbdofs;
ndofs = nvdofs + nedofs + nfdofs + nbdofs;
ConstructDoFTransArray();
@@ -2978,7 +2934,7 @@ void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs,
return;
}
Array<int> V, E, Eo, F, Fo, P, Po; // TODO: LocalArray
Array<int> V, E, Eo, F, Fo; // TODO: LocalArray
int dim = mesh->Dimension();
auto geom = mesh->GetElementGeometry(elem);
@@ -2987,11 +2943,9 @@ void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs,
int nv = fec->GetNumDof(Geometry::POINT, order);
int ne = (dim > 1) ? fec->GetNumDof(Geometry::SEGMENT, order) : 0;
int nb = (dim > 0) ? fec->GetNumDof(geom, order) : 0;
int np = (dim > 3) ? fec->GetNumDof(Geometry::TRIANGLE, order) : 0;
if (nv) { mesh->GetElementVertices(elem, V); }
if (ne) { mesh->GetElementEdges(elem, E, Eo); }
if (np) { mesh->GetElementPlanars(elem, P, Po); }
int nfd = 0;
if (dim > 2 && fec->HasFaceDofs(geom, order))
@@ -3011,7 +2965,7 @@ void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs,
}
dofs.SetSize(0);
dofs.Reserve(nv*V.Size() + ne*E.Size() + np*P.Size() + nfd + nb);
dofs.Reserve(nv*V.Size() + ne*E.Size() + nfd + nb);
if (nv) // vertex DOFs
{
@@ -3038,20 +2992,6 @@ void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs,
}
}
if(np)
{
for (int i = 0; i < P.Size(); i++)
{
int pbase = /* IsVariableOrder() ? FindEdgeDof(E[i], ne) : */P[i]*np;
const int *ind = fec->GetDofOrdering(Geometry::TRIANGLE, order, Po[i]);
for (int j = 0; j < np; j++)
{
dofs.Append(EncodeDof(nvdofs + nedofs + pbase, ind[j]));
}
}
}
if (nfd) // face DOFs
{
for (int i = 0; i < F.Size(); i++)
@@ -3064,7 +3004,7 @@ void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs,
for (int j = 0; j < nf; j++)
{
dofs.Append(EncodeDof(nvdofs + nedofs + npdofs + fbase, ind[j]));
dofs.Append(EncodeDof(nvdofs + nedofs + fbase, ind[j]));
}
}
}
@@ -3072,7 +3012,7 @@ void FiniteElementSpace::GetElementDofs(int elem, Array<int> &dofs,
if (nb) // interior ("bubble") DOFs
{
int bbase = bdofs ? bdofs[elem] : elem*nb;
bbase += nvdofs + nedofs + npdofs + nfdofs;
bbase += nvdofs + nedofs + nfdofs;
for (int j = 0; j < nb; j++)
{
@@ -3110,7 +3050,7 @@ void FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs,
return;
}
Array<int> V, E, Eo, P, Po; // TODO: LocalArray
Array<int> V, E, Eo; // TODO: LocalArray
int F, oF;
int dim = mesh->Dimension();
@@ -3127,13 +3067,9 @@ void FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs,
int nv = fec->GetNumDof(Geometry::POINT, order);
int ne = (dim > 1) ? fec->GetNumDof(Geometry::SEGMENT, order) : 0;
int nf = (dim > 2) ? fec->GetNumDof(geom, order) : 0;
int np = (dim > 3) ? fec->DofForGeometry(Geometry::TRIANGLE) : (0);
if (nv) { mesh->GetBdrElementVertices(bel, V); }
if (ne) { mesh->GetBdrElementEdges(bel, E, Eo); }
if (np) { mesh->GetBdrElementPlanars(bel, P, Po); }
if (nf)
{
mesh->GetBdrElementFace(bel, &F, &oF);
@@ -3150,7 +3086,7 @@ void FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs,
}
dofs.SetSize(0);
dofs.Reserve(nv*V.Size() + ne*E.Size() + np * P.Size() + nf);
dofs.Reserve(nv*V.Size() + ne*E.Size() + nf);
if (nv) // vertex DOFs
{
@@ -3177,20 +3113,6 @@ void FiniteElementSpace::GetBdrElementDofs(int bel, Array<int> &dofs,
}
}
if(np)
{
for (int i = 0; i < P.Size(); i++)
{
int pbase = /* IsVariableOrder() ? FindEdgeDof(E[i], ne) : */P[i]*np;
const int *ind = fec->GetDofOrdering(Geometry::TRIANGLE, order, Po[i]);
for (int j = 0; j < np; j++)
{
dofs.Append(EncodeDof(nvdofs + nedofs + pbase, ind[j]));
}
}
}
if (nf) // face DOFs
{
int fbase = (var_face_dofs.Size() > 0) ? FindFaceDof(F, nf) : F*nf;
@@ -3260,12 +3182,10 @@ int FiniteElementSpace::GetFaceDofs(int face, Array<int> &dofs,
// for 1D, 2D and 3D faces
int nv = fec->GetNumDof(Geometry::POINT, order);
int ne = (dim > 1) ? fec->GetNumDof(Geometry::SEGMENT, order) : 0;
int np = (dim > 3) ? fec->GetNumDof(Geometry::TRIANGLE, order) : 0;
Array<int> V, E, Eo, P, Po;
Array<int> V, E, Eo;
if (nv) { mesh->GetFaceVertices(face, V); }
if (ne) { mesh->GetFaceEdges(face, E, Eo); }
if (np) { mesh->GetFacePlanars(face, P, Po); }
dofs.SetSize(0);
dofs.Reserve(V.Size() * nv + E.Size() * ne + nf);
@@ -3293,92 +3213,14 @@ int FiniteElementSpace::GetFaceDofs(int face, Array<int> &dofs,
}
}
}
if(np)
{
for (int i = 0; i < P.Size(); i++)
{
int pbase = /* IsVariableOrder() ? FindEdgeDof(E[i], ne) : */P[i]*np;
const int *ind = fec->GetDofOrdering(Geometry::TRIANGLE, order, Po[i]);
for (int j = 0; j < np; j++)
{
dofs.Append(EncodeDof(nvdofs + nedofs + pbase, ind[j]));
}
}
}
for (int j = 0; j < nf; j++)
{
dofs.Append(nvdofs + nedofs + npdofs + fbase + j);
dofs.Append(nvdofs + nedofs + fbase + j);
}
return order;
}
void FiniteElementSpace::GetPlanarDofs(int planar, Array<int> &dofs) const
{
MFEM_VERIFY(!orders_changed, msg_orders_changed);
// if (planar_dof)
// {
// planar_dof->GetRow(planar, dofs);
// return;
// }
Array<int> V, E, Eo; // TODO: LocalArray
int dim = mesh->Dimension();
int order = fec->GetOrder();
// if (IsVariableOrder()) // determine order from adjacent element
// {
// int elem, info;
// mesh->GetBdrElementAdjacentElement(bel, elem, info);
// order = elem_order[elem];
// }
int nv = fec->GetNumDof(Geometry::POINT, order);
int ne = (dim > 1) ? fec->GetNumDof(Geometry::SEGMENT, order) : 0;
int np = fec->GetNumDof(Geometry::TRIANGLE, order);
if (nv) { mesh->GetPlanVertices(planar, V); }
if (ne) { mesh->GetPlanarEdges(planar, E, Eo); }
dofs.SetSize(0);
dofs.Reserve(nv*V.Size() + ne*E.Size() + np);
if (nv) // vertex DOFs
{
for (int i = 0; i < V.Size(); i++)
{
for (int j = 0; j < nv; j++)
{
dofs.Append(V[i]*nv + j);
}
}
}
if (ne) // edge DOFs
{
for (int i = 0; i < E.Size(); i++)
{
int ebase = IsVariableOrder() ? FindEdgeDof(E[i], ne) : E[i]*ne;
const int *ind = fec->GetDofOrdering(Geometry::SEGMENT, order, Eo[i]);
for (int j = 0; j < ne; j++)
{
dofs.Append(EncodeDof(nvdofs + ebase, ind[j]));
}
}
}
int pbase = planar*np;
for (int i = 0; i < np; i++)
{
dofs.Append(nvdofs + nedofs + pbase + i);
}
}
int FiniteElementSpace::GetEdgeDofs(int edge, Array<int> &dofs,
int variant) const
{
@@ -3445,7 +3287,7 @@ void FiniteElementSpace::GetElementInteriorDofs(int i, Array<int> &dofs) const
int base = bdofs ? bdofs[i] : i*nb;
dofs.SetSize(nb);
base += nvdofs + nedofs + npdofs + nfdofs;
base += nvdofs + nedofs + nfdofs;
for (int j = 0; j < nb; j++)
{
dofs[j] = base + j;
@@ -3600,11 +3442,6 @@ const FiniteElement *FiniteElementSpace::GetFaceElement(int i) const
return fe;
}
const FiniteElement *FiniteElementSpace::GetPlanarElement(int i) const
{
return fec->FiniteElementForGeometry(mesh->GetPlanarBaseGeometry(i));
}
const FiniteElement *FiniteElementSpace::GetEdgeElement(int i,
int variant) const
{
@@ -3660,11 +3497,21 @@ void FiniteElementSpace::Destroy()
dof_elem_array.DeleteAll();
dof_ldof_array.DeleteAll();
for (int i = 0; i < VNURBSext.Size(); i++)
{
delete VNURBSext[i];
}
if (NURBSext)
{
if (own_ext) { delete NURBSext; }
delete face_dof;
face_to_be.DeleteAll();
if (VNURBSext.Size() > 0 )
{
delete elem_dof;
delete bdr_elem_dof;
}
}
else
{
@@ -3674,10 +3521,10 @@ void FiniteElementSpace::Destroy()
delete bdr_elem_fos;
delete face_dof;
delete [] bdofs;
delete [] pdofs;
}
ceed::RemoveBasisAndRestriction(this);
}
void FiniteElementSpace::DestroyDoFTransArray()
@@ -3696,19 +3543,27 @@ void FiniteElementSpace::GetTransferOperator(
if (T.Type() == Operator::MFEM_SPARSEMAT)
{
Mesh::GeometryList elem_geoms(*mesh);
DenseTensor localP[Geometry::NumGeom];
for (int i = 0; i < elem_geoms.Size(); i++)
if (!IsVariableOrder())
{
GetLocalRefinementMatrices(coarse_fes, elem_geoms[i],
localP[elem_geoms[i]]);
Mesh::GeometryList elem_geoms(*mesh);
DenseTensor localP[Geometry::NumGeom];
for (int i = 0; i < elem_geoms.Size(); i++)
{
GetLocalRefinementMatrices(coarse_fes, elem_geoms[i],
localP[elem_geoms[i]]);
}
T.Reset(RefinementMatrix_main(coarse_fes.GetNDofs(),
coarse_fes.GetElementToDofTable(),
coarse_fes.
GetElementToFaceOrientationTable(),
localP));
}
else
{
T.Reset(VariableOrderRefinementMatrix(coarse_fes.GetNDofs(),
coarse_fes.GetElementToDofTable()));
}
T.Reset(RefinementMatrix_main(coarse_fes.GetNDofs(),
coarse_fes.GetElementToDofTable(),
coarse_fes.
GetElementToFaceOrientationTable(),
localP));
}
else
{
@@ -3759,19 +3614,33 @@ void FiniteElementSpace::GetTrueTransferOperator(
void FiniteElementSpace::UpdateElementOrders()
{
const CoarseFineTransformations &cf_tr = mesh->GetRefinementTransforms();
Array<char> new_order(mesh->GetNE());
switch (mesh->GetLastOperation())
{
case Mesh::REFINE:
{
const CoarseFineTransformations &cf_tr = mesh->GetRefinementTransforms();
for (int i = 0; i < mesh->GetNE(); i++)
{
new_order[i] = elem_order[cf_tr.embeddings[i].parent];
}
break;
}
case Mesh::DEREFINE:
{
const CoarseFineTransformations &cf_tr =
mesh->ncmesh->GetDerefinementTransforms();
Table coarse_to_fine;
cf_tr.MakeCoarseToFineTable(coarse_to_fine);
Array<int> tabrow;
for (int i = 0; i < coarse_to_fine.Size(); i++)
{
coarse_to_fine.GetRow(i, tabrow);
//For now we require that all children are of same polynomial order.
new_order[i] = elem_order[tabrow[0]];
}
break;
}
default:
MFEM_ABORT("not implemented yet");
}
@@ -3866,11 +3735,23 @@ void FiniteElementSpace::Update(bool want_transform)
{
BuildConformingInterpolation();
Th.Reset(DerefinementMatrix(old_ndofs, old_elem_dof, old_elem_fos));
if (cP && cR)
if (IsVariableOrder())
{
Th.SetOperatorOwner(false);
Th.Reset(new TripleProductOperator(cP.get(), cR.get(), Th.Ptr(),
false, false, true));
if (cP && cR_hp)
{
Th.SetOperatorOwner(false);
Th.Reset(new TripleProductOperator(cP.get(), cR_hp.get(), Th.Ptr(),
false, false, true));
}
}
else
{
if (cP && cR)
{
Th.SetOperatorOwner(false);
Th.Reset(new TripleProductOperator(cP.get(), cR.get(), Th.Ptr(),
false, false, true));
}
}
break;
}
@@ -3983,6 +3864,7 @@ FiniteElementCollection *FiniteElementSpace::Load(Mesh *m, std::istream &input)
input >> ord;
NURBSFECollection *nurbs_fec = dynamic_cast<NURBSFECollection*>(r_fec);
if (nurbs_fec) { nurbs_fec->SetDim(m->Dimension()); }
NURBSExtension *nurbs_ext = NULL;
if (fes_format == 90) // original format, v0.9
{
+13 -14
View File
@@ -245,9 +245,9 @@ protected:
to be of the default order (fec->GetOrder()). */
Array<char> elem_order;
int nvdofs, nedofs, nfdofs, nbdofs, npdofs;
int nvdofs, nedofs, nfdofs, nbdofs;
int uni_fdof; ///< # of single face DOFs if all faces uniform; -1 otherwise
int *bdofs, *pdofs; ///< internal DOFs of elements if mixed/var-order; NULL otherwise
int *bdofs; ///< internal DOFs of elements if mixed/var-order; NULL otherwise
/** Variable order spaces only: DOF assignments for edges and faces, see
docs in MakeDofTable. For constant order spaces the tables are empty. */
@@ -268,6 +268,10 @@ protected:
Array<int> dof_elem_array, dof_ldof_array;
NURBSExtension *NURBSext;
/** array of NURBS extension for H(div) and H(curl) vector elements.
For each direction an extension is created from the base NURBSext,
with an increase in order in the appropriate direction. */
Array<NURBSExtension*> VNURBSext;
int own_ext;
mutable Array<int> face_to_be; // NURBS FE space only
@@ -396,7 +400,6 @@ protected:
/// Calculate the cP and cR matrices for a nonconforming mesh.
void BuildConformingInterpolation() const;
void BuildConformingInterpolation4D() const;
static void AddDependencies(SparseMatrix& deps, Array<int>& master_dofs,
Array<int>& slave_dofs, DenseMatrix& I,
@@ -470,6 +473,11 @@ protected:
const Table *coarse_elem_fos,
const DenseTensor localP[]) const;
/* This method returns the Refinement matrix (i.e., the embedding)
from a coarse variable-order fes to a fine fes (after a geometric refinement) */
SparseMatrix *VariableOrderRefinementMatrix(const int coarse_ndofs,
const Table &coarse_elem_dof) const;
void GetLocalRefinementMatrices(Geometry::Type geom,
DenseTensor &localP) const;
void GetLocalDerefinementMatrices(Geometry::Type geom,
@@ -518,6 +526,8 @@ protected:
const Array<int> *perm);
public:
/** @brief Default constructor: the object is invalid until initialized using
the method Load(). */
FiniteElementSpace();
@@ -731,7 +741,6 @@ public:
int GetNVDofs() const { return nvdofs; }
/// Number of all scalar edge-interior dofs
int GetNEDofs() const { return nedofs; }
int GetNPDofs() const { return npdofs; }
/// Number of all scalar face-interior dofs
int GetNFDofs() const { return nfdofs; }
@@ -747,9 +756,6 @@ public:
the edges. */
inline int GetNF() const { return mesh->GetNumFaces(); }
/// Returns number of planars (i.e. co-dimension 2 entities) in the mesh.
inline int GetNP() const { return mesh->GetNPlanars(); }
/// Returns number of boundary elements in the mesh.
inline int GetNBE() const { return mesh->GetNBE(); }
@@ -791,8 +797,6 @@ public:
int GetBdrAttribute(int i) const { return mesh->GetBdrAttribute(i); }
virtual void GetPlanarDofs(int i, Array<int> &dofs) const;
/// @anchor getdof @name Local DoF Access Members
/// These member functions produce arrays of local degree of freedom
/// indices, see @ref ldof. If @b vdim == 1 these indices can be used to
@@ -1094,9 +1098,6 @@ public:
/// not necessarily equal to 1. See GetFaceDofs() for more information.
void GetFaceVDofs(int i, Array<int> &vdofs) const;
/// Returns indexes of degrees of freedom for i'th planar element (4D).
void GetPlanarVDofs(int i, Array<int> &vdofs) const;
/// @brief Returns the indices of the degrees of freedom for the specified
/// edge, including the DOFs for the vertices of the edge.
///
@@ -1188,8 +1189,6 @@ public:
points.*/
const FiniteElement *GetFaceElement(int i) const;
const FiniteElement *GetPlanarElement(int i) const;
/** @brief Returns pointer to the FiniteElement in the FiniteElementCollection
associated with i'th edge in the mesh object. */
const FiniteElement *GetEdgeElement(int i, int variant = 0) const;
+39 -371
View File
@@ -19,11 +19,11 @@ namespace mfem
const char *Geometry::Name[NumGeom] =
{
"Point", "Segment", "Triangle", "Square", "Tetrahedron", "Cube", "Prism",
"Pyramid", "Pentatope", "Tesseract"
"Pyramid"
};
const real_t Geometry::Volume[NumGeom] =
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0, 0.5, 1./3, 1./24., 1.0 };
{ 1.0, 1.0, 0.5, 1.0, 1./6, 1.0, 0.5, 1./3 };
Geometry::Geometry()
{
@@ -165,36 +165,6 @@ Geometry::Geometry()
GeomVert[7]->IntPoint(4).y = 0.0;
GeomVert[7]->IntPoint(4).z = 1.0;
// Vertices for Geometry::PENTATOPE
GeomVert[8] = new IntegrationRule(5);
GeomVert[8]->IntPoint(0).x = 0.0;
GeomVert[8]->IntPoint(0).y = 0.0;
GeomVert[8]->IntPoint(0).z = 0.0;
GeomVert[8]->IntPoint(0).t = 0.0;
GeomVert[8]->IntPoint(1).x = 1.0;
GeomVert[8]->IntPoint(1).y = 0.0;
GeomVert[8]->IntPoint(1).z = 0.0;
GeomVert[8]->IntPoint(1).t = 0.0;
GeomVert[8]->IntPoint(2).x = 0.0;
GeomVert[8]->IntPoint(2).y = 1.0;
GeomVert[8]->IntPoint(2).z = 0.0;
GeomVert[8]->IntPoint(2).t = 0.0;
GeomVert[8]->IntPoint(3).x = 0.0;
GeomVert[8]->IntPoint(3).y = 0.0;
GeomVert[8]->IntPoint(3).z = 1.0;
GeomVert[8]->IntPoint(3).t = 0.0;
GeomVert[8]->IntPoint(4).x = 0.0;
GeomVert[8]->IntPoint(4).y = 0.0;
GeomVert[8]->IntPoint(4).z = 0.0;
GeomVert[8]->IntPoint(4).t = 1.0;
// Vertices for Geometry::TESSERACT
// TODO
GeomCenter[POINT].x = 0.0;
GeomCenter[POINT].y = 0.0;
GeomCenter[POINT].z = 0.0;
@@ -227,14 +197,6 @@ Geometry::Geometry()
GeomCenter[PYRAMID].y = 0.375;
GeomCenter[PYRAMID].z = 0.25;
GeomCenter[PENTATOPE].x = 0.2;
GeomCenter[PENTATOPE].y = 0.2;
GeomCenter[PENTATOPE].z = 0.2;
GeomCenter[PENTATOPE].t = 0.2;
// GeomCenter[TESSERACT]
// TODO
GeomToPerfGeomJac[POINT] = NULL;
GeomToPerfGeomJac[SEGMENT] = new DenseMatrix(1);
GeomToPerfGeomJac[TRIANGLE] = new DenseMatrix(2);
@@ -243,7 +205,6 @@ Geometry::Geometry()
GeomToPerfGeomJac[CUBE] = new DenseMatrix(3);
GeomToPerfGeomJac[PRISM] = new DenseMatrix(3);
GeomToPerfGeomJac[PYRAMID] = new DenseMatrix(3);
GeomToPerfGeomJac[PENTATOPE] = new DenseMatrix(4);
PerfGeomToGeomJac[POINT] = NULL;
PerfGeomToGeomJac[SEGMENT] = NULL;
@@ -253,7 +214,6 @@ Geometry::Geometry()
PerfGeomToGeomJac[CUBE] = NULL;
PerfGeomToGeomJac[PRISM] = new DenseMatrix(3);
PerfGeomToGeomJac[PYRAMID] = new DenseMatrix(3);
PerfGeomToGeomJac[PENTATOPE] = new DenseMatrix(4);
GeomToPerfGeomJac[SEGMENT]->Diag(1.0, 1);
{
@@ -290,16 +250,6 @@ Geometry::Geometry()
*GeomToPerfGeomJac[PYRAMID] = pyr_T.Jacobian();
CalcInverse(pyr_T.Jacobian(), *PerfGeomToGeomJac[PYRAMID]);
}
{
Linear4DFiniteElement PentFE;
IsoparametricTransformation pent_T;
pent_T.SetFE(&PentFE);
GetPerfPointMat (PENTATOPE, pent_T.GetPointMat());
// pent_T.FinalizeTransformation();
pent_T.SetIntPoint(&GeomCenter[PENTATOPE]);
*GeomToPerfGeomJac[PENTATOPE] = pent_T.Jacobian();
CalcInverse(pent_T.Jacobian(), *PerfGeomToGeomJac[PENTATOPE]);
}
}
template <Geometry::Type GEOM>
@@ -352,8 +302,6 @@ const IntegrationRule *Geometry::GetVertices(int GeomType) const
case Geometry::CUBE: return GeomVert[5];
case Geometry::PRISM: return GeomVert[6];
case Geometry::PYRAMID: return GeomVert[7];
case Geometry::PENTATOPE: return GeomVert[8];
case Geometry::TESSERACT: return GeomVert[9];
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
mfem_error("Geometry::GetVertices(...)");
@@ -451,45 +399,6 @@ void Geometry::GetRandomPoint(int GeomType, IntegrationPoint &ip)
ip.x = 1.0 - z;
}
break;
case Geometry::PENTATOPE:
ip.x = real_t(rand()) / real_t(RAND_MAX);
ip.y = real_t(rand()) / real_t(RAND_MAX);
ip.z = real_t(rand()) / real_t(RAND_MAX);
ip.t = real_t(rand()) / real_t(RAND_MAX);
// map to the triangular 4D wedge obtained by extruding the reference
// tetrahedron in t direction
// needs to be updated
// if (ip.x + ip.y > 1.0)
// {
// ip.x = 1.0 - ip.x;
// ip.y = 1.0 - ip.y;
// }
// // split the prism into 3 parts: 1 is the reference tet, and the
// // other two tets (as given below) are mapped to the reference tet
// if (ip.x + ip.z > 1.0)
// {
// // tet with vertices: (0,0,1),(1,0,1),(0,1,1),(1,0,0)
// ip.x = ip.x + ip.z - 1.0;
// // ip.y = ip.y;
// ip.z = 1.0 - ip.z;
// // mapped to: (0,0,0),(1,0,0),(0,1,0),(0,0,1)
// }
// else if (ip.x + ip.y + ip.z > 1.0)
// {
// // tet with vertices: (0,1,1),(0,1,0),(0,0,1),(1,0,0)
// real_t x = ip.x;
// ip.x = 1.0 - x - ip.z;
// ip.y = 1.0 - x - ip.y;
// ip.z = x;
// // mapped to: (0,0,0),(1,0,0),(0,1,0),(0,0,1)
// }
// break;
case Geometry::TESSERACT:
ip.x = real_t(rand()) / real_t(RAND_MAX);
ip.y = real_t(rand()) / real_t(RAND_MAX);
ip.z = real_t(rand()) / real_t(RAND_MAX);
ip.t = real_t(rand()) / real_t(RAND_MAX);
break;
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -556,14 +465,6 @@ bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip)
if (ip.x < 0.0 || ip.y < 0.0 || ip.x+ip.z > 1.0 || ip.y+ip.z > 1.0 ||
ip.z < 0.0 || ip.z > 1.0) { return false; }
break;
case Geometry::PENTATOPE:
if (ip.x < 0.0 || ip.y < 0.0 || ip.z < 0.0 || ip.t < 0 ||
ip.x+ip.y+ip.z+ip.t > 1.0) { return false; }
break;
case Geometry::TESSERACT:
if (ip.x < 0.0 || ip.x > 1.0 || ip.y < 0.0 || ip.y > 1.0 ||
ip.z < 0.0 || ip.z > 1.0 || ip.t < 0.0 || ip.t > 1.0) { return false; }
break;
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -647,29 +548,6 @@ bool Geometry::CheckPoint(int GeomType, const IntegrationPoint &ip, real_t eps)
return false;
}
break;
case Geometry::PENTATOPE:
if ( internal::FuzzyLT(ip.x, 0.0, eps)
|| internal::FuzzyLT(ip.y, 0.0, eps)
|| internal::FuzzyLT(ip.z, 0.0, eps)
|| internal::FuzzyLT(ip.t, 0.0, eps)
|| internal::FuzzyGT(ip.x+ip.y+ip.z+ip.t, 1.0, eps) )
{
return false;
}
break;
case Geometry::TESSERACT:
if ( internal::FuzzyLT(ip.x, 0.0, eps)
|| internal::FuzzyGT(ip.x, 1.0, eps)
|| internal::FuzzyLT(ip.y, 0.0, eps)
|| internal::FuzzyGT(ip.y, 1.0, eps)
|| internal::FuzzyLT(ip.z, 0.0, eps)
|| internal::FuzzyGT(ip.z, 1.0, eps)
|| internal::FuzzyLT(ip.t, 0.0, eps)
|| internal::FuzzyGT(ip.t, 1.0, eps) )
{
return false;
}
break;
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -732,81 +610,6 @@ inline bool ProjectTriangle(real_t &x, real_t &y)
return true;
}
inline bool ProjectTetrahedron(double &x, double &y, double &z)
{
if (z < 0.0)
{
z = 0.0;
internal::ProjectTriangle(x, y);
return false;
}
if (y < 0.0)
{
y = 0.0;
internal::ProjectTriangle(x, z);
return false;
}
if (x < 0.0)
{
x = 0.0;
internal::ProjectTriangle(y, z);
return false;
}
const double l4 = 1.0-x-y-z;
if (l4 < 0.0)
{
const double l4_3 = l4/3;
x += l4_3;
y += l4_3;
internal::ProjectTriangle(x, y);
z = 1.0-x-y;
return false;
}
return true;
}
inline bool ProjectPentatope(double &x, double &y, double &z, double &t)
{
if (t < 0.0)
{
t = 0.0;
internal::ProjectTetrahedron(x, y, z);
return false;
}
if (z < 0.0)
{
z = 0.0;
internal::ProjectTetrahedron(x, y, t);
return false;
}
if (y < 0.0)
{
y = 0.0;
internal::ProjectTetrahedron(x, z, t);
return false;
}
if (x < 0.0)
{
x = 0.0;
internal::ProjectTetrahedron(y, z, t);
return false;
}
const double l5 = 1.0-x-y-z-t;
if (l5 < 0.0)
{
const double l5_4 = l5/4;
// TODO
// In Geometry::ProjectPoint 4d origianlly had const double l5_4 = l5/5
x += l5_4;
y += l5_4;
z += l5_4;
internal::ProjectTetrahedron(x, y, z);
t = 1.0-x-y-z;
return false;
}
return true;
}
}
// static method
@@ -872,22 +675,6 @@ bool Geometry::ProjectPoint(int GeomType, const IntegrationPoint &beg,
};
return internal::IntersectSegment<6,3>(lbeg, lend, end);
}
case Geometry::PENTATOPE:
{
real_t lend[5] = { end.x, end.y, end.z, end.t, fone-end.x-end.y-end.z-end.t };
real_t lbeg[5] = { beg.x, beg.y, beg.z, beg.t, fone-beg.x-beg.y-beg.z-beg.t };
return internal::IntersectSegment<5,4>(lbeg,lend,end);
}
case Geometry::TESSERACT:
{
real_t lend[8] = { end.x, end.y, end.z, end.t,
fone-end.x, fone-end.y, fone-end.z, fone-end.t
};
real_t lbeg[8] = { beg.x, beg.y, beg.z, beg.t,
fone-beg.x, fone-beg.y, fone-beg.z, fone-beg.t
};
return internal::IntersectSegment<8,3>(lbeg, lend, end);
}
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -930,7 +717,35 @@ bool Geometry::ProjectPoint(int GeomType, IntegrationPoint &ip)
case TETRAHEDRON:
{
return internal::ProjectTetrahedron(ip.x, ip.y, ip.z);
if (ip.z < 0.0)
{
ip.z = 0.0;
internal::ProjectTriangle(ip.x, ip.y);
return false;
}
if (ip.y < 0.0)
{
ip.y = 0.0;
internal::ProjectTriangle(ip.x, ip.z);
return false;
}
if (ip.x < 0.0)
{
ip.x = 0.0;
internal::ProjectTriangle(ip.y, ip.z);
return false;
}
const real_t l4 = 1.0-ip.x-ip.y-ip.z;
if (l4 < 0.0)
{
const real_t l4_3 = l4/3;
ip.x += l4_3;
ip.y += l4_3;
internal::ProjectTriangle(ip.x, ip.y);
ip.z = 1.0-ip.x-ip.y;
return false;
}
return true;
}
case CUBE:
@@ -995,29 +810,6 @@ bool Geometry::ProjectPoint(int GeomType, IntegrationPoint &ip)
}
}
case PENTATOPE:
{
return internal::ProjectPentatope(ip.x, ip.y, ip.z, ip.t);
}
case TESSERACT:
{
bool in_x, in_y, in_z, in_t;
if (ip.x < 0.0) { in_x = false; ip.x = 0.0; }
else if (ip.x > 1.0) { in_x = false; ip.x = 1.0; }
else { in_x = true; }
if (ip.y < 0.0) { in_y = false; ip.y = 0.0; }
else if (ip.y > 1.0) { in_y = false; ip.y = 1.0; }
else { in_y = true; }
if (ip.z < 0.0) { in_z = false; ip.z = 0.0; }
else if (ip.z > 1.0) { in_z = false; ip.z = 1.0; }
else { in_z = true; }
if (ip.t < 0.0) { in_t = false; ip.t = 0.0; }
else if (ip.t > 1.0) { in_t = false; ip.t = 1.0; }
else { in_t = true; }
return in_x && in_y && in_z && in_t;
}
case Geometry::POINT:
MFEM_ABORT("Reference element type is not supported!");
case Geometry::INVALID:
@@ -1106,42 +898,6 @@ void Geometry::GetPerfPointMat(int GeomType, DenseMatrix &pm) const
}
break;
case Geometry::PENTATOPE:
{
pm.SetSize(4,5);
pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0; pm(3,0) = 0.0;
pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0; pm(3,1) = 0.0;
pm(0,2) = 0.5; pm(1,2) = 0.86602540378443864676; pm(2,2) = 0.0; pm(3,2) = 0.0;
pm(0,3) = 0.5; pm(1,3) = 0.28867513459481288225;
pm(2,3) = 0.81649658092772603273; pm(3,3) = 0.0;
pm(0,4) = 0.5; pm(1,4) = 0.28867513459481288225;
pm(2,4) = 0.20412414523193150819; pm(3,4) = 0.7905694150420948330;
}
break;
case Geometry::TESSERACT:
{
pm.SetSize (4, 16);
pm(0,0) = 0.0; pm(1,0) = 0.0; pm(2,0) = 0.0; pm(4,0) = 0.0;
pm(0,1) = 1.0; pm(1,1) = 0.0; pm(2,1) = 0.0; pm(4,1) = 0.0;
pm(0,2) = 1.0; pm(1,2) = 1.0; pm(2,2) = 0.0; pm(4,2) = 0.0;
pm(0,3) = 0.0; pm(1,3) = 1.0; pm(2,3) = 0.0; pm(4,3) = 0.0;
pm(0,4) = 0.0; pm(1,4) = 0.0; pm(2,4) = 1.0; pm(4,4) = 0.0;
pm(0,5) = 1.0; pm(1,5) = 0.0; pm(2,5) = 1.0; pm(4,5) = 0.0;
pm(0,6) = 1.0; pm(1,6) = 1.0; pm(2,6) = 1.0; pm(4,6) = 0.0;
pm(0,7) = 0.0; pm(1,7) = 1.0; pm(2,7) = 1.0; pm(4,7) = 0.0;
pm(0,8) = 0.0; pm(1,8) = 0.0; pm(2,8) = 0.0; pm(4,8) = 1.0;
pm(0,9) = 1.0; pm(1,9) = 0.0; pm(2,9) = 0.0; pm(4,9) = 1.0;
pm(0,10) = 1.0; pm(1,10) = 1.0; pm(2,10) = 0.0; pm(4,10) = 1.0;
pm(0,11) = 0.0; pm(1,11) = 1.0; pm(2,11) = 0.0; pm(4,11) = 1.0;
pm(0,12) = 0.0; pm(1,12) = 0.0; pm(2,12) = 1.0; pm(4,12) = 1.0;
pm(0,13) = 1.0; pm(1,13) = 0.0; pm(2,13) = 1.0; pm(4,13) = 1.0;
pm(0,14) = 1.0; pm(1,14) = 1.0; pm(2,14) = 1.0; pm(4,14) = 1.0;
pm(0,15) = 0.0; pm(1,15) = 1.0; pm(2,15) = 1.0; pm(4,15) = 1.0;
}
break;
case Geometry::POINT:
MFEM_ABORT("Reference element type is not supported!");
case Geometry::INVALID:
@@ -1163,13 +919,13 @@ void Geometry::JacToPerfJac(int GeomType, const DenseMatrix &J,
}
}
const int Geometry::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6, 5, 5, 5, 24 };
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3, 3, 3, 4, 4 };
const int Geometry::DimStart[MaxDim+2] =
{ POINT, SEGMENT, TRIANGLE, TETRAHEDRON, PENTATOPE, NUM_GEOMETRIES };
const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8, 6, 5, 5, 16 };
const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12, 9, 8, 10, 32 };
const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6, 5, 5, 5, 24 };
const int Geometry::NumBdrArray[NumGeom] = { 0, 2, 3, 4, 4, 6, 5, 5 };
const int Geometry::Dimension[NumGeom] = { 0, 1, 2, 2, 3, 3, 3, 3 };
const int Geometry::DimStart[MaxDim+2] =
{ POINT, SEGMENT, TRIANGLE, TETRAHEDRON, NUM_GEOMETRIES };
const int Geometry::NumVerts[NumGeom] = { 1, 2, 3, 4, 4, 8, 6, 5 };
const int Geometry::NumEdges[NumGeom] = { 0, 1, 3, 4, 6, 12, 9, 8 };
const int Geometry::NumFaces[NumGeom] = { 0, 0, 1, 1, 4, 6, 5, 5 };
const int Geometry::
Constants<Geometry::POINT>::Orient[1][1] = {{0}};
@@ -1340,63 +1096,6 @@ Constants<Geometry::PYRAMID>::VertToVert::J[8][2] =
{4, 7} // 3,4:7
};
const int Geometry::
Constants<Geometry::PENTATOPE>::Edges[10][2] =
{{0, 1}, {0, 2}, {0, 3}, {0, 4}, {1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {3, 4}};
const int Geometry::
Constants<Geometry::PENTATOPE>::FaceTypes[5] =
{
Geometry::TETRAHEDRON, Geometry::TETRAHEDRON,
Geometry::TETRAHEDRON, Geometry::TETRAHEDRON,
Geometry::TETRAHEDRON
};
const int Geometry::
Constants<Geometry::PENTATOPE>::FaceVert[5][4] =
{
// {0, 1, 2, 3}, {0, 1, 2, 4},
// {0, 1, 3, 4}, {0, 2, 3, 4},
// {1, 2, 3, 4}
{0, 1, 2, 3}, {0, 2, 1, 4}, //<---- sorted such that the normal vectors are outer normal vectors
{0, 1, 3, 4}, {0, 3, 2, 4},
{1, 2, 3, 4}
};
const int Geometry::
Constants<Geometry::PENTATOPE>::PlanarVert[10][3] =
{
{0, 1, 2}, {0, 1, 3}, {0, 1, 4},
{0, 2, 3}, {0, 2, 4}, {0, 3, 4},
{1, 2, 3}, {1, 2, 4}, {1, 3, 4},
{2, 3, 4}
};
//const int Geometry::
//Constants<Geometry::PENTATOPE>::VertToVert::I[4] = {0, 3, 5, 6};
//const int Geometry::
//Constants<Geometry::PENTATOPE>::VertToVert::J[6][2] =
//{{1, 0}, {2, 1}, {3, 2}, {2, 3}, {3, 4}, {3, 5}};
const int Geometry::
Constants<Geometry::TESSERACT>::FaceVert[8][8] =
{
// {8,11,12,15,0,3,4,7}, //x bottom
// {1,2,6,5,9,10,14,13}, //x top
// {0,1,5,4,8,9,13,12}, //y bottom
// {2,3,7,6,10,11,15,14}, //y top
// {8,9,10,11,0,1,2,3}, // z bottom
// {4,5,6,7,12,13,14,15}, //z top
// {0,1,2,3,4,5,6,7}, //t botom
// {12,13,14,15,8,9,10,11} //t top
{8,11,15,12,0,3,7,4}, //x bottom
{1,2,6,5,9,10,14,13}, //x top
{0,1,5,4,8,9,13,12}, //y bottom
{2,3,7,6,10,11,15,14}, //y top
{8,9,10,11,0,1,2,3}, // z bottom
{4,5,6,7,12,13,14,15}, //z top
{0,1,2,3,4,5,6,7}, //t botom
{12,13,14,15,8,9,10,11} //t top
};
GeometryRefiner::~GeometryRefiner()
{
@@ -1957,9 +1656,7 @@ RefinedGeometry *GeometryRefiner::Refine(Geometry::Type Geom, int Times,
RGeom[Geometry::PRISM].Append(RG);
}
break;
case Geometry::PENTATOPE:
case Geometry::TESSERACT:
MFEM_ABORT("Reference element type is not supported!");
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -2071,8 +1768,6 @@ const IntegrationRule *GeometryRefiner::RefineInterior(Geometry::Type Geom,
case Geometry::CUBE:
case Geometry::PYRAMID:
case Geometry::PRISM:
case Geometry::PENTATOPE:
case Geometry::TESSERACT:
MFEM_ABORT("Reference element type is not supported!");
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
@@ -2142,24 +1837,6 @@ int GeometryRefiner::GetRefinementLevelFromPoints(Geometry::Type geom, int Npts)
}
case Geometry::PYRAMID:
MFEM_ABORT("Reference element type is not supported!");
case Geometry::PENTATOPE:
{
for (int n = 0, np = 0; (n < 15) && (np < Npts) ; n++)
{
np = (n+4)*(n+3)*(n+2)*(n+1)/24;
if (np == Npts) { return n; }
}
return -1;
}
case Geometry::TESSERACT:
{
for (int n = 0, np = 0; (n < 15) && (np < Npts) ; n++)
{
np = (n+1)*(n+1)*(n+1)*(n+1);
if (np == Npts) { return n; }
}
return -1;
}
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -2202,15 +1879,6 @@ int GeometryRefiner::GetRefinementLevelFromElems(Geometry::Type geom, int Nels)
}
case Geometry::PYRAMID:
MFEM_ABORT("Reference element type is not supported!");
case Geometry::PENTATOPE:
case Geometry::TESSERACT:
{
for (int n = 0; (n < 15) && (n*n*n*n < Nels+1) ; n++)
{
if (n*n*n*n == Nels) { return n-1; }
}
return -1;
}
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
+2 -52
View File
@@ -28,8 +28,6 @@ namespace mfem
Geometry::CUBE - the unit cube
Geometry::PRISM - w/ vert. (0,0,0),(1,0,0),(0,1,0),(0,0,1),(1,0,1),(0,1,1)
Geometry::PYRAMID - w/ vert. (0,0,0),(1,0,0),(1,1,0),(0,1,0),(0,0,1)
Geometry::PENTATOPE - w/ vert. (0,0,0,0),(1,0,0,0),(0,1,0,0),(0,0,1,0),(0,0,0,1)
Geometry::TESSERACT - the 4d unit cube
*/
class MFEM_EXPORT Geometry
{
@@ -37,12 +35,12 @@ public:
enum Type
{
INVALID = -1,
POINT = 0, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE, PRISM, PYRAMID, PENTATOPE, TESSERACT,
POINT = 0, SEGMENT, TRIANGLE, SQUARE, TETRAHEDRON, CUBE, PRISM, PYRAMID,
NUM_GEOMETRIES
};
static const int NumGeom = NUM_GEOMETRIES;
static const int MaxDim = 4;
static const int MaxDim = 3;
static const int NumBdrArray[NumGeom];
static const char *Name[NumGeom];
static const real_t Volume[NumGeom];
@@ -120,7 +118,6 @@ public:
case 1: return SEGMENT;
case 2: return SQUARE;
case 3: return CUBE;
case 4: return TESSERACT;
default: MFEM_ABORT("Invalid dimension."); return INVALID;
}
}
@@ -308,53 +305,6 @@ template <> struct
};
};
template <> struct
/// @cond Suppress_Doxygen_warnings
MFEM_EXPORT
/// @endcond
Geometry::Constants<Geometry::PENTATOPE>
{
static const int Dimension = 4;
static const int NumVert = 5;
static const int NumEdges = 10;
static const int Edges[NumEdges][2];
static const int NumFaces = 5;
static const int FaceTypes[NumFaces];
static const int MaxFaceVert = 4;
static const int FaceVert[NumFaces][MaxFaceVert];
static const int NumPlanar = 10;
static const int MaxPlanarVert = 3;
static const int PlanarVert[NumPlanar][MaxPlanarVert];
// Lower-triangular part of the local vertex-to-vertex graph.
struct VertToVert
{
static const int I[NumVert];
static const int J[NumEdges][2]; // {end,edge_idx}
};
};
template <> struct
/// @cond Suppress_Doxygen_warnings
MFEM_EXPORT
/// @endcond
Geometry::Constants<Geometry::TESSERACT>
{
static const int Dimension = 4;
static const int NumVert = 16;
static const int NumEdges = 32;
static const int Edges[NumEdges][2];
static const int NumFaces = 8;
static const int FaceTypes[NumFaces];
static const int MaxFaceVert = 8;
static const int FaceVert[NumFaces][MaxFaceVert];
// Lower-triangular part of the local vertex-to-vertex graph.
struct VertToVert
{
static const int I[NumVert];
static const int J[NumEdges][2]; // {end,edge_idx}
};
};
// Defined in fe.cpp to ensure construction after 'mfem::TriangleFE' and
// `mfem::TetrahedronFE`.
extern MFEM_EXPORT Geometry Geometries;
+139 -63
View File
@@ -12,6 +12,8 @@
// Implementation of GridFunction
#include "gridfunc.hpp"
#include "linearform.hpp"
#include "bilinearform.hpp"
#include "quadinterpolator.hpp"
#include "../mesh/nurbs.hpp"
#include "../general/text.hpp"
@@ -2123,15 +2125,8 @@ void GridFunction::AccumulateAndCountBdrValues(
Vector vals;
Mesh *mesh = fes->GetMesh();
NCMesh *ncmesh = mesh->ncmesh;
Array<int> bdr_edges, bdr_vertices, bdr_faces, bdr_planars;
// if (mesh->Dimension() < 4)
// {
ncmesh->GetBoundaryClosure(attr, bdr_vertices, bdr_edges, bdr_faces);
// }
// else
// {
// ncmesh->GetBoundaryClosure(attr, bdr_vertices, bdr_edges, bdr_faces, bdr_planars);
// }
Array<int> bdr_edges, bdr_vertices, bdr_faces;
ncmesh->GetBoundaryClosure(attr, bdr_vertices, bdr_edges, bdr_faces);
auto mark_dofs = [&](ElementTransformation &transf, const FiniteElement &fe)
{
@@ -2195,37 +2190,6 @@ void GridFunction::AccumulateAndCountBdrValues(
const FiniteElement *fe = fes->GetFaceElement(face);
mark_dofs(*transf, *fe);
}
for (int i = 0; i < bdr_planars.Size(); i++)
{
const FiniteElement *fe;
ElementTransformation *transf;
int planar = bdr_planars[i];
fes->GetPlanarVDofs(planar, vdofs);
if (vdofs.Size() == 0) { continue; }
transf = mesh->GetPlanarTransformation(planar);
transf->Attribute = -1; // FIXME: set the boundary attribute
fe = fes->GetPlanarElement(planar);
vals.SetSize(fe->GetDof());
for (int d = 0; d < vdim; d++)
{
if (!coeff[d]) { continue; }
fe->Project(*coeff[d], *transf, vals);
for (int k = 0; k < vals.Size(); k++)
{
int ind = vdofs[d*vals.Size()+k];
if (++values_counter[ind] == 1)
{
(*this)(ind) = vals(k);
}
else
{
(*this)(ind) += vals(k);
}
}
}
}
}
}
@@ -2410,19 +2374,48 @@ void GridFunction::ProjectCoefficient(Coefficient &coeff)
if (delta_c == NULL)
{
Array<int> vdofs;
Vector vals;
for (int i = 0; i < fes->GetNE(); i++)
if (fes->GetNURBSext() == NULL)
{
doftrans = fes->GetElementVDofs(i, vdofs);
vals.SetSize(vdofs.Size());
fes->GetFE(i)->Project(coeff, *fes->GetElementTransformation(i), vals);
if (doftrans)
Array<int> vdofs;
Vector vals;
for (int i = 0; i < fes->GetNE(); i++)
{
doftrans->TransformPrimal(vals);
doftrans = fes->GetElementVDofs(i, vdofs);
vals.SetSize(vdofs.Size());
fes->GetFE(i)->Project(coeff, *fes->GetElementTransformation(i), vals);
if (doftrans)
{
doftrans->TransformPrimal(vals);
}
SetSubVector(vdofs, vals);
}
SetSubVector(vdofs, vals);
}
else
{
// Define and assemble linear form
LinearForm b(fes);
b.AddDomainIntegrator(new DomainLFIntegrator(coeff));
b.Assemble();
// Define and assemble bilinear form
BilinearForm a(fes);
a.AddDomainIntegrator(new MassIntegrator());
a.Assemble();
// Set solver and preconditioner
SparseMatrix A(a.SpMat());
GSSmoother prec(A);
CGSolver cg;
cg.SetOperator(A);
cg.SetPreconditioner(prec);
cg.SetRelTol(1e-12);
cg.SetMaxIter(1000);
cg.SetPrintLevel(0);
// Solve and get solution
*this = 0.0;
cg.Mult(b,*this);
}
}
else
@@ -2463,22 +2456,54 @@ void GridFunction::ProjectCoefficient(
void GridFunction::ProjectCoefficient(VectorCoefficient &vcoeff)
{
int i;
Array<int> vdofs;
Vector vals;
DofTransformation * doftrans = NULL;
for (i = 0; i < fes->GetNE(); i++)
if (fes->GetNURBSext() == NULL)
{
doftrans = fes->GetElementVDofs(i, vdofs);
vals.SetSize(vdofs.Size());
fes->GetFE(i)->Project(vcoeff, *fes->GetElementTransformation(i), vals);
if (doftrans)
int i;
Array<int> vdofs;
Vector vals;
DofTransformation * doftrans = NULL;
for (i = 0; i < fes->GetNE(); i++)
{
doftrans->TransformPrimal(vals);
doftrans = fes->GetElementVDofs(i, vdofs);
vals.SetSize(vdofs.Size());
fes->GetFE(i)->Project(vcoeff, *fes->GetElementTransformation(i), vals);
if (doftrans)
{
doftrans->TransformPrimal(vals);
}
SetSubVector(vdofs, vals);
}
SetSubVector(vdofs, vals);
}
else
{
// Define and assemble linear form
LinearForm b(fes);
b.AddDomainIntegrator(new VectorFEDomainLFIntegrator(vcoeff));
b.Assemble();
// Define and assemble bilinear form
BilinearForm a(fes);
a.AddDomainIntegrator(new VectorFEMassIntegrator());
a.Assemble();
// Set solver and preconditioner
SparseMatrix A(a.SpMat());
GSSmoother prec(A);
CGSolver cg;
cg.SetOperator(A);
cg.SetPreconditioner(prec);
cg.SetRelTol(1e-12);
cg.SetMaxIter(1000);
cg.SetPrintLevel(0);
// Solve and get solution
*this = 0.0;
cg.Mult(b,*this);
}
}
@@ -3026,6 +3051,57 @@ real_t GridFunction::ComputeDivError(
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
real_t GridFunction::ComputeLaplaceError(
Coefficient *exlap, const IntegrationRule *irs[]) const
{
real_t error = 0.0, a;
const FiniteElement *fe;
ElementTransformation *Tr;
Array<int> dofs;
int intorder, fdof;
Vector laplace;
for (int i = 0; i < fes->GetNE(); i++)
{
laplace.SetSize(fdof);
fe = fes->GetFE(i);
Tr = fes->GetElementTransformation(i);
intorder = 2*fe->GetOrder() + 3;
const IntegrationRule *ir;
if (irs)
{
ir = irs[fe->GetGeomType()];
}
else
{
ir = &(IntRules.Get(fe->GetGeomType(), intorder));
}
fes->GetElementDofs(i, dofs);
fdof = fe->GetDof();
laplace.SetSize(fdof);
for (int j = 0; j < ir->GetNPoints(); j++)
{
const IntegrationPoint &ip = ir->IntPoint(j);
Tr->SetIntPoint(&ip);
fe->CalcPhysLaplacian(*Tr, laplace);
a = 0;
for (int k = 0; k < fdof; k++)
if (dofs[k] >= 0)
{
a += (*this)(dofs[k]) * laplace(k);
}
else
{
a -= (*this)(-1-dofs[k]) * laplace(k);
}
a -= exlap->Eval(*Tr, ip);
error += ip.weight * Tr->Weight() * a * a;
}
}
return (error < 0.0) ? -sqrt(-error) : sqrt(error);
}
real_t GridFunction::ComputeDGFaceJumpError(Coefficient *exsol,
Coefficient *ell_coeff,
class JumpScaling jump_scaling,
+8 -2
View File
@@ -387,7 +387,8 @@ public:
/** @brief Project @a coeff Coefficient to @a this GridFunction. The
projection computation depends on the choice of the FiniteElementSpace
#fes. Note that this is usually interpolation at the degrees of freedom
in each element (not L2 projection). */
in each element (not L2 projection). For NURBS spaces these degrees of
freedom are not available and L2 projection is resorted to as fallback. */
virtual void ProjectCoefficient(Coefficient &coeff);
/** @brief Project @a coeff Coefficient to @a this GridFunction, using one
@@ -398,7 +399,8 @@ public:
/** @brief Project @a vcoeff VectorCoefficient to @a this GridFunction. The
projection computation depends on the choice of the FiniteElementSpace
#fes. Note that this is usually interpolation at the degrees of freedom
in each element (not L2 projection).*/
in each element (not L2 projection). For NURBS spaces these degrees of
freedom are not available and L2 projection is resorted to as fallback. */
void ProjectCoefficient(VectorCoefficient &vcoeff);
/** @brief Project @a vcoeff VectorCoefficient to @a this GridFunction, using
@@ -531,6 +533,10 @@ public:
virtual real_t ComputeDivError(Coefficient *exdiv,
const IntegrationRule *irs[] = NULL) const;
/// Returns ||lap u_ex - lap u_h||_L2 for H1 elements
virtual real_t ComputeLaplaceError(Coefficient *exlap,
const IntegrationRule *irs[] = NULL) const;
/// Returns the Face Jumps error for L2 elements. The error can be weighted
/// by a constant nu, by nu/h, or nu*p^2/h, depending on the value of
/// @a jump_scaling.
+1 -194
View File
@@ -151,14 +151,10 @@ void IntegrationRule::GrundmannMollerSimplexRule(int s, int n)
ip.weight = weight;
ip.x = real_t(2*beta[0] + 1)/(d + n - 2*i);
ip.y = real_t(2*beta[1] + 1)/(d + n - 2*i);
if (n >= 3)
if (n == 3)
{
ip.z = real_t(2*beta[2] + 1)/(d + n - 2*i);
}
if (n == 4)
{
ip.t = real_t(2*beta[3] + 1)/(d + n - 2*i);
}
int j = 0;
while (sums[j] == k)
@@ -998,12 +994,6 @@ IntegrationRules::IntegrationRules(int ref, int type)
CubeIntRules.SetSize(32, h_mt);
CubeIntRules = NULL;
PentatopeIntRules.SetSize(32, h_mt);
PentatopeIntRules = NULL;
TesseractIntRules.SetSize(32, h_mt);
TesseractIntRules = NULL;
#if defined(MFEM_THREAD_SAFE) && defined(MFEM_USE_OPENMP)
IntRuleLocks.SetSize(Geometry::NUM_GEOMETRIES, h_mt);
for (int i = 0; i < Geometry::NUM_GEOMETRIES; i++)
@@ -1027,8 +1017,6 @@ const IntegrationRule &IntegrationRules::Get(int GeomType, int Order)
case Geometry::CUBE: ir_array = &CubeIntRules; break;
case Geometry::PRISM: ir_array = &PrismIntRules; break;
case Geometry::PYRAMID: ir_array = &PyramidIntRules; break;
case Geometry::PENTATOPE: ir_array = &PentatopeIntRules; break;
case Geometry::TESSERACT: ir_array = &TesseractIntRules; break;
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -1079,8 +1067,6 @@ void IntegrationRules::Set(int GeomType, int Order, IntegrationRule &IntRule)
case Geometry::CUBE: ir_array = &CubeIntRules; break;
case Geometry::PRISM: ir_array = &PrismIntRules; break;
case Geometry::PYRAMID: ir_array = &PyramidIntRules; break;
case Geometry::PENTATOPE: ir_array = &PentatopeIntRules; break;
case Geometry::TESSERACT: ir_array = &TesseractIntRules; break;
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -1139,8 +1125,6 @@ IntegrationRules::~IntegrationRules()
DeleteIntRuleArray(CubeIntRules);
DeleteIntRuleArray(PrismIntRules);
DeleteIntRuleArray(PyramidIntRules);
DeleteIntRuleArray(PentatopeIntRules);
DeleteIntRuleArray(TesseractIntRules);
}
@@ -1165,10 +1149,6 @@ IntegrationRule *IntegrationRules::GenerateIntegrationRule(int GeomType,
return PrismIntegrationRule(Order);
case Geometry::PYRAMID:
return PyramidIntegrationRule(Order);
case Geometry::PENTATOPE:
return PentatopeIntegrationRule(Order);
case Geometry::TESSERACT:
return TesseractIntegrationRule(Order);
case Geometry::INVALID:
case Geometry::NUM_GEOMETRIES:
MFEM_ABORT("Unknown type of reference element!");
@@ -1882,179 +1862,6 @@ IntegrationRule *IntegrationRules::CubeIntegrationRule(int Order)
return CubeIntRules[Order];
}
IntegrationRule *IntegrationRules::PentatopeIntegrationRule(int Order)
{
IntegrationRule *ir;
#ifdef MFEM_DEBUG_INTRULES
mfem::out << "requesting integration rules for pentatopes ( order = " << Order << " )!" << endl;
#endif
switch (Order)
{
case 0: // 1 point - degree 1
case 1:
PentatopeIntRules[0] = PentatopeIntRules[1] = ir = new IntegrationRule(1);
ir->AddPentMidPoint(0, 1./24.);
ir->SetOrder(1);
return ir;
case 2: // 5 points - degree 2 -- taken from https://doi.org/10.1016/j.camwa.2020.07.004
PentatopeIntRules[2] = ir = new IntegrationRule(5);
ir->AddPentPoints5(0, 0.11835034190722738822731940899757, 1/120.);
ir->SetOrder(2);
return ir;
case 3: // 15 points - degree 3 -- taken from https://doi.org/10.1016/j.camwa.2020.07.004
PentatopeIntRules[3] = ir = new IntegrationRule(15);
ir->AddPentPoints5(0, 0.05666638104005152637432374262971, 0.01971744594977651449108080328187 / 24.);
ir->AddPentPoints10(5, 0.08282378463560803594223358459203, 0.5 - 1.5 * 0.08282378463560803594223358459203, 0.09014127702511173789723386562400 / 24.);
ir->SetOrder(3);
return ir;
case 4: // 35 points - degree 5 -- taken from https://doi.org/10.1016/j.camwa.2020.07.004
case 5:
PentatopeIntRules[4] = PentatopeIntRules[5] = ir = new IntegrationRule(35);
ir->AddPentPoints5(0, 0.08639272923225102540634168235556, 0.05144687284129603743743075483508 / 24.);
ir->AddPentPoints10(5, 0.02401496720062019571417799568280, 0.5 - 1.5 * 0.02401496720062019571417799568280, 0.01075810672318828174753857496171 / 24.);
ir->AddPentPoints20(15, 0.29381800402893687440553094347706, 0.06247517556258090631882140542075, 0.03175922842808185514451579933848 / 24.);
ir->SetOrder(5);
return ir;
case 6: // 70 points - degree 6 -- taken from https://doi.org/10.1016/j.camwa.2020.07.004
PentatopeIntRules[6] = ir = new IntegrationRule(70);
ir->AddPentPoints5(0, 0.154743213149364, 0.027287104452858 / 24.);
ir->AddPentPoints5(5, 0.243583446244066, 0.030022493650412 / 24.);
ir->AddPentPoints10(10, 0.045742589279674, 0.5 - 1.5 * 0.045742589279674, 0.010857537843152 / 24.);
ir->AddPentPoints20(20, 0.034061388191316, 0.153237752298796, 0.004213752156913 / 24.);
ir->AddPentPoints30(40, 0.042203997139861, 0.211681755872075, 0.017353386263795 / 24.);
ir->SetOrder(6);
return ir;
case 7: // 126 points - degree 8 -- taken from https://doi.org/10.1016/j.camwa.2020.07.004
case 8:
PentatopeIntRules[7] = PentatopeIntRules[8] = ir = new IntegrationRule(126);
ir->AddPentMidPoint(0, 0.018477072894310 / 24.);
ir->AddPentPoints5(1, 0.041850193209872, 0.003356028785577 / 24.);
ir->AddPentPoints20(6, 0.013234490721597, 0.279965061732618, 0.001166950584118 / 24.);
ir->AddPentPoints20(26, 0.183538643543872, 0.051063845643639, 0.019804745119265 / 24.);
ir->AddPentPoints20(46, 0.311385773831175, 0.014631015332223, 0.005373375682319 / 24.);
ir->AddPentPoints30(66, 0.032042227982220, 0.160928155464441, 0.007544402046650 / 24.);
ir->AddPentPoints30(96, 0.088725307776945, 0.403464343042675, 0.007050309802142 / 24.);
ir->SetOrder(8);
return ir;
case -1:
{
//construct the higher integration rules with the duffy transformation --> 1d integral in time and a tet quad-rule w.r.t space
IntegrationRule *timeIR = SegmentIntegrationRule(Order + 2);
IntegrationRule *tetIR = TetrahedronIntegrationRule(Order);
int NIP = timeIR->GetNPoints() * tetIR->GetNPoints();
AllocIntRule(PentatopeIntRules, Order);
PentatopeIntRules[Order] = ir = new IntegrationRule(NIP);
#ifdef MFEM_DEBUG
mfem::out << "higher integration rules for pentatopes implemented with duffy ( order = " << Order << " ) --> " << NIP << " int. points!" << endl;
#endif
double xi,yi,zi,ti, weight;
int pos = 0;
for (int i=0; i<timeIR->GetNPoints(); i++)
{
ti = timeIR->IntPoint(i).x;
for (int j=0; j<tetIR->GetNPoints(); j++)
{
xi = (1. - ti) * tetIR->IntPoint(j).x;
yi = (1. - ti) * tetIR->IntPoint(j).y;
zi = (1. - ti) * tetIR->IntPoint(j).z;
weight = timeIR->IntPoint(i).weight * tetIR->IntPoint(j).weight * (1.-ti) *
(1.-ti) * (1.-ti);
#ifdef MFEM_DEBUG
if(weight<0) mfem::out << "warning weight is negative!" << endl;
#endif
ir->AddPentPoint(pos, xi,yi,zi,ti,weight);
pos++;
}
}
#ifdef MFEM_DEBUG_INTRULES
char str[256];
mfem::out << "The points and weights are:" << endl;
for (int k = 0; k < ir->Size(); ++k)
{
const IntegrationPoint &ip = ir->IntPoint(k);
sprintf(str, "{%.16f, {%.16f, %.16f, %.16f, %.16f}},", ip.weight, ip.x, ip.y, ip.z, ip.t);
mfem::out << str << endl;
}
#endif
// 2025 November: Don't we need "return ir;"? It was not there
return ir;
break;
}
default:
{
int i = (Order / 2) * 2 + 1; // Get closest odd # >= Order
AllocIntRule(PentatopeIntRules, i);
ir = new IntegrationRule;
ir->GrundmannMollerSimplexRule(i/2,4);
PentatopeIntRules[i-1] = PentatopeIntRules[i] = ir;
return ir;
}
}
return PentatopeIntRules[Order];
}
IntegrationRule *IntegrationRules::TesseractIntegrationRule(int Order)
{
int k, l, m, n, np, index;
int i = (Order / 2) * 2 + 1; // Get closest odd # >= Order
if (!HaveIntRule(SegmentIntRules, i))
{
SegmentIntegrationRule(i);
}
AllocIntRule(TesseractIntRules, i);
np = SegmentIntRules[i] -> GetNPoints();
TesseractIntRules[i-1] = TesseractIntRules[i] = new IntegrationRule(
np*np*np*np);
index = 0;
for (k = 0; k < np; k++)
for (l = 0; l < np; l++)
for (m = 0; m < np; m++)
for (n = 0; n < np; n++)
{
// index = ((k*np+l)*np+m)*np + n;
TesseractIntRules[i] -> IntPoint(index).x =
SegmentIntRules[i] -> IntPoint(n).x;
TesseractIntRules[i] -> IntPoint(index).y =
SegmentIntRules[i] -> IntPoint(m).x;
TesseractIntRules[i] -> IntPoint(index).z =
SegmentIntRules[i] -> IntPoint(l).x;
TesseractIntRules[i] -> IntPoint(index).t =
SegmentIntRules[i] -> IntPoint(k).x;
TesseractIntRules[i] -> IntPoint(index).weight =
SegmentIntRules[i] -> IntPoint(k).weight *
SegmentIntRules[i] -> IntPoint(l).weight *
SegmentIntRules[i] -> IntPoint(m).weight *
SegmentIntRules[i] -> IntPoint(n).weight;
index++;
}
TesseractIntRules[i]->SetOrder(i);
return TesseractIntRules[i];
}
IntegrationRule& NURBSMeshRules::GetElementRule(const int elem,
const int patch, const int *ijk,
Array<const KnotVector*> const& kv,
+4 -124
View File
@@ -34,18 +34,18 @@ class Mesh;
class IntegrationPoint
{
public:
real_t x, y, z, t, weight;
real_t x, y, z, weight;
int index;
void Init(int const i)
{
x = y = z = t = weight = 0.0;
x = y = z = weight = 0.0;
index = i;
}
void Set(const real_t *p, const int dim)
{
MFEM_ASSERT(1 <= dim && dim <= 4, "invalid dim: " << dim);
MFEM_ASSERT(1 <= dim && dim <= 3, "invalid dim: " << dim);
x = p[0];
if (dim > 1)
{
@@ -53,17 +53,13 @@ public:
if (dim > 2)
{
z = p[2];
if (dim > 3)
{
t = p[3];
}
}
}
}
void Get(real_t *p, const int dim) const
{
MFEM_ASSERT(1 <= dim && dim <= 4, "invalid dim: " << dim);
MFEM_ASSERT(1 <= dim && dim <= 3, "invalid dim: " << dim);
p[0] = x;
if (dim > 1)
{
@@ -71,10 +67,6 @@ public:
if (dim > 2)
{
p[2] = z;
if (dim > 3)
{
p[3] = t;
}
}
}
}
@@ -82,17 +74,6 @@ public:
void Set(const real_t x1, const real_t x2, const real_t x3, const real_t w)
{ x = x1; y = x2; z = x3; weight = w; }
void Set4w(const real_t *p) { x = p[0]; y = p[1]; z = p[2]; t = p[3]; weight = p[4]; }
void Set4w(const real_t x1, const real_t x2, const real_t x3, const real_t x4,
const real_t w)
{ x = x1; y = x2; z = x3; t = x4; weight = w; }
void Set4(const real_t *p) { x = p[0]; y = p[1]; z = p[2]; t = p[3]; }
void Set4(const real_t x1, const real_t x2, const real_t x3, const real_t x4)
{ x = x1; y = x2; z = x3; t = x4; }
void Set3w(const real_t *p) { x = p[0]; y = p[1]; z = p[2]; weight = p[3]; }
void Set3(const real_t x1, const real_t x2, const real_t x3)
@@ -238,103 +219,6 @@ private:
AddTetPoints6(off + 6, a, b, c, weight);
}
void AddPentMidPoint(const int off, const double weight)
{ IntPoint(off).Set4w(0.2, 0.2, 0.2, 0.2, weight); }
void AddPentPoint(const int off, const double x, const double y, const double z,
const double t, double weight)
{
IntPoint(off).Set4w(x, y, z, t, weight);
}
// given (a), add the permuations of (a,a,a,a,b), b = 1 - 4*a
void AddPentPoints5(const int off, const double a,
double weight)
{
const double b = 1. - 4 * a;
IntPoint(off + 0).Set4w(a, a, a, a, weight);
IntPoint(off + 1).Set4w(b, a, a, a, weight);
IntPoint(off + 2).Set4w(a, b, a, a, weight);
IntPoint(off + 3).Set4w(a, a, b, a, weight);
IntPoint(off + 4).Set4w(a, a, a, b, weight);
}
// given (a,b), add the permuations of (a,a,a,b,b)
void AddPentPoints10(const int off, const double a, const double b, double weight)
{
IntPoint(off + 0).Set4w(a, a, a, b, weight);
IntPoint(off + 1).Set4w(a, a, b, a, weight);
IntPoint(off + 2).Set4w(a, a, b, b, weight);
IntPoint(off + 3).Set4w(a, b, a, a, weight);
IntPoint(off + 4).Set4w(a, b, a, b, weight);
IntPoint(off + 5).Set4w(a, b, b, a, weight);
IntPoint(off + 6).Set4w(b, a, a, a, weight);
IntPoint(off + 7).Set4w(b, a, a, b, weight);
IntPoint(off + 8).Set4w(b, a, b, a, weight);
IntPoint(off + 9).Set4w(b, b, a, a, weight);
}
// given (a,b,c), add the permuations of (a,a,a,b,c), c = 1 - 3 a - b
void AddPentPoints20(const int off, const double a, const double b, double weight)
{
const double c = 1. - 3. * a - b;
IntPoint(off + 0).Set4w(a, a, a, b, weight);
IntPoint(off + 1).Set4w(a, a, a, c, weight);
IntPoint(off + 2).Set4w(a, a, b, a, weight);
IntPoint(off + 3).Set4w(a, a, b, c, weight);
IntPoint(off + 4).Set4w(a, a, c, a, weight);
IntPoint(off + 5).Set4w(a, a, c, b, weight);
IntPoint(off + 6).Set4w(a, b, a, a, weight);
IntPoint(off + 7).Set4w(a, b, a, c, weight);
IntPoint(off + 8).Set4w(a, b, c, a, weight);
IntPoint(off + 9).Set4w(a, c, a, a, weight);
IntPoint(off + 10).Set4w(a, c, a, b, weight);
IntPoint(off + 11).Set4w(a, c, b, a, weight);
IntPoint(off + 12).Set4w(b, a, a, a, weight);
IntPoint(off + 13).Set4w(b, a, a, c, weight);
IntPoint(off + 14).Set4w(b, a, c, a, weight);
IntPoint(off + 15).Set4w(b, c, a, a, weight);
IntPoint(off + 16).Set4w(c, a, a, a, weight);
IntPoint(off + 17).Set4w(c, a, a, b, weight);
IntPoint(off + 18).Set4w(c, a, b, a, weight);
IntPoint(off + 19).Set4w(c, b, a, a, weight);
}
// given (a,b,c), add the permutations of (a,a,b,b,c), c = 1 - 2 a - 2 b
void AddPentPoints30(const int off, const double a, const double b, double weight)
{
double c = 1. - 2. * a - 2. * b;
IntPoint(off + 0).Set4w(a, a, b, b, weight);
IntPoint(off + 1).Set4w(a, a, b, c, weight);
IntPoint(off + 2).Set4w(a, a, c, b, weight);
IntPoint(off + 3).Set4w(a, b, a, b, weight);
IntPoint(off + 4).Set4w(a, b, a, c, weight);
IntPoint(off + 5).Set4w(a, b, b, a, weight);
IntPoint(off + 6).Set4w(a, b, b, c, weight);
IntPoint(off + 7).Set4w(a, b, c, a, weight);
IntPoint(off + 8).Set4w(a, b, c, b, weight);
IntPoint(off + 9).Set4w(a, c, a, b, weight);
IntPoint(off + 10).Set4w(a, c, b, a, weight);
IntPoint(off + 11).Set4w(a, c, b, b, weight);
IntPoint(off + 12).Set4w(b, a, a, b, weight);
IntPoint(off + 13).Set4w(b, a, a, c, weight);
IntPoint(off + 14).Set4w(b, a, b, a, weight);
IntPoint(off + 15).Set4w(b, a, b, c, weight);
IntPoint(off + 16).Set4w(b, a, c, a, weight);
IntPoint(off + 17).Set4w(b, a, c, b, weight);
IntPoint(off + 18).Set4w(b, b, a, a, weight);
IntPoint(off + 19).Set4w(b, b, a, c, weight);
IntPoint(off + 20).Set4w(b, b, c, a, weight);
IntPoint(off + 21).Set4w(b, c, a, a, weight);
IntPoint(off + 22).Set4w(b, c, a, b, weight);
IntPoint(off + 23).Set4w(b, c, b, a, weight);
IntPoint(off + 24).Set4w(c, a, a, b, weight);
IntPoint(off + 25).Set4w(c, a, b, a, weight);
IntPoint(off + 26).Set4w(c, a, b, b, weight);
IntPoint(off + 27).Set4w(c, b, a, a, weight);
IntPoint(off + 28).Set4w(c, b, a, b, weight);
IntPoint(off + 29).Set4w(c, b, b, a, weight);
}
public:
IntegrationRule() :
Array<IntegrationPoint>() { }
@@ -546,8 +430,6 @@ private:
Array<IntegrationRule *> PyramidIntRules;
Array<IntegrationRule *> PrismIntRules;
Array<IntegrationRule *> CubeIntRules;
Array<IntegrationRule *> PentatopeIntRules;
Array<IntegrationRule *> TesseractIntRules;
#if defined(MFEM_THREAD_SAFE) && defined(MFEM_USE_OPENMP)
Array<omp_lock_t> IntRuleLocks;
@@ -582,8 +464,6 @@ private:
IntegrationRule *PyramidIntegrationRule(int Order);
IntegrationRule *PrismIntegrationRule(int Order);
IntegrationRule *CubeIntegrationRule(int Order);
IntegrationRule *PentatopeIntegrationRule(int Order);
IntegrationRule *TesseractIntegrationRule(int Order);
public:
/// Sets initial sizes for the integration rule arrays, but rules
+44 -44
View File
@@ -220,8 +220,8 @@ void MomentFittingIntRules::ComputeSurfaceWeights1D(ElementTransformation& Tr)
{
IntegrationPoint ip2;
ip2.x = .5;
while (LvlSet->Eval(Tr, ip2) > 1e-12
|| LvlSet->Eval(Tr, ip2) < -1e-12)
while (LvlSet->Eval(Tr, ip2) > tol_1
|| LvlSet->Eval(Tr, ip2) < -tol_1)
{
if (LvlSet->Eval(Tr, ip0) * LvlSet->Eval(Tr, ip2) < 0.)
{
@@ -237,12 +237,12 @@ void MomentFittingIntRules::ComputeSurfaceWeights1D(ElementTransformation& Tr)
intp.x = ip2.x;
intp.weight = 1. / Tr.Weight();
}
else if (LvlSet->Eval(Tr, ip0) > 0. && LvlSet->Eval(Tr, ip1) <= 1e-12)
else if (LvlSet->Eval(Tr, ip0) > 0. && LvlSet->Eval(Tr, ip1) <= tol_1)
{
intp.x = 1.;
intp.weight = 1. / Tr.Weight();
}
else if (LvlSet->Eval(Tr, ip1) > 0. && LvlSet->Eval(Tr, ip0) <= 1e-12)
else if (LvlSet->Eval(Tr, ip1) > 0. && LvlSet->Eval(Tr, ip0) <= tol_1)
{
intp.x = 0.;
intp.weight = 1. / Tr.Weight();
@@ -290,8 +290,8 @@ void MomentFittingIntRules::ComputeVolumeWeights1D(ElementTransformation& Tr,
}
}
}
else if (LvlSet->Eval(Tr, ip0) <= -1e-12
|| LvlSet->Eval(Tr, ip1) <= -1e-12)
else if (LvlSet->Eval(Tr, ip0) <= -tol_1
|| LvlSet->Eval(Tr, ip1) <= -tol_1)
{
for (int ip = 0; ip < ir.GetNPoints(); ip++)
{
@@ -356,24 +356,24 @@ void MomentFittingIntRules::ComputeSurfaceWeights2D(ElementTransformation& Tr)
IntegrationPoint ipB;
Trafo.TransformBack(pointB, ipB);
if (LvlSet->Eval(Trafo, ipA) < -1e-12
|| LvlSet->Eval(Trafo, ipB) < -1e-12)
if (LvlSet->Eval(Trafo, ipA) < -tol_1
|| LvlSet->Eval(Trafo, ipB) < -tol_1)
{
interior = false;
}
if (LvlSet->Eval(Trafo, ipA) > -1e-12
&& LvlSet->Eval(Trafo, ipB) > -1e-12)
if (LvlSet->Eval(Trafo, ipA) > -tol_1
&& LvlSet->Eval(Trafo, ipB) > -tol_1)
{
layout = Layout::inside;
}
else if (LvlSet->Eval(Trafo, ipA) > 1e-15
else if (LvlSet->Eval(Trafo, ipA) > tol_2
&& LvlSet->Eval(Trafo, ipB) <= 0.)
{
layout = Layout::intersected;
}
else if (LvlSet->Eval(Trafo, ipA) <= 0.
&& LvlSet->Eval(Trafo, ipB) > 1e-15)
&& LvlSet->Eval(Trafo, ipB) > tol_2)
{
layout = Layout::intersected;
Vector temp(pointA.Size());
@@ -399,10 +399,10 @@ void MomentFittingIntRules::ComputeSurfaceWeights2D(ElementTransformation& Tr)
IntegrationPoint ip;
Trafo.TransformBack(mid, ip);
while (LvlSet->Eval(Trafo, ip) > 1e-12
|| LvlSet->Eval(Trafo, ip) < -1e-12)
while (LvlSet->Eval(Trafo, ip) > tol_1
|| LvlSet->Eval(Trafo, ip) < -tol_1)
{
if (LvlSet->Eval(Trafo, ip) > 1e-12)
if (LvlSet->Eval(Trafo, ip) > tol_1)
{
pointC = mid;
}
@@ -539,7 +539,7 @@ void MomentFittingIntRules::ComputeSurfaceWeights2D(ElementTransformation& Tr)
temp2 = 0.;
for (int i = 0; i < nBasis; i++)
{
if (SVD.Singularvalue(i) > 1e-12)
if (SVD.Singularvalue(i) > tol_1)
{
temp2(i) = temp(i) / SVD.Singularvalue(i);
}
@@ -606,24 +606,24 @@ void MomentFittingIntRules::ComputeVolumeWeights2D(ElementTransformation& Tr,
IntegrationPoint ipB;
Trafo.TransformBack(pointB, ipB);
if (LvlSet->Eval(Trafo, ipA) < -1e-12
|| LvlSet->Eval(Trafo, ipB) < -1e-12)
if (LvlSet->Eval(Trafo, ipA) < -tol_1
|| LvlSet->Eval(Trafo, ipB) < -tol_1)
{
interior = false;
}
if (LvlSet->Eval(Trafo, ipA) > -1e-12
&& LvlSet->Eval(Trafo, ipB) > -1e-12)
if (LvlSet->Eval(Trafo, ipA) > -tol_1
&& LvlSet->Eval(Trafo, ipB) > -tol_1)
{
layout = Layout::inside;
}
else if (LvlSet->Eval(Trafo, ipA) > 1e-15
else if (LvlSet->Eval(Trafo, ipA) > tol_2
&& LvlSet->Eval(Trafo, ipB) <= 0.)
{
layout = Layout::intersected;
}
else if (LvlSet->Eval(Trafo, ipA) <= 0.
&& LvlSet->Eval(Trafo, ipB) > 1e-15)
&& LvlSet->Eval(Trafo, ipB) > tol_2)
{
layout = Layout::intersected;
Vector temp(pointA.Size());
@@ -648,10 +648,10 @@ void MomentFittingIntRules::ComputeVolumeWeights2D(ElementTransformation& Tr,
IntegrationPoint ip;
Trafo.TransformBack(mid, ip);
while (LvlSet->Eval(Trafo, ip) > 1e-12
|| LvlSet->Eval(Trafo, ip) < -1e-12)
while (LvlSet->Eval(Trafo, ip) > tol_1
|| LvlSet->Eval(Trafo, ip) < -tol_1)
{
if (LvlSet->Eval(Trafo, ip) > 1e-12)
if (LvlSet->Eval(Trafo, ip) > tol_1)
{
pointC = mid;
}
@@ -786,7 +786,7 @@ void MomentFittingIntRules::ComputeVolumeWeights2D(ElementTransformation& Tr,
VolumeSVD->LeftSingularvectors().MultTranspose(RHS, temp);
for (int i = 0; i < nBasisVolume; i++)
{
if (VolumeSVD->Singularvalue(i) > 1e-12)
if (VolumeSVD->Singularvalue(i) > tol_1)
{
temp2(i) = temp(i) / VolumeSVD->Singularvalue(i);
}
@@ -865,18 +865,18 @@ void MomentFittingIntRules::ComputeSurfaceWeights3D(ElementTransformation& Tr)
IntegrationPoint ipD;
Trafo.TransformBack(pointD, ipD);
if (LvlSet->Eval(Trafo, ipA) < -1e-12
|| LvlSet->Eval(Trafo, ipB) < -1e-12
|| LvlSet->Eval(Trafo, ipC) < -1e-12
|| LvlSet->Eval(Trafo, ipD) < -1e-12)
if (LvlSet->Eval(Trafo, ipA) < -tol_1
|| LvlSet->Eval(Trafo, ipB) < -tol_1
|| LvlSet->Eval(Trafo, ipC) < -tol_1
|| LvlSet->Eval(Trafo, ipD) < -tol_1)
{
interior = false;
}
if (LvlSet->Eval(Trafo, ipA) > -1e-12
|| LvlSet->Eval(Trafo, ipB) > -1e-12
|| LvlSet->Eval(Trafo, ipC) > -1e-12
|| LvlSet->Eval(Trafo, ipD) > -1e-12)
if (LvlSet->Eval(Trafo, ipA) > -tol_1
|| LvlSet->Eval(Trafo, ipB) > -tol_1
|| LvlSet->Eval(Trafo, ipC) > -tol_1
|| LvlSet->Eval(Trafo, ipD) > -tol_1)
{
element_int = true;
}
@@ -978,7 +978,7 @@ void MomentFittingIntRules::ComputeSurfaceWeights3D(ElementTransformation& Tr)
temp2 = 0.;
for (int i = 0; i < nBasis; i++)
{
if (SVD.Singularvalue(i) > 1e-12)
if (SVD.Singularvalue(i) > tol_1)
{
temp2(i) = temp(i) / SVD.Singularvalue(i);
}
@@ -1047,18 +1047,18 @@ void MomentFittingIntRules::ComputeVolumeWeights3D(ElementTransformation& Tr,
IntegrationPoint ipD;
Trafo.TransformBack(pointD, ipD);
if (LvlSet->Eval(Trafo, ipA) < -1e-12
|| LvlSet->Eval(Trafo, ipB) < -1e-12
|| LvlSet->Eval(Trafo, ipC) < -1e-12
|| LvlSet->Eval(Trafo, ipD) < -1e-12)
if (LvlSet->Eval(Trafo, ipA) < -tol_1
|| LvlSet->Eval(Trafo, ipB) < -tol_1
|| LvlSet->Eval(Trafo, ipC) < -tol_1
|| LvlSet->Eval(Trafo, ipD) < -tol_1)
{
interior = false;
}
if (LvlSet->Eval(Trafo, ipA) > -1e-12
|| LvlSet->Eval(Trafo, ipB) > -1e-12
|| LvlSet->Eval(Trafo, ipC) > -1e-12
|| LvlSet->Eval(Trafo, ipD) > -1e-12)
if (LvlSet->Eval(Trafo, ipA) > -tol_1
|| LvlSet->Eval(Trafo, ipB) > -tol_1
|| LvlSet->Eval(Trafo, ipC) > -tol_1
|| LvlSet->Eval(Trafo, ipD) > -tol_1)
{
element_int = true;
}
@@ -1159,7 +1159,7 @@ void MomentFittingIntRules::ComputeVolumeWeights3D(ElementTransformation& Tr,
VolumeSVD->LeftSingularvectors().MultTranspose(RHS, temp);
temp2 = 0.;
for (int i = 0; i < nBasisVolume; i++)
if (VolumeSVD->Singularvalue(i) > 1e-12)
if (VolumeSVD->Singularvalue(i) > tol_1)
{
temp2(i) = temp(i) / VolumeSVD->Singularvalue(i);
}
+11
View File
@@ -36,6 +36,17 @@ protected:
/// Space order for the LS projection.
int lsOrder;
/// @name Tolerances used for point comparisons
///@{
#ifdef MFEM_USE_DOUBLE
static constexpr real_t tol_1 = 1e-12;
static constexpr real_t tol_2 = 1e-15;
#elif defined(MFEM_USE_SINGLE)
static constexpr real_t tol_1 = 1e-5;
static constexpr real_t tol_2 = 1e-7;
#endif
///@}
/** @brief Constructor to set up the generated cut IntegrationRules.
@param [in] order Order of the constructed IntegrationRule.
-6
View File
@@ -249,12 +249,6 @@ public:
FiniteElementSpace #fes. */
LinearForm &operator=(const Vector &v);
/// Change ownership of linear form integrators.
void SetIntegratorOwnership(int _extern_lfs)
{
extern_lfs = _extern_lfs;
}
/// Destroys linear form.
~LinearForm();
};
+29
View File
@@ -123,6 +123,35 @@ void DomainLFGradIntegrator::AssembleDeltaElementVect(
dshape.Mult(Qvec, elvect);
}
void DomainLFLaplaceIntegrator::AssembleRHSElementVect(const FiniteElement &el,
ElementTransformation &Tr,
Vector &elvect)
{
int dof = el.GetDof();
laplace.SetSize(dof); // vector of size dof
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = NULL;//IntRule;
if (ir == NULL)
{
ir = &IntRules.Get(el.GetGeomType(), oa * el.GetOrder() + ob + 4);
}
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Tr.SetIntPoint (&ip);
real_t val = Tr.Weight() * Q.Eval(Tr, ip) * alpha;
el.CalcPhysLaplacian(Tr, laplace);
add(elvect, ip.weight * val, laplace, elvect);
}
}
void BoundaryLFIntegrator::AssembleRHSElementVect(
const FiniteElement &el, ElementTransformation &Tr, Vector &elvect)
{
+24 -51
View File
@@ -174,6 +174,30 @@ public:
using LinearFormIntegrator::AssembleRHSElementVect;
};
/// Class for domain integrator $ L(v) := (f, \Delta v) $
class DomainLFLaplaceIntegrator : public LinearFormIntegrator
{
private:
Vector laplace;
Coefficient &Q;
real_t alpha;
int oa, ob;
public:
/// Constructs the domain integrator $ (Q, \nabla v) $
DomainLFLaplaceIntegrator(Coefficient &QF, real_t alp = 1.0, int a = 2,
int b = 0)
: Q(QF), oa(a), ob(b) { alpha = alp; }
/** Given a particular Finite Element and a transformation (Tr)
computes the element right hand side element vector, elvect. */
virtual void AssembleRHSElementVect(const FiniteElement &el,
ElementTransformation &Tr,
Vector &elvect);
using LinearFormIntegrator::AssembleRHSElementVect;
};
/// Class for boundary integration $ L(v) := (g, v) $
class BoundaryLFIntegrator : public LinearFormIntegrator
{
@@ -781,57 +805,6 @@ public:
}
};
class MatFEDomainLFIntegrator : public LinearFormIntegrator
{
private:
MatrixCoefficient &QF;
DenseMatrix vshape;
DenseMatrix mat;
Vector matToVec;
public:
MatFEDomainLFIntegrator (MatrixCoefficient &F) : QF(F) { }
virtual void AssembleRHSElementVect(const FiniteElement &el,
ElementTransformation &Tr,
Vector &elvect)
{
int dof = el.GetDof();
int dim = el.GetDim();
vshape.SetSize(dof,dim*dim);
mat.SetSize(dim,dim);
matToVec.SetSize(dim*dim);
elvect.SetSize(dof);
elvect = 0.0;
const IntegrationRule *ir = IntRule;
if (ir == NULL)
{
// int intorder = 2*el.GetOrder() - 1; // ok for O(h^{k+1}) conv. in L2
int intorder = 2*el.GetOrder() + 2;
ir = &IntRules.Get(el.GetGeomType(), intorder);
}
for (int i = 0; i < ir->GetNPoints(); i++)
{
const IntegrationPoint &ip = ir->IntPoint(i);
Tr.SetIntPoint (&ip);
el.CalcVShape(Tr, vshape);
QF.Eval (mat, Tr, ip);
mat *= ip.weight * fabs(Tr.Weight());
for (int ki=0; ki<dim; ki++) for (int kj=0; kj<dim; kj++) { matToVec(dim*ki+kj) = mat(ki,kj); }
vshape.AddMult(matToVec, elvect);
}
}
using LinearFormIntegrator::AssembleRHSElementVect;
};
}
-12
View File
@@ -330,18 +330,6 @@ public:
/// Compute y += a (P^t A P) x, where x and y are vectors on the true dofs
void TrueAddMult(const Vector &x, Vector &y, const real_t a = 1.0) const;
using MixedBilinearForm::Update;
virtual void Update(ParFiniteElementSpace *ntr_fes = NULL,
ParFiniteElementSpace *nte_fes = NULL)
{
MixedBilinearForm::Update(ntr_fes, nte_fes);
if (ntr_fes && nte_fes )
{
trial_pfes = ntr_fes;
test_pfes = nte_fes;
}
}
virtual ~ParMixedBilinearForm() { }
};
+6 -269
View File
@@ -174,11 +174,10 @@ void ParFiniteElementSpace::Construct()
ngfdofs = pncmesh->GetNGhostFaces()
* fec->DofForGeometry(Geometry::Type::SQUARE);
}
ngpdofs = 0;
// total number of ghost DOFs. Ghost DOFs start at index 'ndofs', i.e.,
// after all regular DOFs
ngdofs = ngvdofs + ngedofs + ngfdofs + ngpdofs;
ngdofs = ngvdofs + ngedofs + ngfdofs;
// get P and R matrices, initialize DOF offsets, etc. NOTE: in the NC
// case this needs to be done here to get the number of true DOFs
@@ -236,11 +235,8 @@ void ParFiniteElementSpace::GetGroupComm(
int gr;
int ng = pmesh->GetNGroups();
int nvd, ned, ntd = 0, nqd = 0;
int nted = 0;
Array<int> dofs;
int dim = pmesh->Dimension();
int group_ldof_counter;
Table &group_ldof = gc.GroupLDofTable();
@@ -257,10 +253,6 @@ void ParFiniteElementSpace::GetGroupComm(
{
nqd = fec->DofForGeometry(Geometry::SQUARE);
}
if (mesh->HasGeometry(Geometry::TETRAHEDRON) && dim > 3)
{
nted = fec->DofForGeometry(Geometry::TETRAHEDRON);
}
}
if (g_ldof_sign)
@@ -277,11 +269,6 @@ void ParFiniteElementSpace::GetGroupComm(
group_ldof_counter += ned * pmesh->GroupNEdges(gr);
group_ldof_counter += ntd * pmesh->GroupNTriangles(gr);
group_ldof_counter += nqd * pmesh->GroupNQuadrilaterals(gr);
if (dim > 3)
{
group_ldof_counter += nted * pmesh->GroupNTetrahedra(
gr); // FIXME: ensure that tet-group is always build
}
}
if (ldof_type)
{
@@ -295,14 +282,13 @@ void ParFiniteElementSpace::GetGroupComm(
group_ldof.GetI()[0] = group_ldof.GetI()[1] = 0;
for (gr = 1; gr < ng; gr++)
{
int j, k, l, m, o, nv, ne, nt, nq, nte;
int j, k, l, m, o, nv, ne, nt, nq;
const int *ind;
nv = pmesh->GroupNVertices(gr);
ne = pmesh->GroupNEdges(gr);
nt = pmesh->GroupNTriangles(gr);
nq = pmesh->GroupNQuadrilaterals(gr);
nte = (dim>3) ? pmesh->GroupNTetrahedra(gr) : 0; // FIXME
// vertices
if (nvd > 0)
@@ -376,14 +362,7 @@ void ParFiniteElementSpace::GetGroupComm(
pmesh->GroupTriangle(gr, j, k, o);
dofs.SetSize(ntd);
if (dim == 4)
{
m = nvdofs+nedofs+pdofs[k];
}
else
{
m = nvdofs + nedofs + FirstFaceDof(k);
}
m = nvdofs + nedofs + FirstFaceDof(k);
ind = fec->DofOrderForOrientation(Geometry::TRIANGLE, o);
for (l = 0; l < ntd; l++)
{
@@ -451,45 +430,6 @@ void ParFiniteElementSpace::GetGroupComm(
}
}
// tetrahedra (4D)
if (nted > 0)
{
for (j = 0; j < nte; j++)
{
pmesh->GroupTetrahedron(gr, j, k, o);
dofs.SetSize(nted);
m = nvdofs+nedofs+npdofs+ FirstFaceDof(k);
ind = fec->DofOrderForOrientation(
mesh->GetFaceGeometry(k), o);
for (l = 0; l < nted; l++)
{
if (ind[l] < 0)
{
dofs[l] = m + (-1-ind[l]);
if (g_ldof_sign)
{
(*g_ldof_sign)[dofs[l]] = -1;
}
}
else
{
dofs[l] = m + ind[l];
}
}
if (ldof_type)
{
DofsToVDofs(dofs);
}
for (l = 0; l < dofs.Size(); l++)
{
group_ldof.GetJ()[group_ldof_counter++] = dofs[l];
}
}
}
group_ldof.GetI()[gr+1] = group_ldof_counter;
}
@@ -711,30 +651,6 @@ void ParFiniteElementSpace::GetSharedQuadrilateralDofs(
}
}
void ParFiniteElementSpace::GetSharedTetrahedronDofs(
int group, int fi, Array<int> &dofs) const
{
int l_face, ori;
MFEM_ASSERT(0 <= fi &&
fi < pmesh->GroupNTetrahedra(group), "invalid face index");
pmesh->GroupTetrahedron(group, fi, l_face, ori);
if (ori == 0)
{
GetFaceDofs(l_face, dofs);
}
else
{
Array<int> rdofs;
fec->SubDofOrder(pmesh->GetFaceGeometry(l_face), 2, ori, dofs);
GetFaceDofs(l_face, rdofs);
for (int i = 0; i < dofs.Size(); i++)
{
const int di = dofs[i];
dofs[i] = (di >= 0) ? rdofs[di] : -1-rdofs[-1-di];
}
}
}
void ParFiniteElementSpace::GenerateGlobalOffsets() const
{
MFEM_ASSERT(Conforming(), "wrong code path");
@@ -1822,115 +1738,6 @@ void ParFiniteElementSpace::GetGhostFaceDofs(const MeshId &face_id,
}
}
void ParFiniteElementSpace::GetGhostFaceDofs4D(const MeshId &face_id,
Array<int> &dofs) const
{
#if 0
MFEM_ASSERT(mesh->GetFaceBaseGeometry(0) == Geometry::TETRAHEDRON, "");
int nv = fec->DofForGeometry(Geometry::POINT);
int ne = fec->DofForGeometry(Geometry::SEGMENT);
int np = fec->DofForGeometry(Geometry::TRIANGLE);
int nf = fec->DofForGeometry(Geometry::TETRAHEDRON);
dofs.SetSize(4*nv + 6*ne + 4*np + nf);
int V[4], E[6], Eo[6], P[4], Po[4];
pmesh->pncmesh->GetFaceVerticesEdgesPlanars(face_id, V, E, Eo, P, Po);
int offset = 0;
for (int i = 0; i < 4; i++)
{
int ghost = pncmesh->GetNVertices();
int first = (V[i] < ghost) ? V[i]*nv : (ndofs + (V[i] - ghost)*nv);
for (int j = 0; j < nv; j++)
{
dofs[offset++] = first + j;
}
}
for (int i = 0; i < 6; i++)
{
int ghost = pncmesh->GetNEdges();
int first = (E[i] < ghost) ? nvdofs + E[i]*ne
/* */ : ndofs + ngvdofs + (E[i] - ghost)*ne;
const int *ind = fec->DofOrderForOrientation(Geometry::SEGMENT, Eo[i]);
for (int j = 0; j < ne; j++)
{
dofs[offset++] = (ind[j] >= 0) ? (first + ind[j])
/* */ : (-1 - (first + (-1 - ind[j])));
}
}
for (int i = 0; i < 4; i++)
{
// TODO higher order
int ghost = pncmesh->GetNPlanars();
int first = (P[i] < ghost) ? nvdofs + nedofs + P[i]*np
/* */ : ndofs + ngvdofs + nedofs + ngedofs + (P[i] - ghost)*np;
// const int *ind = fec->DofOrderForOrientation(Geometry::SEGMENT, Eo[i]);
for (int j = 0; j < np; j++)
{
dofs[offset++] = first + j;
}
}
int first = ndofs + ngvdofs + ngedofs +
(face_id.index - pncmesh->GetNFaces())*nf;
for (int j = 0; j < nf; j++)
{
dofs[offset++] = first + j;
}
#endif
}
void ParFiniteElementSpace::GetGhostPlanarDofs(const MeshId &planar_id,
Array<int> &dofs) const
{
#if 0
MFEM_ASSERT(mesh->GetPlanarBaseGeometry(0) == Geometry::TRIANGLE, "");
int nv = fec->DofForGeometry(Geometry::POINT);
int ne = fec->DofForGeometry(Geometry::SEGMENT);
int np = fec->DofForGeometry(Geometry::TRIANGLE);
dofs.SetSize(3*nv + 3*ne + np);
int V[3], E[3], Eo[3];
pmesh->pncmesh->GetPlanarVerticesEdges(planar_id, V, E, Eo);
int offset = 0;
for (int i = 0; i < 3; i++)
{
int ghost = pncmesh->GetNVertices();
int first = (V[i] < ghost) ? V[i]*nv : (ndofs + (V[i] - ghost)*nv);
for (int j = 0; j < nv; j++)
{
dofs[offset++] = first + j;
}
}
for (int i = 0; i < 3; i++)
{
int ghost = pncmesh->GetNEdges();
int first = (E[i] < ghost) ? nvdofs + E[i]*ne
/* */ : ndofs + ngvdofs + (E[i] - ghost)*ne;
const int *ind = fec->DofOrderForOrientation(Geometry::SEGMENT, Eo[i]);
for (int j = 0; j < ne; j++)
{
dofs[offset++] = (ind[j] >= 0) ? (first + ind[j])
/* */ : (-1 - (first + (-1 - ind[j])));
}
}
int first = ndofs + ngvdofs + ngedofs +
(planar_id.index - pncmesh->GetNPlanars())*np;
for (int j = 0; j < np; j++)
{
dofs[offset++] = first + j;
}
#endif
}
void ParFiniteElementSpace::GetGhostDofs(int entity, const MeshId &id,
Array<int> &dofs) const
{
@@ -1943,19 +1750,6 @@ void ParFiniteElementSpace::GetGhostDofs(int entity, const MeshId &id,
}
}
void ParFiniteElementSpace::GetGhostDofs4D(int entity, const MeshId &id,
Array<int> &dofs) const
{
// helper to get ghost vertex, ghost edge or ghost face DOFs
switch (entity)
{
case 0: GetGhostVertexDofs(id, dofs); break;
case 1: GetGhostEdgeDofs(id, dofs); break;
case 2: GetGhostPlanarDofs(id, dofs); break;
case 3: GetGhostFaceDofs4D(id, dofs); break;
}
}
void ParFiniteElementSpace::GetBareDofs(int entity, int index,
Array<int> &dofs) const
{
@@ -2006,55 +1800,6 @@ void ParFiniteElementSpace::GetBareDofs(int entity, int index,
}
}
void ParFiniteElementSpace::GetBareDofs4D(int entity, int index,
Array<int> &dofs) const
{
#if 0
int ned, ghost, first;
switch (entity)
{
case 0:
ned = fec->DofForGeometry(Geometry::POINT);
ghost = pncmesh->GetNVertices();
first = (index < ghost)
? index*ned // regular vertex
: ndofs + (index - ghost)*ned; // ghost vertex
break;
case 1:
ned = fec->DofForGeometry(Geometry::SEGMENT);
ghost = pncmesh->GetNEdges();
first = (index < ghost)
? nvdofs + index*ned // regular edge
: ndofs + ngvdofs + (index - ghost)*ned; // ghost edge
break;
case 2:
ned = fec->DofForGeometry(mesh->GetPlanarBaseGeometry(0));
ghost = pncmesh->GetNPlanars();
first = (index < ghost)
? nvdofs + nedofs + index*ned
: ndofs + ngvdofs + ngedofs + (index - ghost)*ned;
break;
default:
ned = fec->DofForGeometry(mesh->GetFaceBaseGeometry(0));
ghost = pncmesh->GetNFaces();
first = (index < ghost)
? nvdofs + nedofs + npdofs + index*ned // regular face
: ndofs + ngvdofs + ngedofs + ngpdofs + (index - ghost)*ned; // ghost
break;
}
dofs.SetSize(ned);
for (int i = 0; i < ned; i++)
{
dofs[i] = first + i;
}
#endif
}
int ParFiniteElementSpace::PackDof(int entity, int index, int edof) const
{
// DOFs are ordered as follows:
@@ -2661,7 +2406,7 @@ int ParFiniteElementSpace
Array<int> *dof_tdof,
bool partial) const
{
const bool dg = (nvdofs == 0 && nedofs == 0 && nfdofs == 0 && npdofs == 0);
const bool dg = (nvdofs == 0 && nedofs == 0 && nfdofs == 0);
#ifdef MFEM_PMATRIX_STATS
n_msgs_sent = n_msgs_recv = 0;
@@ -2724,7 +2469,7 @@ int ParFiniteElementSpace
list.OrientedPointMatrix(sf, T.GetPointMat());
fe->GetLocalInterpolation(T, I);
// mfem::out << "**************\n";
// make each slave DOF dependent on all master DOFs
AddDependencies(deps, master_dofs, slave_dofs, I);
}
@@ -2752,14 +2497,7 @@ int ParFiniteElementSpace
GroupId owner = pncmesh->GetEntityOwnerId(entity, id.index);
GroupId group = pncmesh->GetEntityGroupId(entity, id.index);
if (pmesh->Dimension() <= 3)
{
GetBareDofs(entity, id.index, dofs);
}
else
{
GetBareDofs4D(entity, id.index, dofs);
}
GetBareDofs(entity, id.index, dofs);
for (auto dof : dofs)
{
@@ -2768,7 +2506,6 @@ int ParFiniteElementSpace
}
};
// initialize dof_group[], dof_owner[] in sequence
for (int entity : {0,1,2})
{
+1 -7
View File
@@ -45,7 +45,7 @@ private:
mutable int ltdof_size;
/// Number of vertex/edge/face/total ghost DOFs (nonconforming case).
int ngvdofs, ngedofs, ngfdofs, ngdofs, ngpdofs;
int ngvdofs, ngedofs, ngfdofs, ngdofs;
/// The group of each local dof.
Array<int> ldof_group;
@@ -126,13 +126,8 @@ private:
void GetGhostFaceDofs(const MeshId &face_id, Array<int> &dofs) const;
void GetGhostDofs(int entity, const MeshId &id, Array<int> &dofs) const;
void GetGhostFaceDofs4D(const MeshId &face_id, Array<int> &dofs) const;
void GetGhostPlanarDofs(const MeshId &planar_id, Array<int> &dofs) const;
void GetGhostDofs4D(int entity, const MeshId &id, Array<int> &dofs) const;
/// Return the dofs associated with the interior of the given mesh entity.
void GetBareDofs(int entity, int index, Array<int> &dofs) const;
void GetBareDofs4D(int entity, int index, Array<int> &dofs) const;
int PackDof(int entity, int index, int edof) const;
void UnpackDof(int dof, int &entity, int &index, int &edof) const;
@@ -327,7 +322,6 @@ public:
void GetSharedEdgeDofs(int group, int ei, Array<int> &dofs) const;
void GetSharedTriangleDofs(int group, int fi, Array<int> &dofs) const;
void GetSharedQuadrilateralDofs(int group, int fi, Array<int> &dofs) const;
void GetSharedTetrahedronDofs(int group, int fi, Array<int> &dofs) const;
/// The true dof-to-dof interpolation matrix
HypreParMatrix *Dof_TrueDof_Matrix() const
+2
View File
@@ -1233,6 +1233,8 @@ void PRefinementTransferOperator::Mult(const Vector& x, Vector& y) const
int vdim = lFESpace.GetVDim();
y = 0.0;
for (int i = 0; i < mesh->GetNE(); i++)
{
DofTransformation * doftrans_h = hFESpace.GetElementDofs(i, h_dofs);
+2 -2
View File
@@ -63,9 +63,9 @@
#define MFEM_FOREACH_THREAD(i,k,N) for(int i=0; i<N; i++)
#endif
// 'double' atomicAdd implementation for previous versions of CUDA
// 'double' and 'float' atomicAdd implementation for previous versions of CUDA
#if defined(MFEM_USE_CUDA) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ < 600
MFEM_DEVICE inline real_t atomicAdd(real_t *add, real_t val)
MFEM_DEVICE inline mfem::real_t atomicAdd(mfem::real_t *add, mfem::real_t val)
{
unsigned long long int *ptr = (unsigned long long int *) add;
unsigned long long int old = *ptr, reg;
-125
View File
@@ -39,22 +39,12 @@ struct Hashed4
int next;
};
/** A concept for items that should be used in HashTable and be accessible by
* hashing 5 IDs. temporary workaround for 4D (need a structure where all 4 ids a stored)
*/
struct Hashed5
{
int p1, p2, p3, p4; // NOTE: p5 is not hashed nor stored
int next;
};
/** HashTable is a container for items that require associative access through
* pairs (or quadruples) of indices:
*
* (p1, p2) -> item
* (p1, p2, p3, p4) -> item
* (p1, p2, p3, p4, p5) -> item
*
* An example of this are edges and faces in a mesh. Each edge is uniquely
* identified by two parent vertices and so can be easily accessed from
@@ -130,7 +120,6 @@ public:
@warning This method should only be called if T inherits from Hashed4. */
T* Get(int p1, int p2, int p3, int p4 = -1 /* p4 optional */);
T* Get(int p1, int p2, int p3, int p4, int p5);
/// Get id of item whose parents are p1, p2... Create it if it doesn't exist.
/** @brief Get the "id" of an item, this "id" corresponding to the index of the
@@ -156,7 +145,6 @@ public:
@warning This method should only be called if T inherits from Hashed4. */
int GetId(int p1, int p2, int p3, int p4 = -1);
int GetId(int p1, int p2, int p3, int p4, int p5);
/// Find item whose parents are p1, p2... Return NULL if it doesn't exist.
/** @brief Item accessor with key (or parents) the pair 'p1', 'p2'. Return
@@ -181,7 +169,6 @@ public:
@warning This method should only be called if T inherits from Hashed4. */
T* Find(int p1, int p2, int p3, int p4 = -1);
T* Find(int p1, int p2, int p3, int p4, int p5);
/** @brief Item const accessor with key (or parents) the pair 'p1', 'p2'.
Return nullptr if no value correspond to the requested key.
@@ -205,7 +192,6 @@ public:
@warning This method should only be called if T inherits from Hashed4. */
const T* Find(int p1, int p2, int p3, int p4 = -1) const;
const T* Find(int p1, int p2, int p3, int p4, int p5) const;
/// Find id of item whose parents are p1, p2... Return -1 if it doesn't exist.
/** @brief Find the "id" of an item, this "id" corresponding to the index of
@@ -231,7 +217,6 @@ public:
@warning This method should only be called if T inherits from Hashed4. */
int FindId(int p1, int p2, int p3, int p4 = -1) const;
int FindId(int p1, int p2, int p3, int p4, int p5) const;
/// @brief Return the number of elements currently stored in the HashTable.
int Size() const { return Base::Size() - unused.Size(); }
@@ -298,8 +283,6 @@ public:
@warning This method should only be called if T inherits from Hashed4. */
void Reparent(int id, int new_p1, int new_p2, int new_p3, int new_p4 = -1);
void Reparent(int id, int new_p1, int new_p2, int new_p3, int new_p4,
int new_p5);
/// @brief Return total size of allocated memory (tables plus items), in bytes.
std::size_t MemoryUsage() const;
@@ -397,9 +380,6 @@ protected:
inline int Hash(size_t p1, size_t p2, size_t p3) const
{ return (984120265ul*p1 + 125965121ul*p2 + 495698413ul*p3) & mask; }
inline int Hash(int p1, int p2, int p3, int p4) const
{ return (984120265*p1 + 125965121*p2 + 495698413*p3 + 179424673*p4) & mask; }
// Delete() and Reparent() use one of these:
/// @brief Hash function for items of type T that inherit from Hashed2.
inline int Hash(const Hashed2& item) const
@@ -409,9 +389,6 @@ protected:
inline int Hash(const Hashed4& item) const
{ return Hash(item.p1, item.p2, item.p3); }
inline int Hash(const Hashed5& item) const
{ return Hash(item.p1, item.p2, item.p3, item.p4); };
/** @brief Search the index of the item associated to the key (p1,p2)
starting from the item with index @a id.
@@ -434,7 +411,6 @@ protected:
@warning This method should only be called if T inherits from Hashed4. */
int SearchList(int id, int p1, int p2, int p3) const;
int SearchList(int id, int p1, int p2, int p3, int p4) const;
/** @brief Insert the item 'id' into bin 'idx'.
@@ -605,17 +581,6 @@ inline void sort4(int &a, int &b, int &c, int &d)
sort3(b, c, d);
}
inline void sort5(int &a, int &b, int &c, int &d, int &e)
{
sort4(a,b,c,d);
sort4(b,c,d,e);
if (a > b)
{
int t = a; a = b; b = t;
}
}
inline void sort4_ext(int &a, int &b, int &c, int &d)
{
if (d < 0) // support optional last index
@@ -642,12 +607,6 @@ inline T* HashTable<T>::Get(int p1, int p2, int p3, int p4)
return &(Base::At(GetId(p1, p2, p3, p4)));
}
template<typename T>
inline T* HashTable<T>::Get(int p1, int p2, int p3, int p4, int p5)
{
return &(Base::At(GetId(p1, p2, p3, p4, p5)));
}
template<typename T>
int HashTable<T>::GetId(int p1, int p2)
{
@@ -711,39 +670,6 @@ int HashTable<T>::GetId(int p1, int p2, int p3, int p4)
return new_id;
}
template<typename T>
int HashTable<T>::GetId(int p1, int p2, int p3, int p4, int p5)
{
// search for the item in the hashtable
internal::sort5(p1, p2, p3, p4, p5);
int idx = Hash(p1, p2, p3, p4);
int id = SearchList(table[idx], p1, p2, p3, p4);
if (id >= 0) { return id; }
// not found - use an unused item or create a new one
int new_id;
if (unused.Size())
{
new_id = unused.Last();
unused.DeleteLast();
}
else
{
new_id = Base::Append();
}
T& item = Base::At(new_id);
item.p1 = p1;
item.p2 = p2;
item.p3 = p3;
item.p4 = p4;
// insert into hashtable
Insert(idx, new_id, item);
CheckRehash();
return new_id;
}
template<typename T>
inline T* HashTable<T>::Find(int p1, int p2)
{
@@ -758,13 +684,6 @@ inline T* HashTable<T>::Find(int p1, int p2, int p3, int p4)
return (id >= 0) ? &(Base::At(id)) : NULL;
}
template<typename T>
inline T* HashTable<T>::Find(int p1, int p2, int p3, int p4, int p5)
{
int id = FindId(p1, p2, p3, p4, p5);
return (id >= 0) ? &(Base::At(id)) : NULL;
}
template<typename T>
inline const T* HashTable<T>::Find(int p1, int p2) const
{
@@ -779,13 +698,6 @@ inline const T* HashTable<T>::Find(int p1, int p2, int p3, int p4) const
return (id >= 0) ? &(Base::At(id)) : NULL;
}
template<typename T>
inline const T* HashTable<T>::Find(int p1, int p2, int p3, int p4, int p5) const
{
int id = FindId(p1, p2, p3, p4, p5);
return (id >= 0) ? &(Base::At(id)) : NULL;
}
template<typename T>
int HashTable<T>::FindId(int p1, int p2) const
{
@@ -800,13 +712,6 @@ int HashTable<T>::FindId(int p1, int p2, int p3, int p4) const
return SearchList(table[Hash(p1, p2, p3)], p1, p2, p3);
}
template<typename T>
int HashTable<T>::FindId(int p1, int p2, int p3, int p4, int p5) const
{
internal::sort5(p1, p2, p3, p4, p5);
return SearchList(table[Hash(p1, p2, p3, p4)], p1, p2, p3, p4);
}
template<typename T>
int HashTable<T>::SearchList(int id, int p1, int p2) const
{
@@ -831,18 +736,6 @@ int HashTable<T>::SearchList(int id, int p1, int p2, int p3) const
return -1;
}
template<typename T>
int HashTable<T>::SearchList(int id, int p1, int p2, int p3, int p4) const
{
while (id >= 0)
{
const T& item = Base::At(id);
if (item.p1 == p1 && item.p2 == p2 && item.p3 == p3 && item.p4 == p4) { return id; }
id = item.next;
}
return -1;
}
template<typename T>
inline void HashTable<T>::CheckRehash()
{
@@ -984,24 +877,6 @@ void HashTable<T>::Reparent(int id,
Insert(new_idx, id, item);
}
template<typename T>
void HashTable<T>::Reparent(int id,
int new_p1, int new_p2, int new_p3, int new_p4, int new_p5)
{
T& item = Base::At(id);
Unlink(Hash(item), id);
internal::sort5(new_p1, new_p2, new_p3, new_p4, new_p5);
item.p1 = new_p1;
item.p2 = new_p2;
item.p3 = new_p3;
item.p4 = new_p4;
// reinsert under new parent IDs
int new_idx = Hash(new_p1, new_p2, new_p3, new_p4);
Insert(new_idx, id, item);
}
template<typename T>
std::size_t HashTable<T>::MemoryUsage() const
{
+30 -247
View File
@@ -10,7 +10,6 @@
// CONTRIBUTING.md for details.
#include <iostream>
#include "error.hpp"
#include "stable3d.hpp"
@@ -32,6 +31,36 @@ STable3D::STable3D (int nr)
NElem = 0;
}
inline void Sort3 (int &r, int &c, int &f)
{
int t;
if (r > c)
if (c > f)
{
t = r; r = f; f = t; // (r,c,f) --> (f,c,r)
}
else if (r > f)
{
t = r; r = c; c = f; f = t; // (r,c,f) --> (c,f,r)
}
else
{
t = r; r = c; c = t; // (r,c,f) --> (c,r,f)
}
else if (c > f)
{
if (r > f)
{
t = f; f = c; c = r; r = t; // (r,c,f) --> (f,r,c)
}
else
{
t = c; c = f; f = t; // (r,c,f) --> (r,f,c)
}
}
}
int STable3D::Push (int r, int c, int f)
{
STable3DNode *node;
@@ -196,250 +225,4 @@ void STable3D::Print(std::ostream & os) const
}
}
STable4D::STable4D (int nr)
{
int i;
Size = nr;
Rows = new STable4DNode *[nr];
for (i = 0; i < nr; i++)
{
Rows[i] = NULL;
}
NElem = 0;
}
int STable4D::Push (int r, int c, int f, int t)
{
STable4DNode *node;
MFEM_ASSERT(r != c && c != f && f != r && r!=t && c!=t && f!=t,
"STable4D::Push : r = " << r << ", c = " << c << ", f = " << f << ", t = " <<
t);
Sort4(r, c, f, t);
for (node = Rows[r]; node != NULL; node = node->Prev)
{
if (node->Column == c)
if (node->Floor == f)
if (node->Trace == t)
{
return node->Number;
}
}
#ifdef MFEM_USE_MEMALLOC
node = NodesMem.Alloc ();
#else
node = new STable4DNode;
#endif
node->Column = c;
node->Floor = f;
node->Trace = t;
node->Number = NElem;
node->Prev = Rows[r];
Rows[r] = node;
NElem++;
return (NElem-1);
}
int STable4D::operator() (int r, int c, int f, int t) const
{
STable4DNode *node;
Sort4(r, c, f, t);
for (node = Rows[r]; node != NULL; node = node->Prev)
{
if (node->Column == c)
if (node->Floor == f)
if (node->Trace == t)
{
return node->Number;
}
}
MFEM_ABORT("STable4D::operator(): (r,c,f,t) = (" << r << "," << c << "," << f <<
"," << t <<")");
return -1;
}
int STable4D::Index (int r, int c, int f, int t) const
{
STable4DNode *node;
Sort4(r, c, f, t);
for (node = Rows[r]; node != NULL; node = node->Prev)
{
if (node->Column == c)
if (node->Floor == f)
if (node->Trace == t)
{
return node->Number;
}
}
return -1;
}
STable4D::~STable4D ()
{
#ifdef MFEM_USE_MEMALLOC
// NodesMem.Clear(); // this is done implicitly
#else
for (int i = 0; i < Size; i++)
{
STable4DNode *aux, *node_p = Rows[i];
while (node_p != NULL)
{
aux = node_p;
node_p = node_p->Prev;
delete aux;
}
}
#endif
delete [] Rows;
}
STable5D::STable5D (int nr)
{
int i;
Size = nr;
Rows = new STable5DNode *[nr];
for (i = 0; i < nr; i++)
{
Rows[i] = NULL;
}
NElem = 0;
}
int STable5D::Push (int r, int c, int f, int t, int u)
{
STable5DNode *node;
MFEM_ASSERT(r != c && c != f && f != r && r!=t && c!=t && f!=t && r!=u &&
c!=u && f!=u && t!=u,
"STable5D::Push : r = " << r << ", c = " << c << ", f = " << f << ", t = " << t
<< ", u = " << u);
Sort5(r, c, f, t, u);
for (node = Rows[r]; node != NULL; node = node->Prev)
{
if (node->Column == c)
if (node->Floor == f)
if (node->Trace == t)
if (node->Next == u)
{
return node->Number;
}
}
#ifdef MFEM_USE_MEMALLOC
node = NodesMem.Alloc ();
#else
node = new STable5DNode;
#endif
node->Column = c;
node->Floor = f;
node->Trace = t;
node->Next = u;
node->Number = NElem;
node->Prev = Rows[r];
Rows[r] = node;
NElem++;
return (NElem-1);
}
int STable5D::operator() (int r, int c, int f, int t, int u) const
{
STable5DNode *node;
Sort5(r, c, f, t, u);
for (node = Rows[r]; node != NULL; node = node->Prev)
{
if (node->Column == c)
if (node->Floor == f)
if (node->Trace == t)
if (node->Next == u)
{
return node->Number;
}
}
MFEM_ABORT("STable4D::operator(): (r,c,f,t,u) = (" << r << "," << c << "," << f
<< "," << t << "," << u <<")");
return 0;
}
int STable5D::Index (int r, int c, int f, int t, int u) const
{
STable5DNode *node;
Sort5(r, c, f, t, u);
for (node = Rows[r]; node != NULL; node = node->Prev)
{
if (node->Column == c)
if (node->Floor == f)
if (node->Trace == t)
{
return node->Number;
}
}
return -1;
}
int STable5D::Push8 (int u1, int u2, int u3, int u4, int u5, int u6, int u7,
int u8)
{
Sort8(u1, u2, u3, u4, u5, u6, u7, u8);
return (*this).Push(u1,u2,u3,u4,u5);
}
int STable5D::operator() (int u1, int u2, int u3, int u4, int u5, int u6,
int u7, int u8) const
{
Sort8(u1, u2, u3, u4, u5, u6, u7, u8);
return (*this)(u1,u2,u3,u4,u5);
}
STable5D::~STable5D ()
{
#ifdef MFEM_USE_MEMALLOC
// NodesMem.Clear(); // this is done implicitly
#else
for (int i = 0; i < Size; i++)
{
STable5DNode *aux, *node_p = Rows[i];
while (node_p != NULL)
{
aux = node_p;
node_p = node_p->Prev;
delete aux;
}
}
#endif
delete [] Rows;
}
}
-159
View File
@@ -75,165 +75,6 @@ public:
~STable3D ();
};
class STable4DNode
{
public:
STable4DNode *Prev;
int Column, Floor, Trace, Number;
};
/// Symmetric 4D Table
class STable4D
{
private:
int Size, NElem;
STable4DNode **Rows;
#ifdef MFEM_USE_MEMALLOC
MemAlloc <STable4DNode, 1024> NodesMem;
#endif
public:
explicit STable4D (int nr);
int Push (int r, int c, int f, int t);
int operator() (int r, int c, int f, int t) const;
int Index (int r, int c, int f, int t) const;
int NumberOfElements() { return NElem; };
~STable4D ();
};
class STable5DNode
{
public:
STable5DNode *Prev;
int Column, Floor, Trace, Next, Number;
};
/// Symmetric 5D Table
class STable5D
{
private:
int Size, NElem;
STable5DNode **Rows;
#ifdef MFEM_USE_MEMALLOC
MemAlloc <STable5DNode, 1024> NodesMem;
#endif
public:
explicit STable5D (int nr);
int Push (int r, int c, int f, int t, int u);
int operator() (int r, int c, int f, int t, int u) const;
int Index (int r, int c, int f, int t, int u) const;
int Push8 (int u1, int u2, int u3, int u4, int u5, int u6, int u7, int u8);
int operator() (int u1, int u2, int u3, int u4, int u5, int u6, int u7,
int u8) const;
int NumberOfElements() { return NElem; };
~STable5D ();
};
inline void Sort3 (int &r, int &c, int &f)
{
int t;
if (r > c)
if (c > f)
{
t = r; r = f; f = t; // (r,c,f) --> (f,c,r)
}
else if (r > f)
{
t = r; r = c; c = f; f = t; // (r,c,f) --> (c,f,r)
}
else
{
t = r; r = c; c = t; // (r,c,f) --> (c,r,f)
}
else if (c > f)
{
if (r > f)
{
t = f; f = c; c = r; r = t; // (r,c,f) --> (f,r,c)
}
else
{
t = c; c = f; f = t; // (r,c,f) --> (r,f,c)
}
}
}
inline void Sort4 (int &r, int &c, int &f, int &u)
{
Sort3(c,f,u);
int t;
if (r > c)
{
if (r <= f) //(r, c, f, u) --> (c, r, f, u)
{
t = r; r = c; c = t;
}
else if (r <= u) //(r, c, f, u) --> (c, f, r, u)
{
t = r; r = c; c = t;
t = c; c = f; f = t;
}
else if (r > u) //(r, c, f, u) --> (c, f, u, r)
{
t = r; r = c; c = t;
t = c; c = f; f = t;
t = f; f = u; u = t;
}
}
}
inline void Sort5 (int &r, int &c, int &f, int &u, int &v)
{
Sort4(r,c,f,u);
Sort4(c,f,u,v);
if (r > c)
{
int t = r; r = c; c = t;
}
}
//should be optimized
inline void Sort8 (int &u1, int &u2, int &u3, int &u4, int &u5, int &u6,
int &u7, int &u8)
{
Sort5(u1,u2,u3,u4,u5);
Sort5(u4,u5,u6,u7,u8);
Sort5(u1,u2,u3,u4,u5);
Sort5(u4,u5,u6,u7,u8);
Sort5(u1,u2,u3,u4,u5);
Sort5(u4,u5,u6,u7,u8);
Sort5(u1,u2,u3,u4,u5);
Sort5(u4,u5,u6,u7,u8);
}
}
#endif
+72
View File
@@ -37,6 +37,78 @@ Table::Table(const Table &table)
}
}
Table::Table(const Table &table1,
const Table &table2, int offset)
{
MFEM_ASSERT(table1.size == table2.size,
"Tables have different sizes can not merge.");
size = table1.size;
const int nnz = table1.I[size] + table2.I[size];
I.New(size+1, table1.I.GetMemoryType());
J.New(nnz, table1.J.GetMemoryType());
I[0] = 0;
Array<int> row;
for (int i = 0; i < size; i++)
{
I[i+1] = I[i];
table1.GetRow(i, row);
for (int r = 0; r < row.Size(); r++, I[i+1] ++)
{
J[ I[i+1] ] = row[r];
}
table2.GetRow(i, row);
for (int r = 0; r < row.Size(); r++, I[i+1] ++)
{
J[ I[i+1] ] = (row[r] < 0) ? row[r] - offset : row[r] + offset;
}
}
}
Table::Table(const Table &table1,
const Table &table2, int offset2,
const Table &table3, int offset3)
{
MFEM_ASSERT(table1.size == table2.size,
"Tables have different sizes can not merge.");
MFEM_ASSERT(table1.size == table3.size,
"Tables have different sizes can not merge.");
size = table1.size;
const int nnz = table1.I[size] + table2.I[size] + table3.I[size];
I.New(size+1, table1.I.GetMemoryType());
J.New(nnz, table1.J.GetMemoryType());
I[0] = 0;
Array<int> row;
for (int i = 0; i < size; i++)
{
I[i+1] = I[i];
table1.GetRow(i, row);
for (int r = 0; r < row.Size(); r++, I[i+1] ++)
{
J[ I[i+1] ] = row[r];
}
table2.GetRow(i, row);
for (int r = 0; r < row.Size(); r++, I[i+1] ++)
{
J[ I[i+1] ] = (row[r] < 0) ? row[r] - offset2 : row[r] + offset2;
}
table3.GetRow(i, row);
for (int r = 0; r < row.Size(); r++, I[i+1] ++)
{
J[ I[i+1] ] = (row[r] < 0) ? row[r] - offset3 : row[r] + offset3;
}
}
}
Table& Table::operator=(const Table &rhs)
{
Clear();
+8
View File
@@ -58,6 +58,14 @@ public:
/// Copy constructor
Table(const Table &);
/** Merge constructors
This is used to combine two or three tables into one table.*/
Table(const Table &table1,
const Table &table2, int offset2);
Table(const Table &table1,
const Table &table2, int offset2,
const Table &table3, int offset3);
/// Assignment operator: deep copy
Table& operator=(const Table &rhs);
+1
View File
@@ -44,6 +44,7 @@ list(APPEND HDRS
handle.hpp
invariants.hpp
kernels.hpp
lapack.hpp
linalg.hpp
matrix.hpp
ode.hpp
+20 -138
View File
@@ -10,60 +10,9 @@
// CONTRIBUTING.md for details.
#include "complex_densemat.hpp"
#include "lapack.hpp"
#include <complex>
#ifdef MFEM_USE_LAPACK
#ifdef MFEM_USE_SINGLE
extern "C" void
cgetrf_(int *, int *, std::complex<float> *, int *, int *, int *);
extern "C" void
cgetrs_(char *, int *, int *, std::complex<float> *, int *, int *,
std::complex<float> *, int *, int *);
extern "C" void
cgetri_(int *, std::complex<float> *, int *, int *,
std::complex<float> *, int *, int *);
extern "C" void
ctrsm_(char *, char *, char *, char *, int *, int *, std::complex<float> *,
std::complex<float> *, int *, std::complex<float> *, int *);
extern "C" void
cpotrf_(char *, int *, std::complex<float> *, int *, int *);
extern "C" void
ctrtrs_(char *, char*, char *, int *, int *, std::complex<float> *, int *,
std::complex<float> *, int *, int *);
extern "C" void
cpotri_(char *, int *, std::complex<float> *, int*, int *);
extern "C" void
cpotrs_(char *, int *, int *, std::complex<float> *, int *,
std::complex<float> *, int *, int *);
#elif defined MFEM_USE_DOUBLE
extern "C" void
zgetrf_(int *, int *, std::complex<double> *, int *, int *, int *);
extern "C" void
zgetrs_(char *, int *, int *, std::complex<double> *, int *, int *,
std::complex<double> *, int *, int *);
extern "C" void
zgetri_(int *, std::complex<double> *, int *, int *,
std::complex<double> *, int *, int *);
extern "C" void
ztrsm_(char *, char *, char *, char *, int *, int *, std::complex<double> *,
std::complex<double> *, int *, std::complex<double> *, int *);
extern "C" void
zpotrf_(char *, int *, std::complex<double> *, int *, int *);
extern "C" void
ztrtrs_(char *, char*, char *, int *, int *, std::complex<double> *, int *,
std::complex<double> *, int *, int *);
extern "C" void
zpotri_(char *, int *, std::complex<double> *, int*, int *);
extern "C" void
zpotrs_(char *, int *, int *, std::complex<double> *, int *,
std::complex<double> *, int *, int *);
#endif
#endif
namespace mfem
{
@@ -175,35 +124,17 @@ ComplexDenseMatrix * ComplexDenseMatrix::ComputeInverse()
std::complex<real_t> qwork, *work;
int info;
#ifdef MFEM_USE_SINGLE
cgetrf_(&w, &w, data, &w, ipiv, &info);
#elif defined MFEM_USE_DOUBLE
zgetrf_(&w, &w, data, &w, ipiv, &info);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(getrf_)(&w, &w, data, &w, ipiv, &info);
if (info)
{
mfem_error("DenseMatrix::Invert() : Error in ZGETRF");
}
#ifdef MFEM_USE_SINGLE
cgetri_(&w, data, &w, ipiv, &qwork, &lwork, &info);
#elif defined MFEM_USE_DOUBLE
zgetri_(&w, data, &w, ipiv, &qwork, &lwork, &info);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(getri_)(&w, data, &w, ipiv, &qwork, &lwork, &info);
lwork = (int) qwork.real();
work = new std::complex<real_t>[lwork];
#ifdef MFEM_USE_SINGLE
cgetri_(&w, data, &w, ipiv, work, &lwork, &info);
#elif defined MFEM_USE_DOUBLE
zgetri_(&w, data, &w, ipiv, work, &lwork, &info);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(getri_)(&w, data, &w, ipiv, work, &lwork, &info);
if (info)
{
mfem_error("DenseMatrix::Invert() : Error in ZGETRI");
@@ -493,11 +424,7 @@ bool ComplexLUFactors::Factor(int m, real_t TOL)
#ifdef MFEM_USE_LAPACK
int info = 0;
MFEM_VERIFY(data, "Matrix data not set");
#ifdef MFEM_USE_SINGLE
if (m) { cgetrf_(&m, &m, data, &m, ipiv, &info); }
#elif defined MFEM_USE_DOUBLE
if (m) { zgetrf_(&m, &m, data, &m, ipiv, &info); }
#endif
if (m) { MFEM_LAPACK_COMPLEX(getrf_)(&m, &m, data, &m, ipiv, &info); }
return info == 0;
#else
// compiling without LAPACK
@@ -659,13 +586,10 @@ void ComplexLUFactors::Solve(int m, int n, real_t *X_r, real_t * X_i) const
std::complex<real_t> * x = ComplexFactors::RealToComplex(m*n,X_r,X_i);
char trans = 'N';
int info = 0;
#ifdef MFEM_USE_SINGLE
if (m > 0 && n > 0) { cgetrs_(&trans, &m, &n, data, &m, ipiv, x, &m, &info); }
#elif defined MFEM_USE_DOUBLE
if (m > 0 && n > 0) { zgetrs_(&trans, &m, &n, data, &m, ipiv, x, &m, &info); }
#else
MFEM_ABORT("Floating point type undefined");
#endif
if (m > 0 && n > 0)
{
MFEM_LAPACK_COMPLEX(getrs_)(&trans, &m, &n, data, &m, ipiv, x, &m, &info);
}
MFEM_VERIFY(!info, "LAPACK: error in ZGETRS");
ComplexFactors::ComplexToReal(m*n,x,X_r,X_i);
delete [] x;
@@ -685,15 +609,8 @@ void ComplexLUFactors::RightSolve(int m, int n, real_t *X_r, real_t * X_i) const
if (m > 0 && n > 0)
{
std::complex<real_t> alpha(1.0,0.0);
#ifdef MFEM_USE_SINGLE
ctrsm_(&side,&u_ch,&n_ch,&n_ch,&n,&m,&alpha,data,&m,X,&n);
ctrsm_(&side,&l_ch,&n_ch,&u_ch,&n,&m,&alpha,data,&m,X,&n);
#elif defined MFEM_USE_DOUBLE
ztrsm_(&side,&u_ch,&n_ch,&n_ch,&n,&m,&alpha,data,&m,X,&n);
ztrsm_(&side,&l_ch,&n_ch,&u_ch,&n,&m,&alpha,data,&m,X,&n);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(trsm_)(&side,&u_ch,&n_ch,&n_ch,&n,&m,&alpha,data,&m,X,&n);
MFEM_LAPACK_COMPLEX(trsm_)(&side,&l_ch,&n_ch,&u_ch,&n,&m,&alpha,data,&m,X,&n);
}
#else
// compiling without LAPACK
@@ -815,13 +732,7 @@ bool ComplexCholeskyFactors::Factor(int m, real_t TOL)
int info = 0;
char uplo = 'L';
MFEM_VERIFY(data, "Matrix data not set");
#ifdef MFEM_USE_SINGLE
if (m) {cpotrf_(&uplo, &m, data, &m, &info);}
#elif defined MFEM_USE_DOUBLE
if (m) {zpotrf_(&uplo, &m, data, &m, &info);}
#else
MFEM_ABORT("Floating point type undefined");
#endif
if (m) { MFEM_LAPACK_COMPLEX(potrf_)(&uplo, &m, data, &m, &info); }
return info == 0;
#else
// CholeskyCrout algorithm
@@ -921,13 +832,8 @@ void ComplexCholeskyFactors::LSolve(int m, int n, real_t * X_r,
char diag = 'N';
int info = 0;
#ifdef MFEM_USE_SINGLE
ctrtrs_(&uplo, &trans, &diag, &m, &n, data, &m, x, &m, &info);
#elif defined MFEM_USE_DOUBLE
ztrtrs_(&uplo, &trans, &diag, &m, &n, data, &m, x, &m, &info);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(trtrs_)(&uplo, &trans, &diag, &m, &n, data, &m, x, &m,
&info);
MFEM_VERIFY(!info, "ComplexCholeskyFactors:LSolve:: info");
#else
for (int k = 0; k < n; k++)
@@ -960,13 +866,8 @@ void ComplexCholeskyFactors::USolve(int m, int n, real_t * X_r,
char diag = 'N';
int info = 0;
#ifdef MFEM_USE_SINGLE
ctrtrs_(&uplo, &trans, &diag, &m, &n, data, &m, x, &m, &info);
#elif defined MFEM_USE_DOUBLE
ztrtrs_(&uplo, &trans, &diag, &m, &n, data, &m, x, &m, &info);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(trtrs_)(&uplo, &trans, &diag, &m, &n, data, &m, x, &m,
&info);
MFEM_VERIFY(!info, "ComplexCholeskyFactors:USolve:: info");
#else
// X <- L^{-t} X
@@ -994,13 +895,7 @@ void ComplexCholeskyFactors::Solve(int m, int n, real_t * X_r,
char uplo = 'L';
int info = 0;
std::complex<real_t> *x = ComplexFactors::RealToComplex(m*n,X_r,X_i);
#ifdef MFEM_USE_SINGLE
cpotrs_(&uplo, &m, &n, data, &m, x, &m, &info);
#elif defined MFEM_USE_DOUBLE
zpotrs_(&uplo, &m, &n, data, &m, x, &m, &info);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(potrs_)(&uplo, &m, &n, data, &m, x, &m, &info);
MFEM_VERIFY(!info, "ComplexCholeskyFactors:Solve:: info");
ComplexFactors::ComplexToReal(m*n,x,X_r,X_i);
delete x;
@@ -1026,15 +921,8 @@ void ComplexCholeskyFactors::RightSolve(int m, int n, real_t * X_r,
std::complex<real_t> alpha(1.0,0.0);
if (m > 0 && n > 0)
{
#ifdef MFEM_USE_SINGLE
ctrsm_(&side,&uplo,&transt,&diag,&n,&m,&alpha,data,&m,x,&n);
ctrsm_(&side,&uplo,&trans,&diag,&n,&m,&alpha,data,&m,x,&n);
#elif defined MFEM_USE_DOUBLE
ztrsm_(&side,&uplo,&transt,&diag,&n,&m,&alpha,data,&m,x,&n);
ztrsm_(&side,&uplo,&trans,&diag,&n,&m,&alpha,data,&m,x,&n);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(trsm_)(&side,&uplo,&transt,&diag,&n,&m,&alpha,data,&m,x,&n);
MFEM_LAPACK_COMPLEX(trsm_)(&side,&uplo,&trans,&diag,&n,&m,&alpha,data,&m,x,&n);
}
#else
// X <- X L^{-H}
@@ -1085,13 +973,7 @@ void ComplexCholeskyFactors::GetInverseMatrix(int m, real_t * X_r,
}
char uplo = 'L';
int info = 0;
#ifdef MFEM_USE_SINGLE
cpotri_(&uplo, &m, X, &m, &info);
#elif defined MFEM_USE_DOUBLE
zpotri_(&uplo, &m, X, &m, &info);
#else
MFEM_ABORT("Floating point type undefined");
#endif
MFEM_LAPACK_COMPLEX(potri_)(&uplo, &m, X, &m, &info);
MFEM_VERIFY(!info, "ComplexCholeskyFactors:GetInverseMatrix:: info");
// fill in the upper triangular part
for (int i = 0; i<m; i++)
+485 -625
View File
File diff suppressed because it is too large Load Diff
+24 -8
View File
@@ -272,35 +272,51 @@ public:
/// Compute the square of the Frobenius norm of the matrix
real_t FNorm2() const { real_t s, n2; FNorm(s, n2); return s*s*n2; }
/// Compute eigenvalues of A x = ev x where A = *this
/** Compute eigenvalues of A x = ev x where A = *this
A is assumed to be symmetric. */
void Eigenvalues(Vector &ev)
{ Eigensystem(ev); }
/// Compute eigenvalues and eigenvectors of A x = ev x where A = *this
/** Compute ith eigenvalue of A x = ev x where A = *this
A is assumed to be symmetric. */
real_t Eigenvalue(int i = -1);
/** Compute eigenvalues and eigenvectors of A x = ev x where A = *this
A is assumed to be symmetric. */
void Eigenvalues(Vector &ev, DenseMatrix &evect)
{ Eigensystem(ev, &evect); }
/// Compute eigenvalues and eigenvectors of A x = ev x where A = *this
/** Compute eigenvalues and eigenvectors of A x = ev x where A = *this
A is assumed to be symmetric. */
void Eigensystem(Vector &ev, DenseMatrix &evect)
{ Eigensystem(ev, &evect); }
/** Compute generalized eigenvalues and eigenvectors of A x = ev B x,
where A = *this */
/** Compute generalized eigenvalues of A x = ev B x, where A = *this
A and B are assumed to be symmetric. */
void Eigenvalues(DenseMatrix &b, Vector &ev)
{ Eigensystem(b, ev); }
/// Compute generalized eigenvalues of A x = ev B x, where A = *this
/** Compute ith eigenvalue of A x = ev B x where A = *this
A and B are assumed to be symmetric. */
real_t Eigenvalue(DenseMatrix &b, int i = -1);
/** Compute generalized eigenvalues and eigenvectors of A x = ev B x,
where A = *this. A and B are assumed to be symmetric.*/
void Eigenvalues(DenseMatrix &b, Vector &ev, DenseMatrix &evect)
{ Eigensystem(b, ev, &evect); }
/** Compute generalized eigenvalues and eigenvectors of A x = ev B x,
where A = *this */
where A = *this. A and B are assumed to be symmetric.*/
void Eigensystem(DenseMatrix &b, Vector &ev, DenseMatrix &evect)
{ Eigensystem(b, ev, &evect); }
void SingularValues(Vector &sv) const;
int Rank(real_t tol) const;
/** Compute the Null Space of the matrix, such that A x = 0,
where A = *this* and x is a column of ns */
void NullSpace(DenseMatrix &ns, real_t tol);
/// Return the i-th singular value (decreasing order) of NxN matrix, N=1,2,3.
real_t CalcSingularvalue(const int i) const;
@@ -322,7 +338,6 @@ public:
void SetCol(int c, const real_t* col);
void SetCol(int c, const Vector &col);
/// Set all entries of a row to the specified value.
void SetRow(int row, real_t value);
/// Set all entries of a column to the specified value.
@@ -346,6 +361,7 @@ public:
void Transpose(const DenseMatrix &A);
/// (*this) = 1/2 ((*this) + (*this)^t)
void Symmetrize();
bool IsSymmetric(real_t tol = 1e-10);
void Lump();
-1
View File
@@ -3513,7 +3513,6 @@ HypreSmoother::HypreSmoother() : Solver()
omega = 1.0;
poly_order = 2;
poly_fraction = .3;
poly_iter = 10;
lambda = 0.5;
mu = -0.5;
taubin_iter = 40;
-2
View File
@@ -1049,8 +1049,6 @@ protected:
real_t poly_fraction;
/// Apply the polynomial smoother to A or D^{-1/2} A D^{-1/2}
int poly_scale;
/// Number of CG iterations to determine eigenvalue estimates, 0 means the max norm
int poly_iter;
/// Taubin's lambda-mu method parameters
real_t lambda;
+141
View File
@@ -0,0 +1,141 @@
// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
// LICENSE and NOTICE for details. LLNL-CODE-806117.
//
// This file is part of the MFEM library. For more information and source code
// availability visit https://mfem.org.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the BSD-3 license. We welcome feedback and contributions, see file
// CONTRIBUTING.md for details.
#ifndef MFEM_LAPACK_HPP
#define MFEM_LAPACK_HPP
#include "../config/config.hpp"
#ifdef MFEM_USE_LAPACK
#ifdef MFEM_USE_SINGLE
#define MFEM_LAPACK_PREFIX(stub) s##stub
#define MFEM_LAPACK_COMPLEX(stub) c##stub
#elif defined(MFEM_USE_DOUBLE)
#define MFEM_LAPACK_PREFIX(stub) d##stub
#define MFEM_LAPACK_COMPLEX(stub) z##stub
#endif
namespace mfem
{
extern "C" void
MFEM_LAPACK_PREFIX(gemm_)(char *, char *, int *, int *, int *, real_t *,
real_t *, int *, real_t *, int *, real_t *, real_t *,
int *);
extern "C" void
MFEM_LAPACK_PREFIX(getrf_)(int *, int *, real_t *, int *, int *, int *);
extern "C" void
MFEM_LAPACK_PREFIX(getrs_)(char *, int *, int *, real_t *, int *, int *,
real_t *, int *, int *);
extern "C" void
MFEM_LAPACK_PREFIX(getri_)(int *N, real_t *A, int *LDA, int *IPIV, real_t *WORK,
int *LWORK, int *INFO);
extern "C" void
MFEM_LAPACK_PREFIX(syevr_)(char *JOBZ, char *RANGE, char *UPLO, int *N,
real_t *A, int *LDA, real_t *VL, real_t *VU, int *IL,
int *IU, real_t *ABSTOL, int *M, real_t *W,
real_t *Z, int *LDZ, int *ISUPPZ, real_t *WORK,
int *LWORK, int *IWORK, int *LIWORK, int *INFO);
extern "C" void
MFEM_LAPACK_PREFIX(syev_)(char *JOBZ, char *UPLO, int *N, real_t *A, int *LDA,
real_t *W, real_t *WORK, int *LWORK, int *INFO);
extern "C" void
MFEM_LAPACK_PREFIX(sygv_) (int *ITYPE, char *JOBZ, char *UPLO, int * N,
real_t *A, int *LDA, real_t *B, int *LDB, real_t *W,
real_t *WORK, int *LWORK, int *INFO);
extern "C" void
MFEM_LAPACK_PREFIX(sygvx_)(int *ITYPE, char *JOBZ, char *RANGE, char *UPLO,
int *N, double *A, int *LDA, double *B, int *LDB,
double *VL, double *VU, int *IL, int *IU,
double *ABSTOL, int *M, double *W, double *Z,
int *LDZ, double *WORK, int *LWORK,int *IWORK,
int *IFAIL, int *INFO);
extern "C" void
MFEM_LAPACK_PREFIX(gesvd_)(char *JOBU, char *JOBVT, int *M, int *N, real_t *A,
int *LDA, real_t *S, real_t *U, int *LDU, real_t *VT,
int *LDVT, real_t *WORK, int *LWORK, int *INFO);
extern "C" void
MFEM_LAPACK_PREFIX(trsm_)(char *side, char *uplo, char *transa, char *diag,
int *m, int *n, real_t *alpha, real_t *a, int *lda,
real_t *b, int *ldb);
extern "C" void
MFEM_LAPACK_PREFIX(ggev_)(char *jobvl, char *jobvr, int *n, real_t *a, int *lda,
real_t *B, int *ldb, real_t *alphar, real_t *alphai,
real_t *beta, real_t *vl, int * ldvl, real_t * vr,
int * ldvr, real_t * work, int * lwork, int* info);
// Cholesky factorizations/solves
extern "C" void
MFEM_LAPACK_PREFIX(potrf_)(char *, int *, real_t *, int *, int *);
// Solve
extern "C" void
MFEM_LAPACK_PREFIX(potrs_)(char *, int *, int *, real_t *, int *, real_t *,
int *, int *);
// Triangular Solves
extern "C" void
MFEM_LAPACK_PREFIX(trtrs_)(char *, char*, char *, int *, int *, real_t *, int *,
real_t *, int *, int *);
extern "C" void
MFEM_LAPACK_PREFIX(potri_)(char *, int *, real_t *, int*, int *);
// LAPACK routines for NNLSSolver
extern "C" void
MFEM_LAPACK_PREFIX(ormqr_)(char *, char *, int *, int *, int *, real_t *, int*,
real_t *, real_t *, int *, real_t *, int*, int*);
extern "C" void
MFEM_LAPACK_PREFIX(geqrf_)(int *, int *, real_t *, int *, real_t *, real_t *,
int *, int *);
extern "C" void
MFEM_LAPACK_PREFIX(gemv_)(char *, int *, int *, real_t *, real_t *, int *,
real_t *, int *, real_t *, real_t *, int *);
extern "C" void
MFEM_LAPACK_PREFIX(trsm_)(char *side, char *uplo, char *transa, char *diag,
int *m, int *n, real_t *alpha, real_t *a, int *lda,
real_t *b, int *ldb);
// Complex
extern "C" void
MFEM_LAPACK_COMPLEX(getrf_)(int *, int *, std::complex<real_t> *, int *, int *,
int *);
extern "C" void
MFEM_LAPACK_COMPLEX(getrs_)(char *, int *, int *, std::complex<real_t> *, int *,
int *, std::complex<real_t> *, int *, int *);
extern "C" void
MFEM_LAPACK_COMPLEX(getri_)(int *, std::complex<real_t> *, int *, int *,
std::complex<real_t> *, int *, int *);
extern "C" void
MFEM_LAPACK_COMPLEX(trsm_)(char *, char *, char *, char *, int *, int *,
std::complex<real_t> *, std::complex<real_t> *,
int *, std::complex<real_t> *, int *);
extern "C" void
MFEM_LAPACK_COMPLEX(potrf_)(char *, int *, std::complex<real_t> *, int *,
int *);
extern "C" void
MFEM_LAPACK_COMPLEX(trtrs_)(char *, char*, char *, int *, int *,
std::complex<real_t> *, int *,
std::complex<real_t> *, int *, int *);
extern "C" void
MFEM_LAPACK_COMPLEX(potri_)(char *, int *, std::complex<real_t> *, int*, int *);
extern "C" void
MFEM_LAPACK_COMPLEX(potrs_)(char *, int *, int *, std::complex<real_t> *, int *,
std::complex<real_t> *, int *, int *);
}
#endif
#endif
+53 -138
View File
@@ -10,6 +10,7 @@
// CONTRIBUTING.md for details.
#include "linalg.hpp"
#include "lapack.hpp"
#include "../general/annotation.hpp"
#include "../general/forall.hpp"
#include "../general/globals.hpp"
@@ -3543,38 +3544,6 @@ void AuxSpaceSmoother::Mult(const Vector &x, Vector &y, bool transpose) const
#endif // MFEM_USE_MPI
#ifdef MFEM_USE_LAPACK
// LAPACK routines for NNLSSolver
#ifdef MFEM_USE_SINGLE
extern "C" void
sormqr_(char *, char *, int *, int *, int *, float *, int*, float *,
float *, int *, float *, int*, int*);
extern "C" void
sgeqrf_(int *, int *, float *, int *, float *, float *, int *, int *);
extern "C" void
sgemv_(char *, int *, int *, float *, float *, int *, float *, int *,
float *, float *, int *);
extern "C" void
strsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n,
float *alpha, float *a, int *lda, float *b, int *ldb);
#elif defined MFEM_USE_DOUBLE
extern "C" void
dormqr_(char *, char *, int *, int *, int *, double *, int*, double *,
double *, int *, double *, int*, int*);
extern "C" void
dgeqrf_(int *, int *, double *, int *, double *, double *, int *, int *);
extern "C" void
dgemv_(char *, int *, int *, double *, double *, int *, double *, int *,
double *, double *, int *);
extern "C" void
dtrsm_(char *side, char *uplo, char *transa, char *diag, int *m, int *n,
double *alpha, double *a, int *lda, double *b, int *ldb);
#endif
NNLSSolver::NNLSSolver()
: Solver(0), mat(nullptr), const_tol_(1.0e-14), min_nnz_(0),
@@ -3938,25 +3907,19 @@ void NNLSSolver::Solve(const Vector& rhs_lb, const Vector& rhs_ub,
lwork = -1;
work.resize(10);
#ifdef MFEM_USE_SINGLE
sormqr_(&lside, &trans, &m, &n_update, &i_qr_start,
#elif defined MFEM_USE_DOUBLE
dormqr_(&lside, &trans, &m, &n_update, &i_qr_start,
#endif
mat_qr_data.GetData(), &m, tau.GetData(),
mat_qr_data.GetData() + (i_qr_start * m), &m,
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(ormqr_)(&lside, &trans, &m, &n_update,
&i_qr_start, mat_qr_data.GetData(), &m,
tau.GetData(),
mat_qr_data.GetData() + (i_qr_start * m),
&m, work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // Q^T A update work calculation failed
lwork = static_cast<int>(work[0]);
work.resize(lwork);
#ifdef MFEM_USE_SINGLE
sormqr_(&lside, &trans, &m, &n_update, &i_qr_start,
#elif defined MFEM_USE_DOUBLE
dormqr_(&lside, &trans, &m, &n_update, &i_qr_start,
#endif
mat_qr_data.GetData(), &m, tau.GetData(),
mat_qr_data.GetData() + (i_qr_start * m), &m,
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(ormqr_)(&lside, &trans, &m, &n_update,
&i_qr_start, mat_qr_data.GetData(), &m,
tau.GetData(),
mat_qr_data.GetData() + (i_qr_start * m),
&m, work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // Q^T A update failed
// Compute QR factorization of the submatrix
lwork = -1;
@@ -3977,24 +3940,16 @@ void NNLSSolver::Solve(const Vector& rhs_lb, const Vector& rhs_ub,
sub_tau[j] = tau[i_qr_start + j];
}
#ifdef MFEM_USE_SINGLE
sgeqrf_(&m_update, &n_update,
#elif defined MFEM_USE_DOUBLE
dgeqrf_(&m_update, &n_update,
#endif
submat_data.GetData(), &m_update, sub_tau.GetData(),
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(geqrf_)(&m_update, &n_update, submat_data.GetData(),
&m_update, sub_tau.GetData(), work.data(),
&lwork, &info);
MFEM_VERIFY(info == 0, ""); // QR update factorization work calc
lwork = static_cast<int>(work[0]);
if (lwork == 0) { lwork = 1; }
work.resize(lwork);
#ifdef MFEM_USE_SINGLE
sgeqrf_(&m_update, &n_update,
#elif defined MFEM_USE_DOUBLE
dgeqrf_(&m_update, &n_update,
#endif
submat_data.GetData(), &m_update, sub_tau.GetData(),
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(geqrf_)(&m_update, &n_update, submat_data.GetData(),
&m_update, sub_tau.GetData(), work.data(),
&lwork, &info);
MFEM_VERIFY(info == 0, ""); // QR update factorization failed
// Copy result back
@@ -4023,23 +3978,13 @@ void NNLSSolver::Solve(const Vector& rhs_lb, const Vector& rhs_ub,
// perform qr)
lwork = -1;
work.resize(10);
#ifdef MFEM_USE_SINGLE
sgeqrf_(&m, &n_glob,
#elif defined MFEM_USE_DOUBLE
dgeqrf_(&m, &n_glob,
#endif
mat_qr_data.GetData(), &m, tau.GetData(),
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(geqrf_)(&m, &n_glob, mat_qr_data.GetData(), &m,
tau.GetData(), work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // QR factorization work calculation
lwork = static_cast<int>(work[0]);
work.resize(lwork);
#ifdef MFEM_USE_SINGLE
sgeqrf_(&m, &n_glob,
#elif defined MFEM_USE_DOUBLE
dgeqrf_(&m, &n_glob,
#endif
mat_qr_data.GetData(), &m, tau.GetData(),
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(geqrf_)(&m, &n_glob, mat_qr_data.GetData(), &m,
tau.GetData(), work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // QR factorization failed
}
@@ -4067,25 +4012,17 @@ void NNLSSolver::Solve(const Vector& rhs_lb, const Vector& rhs_ub,
sub_tau[0] = tau[i_qr_start];
#ifdef MFEM_USE_SINGLE
sormqr_(&lside, &trans, &m_update, &ione, &ione,
#elif defined MFEM_USE_DOUBLE
dormqr_(&lside, &trans, &m_update, &ione, &ione,
#endif
submat_data.GetData(), &m_update, sub_tau.GetData(),
sub_qt.GetData(), &m_update,
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(ormqr_)(&lside, &trans, &m_update, &ione, &ione,
submat_data.GetData(), &m_update,
sub_tau.GetData(), sub_qt.GetData(),
&m_update, work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // H_last y work calculation failed
lwork = static_cast<int>(work[0]);
work.resize(lwork);
#ifdef MFEM_USE_SINGLE
sormqr_(&lside, &trans, &m_update, &ione, &ione,
#elif defined MFEM_USE_DOUBLE
dormqr_(&lside, &trans, &m_update, &ione, &ione,
#endif
submat_data.GetData(), &m_update, sub_tau.GetData(),
sub_qt.GetData(), &m_update,
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(ormqr_)(&lside, &trans, &m_update, &ione, &ione,
submat_data.GetData(), &m_update,
sub_tau.GetData(), sub_qt.GetData(),
&m_update, work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // H_last y failed
// Copy result back
for (int i=0; i<m_update; ++i)
@@ -4099,25 +4036,17 @@ void NNLSSolver::Solve(const Vector& rhs_lb, const Vector& rhs_ub,
qt_rhs_glob = rhs_avg_glob;
lwork = -1;
work.resize(10);
#ifdef MFEM_USE_SINGLE
sormqr_(&lside, &trans, &m, &ione, &n_glob,
#elif defined MFEM_USE_DOUBLE
dormqr_(&lside, &trans, &m, &ione, &n_glob,
#endif
mat_qr_data.GetData(), &m, tau.GetData(),
qt_rhs_glob.GetData(), &m,
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(ormqr_)(&lside, &trans, &m, &ione, &n_glob,
mat_qr_data.GetData(), &m, tau.GetData(),
qt_rhs_glob.GetData(), &m,
work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // Q^T b work calculation failed
lwork = static_cast<int>(work[0]);
work.resize(lwork);
#ifdef MFEM_USE_SINGLE
sormqr_(&lside, &trans, &m, &ione, &n_glob,
#elif defined MFEM_USE_DOUBLE
dormqr_(&lside, &trans, &m, &ione, &n_glob,
#endif
mat_qr_data.GetData(), &m, tau.GetData(),
qt_rhs_glob.GetData(), &m,
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(ormqr_)(&lside, &trans, &m, &ione, &n_glob,
mat_qr_data.GetData(), &m, tau.GetData(),
qt_rhs_glob.GetData(), &m,
work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // Q^T b failed
}
@@ -4130,14 +4059,10 @@ void NNLSSolver::Solve(const Vector& rhs_lb, const Vector& rhs_ub,
char upper = 'U';
char nounit = 'N';
vec1 = qt_rhs_glob;
#ifdef MFEM_USE_SINGLE
strsm_(&lside, &upper, &notrans, &nounit,
#elif defined MFEM_USE_DOUBLE
dtrsm_(&lside, &upper, &notrans, &nounit,
#endif
&n_glob, &ione, &fone,
mat_qr_data.GetData(), &m,
vec1.GetData(), &n_glob);
MFEM_LAPACK_PREFIX(trsm_)(&lside, &upper, &notrans, &nounit,
&n_glob, &ione, &fone,
mat_qr_data.GetData(), &m,
vec1.GetData(), &n_glob);
if (verbosity_ > 2)
{
@@ -4360,14 +4285,10 @@ void NNLSSolver::Solve(const Vector& rhs_lb, const Vector& rhs_ub,
{
res_glob = rhs_avg_glob;
real_t fmone = -1.0;
#ifdef MFEM_USE_SINGLE
sgemv_(&notrans, &m, &n_glob, &fmone,
#elif defined MFEM_USE_DOUBLE
dgemv_(&notrans, &m, &n_glob, &fmone,
#endif
mat_0_data.GetData(), &m,
soln_nz_glob.GetData(), &ione, &fone,
res_glob.GetData(), &ione);
MFEM_LAPACK_PREFIX(gemv_)(&notrans, &m, &n_glob, &fmone,
mat_0_data.GetData(), &m,
soln_nz_glob.GetData(), &ione, &fone,
res_glob.GetData(), &ione);
}
else
{
@@ -4381,24 +4302,18 @@ void NNLSSolver::Solve(const Vector& rhs_lb, const Vector& rhs_ub,
qqt_rhs_glob(i) = qt_rhs_glob(i);
}
#ifdef MFEM_USE_SINGLE
sormqr_(&lside, &notrans, &m, &ione, &n_glob, mat_qr_data.GetData(), &m,
#elif defined MFEM_USE_DOUBLE
dormqr_(&lside, &notrans, &m, &ione, &n_glob, mat_qr_data.GetData(), &m,
#endif
tau.GetData(), qqt_rhs_glob.GetData(), &m,
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(ormqr_)(&lside, &notrans, &m, &ione, &n_glob,
mat_qr_data.GetData(), &m,
tau.GetData(), qqt_rhs_glob.GetData(), &m,
work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // Q Q^T b work calculation failed.
lwork = static_cast<int>(work[0]);
work.resize(lwork);
#ifdef MFEM_USE_SINGLE
sormqr_(&lside, &notrans, &m, &ione, &n_glob, mat_qr_data.GetData(), &m,
#elif defined MFEM_USE_DOUBLE
dormqr_(&lside, &notrans, &m, &ione, &n_glob, mat_qr_data.GetData(), &m,
#endif
tau.GetData(), qqt_rhs_glob.GetData(), &m,
work.data(), &lwork, &info);
MFEM_LAPACK_PREFIX(ormqr_)(&lside, &notrans, &m, &ione, &n_glob,
mat_qr_data.GetData(), &m,
tau.GetData(), qqt_rhs_glob.GetData(), &m,
work.data(), &lwork, &info);
MFEM_VERIFY(info == 0, ""); // Q Q^T b calculation failed.
res_glob = rhs_avg_glob;
res_glob -= qqt_rhs_glob;
+1 -5
View File
@@ -30,8 +30,6 @@ set(SRCS
vertex.cpp
vtk.cpp
wedge.cpp
pentatope.cpp
tesseract.cpp
submesh/submesh.cpp
submesh/submesh_utils.cpp
submesh/transfermap.cpp
@@ -59,13 +57,11 @@ set(HDRS
vertex.hpp
vtk.hpp
wedge.hpp
pentatope.hpp
tesseract.hpp
submesh/submesh.hpp
submesh/submesh_utils.hpp
submesh/transfer_category.hpp
submesh/transfermap.hpp
)
)
if (MFEM_USE_MPI)
list(APPEND SRCS
+1 -16
View File
@@ -39,8 +39,7 @@ public:
/// Constants for the classes derived from Element.
enum Type { POINT, SEGMENT, TRIANGLE, QUADRILATERAL,
TETRAHEDRON, HEXAHEDRON, WEDGE, PYRAMID,
PENTATOPE, TESSERACT
TETRAHEDRON, HEXAHEDRON, WEDGE, PYRAMID
};
/// Default element constructor.
@@ -77,22 +76,8 @@ public:
virtual int GetNEdges() const = 0;
virtual int GetNPlanars() const
{
mfem_error ("Element::GetNPlanars(...)\n"
" is not implemented for this class!");
return 0;
}
virtual const int *GetEdgeVertices(int) const = 0;
virtual const int *GetPlanarsVertices(int) const
{
mfem_error ("Element::GetPlanarsVertices(...)\n"
" is not implemented for this class!");
return NULL;
}
/// @deprecated Use GetNFaces(void) and GetNFaceVertices(int) instead.
MFEM_DEPRECATED virtual int GetNFaces(int &nFaceVertices) const = 0;
+75 -2225
View File
File diff suppressed because it is too large Load Diff
+4 -155
View File
@@ -70,7 +70,6 @@ protected:
int NumOfVertices, NumOfElements, NumOfBdrElements;
int NumOfEdges, NumOfFaces;
int NumOfPlanars;
/** These variables store the number of Interior and Boundary faces. Calling
fes->GetMesh()->GetNBE() doesn't return the expected value in 3D because
periodic meshes in 3D have some of their faces marked as boundary for
@@ -98,13 +97,6 @@ protected:
Array<Vertex> vertices;
Array<Element *> boundary;
Array<Element *> faces;
Array<Element *> planars; //only for 4d meshes
Array<bool> swappedFaces; //only for 4d meshes
Array<bool> swappedBdr; //only for 4d meshes
// Flag to indicate if two neighbours are reflected neighbours (4D)
bool is_reflected;
/** @brief This structure stores the low level information necessary to
interpret the configuration of elements on a specific face. This
@@ -234,12 +226,10 @@ protected:
Table *el_to_edge;
Table *el_to_face;
Table *el_to_planar; // for 4D
Table *el_to_el;
Array<int> be_to_face; // faces = vertices (1D), edges (2D), faces (3D)
Table *bel_to_edge; // for 3D only
Table *bel_to_planar; // for 4D only
// Note that the following tables are owned by this class and should not be
// deleted by the caller. Of these three tables, only face_edge and
@@ -248,13 +238,9 @@ protected:
mutable Table *face_edge; // Returned by GetFaceEdgeTable().
mutable Table *edge_vertex; // Returned by GetEdgeVertexTable().
mutable Table *face_planar; // for 4D
mutable Table *planar_edge; // for 4D
IsoparametricTransformation Transformation, Transformation2;
IsoparametricTransformation BdrTransformation;
IsoparametricTransformation FaceTransformation, PlanarTransformation,
EdgeTransformation;
IsoparametricTransformation FaceTransformation, EdgeTransformation;
FaceElementTransformations FaceElemTr;
// refinement embeddings for forward compatibility with NCMesh
@@ -287,8 +273,6 @@ public:
typedef Geometry::Constants<Geometry::CUBE> hex_t;
typedef Geometry::Constants<Geometry::PRISM> pri_t;
typedef Geometry::Constants<Geometry::PYRAMID> pyr_t;
typedef Geometry::Constants<Geometry::PENTATOPE> pent_t;
typedef Geometry::Constants<Geometry::TESSERACT> tess_t;
enum Operation { NONE, REFINE, DEREFINE, REBALANCE };
@@ -371,10 +355,6 @@ protected:
void GetEdgeOrdering(const DSTable &v_to_v, Array<int> &order);
virtual void MarkTetMeshForRefinement(const DSTable &v_to_v);
// Removed 2025 November
// virtual void MarkTetMeshForRefinement(DSTable &v_to_v);
virtual void MakeReflectedPentMesh();
// Methods used to prepare and apply permutation of the mesh nodes assuming
// that the mesh elements may be rotated (e.g. to mark triangle or tet edges
// for refinement) between the two calls - PrepareNodeReorder() and
@@ -385,8 +365,6 @@ protected:
STable3D *GetFacesTable();
STable3D *GetElementToFaceTable(int ret_ftbl = 0);
STable4D *GetElementToFaceTable4D(int ret_ftbl = 0);
STable3D *GetElementToPlanarTable(int ret_ftbl = 0);
/** Red refinement. Element with index i is refined. The default
red refinement for now is Uniform. */
@@ -409,9 +387,6 @@ protected:
/// Bisect a boundary triangle: boundary element with index @a i is bisected.
void BdrBisection(int i, const HashTable<Hashed2> &);
void RedRefinementPentatope(int i, HashTable<Hashed2> & v_to_v);
void RedRefinementBoundaryTet(int i, HashTable<Hashed2> & v_to_v);
/** Uniform Refinement. Element with index i is refined uniformly. */
void UniformRefinement(int i, const DSTable &, int *, int *, int *);
@@ -501,8 +476,6 @@ protected:
int i) const;
void GetLocalQuadToPyrTransformation(IsoparametricTransformation &loc,
int i) const;
void GetLocalTetToPentTransformation(IsoparametricTransformation &loc,
int i) const;
/** Used in GetFaceElementTransformations to account for the fact that a
slave face occupies only a portion of its master face. */
@@ -540,8 +513,6 @@ protected:
/// Returns the orientation of "test" relative to "base"
static int GetTetOrientation(const int *base, const int *test);
static int GetHexOrientation(const int * base, const int * test);
static void GetElementArrayEdgeTable(const Array<Element*> &elem_array,
const DSTable &v_to_v,
Table &el_to_edge);
@@ -563,15 +534,6 @@ protected:
void AddQuadFaceElement (int lf, int gf, int el,
int v0, int v1, int v2, int v3);
void AddTetrahedralFaceElement(int lf, int gf, int el,
int v0, int v1, int v2, int v3);
void AddHexahedralFaceElement(int lf, int gf, int el,
int v0, int v1, int v2, int v3,
int v4, int v5, int v6, int v7);
/** For a serial Mesh, return true if the face is interior. For a parallel
ParMesh return true if the face is interior or shared. In parallel, this
method only works if the face neighbor data is exchanged. */
@@ -580,14 +542,10 @@ protected:
return FaceIsInterior(FaceNo) || (faces_info[FaceNo].Elem2Inf >= 0);
}
//swap first two entries of *a
inline void Swap(int *a) const;
void FreeElement(Element *E);
void GenerateFaces();
void GenerateNCFaceInfo();
void GeneratePlanars();
/// Begin construction of a mesh
void InitMesh(int Dim_, int spaceDim_, int NVert, int NElem, int NBdrElem);
@@ -607,16 +565,6 @@ protected:
std::string section_delimiter = "",
const std::string &comments = "") const;
/** Creates mesh for the hyper-prism spatial_mesh x[0,st], divided into
4*nt*spatial_mesh.NumElem pentatopes. */
void Make4D(Mesh* spatial_mesh, int nt, Element::Type type, double st);
/** Creates mesh for the 4-parallelotope [0,sx]x[0,sy]x[0,sz]x[0,st], divided into
nx*ny*nz*nt tesseracts if type=TESSERACT or into 24*nx*ny*nz*nt pentatopes if
type=PENTATOPE. */
void Make4D(int nx, int ny, int nz, int nt, Element::Type type, double sx,
double sy, double sz, double st);
/// @brief Creates a mesh for the parallelepiped [0,sx]x[0,sy]x[0,sz],
/// divided into nx*ny*nz hexahedra if @a type = HEXAHEDRON or into
/// 6*nx*ny*nz tetrahedrons if @a type = TETRAHEDRON.
@@ -982,11 +930,6 @@ public:
/// 8 vertices @a vi.
void AddHexAsPyramids(const int *vi, int attr = 1);
int AddPent(const int *vi, int attr = 1);
int AddTes(const int *vi, int attr = 1);
void AddTesAsPentatopes(const int *vi, int attr = 1);
void AddHyperPrismAsPentatopes(const int *vi, int attr = 1);
/// @brief Adds 24 tetrahedrons to the mesh by splitting a hexahedron.
///
/// @a vi are the 8 vertices of the hexahedron, @a hex_face_verts has the
@@ -1028,10 +971,6 @@ public:
int AddBdrQuad(int v1, int v2, int v3, int v4, int attr = 1);
int AddBdrQuad(const int *vi, int attr = 1);
void AddBdrQuadAsTriangles(const int *vi, int attr = 1);
int AddBdrTet(const int *vi, int attr = 1);
int AddBdrHex(const int *vi, int attr = 1);
void AddBdrHexAsTets(const int *vi, int perm, int attr = 1);
void AddBdrPrismAsTets(const int *vi, int attr = 1);
int AddBdrPoint(int v, int attr = 1);
@@ -1051,8 +990,6 @@ public:
/// Finalize the construction of a hexahedral Mesh.
void FinalizeHexMesh(int generate_edges = 0, int refine = 0,
bool fix_orientation = true);
void FinalizeTesMesh(int generate_edges = 0, int refine = 0,
bool fix_orientation = true);
/// Finalize the construction of any type of Mesh.
/** This method calls FinalizeTopology() and Finalize(). */
void FinalizeMesh(int refine = 0, bool fix_orientation = true);
@@ -1218,32 +1155,6 @@ public:
/// @}
/** Creates mesh for the hyper-prism spatial_mesh x[0,st], divided into
4*nt*spatial_mesh.NumElem pentatopes. If refine = true (default) the
mesh is made conforming for the bisection algorithm, i.e., each
pentatope is again subdivided into 60 sub-pentatopes. */
Mesh(Mesh* spatial_mesh, int nt, Element::Type type, bool refine = true, double st = 1.0)
: attribute_sets(attributes), bdr_attribute_sets(bdr_attributes)
{
Make4D(spatial_mesh, nt, type, st);
Finalize(refine, true);
}
/** Creates mesh for the 4-parallelotope [0,sx]x[0,sy]x[0,sz]x[0,st], divided into
nx*ny*nz*nt tesseracts if type=TESSERACT or into 24*nx*ny*nz*nt pentatopes if
type=PENTATOPE. If refine = true (default) the mesh is made conforming
for the bisection algorithm, i.e., each pentatope is again subdivided
into 60 sub-pentatopes. */
Mesh(int nx, int ny, int nz, int nt, Element::Type type, bool refine = true,
double sx = 1.0, double sy = 1.0, double sz = 1.0, double st = 1.0)
: attribute_sets(attributes), bdr_attribute_sets(bdr_attributes)
{
Make4D(nx, ny, nz, nt, type, sx, sy, sz, st);
Finalize(refine,true);
}
/// @name Information about the mesh as a whole
/// @{
@@ -1260,9 +1171,6 @@ public:
inline int EulerNumber2D() const
{ return NumOfVertices - NumOfEdges + NumOfElements; }
inline int EulerNumber4D() const
{ return NumOfVertices - NumOfEdges + NumOfPlanars - NumOfFaces + NumOfElements;}
/** @brief Get the mesh generator/type.
The purpose of this is to be able to quickly tell what type of elements
@@ -1328,9 +1236,6 @@ public:
/// Return the number of faces in a 3D mesh.
inline int GetNFaces() const { return NumOfFaces; }
/// Return the number of planars in a 4D mesh.
inline int GetNPlanars() const { return NumOfPlanars; }
/// Return the number of faces (3D), edges (2D) or vertices (1D).
int GetNumFaces() const;
@@ -1386,11 +1291,6 @@ public:
/// the Element object itself should not be deleted by the caller.
Element *GetElement(int i) { return elements[i]; }
bool getSwappedElementInfo(int i) const { return false; }
bool getSwappedFaceElementInfo(int i) const { return swappedFaces[i]; }
bool getSwappedBdrElementInfo(int i) const { return swappedBdr[i]; }
/// @brief Return pointer to the i'th boundary element object
///
/// The index @a i should be in the range [0, Mesh::GetNBE())
@@ -1470,14 +1370,6 @@ public:
/// Return the Geometry::Type associated with face @a i.
Geometry::Type GetFaceGeometry(int i) const;
const Element *GetPlanar(int i) const
{ return planars[i]; }
Geometry::Type GetPlanarBaseGeometry(int i) const
{
return planars[i]->GetGeometryType();
}
Geometry::Type GetElementGeometry(int i) const
{
return elements[i]->GetGeometryType();
@@ -1488,8 +1380,6 @@ public:
return boundary[i]->GetGeometryType();
}
Geometry::Type GetBdrPlanarBaseGeometry(int i) const;
/// Deprecated in favor of Mesh::GetFaceGeometry
MFEM_DEPRECATED Geometry::Type GetFaceBaseGeometry(int i) const
{ return GetFaceGeometry(i); }
@@ -1560,21 +1450,10 @@ public:
/// Return the indices and the orientations of all edges of bdr element i.
void GetBdrElementEdges(int i, Array<int> &edges, Array<int> &cor) const;
/// Return the indices and the orientations of all planars of element i.
void GetBdrElementPlanars(int i, Array<int> &pls, Array<int> &cor) const;
/** Return the indices and the orientations of all edges of face i.
Works for both 2D (face=edge) and 3D faces. */
void GetFaceEdges(int i, Array<int> &edges, Array<int> &o) const;
/** Return the indices and the orientations of all edges of planar i.
Works only in 4D. */
void GetPlanarEdges(int i, Array<int> &, Array<int> &) const;
/** Return the indices and the orientations of all planars of face i.
Works for 4D faces. */
void GetFacePlanars(int i, Array<int> &, Array<int> &) const;
/// Returns the indices of the vertices of face i.
void GetFaceVertices(int i, Array<int> &vert) const
{
@@ -1591,9 +1470,6 @@ public:
/// Returns the indices of the vertices of edge i.
void GetEdgeVertices(int i, Array<int> &vert) const;
/// Returns the indices of the vertices of planar i.
void GetPlanVertices(int i, Array<int> &vert) const;
/// Return the indices and the orientations of all faces of element i.
void GetElementFaces(int i, Array<int> &faces, Array<int> &ori) const;
@@ -1609,9 +1485,6 @@ public:
GetElementEdges/GetBdrElementEdges. */
void GetBdrElementFace(int i, int *f, int *o) const;
/// Return the indices and the orientations of all planars of element i.
void GetElementPlanars(int i, Array<int> &pls, Array<int> &cor) const;
/** @brief For the given boundary element, bdr_el, return its adjacent
element and its info, i.e. 64*local_bdr_index+bdr_orientation.
@@ -1664,6 +1537,9 @@ public:
/// @note The returned Table should be deleted by the caller
Table *GetVertexToElementTable();
/// @note The returned Table should be deleted by the caller
Table *GetVertexToBdrElementTable();
/// Return the "face"-element Table. Here "face" refers to face (3D),
/// edge (2D), or vertex (1D).
///
@@ -1680,15 +1556,6 @@ public:
/// @note The returned object should NOT be deleted by the caller.
Table *GetEdgeVertexTable() const;
Table *GetFacePlanarTable() const;
/// Returns the planar-to-edge Table (4D)
///
/// @note The returned object should NOT be deleted by the caller.
Table *GetPlanarEdgeTable() const;
/** Return vertex to vertex table. The connections stored in the table
are from smaller to bigger vertex index, i.e. if i<j and (i, j) is
in the table, then (j, i) is not stored.
@@ -1818,13 +1685,6 @@ public:
/// Also, the returned object should NOT be deleted by the caller.
ElementTransformation *GetEdgeTransformation(int EdgeNo);
/** Returns the transformation defining the given planar element.
The transformation is stored in a user-defined variable. */
void GetPlanarTransformation(int i, IsoparametricTransformation *PlTr);
/// Returns the transformation defining the given face element
ElementTransformation *GetPlanarTransformation(int PlanarNo);
/// Returns (a pointer to an object containing) the following data:
///
/// 1) Elem1No - the index of the first element that contains this face this
@@ -2157,10 +2017,6 @@ public:
/// @}
const Table &ElementToPlanTable() const;
void ReplaceBoundaryFromFaces();
/// @name Methods related to mesh partitioning
/// @{
@@ -3064,13 +2920,6 @@ Mesh *Extrude1D(Mesh *mesh, const int ny, const real_t sy,
/// Extrude a 2D mesh
Mesh *Extrude2D(Mesh *mesh, const int nz, const real_t sz);
inline void Mesh::Swap(int *a) const
{
int temp = a[0];
a[0] = a[1];
a[1] = temp;
}
// shift cyclically 3 integers left-to-right
inline void ShiftRight(int &a, int &b, int &c)
{
-2
View File
@@ -22,8 +22,6 @@
#include "quadrilateral.hpp"
#include "hexahedron.hpp"
#include "tetrahedron.hpp"
#include "pentatope.hpp"
#include "tesseract.hpp"
#include "ncmesh.hpp"
#include "mesh.hpp"
#include "mesh_operators.hpp"
+1 -1
View File
@@ -2452,7 +2452,7 @@ const real_t* NCMesh::CalcVertexPos(int node) const
const real_t* pos1 = CalcVertexPos(nd.p1);
const real_t* pos2 = CalcVertexPos(nd.p2);
for (int i = 0; i < Dim; i++) // TODO check if any memory violations occur
for (int i = 0; i < 3; i++)
{
tv.pos[i] = (pos1[i] + pos2[i]) * 0.5;
}
+4 -9
View File
@@ -935,7 +935,7 @@ protected: // implementation
struct Point
{
int dim;
real_t coord[4];
real_t coord[3];
Point() { dim = 0; }
@@ -950,9 +950,6 @@ protected: // implementation
Point(real_t x, real_t y, real_t z)
{ dim = 3; coord[0] = x; coord[1] = y; coord[2] = z; }
Point(double x, double y, double z, double t)
{ dim = 4; coord[0] = x; coord[1] = y; coord[2] = z; coord[3] = t; }
Point(const Point& p0, const Point& p1)
{
dim = p0.dim;
@@ -1013,14 +1010,13 @@ protected: // implementation
PointMatrix(const Point& p0, const Point& p1, const Point& p2, const Point& p3)
{ np = 4; points[0] = p0; points[1] = p1; points[2] = p2; points[3] = p3; }
PointMatrix(const Point& p0, const Point& p1, const Point& p2, const Point& p3,
const Point& p4)
PointMatrix(const Point& p0, const Point& p1, const Point& p2,
const Point& p3, const Point& p4)
{
np = 5;
points[0] = p0; points[1] = p1; points[2] = p2;
points[3] = p3; points[4] = p4;
}
PointMatrix(const Point& p0, const Point& p1, const Point& p2,
const Point& p3, const Point& p4, const Point& p5)
{
@@ -1028,7 +1024,6 @@ protected: // implementation
points[0] = p0; points[1] = p1; points[2] = p2;
points[3] = p3; points[4] = p4; points[5] = p5;
}
PointMatrix(const Point& p0, const Point& p1, const Point& p2,
const Point& p3, const Point& p4, const Point& p5,
const Point& p6, const Point& p7)
@@ -1077,7 +1072,7 @@ protected: // implementation
struct TmpVertex
{
bool valid, visited;
real_t pos[4];
real_t pos[3];
TmpVertex() : valid(false), visited(false) {}
};
+103 -18
View File
@@ -1857,7 +1857,7 @@ NURBSPatch *Revolve3D(NURBSPatch &patch, real_t n[], real_t ang, int times)
{
if (patch.Dim != 4)
{
mfem_error("Revolve3D(NURBSPatch &, double [], double)");
mfem_error("Revolve3D(NURBSPatch &, real_t [], real_t)");
}
int size = 1, ns;
@@ -2008,23 +2008,23 @@ NURBSExtension::NURBSExtension(std::istream &input, bool spacing)
input >> numSpacing;
for (int j = 0; j < numSpacing; j++)
{
int ki, spacingType, numIntParam, numDoubleParam;
input >> ki >> spacingType >> numIntParam >> numDoubleParam;
int ki, spacingType, numIntParam, numRealParam;
input >> ki >> spacingType >> numIntParam >> numRealParam;
MFEM_VERIFY(0 <= ki && ki < NumOfKnotVectors,
"Invalid knotvector index");
MFEM_VERIFY(numIntParam >= 0 && numDoubleParam >= 0,
MFEM_VERIFY(numIntParam >= 0 && numRealParam >= 0,
"Invalid number of parameters in KnotVector");
Array<int> ipar(numIntParam);
Vector dpar(numDoubleParam);
Vector dpar(numRealParam);
for (int i=0; i<numIntParam; ++i)
{
input >> ipar[i];
}
for (int i=0; i<numDoubleParam; ++i)
for (int i=0; i<numRealParam; ++i)
{
input >> dpar[i];
}
@@ -2064,7 +2064,7 @@ NURBSExtension::NURBSExtension(std::istream &input, bool spacing)
new KnotVector(*patches[p]->GetKV(0));
}
}
if (Dimension() == 2)
else if (Dimension() == 2)
{
patchTopo->GetElementEdges(p, edges, oedge);
if (knotVectors[KnotInd(edges[0])] == NULL)
@@ -2230,7 +2230,8 @@ NURBSExtension::NURBSExtension(NURBSExtension *parent, int newOrder)
}
NURBSExtension::NURBSExtension(NURBSExtension *parent,
const Array<int> &newOrders)
const Array<int> &newOrders, Mode mode)
: mode(mode)
{
newOrders.Copy(mOrders);
SetOrderFromOrders();
@@ -3891,7 +3892,16 @@ void NURBSExtension::GenerateBdrElementDofTable()
int ndof = bel_dof->Size_of_connections();
for (int i = 0; i < ndof; i++)
{
dof[i] = activeDof[dof[i]] - 1;
int idx = dof[i];
if (idx < 0)
{
dof[i] = -1 - (activeDof[-1-idx] - 1);
dof[i] = -activeDof[-1-idx];
}
else
{
dof[i] = activeDof[idx] - 1;
}
}
}
@@ -3943,6 +3953,22 @@ void NURBSExtension::Generate2DBdrElementDofTable()
// Load dofs
const int nks0 = kv[0]->GetNKS();
const int ord0 = kv[0]->GetOrder();
bool add_dofs = true;
int s = 1;
if (mode == Mode::H_DIV)
{
int fn = patchTopo->GetBdrElementFaceIndex(b);
if (ord0 == mOrders.Max()) { add_dofs = false; }
if (fn == 0) { s = -1; }
if (fn == 2) { s = -1; }
}
else if (mode == Mode::H_CURL)
{
if (ord0 == mOrders.Max()) { add_dofs = false; }
}
for (int i = 0; i < nks0; i++)
{
if (kv[0]->isElement(i))
@@ -3950,10 +3976,14 @@ void NURBSExtension::Generate2DBdrElementDofTable()
if (activeBdrElem[gbe])
{
Connection conn(lbe,0);
for (int ii = 0; ii <= ord0; ii++)
if (add_dofs)
{
conn.to = DofMap(p2g[(okv[0] >= 0) ? (i+ii) : (nx-i-ii)]);
bel_dof_list.Append(conn);
for (int ii = 0; ii <= ord0; ii++)
{
conn.to = DofMap(p2g[(okv[0] >= 0) ? (i+ii) : (nx-i-ii)]);
if (s == -1) { conn.to = -1 -conn.to; }
bel_dof_list.Append(conn);
}
}
bel_to_patch[lbe] = b;
bel_to_IJK(lbe,0) = (okv[0] >= 0) ? i : (-1-i);
@@ -3990,6 +4020,25 @@ void NURBSExtension::Generate3DBdrElementDofTable()
const int ord0 = kv[0]->GetOrder();
const int nks1 = kv[1]->GetNKS();
const int ord1 = kv[1]->GetOrder();
// Check if dofs are actually defined on boundary
bool add_dofs = true;
int s = 1;
if (mode == Mode::H_DIV)
{
int fn = patchTopo->GetBdrElementFaceIndex(b);
if (ord0 != ord1) { add_dofs = false; }
if (fn == 4) { s = -1; }
if (fn == 1) { s = -1; }
if (fn == 0) { s = -1; }
}
else if (mode == Mode::H_CURL)
{
if (ord0 == ord1) { add_dofs = false; }
}
for (int j = 0; j < nks1; j++)
{
if (kv[1]->isElement(j))
@@ -4001,14 +4050,18 @@ void NURBSExtension::Generate3DBdrElementDofTable()
if (activeBdrElem[gbe])
{
Connection conn(lbe,0);
for (int jj = 0; jj <= ord1; jj++)
if (add_dofs)
{
const int jj_ = (okv[1] >= 0) ? (j+jj) : (ny-j-jj);
for (int ii = 0; ii <= ord0; ii++)
for (int jj = 0; jj <= ord1; jj++)
{
const int ii_ = (okv[0] >= 0) ? (i+ii) : (nx-i-ii);
conn.to = DofMap(p2g(ii_, jj_));
bel_dof_list.Append(conn);
const int jj_ = (okv[1] >= 0) ? (j+jj) : (ny-j-jj);
for (int ii = 0; ii <= ord0; ii++)
{
const int ii_ = (okv[0] >= 0) ? (i+ii) : (nx-i-ii);
conn.to = DofMap(p2g(ii_, jj_));
if (s == -1) { conn.to = -1 -conn.to; }
bel_dof_list.Append(conn);
}
}
}
bel_to_patch[lbe] = b;
@@ -4241,6 +4294,38 @@ void NURBSExtension::DegreeElevate(int rel_degree, int degree)
}
}
NURBSExtension* NURBSExtension::GetDivExtension(int component)
{
// Smarter routine
if (GetNP() > 1)
{
mfem_error("NURBSExtension::GetDivExtension currently "
"only works for single patch NURBS meshes ");
}
Array<int> newOrders = GetOrders();
newOrders[component] += 1;
return new NURBSExtension(this, newOrders, Mode::H_DIV);
}
NURBSExtension* NURBSExtension::GetCurlExtension(int component)
{
// Smarter routine
if (GetNP() > 1)
{
mfem_error("NURBSExtension::GetCurlExtension currently "
"only works for single patch NURBS meshes ");
}
Array<int> newOrders = GetOrders();
for (int c = 0; c < newOrders.Size(); c++) { newOrders[c]++; }
newOrders[component] -= 1;
return new NURBSExtension(this, newOrders, Mode::H_CURL);
}
void NURBSExtension::UniformRefinement(Array<int> const& rf)
{
for (int p = 0; p < patches.Size(); p++)
+24 -1
View File
@@ -426,6 +426,16 @@ class NURBSExtension
friend class NURBSPatchMap;
protected:
/// Flag for indicating what type of NURBS fespace this extension is used for.
enum class Mode
{
H_1, ///> Extension for a standard scalar-valued space
H_DIV, ///> Extension for a divergence conforming vector-valued space
H_CURL, ///> Extension for a curl conforming vector-valued space
};
Mode mode = Mode::H_1;
/// Order of KnotVectors, see GetOrder() for description.
int mOrder;
@@ -655,8 +665,10 @@ public:
/** @a note If a KnotVector in @a parent already has order greater than or
equal to the corresponding entry in @a newOrder, it will be used
unmodified. */
NURBSExtension(NURBSExtension *parent, const Array<int> &newOrders);
NURBSExtension(NURBSExtension *parent, const Array<int> &newOrders,
Mode mode = Mode::H_1);
/// Construct a NURBSExtension by merging a partitioned NURBS mesh.
NURBSExtension(Mesh *mesh_array[], int num_pieces);
/// Copy assignment not supported.
@@ -841,6 +853,16 @@ public:
void KnotInsert(Array<KnotVector *> &kv);
void KnotInsert(Array<Vector *> &kv);
/** Returns the NURBSExtension to be used for @a component of
an H(div) conforming NURBS space. Caller gets ownership of
the returned object, and is responsible for deletion.*/
NURBSExtension* GetDivExtension(int component);
/** Returns the NURBSExtension to be used for @a component of
an H(curl) conforming NURBS space. Caller gets ownership of
the returned object, and is responsible for deletion.*/
NURBSExtension* GetCurlExtension(int component);
void KnotRemove(Array<Vector *> &kv, real_t tol = 1.0e-12);
/** Calls GetCoarseningFactors for each patch and finds the minimum factor
@@ -848,6 +870,7 @@ public:
non-nested spacing functions. */
void GetCoarseningFactors(Array<int> & f) const;
/// Returns the index of the patch containing element @a elem.
int GetElementPatch(int elem) const { return el_to_patch[elem]; }
-246
View File
@@ -1,246 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.googlecode.com.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
// Implementation of class Pentatope
#include "mesh_headers.hpp"
namespace mfem
{
Pentatope::Pentatope(const int *ind, int attr, unsigned char f)
: Element(Geometry::PENTATOPE)
{
attribute = attr;
for (int i = 0; i < 5; i++)
{
indices[i] = ind[i];
}
transform = 0;
flag = f;
}
Pentatope::Pentatope(int ind1, int ind2, int ind3, int ind4, int ind5, int attr, unsigned char f)
: Element(Geometry::PENTATOPE)
{
attribute = attr;
indices[0] = ind1;
indices[1] = ind2;
indices[2] = ind3;
indices[3] = ind4;
indices[4] = ind5;
transform = 0;
flag = f;
}
// Cancelled and added new version at the end of the file (2025 November)
// void Pentatope::GetVertices(Array<int> &v) const
// {
// v.SetSize(5);
// for (int i = 0; i < 5; i++)
// {
// v[i] = indices[i];
// }
// }
//
// void Pentatope::SetVertices(const int *ind)
// {
// for (int i = 0; i < 5; i++)
// {
// indices[i] = ind[i];
// }
// }
//static method
void Pentatope::GetPointMatrix(unsigned transform, DenseMatrix &pm) // FIXME for bisection
{
double* a = &pm(0,0), *b = &pm(0,1), *c = &pm(0,2), *d = &pm(0,3), *e = &pm(0,
4);
// initialize to identity
a[0] = 0.0, a[1] = 0.0, a[2] = 0.0, a[3] = 0.0;
b[0] = 1.0, b[1] = 0.0, b[2] = 0.0, b[3] = 0.0;
c[0] = 0.0, c[1] = 1.0, c[2] = 0.0, c[3] = 0.0;
d[0] = 0.0, d[1] = 0.0, d[2] = 1.0, d[3] = 0.0;
e[0] = 0.0, e[1] = 0.0, e[2] = 0.0, e[3] = 1.0;
int chain[12], n = 0;
bool swapped[12];
while (transform)
{
chain[n++] = (transform & 15) - 1;
swapped[n-1] = ( (transform & 31) / 16 == 1);
transform >>= 5;
}
#define ASGN(a, b) (a[0] = b[0], a[1] = b[1], a[2] = b[2], a[3] = b[3])
#define SWAP(a, b) for (int i = 0; i < 4; i++) { std::swap(a[i], b[i]); }
#define AVG(a, b, c) for (int i = 0; i < 4; i++) { a[i] = (b[i]+c[i])*0.5; }
double f[4];
while (n)
{
switch (chain[--n])
{
case 0:
if (swapped[n]) SWAP(a,e);
AVG(f,a,e); ASGN(e,d); ASGN(d,c); ASGN(c,b); ASGN(b,f);
if (!swapped[n]) SWAP(a,e);
break; // chilTesseractd 1, tag 0 parent
case 1:
if (swapped[n]) SWAP(a,e);
AVG(f,a,e); ASGN(e,d); ASGN(d,c); ASGN(c,b); ASGN(b,f);
if (!swapped[n]) SWAP(a,e);
break; // child 1, tag 1 parent
case 2:
if (swapped[n]) SWAP(a,e);
AVG(f,a,e); ASGN(e,d); ASGN(d,c); ASGN(c,b); ASGN(b,f);
if (!swapped[n]) SWAP(a,e);
break; // child 1, tag 2 parent
case 3:
if (swapped[n]) SWAP(a,e);
AVG(f,a,e); ASGN(e,d); ASGN(d,c); ASGN(c,b); ASGN(b,f);
if (!swapped[n]) SWAP(a,e);
break; // child 1, tag 3 parent
case 10:
if (swapped[n]) SWAP(a,e);
AVG(f,a,e); ASGN(a,e); ASGN(e,b); SWAP(c,d); ASGN(b,f);
if (!swapped[n]) SWAP(a,e);
break; // child 2, tag 0 parent
case 11:
if (swapped[n]) SWAP(a,e);
AVG(f,a,e); ASGN(a,e); ASGN(e,c); ASGN(c,b); ASGN(b,f);
if (!swapped[n]) SWAP(a,e);
break; // child 2, tag 1 parent
case 12:
if (swapped[n]) SWAP(a,e);
AVG(f,a,e); ASGN(a,e); ASGN(e,d); ASGN(d,c); ASGN(c,b); ASGN(b,f);
if (swapped[n]) SWAP(a,e);
break; // child 2, tag 2 parent
case 13:
if (swapped[n]) SWAP(a,e);
AVG(f,a,e); ASGN(a,e); ASGN(e,d); ASGN(d,c); ASGN(c,b); ASGN(b,f);
if (swapped[n]) SWAP(a,e);
break; // child 2, tag 3 parent
#if 0 // Freudenthal
case 0 : AVG(b,a,b); AVG(c,a,c); AVG(d,a,d); AVG(e,a,e); break; // 1,6,7,8,9
case 1 : AVG(a,a,b); AVG(c,b,c); AVG(d,b,d); AVG(e,b,e); break; // 6,2,10,11,12
case 2 : AVG(a,a,c); AVG(b,b,c); AVG(d,c,d); AVG(e,c,e); break; // 7,10,3,13,14
case 3 : AVG(a,a,d); AVG(b,b,d); AVG(c,c,d); AVG(e,d,e); break; // 8,11,13,4,15
case 4 : AVG(a,a,e); AVG(b,b,e); AVG(c,c,e); AVG(d,d,e); break; // 9,12,14,15,5
case 5 : ASGN(f,e); AVG(e,d,e); AVG(d,c,d); ASGN(g,b); AVG(c,b,c); AVG(b,a,f);
AVG(a,a,g); break; // 6,9,10,13,15
case 6 : ASGN(f,a); AVG(a,a,b); AVG(b,f,d); ASGN(g,c); AVG(c,f,e); AVG(e,d,e);
AVG(d,g,d); break; // 6,8,9,13,15
case 7 : ASGN(f,e); AVG(e,d,e); AVG(d,b,d); ASGN(g,c); AVG(c,b,c); AVG(b,a,f);
AVG(a,a,g); break; // 7,9,10,11,13
case 8 : ASGN(f,a); AVG(a,a,b); AVG(b,f,c); ASGN(g,e); AVG(e,c,d); AVG(c,f,d);
AVG(d,f,g); break; // 6,7,8,9,13
case 9 : ASGN(f,e); AVG(a,a,e); AVG(e,f,d); ASGN(g,c); AVG(b,b,c); AVG(c,c,d);
AVG(d,f,g); break; // 9,10,13,14,15
case 10: ASGN(f,a); AVG(a,a,b); AVG(c,b,c); ASGN(g,e); AVG(e,d,e); AVG(d,b,g);
AVG(b,f,g); break; // 6,9,10,12,15
case 11: ASGN(f,d); AVG(d,c,d); AVG(e,d,e); ASGN(g,a); AVG(a,a,b); AVG(c,b,f);
AVG(b,g,f); break; // 6,8,11,13,15
case 12: ASGN(f,b); AVG(a,a,b); AVG(b,b,c); ASGN(g,e); AVG(e,d,e); AVG(c,f,d);
AVG(d,f,g); break; // 6,10,11,12,15
case 13: ASGN(f,c); AVG(c,a,e); AVG(e,c,d); ASGN(g,a); AVG(a,a,b); AVG(d,b,f);
AVG(b,f,g); break; // 6,7,9,10,13
case 14: ASGN(f,b); AVG(b,b,c); AVG(a,a,e); ASGN(g,e); AVG(e,d,e); AVG(d,c,g);
AVG(c,f,g); break; // 9,10,12,14,15
case 15: ASGN(f,d); AVG(d,c,d); AVG(a,a,b); ASGN(g,b); AVG(b,b,c); AVG(e,f,e);
AVG(c,g,f); break; // 6,10,11,13,15
#endif
default:
MFEM_ABORT("Invalid transform.");
}
}
}
Element *Pentatope::Duplicate(Mesh *m) const
{
Pentatope *pent = new Pentatope;
pent->SetVertices(indices);
pent->SetAttribute(attribute);
pent->SetFlag(flag);
return pent;
}
int Pentatope::NeedRefinement(HashTable<Hashed2> &v_to_v) const
{
if (v_to_v.FindId(indices[0], indices[1]) != -1) { return 1; }
if (v_to_v.FindId(indices[1], indices[2]) != -1) { return 1; }
if (v_to_v.FindId(indices[2], indices[0]) != -1) { return 1; }
if (v_to_v.FindId(indices[0], indices[3]) != -1) { return 1; }
if (v_to_v.FindId(indices[1], indices[3]) != -1) { return 1; }
if (v_to_v.FindId(indices[2], indices[3]) != -1) { return 1; }
if (v_to_v.FindId(indices[0], indices[4]) != -1) { return 1; }
if (v_to_v.FindId(indices[1], indices[4]) != -1) { return 1; }
if (v_to_v.FindId(indices[2], indices[4]) != -1) { return 1; }
if (v_to_v.FindId(indices[4], indices[3]) != -1) { return 1; }
return 0;
}
void Pentatope::CreateFlag(char t, bool swap)
{
flag = t;
flag <<= 1;
flag |= swap;
}
void Pentatope::ParseFlag(char& t, bool& swap)
{
unsigned char f = flag;
swap = (f & 1);
f >>= 1;
t = (f & 3);
}
void Pentatope::GetFace(int fi, int *fv)
{
// const int faces[5][4] = { {0, 1, 2, 3}, {0, 1, 2, 4},
// {0, 1, 3, 4}, {0, 2, 3, 4},
// {1, 2, 3, 4}};
const int *v = geom_p::FaceVert[fi];
for (int k = 0; k < 4; ++k)
{
fv[k] = indices[v[k]];
}
// if (fi % 2 == 1)
// std::swap(fv[1], fv[2]);
}
void Pentatope::GetVertices(Array<int> &v) const
{
v.SetSize(5);
std::copy(indices, indices + 5, v.begin());
}
void Pentatope::SetVertices(const Array<int> &v)
{
MFEM_ASSERT(v.Size() == 5, "!");
std::copy(v.begin(), v.end(), indices);
}
void Pentatope::SetVertices(const int *ind)
{
std::copy(ind, ind + 5, indices);
}
}
-144
View File
@@ -1,144 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.googlecode.com.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_PENTATOPE
#define MFEM_PENTATOPE
#include "../config/config.hpp"
#include "../fem/fe.hpp"
#include "element.hpp"
namespace mfem
{
/// Data type pentatope element
class Pentatope : public Element
{
protected:
int indices[5];
unsigned transform;
/* Flag holds currently
* One bit indicating if the element has been swapped.
* Two bits indicating the tag of the simplex (0, 1, 2, 3)
*/
unsigned char flag;
public:
typedef Geometry::Constants<Geometry::PENTATOPE> geom_p;
Pentatope() : Element(Geometry::PENTATOPE) { transform = 0; flag = 0;};
/// Constructs pentatope by specifying the indices and the attribute.
Pentatope(const int *ind, int attr = 1, unsigned char type = 0);
/// Constructs pentatope by specifying the indices and the attribute.
Pentatope(int ind1, int ind2, int ind3, int ind4, int ind5, int attr = 1, unsigned char type = 0);
virtual int GetRefinementFlag()
{ MFEM_ABORT("PENTATOPE:: GetRefinementFlag not implemented"); return 0; }
/// Return 1 if the element needs refinement in order to get conforming mesh.
virtual int NeedRefinement(HashTable<Hashed2> &v_to_v) const;
/// Mark the longest edge by assuming/changing the order of the vertices.
virtual void MarkEdge(DenseMatrix &pmat)
{ MFEM_ABORT("PENTATOPE:: MarkEdge not implemented"); }
/** Reorder the vertices so that the longest edge is from vertex 0
to vertex 1. If called it should be once from the mesh constructor,
because the order may be used later for setting the edges. **/
virtual void MarkEdge(const DSTable &v_to_v, const int *length)
{ MFEM_ABORT("PENTATOPE:: MarkEdge not implemented"); }
virtual void GetFace(int fi, int *fv);
/// Return element's type.
virtual Type GetType() const { return Element::PENTATOPE; }
virtual void CreateFlag(char t, bool swap);
virtual void ParseFlag(char &t, bool &swap);
virtual void SetFlag(const unsigned char t) { flag = t; }
/// Return flag of element.
virtual unsigned char GetFlag() const { return flag; }
// Cancelled and added new version at the end of the file (2025 November)
// /// Set the vertices according to the given input.
// virtual void SetVertices(const int *ind);
//
// /// Returns the indices of the element's vertices.
// virtual void GetVertices(Array<int> &v) const;
//
// virtual int *GetVertices() { return indices; }
virtual int GetNVertices() const { return 5; }
virtual int GetNEdges() const { return 10; }
virtual int GetNPlanars() const { return 10; }
virtual const int *GetEdgeVertices(int ei) const { return (geom_p::Edges[ei]); }
virtual const int *GetPlanarsVertices(int pi) const { return (geom_p::PlanarVert[pi]); }
MFEM_DEPRECATED virtual int GetNFaces(int &nFaceVertices) const
{ nFaceVertices = 4; return 5; }
virtual int GetNFaces() const { return 5; };
virtual int GetNFaceVertices(int fi) const { return 4; };
virtual const int *GetFaceVertices(int fi) const
{ return geom_p::FaceVert[fi]; }
/// Calculate point matrix corresponding to a chain of transformations.
static void GetPointMatrix(unsigned transform, DenseMatrix &pm);
virtual void ResetTransform(int tr) { transform = tr; }
virtual unsigned GetTransform() const { return transform; }
virtual void PushTransform(int tr)
{ transform = (transform << 5) | (tr + 1); }
virtual Element *Duplicate(Mesh *m) const;
/// Get the indices defining the vertices.
void GetVertices(Array<int> &v) const override;
/// Set the indices defining the vertices.
void SetVertices(const Array<int> &v) override;
/// @note The returned array should NOT be deleted by the caller.
int * GetVertices () override { return indices; }
/// Set the indices defining the vertices.
void SetVertices(const int *ind) override;
virtual ~Pentatope() { }
};
extern MFEM_EXPORT Linear4DFiniteElement PentatopeFE;
}
#endif
+43 -1729
View File
File diff suppressed because it is too large Load Diff
+1 -64
View File
@@ -63,48 +63,26 @@ protected:
void Set(int v0, int v1, int v2, int v3)
{ v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; }
void Set(const int *w)
{ v[0] = w[0]; v[1] = w[1]; v[2] = w[2]; v[3] = w[3];}
{ v[0] = w[0]; v[1] = w[1]; v[2] = w[2]; v[3] = w[3]; }
};
struct Vert4_tag
{
int v[4];
char tag;
Vert4_tag() = default;
Vert4_tag(int v0, int v1, int v2, int v3, char _tag = 0)
{
v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; tag = _tag;
}
void Set(int v0, int v1, int v2, int v3, char _tag = 0)
{ v[0] = v0; v[1] = v1; v[2] = v2; v[3] = v3; tag = _tag; }
void Set(const int *w, char _tag = 0)
{ v[0] = w[0]; v[1] = w[1]; v[2] = w[2]; v[3] = w[3]; tag = _tag; }
};
Array<Element *> shared_edges;
// shared face id 'i' is:
// * triangle id 'i', if i < shared_trias.Size()
// * quad id 'i-shared_trias.Size()', otherwise
Array<Vert3> shared_trias;
Array<Vert4> shared_quads;
Array<Vert4_tag> shared_tetra;
// Array<Element *> shared_planars;
/// Shared objects in each group.
Table group_svert;
Table group_sedge;
Table group_stria; // contains shared triangle indices
Table group_squad; // contains shared quadrilateral indices
Table group_stetr;
// Table group_splan;
/// Shared to local index mapping.
Array<int> svert_lvert;
Array<int> sedge_ledge;
Array<int> splan_lplan;
// sface ids: all triangles first, then all quads
// in 4D, just all tetrahedra
Array<int> sface_lface;
/// Table that maps from face neighbor element number, to the face numbers of
@@ -144,18 +122,6 @@ protected:
bool DecodeFaceSplittings(HashTable<Hashed2> &v_to_v, const int *v,
const Array<unsigned> &codes, int &pos);
void GetFaceSplittings4D(const Vert4_tag &f, const HashTable<Hashed2> &v_to_v,
const DSTable &edges, Array<unsigned> &codes);
bool DecodeFaceSplittings4D(HashTable<Hashed2> &v_to_v, const Vert4_tag &v,
const Array<unsigned> &codes, int &pos);
void GetFaceSplittings4D_old(const Vert4_tag &f, const HashTable<Hashed2> &v_to_v,
Array<unsigned> &codes);
bool DecodeFaceSplittings4D_old(HashTable<Hashed2> &v_to_v, const Vert4_tag &v,
const Array<unsigned> &codes, int &pos);
// Given a completed FacesTable and SharedFacesTable, construct a table that
// maps from face neighbor element number, to the set of faces of that
// element. Store the resulting data in the member variable
@@ -200,9 +166,6 @@ protected:
/// Update the groups after tetrahedron refinement
void RefineGroups(int old_nv, const HashTable<Hashed2> &v_to_v);
void RefineGroups4D(int old_nv, const HashTable<Hashed2> &v_to_v);
void UniformRefineGroups4D_Freudenthal(int old_nv, const HashTable<Hashed2> &v_to_v);
void UniformRefineGroups2D(int old_nv);
// f2qf can be NULL if all faces are quads or there are no quad faces
@@ -263,9 +226,6 @@ protected:
Array<int>& face_group,
ListOfIntegerSets& groups);
int FindSharedPlanars(const Mesh &mesh, const int* partition,
Table* &plan_element, ListOfIntegerSets &groups);
int FindSharedEdges(const Mesh &mesh, const int* partition,
Table* &edge_element, ListOfIntegerSets& groups);
@@ -276,13 +236,6 @@ protected:
const Array<int>& face_group,
int &nstria, int &nsquad);
void BuildFaceGroup4D(int ngroups, const Mesh &mesh,
const Array<int>& face_group,
int &nstetr, int &nshexa);
void BuildPlanarGroup(int ngroups, const Mesh &mesh,const Table& plan_element,
int &nstria, int &nsquad);
void BuildEdgeGroup(int ngroups, const Table& edge_element);
void BuildVertexGroup(int ngroups, const Table& vert_element);
@@ -293,17 +246,6 @@ protected:
const Array<int> &face_group,
const Array<int> &vert_global_local);
void BuildSharedFaceElems4D(int ntet_faces, int nhex_faces,
const Mesh &mesh, int *partitioning,
const STable4D *faces_tbl_4d,
const Array<int> &face_group,
const Array<int> &vert_global_local,
const std::map<int,char> &vert_to_type);
void BuildSharedPlanarElems(int ntri_planars, int nquad_planars,
const Mesh &mesh, const Array<int>& vert_global_local,
const STable3D *planar_tbl, const Table* plan_element);
void BuildSharedEdgeElems(int nedges, Mesh &mesh,
const Array<int> &vert_global_local,
const Table *edge_element);
@@ -505,17 +447,12 @@ public:
int GroupNEdges(int group) const { return group_sedge.RowSize(group-1); }
int GroupNTriangles(int group) const { return group_stria.RowSize(group-1); }
int GroupNQuadrilaterals(int group) const { return group_squad.RowSize(group-1); }
// int GroupNPlanars(int group) const { return group_splan.RowSize(group-1); }
int GroupNTetrahedra(int group) const { return group_stetr.RowSize(group-1); }
int GroupVertex(int group, int i) const
{ return svert_lvert[group_svert.GetRow(group-1)[i]]; }
void GroupEdge(int group, int i, int &edge, int &o) const;
void GroupTriangle(int group, int i, int &face, int &o) const;
void GroupQuadrilateral(int group, int i, int &face, int &o) const;
void GroupTetrahedron(int group, int i, int &face, int &o) const;
///@}
/**
-116
View File
@@ -1,116 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.googlecode.com.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#include "mesh_headers.hpp"
namespace mfem
{
const int Tesseract::edges[32][2] =
{
{0, 1}, {1, 2}, {3, 2}, {0, 3},
{4, 5}, {5, 6}, {7, 6}, {4, 7},
{0, 4}, {1, 5}, {2, 6}, {3, 7},
{8, 9}, {9, 10}, {11, 10}, {8, 11},
{12, 13}, {13, 14}, {15, 14}, {12, 15},
{8, 12}, {9, 13}, {10, 14}, {11, 15},
{0, 8}, {1, 9}, {2, 10}, {3, 11},
{4, 12}, {5, 13}, {6, 14}, {7, 15}
};
// same as Mesh::hex_faces
const int Tesseract::faces[8][8] =
{
// {8,11,12,15,0,3,4,7}, //x bottom
// {1,2,6,5,9,10,14,13}, //x top
// {0,1,5,4,8,9,13,12}, //y bottom
// {2,3,7,6,10,11,15,14}, //y top
// {8,9,10,11,0,1,2,3}, // z bottom
// {4,5,6,7,12,13,14,15}, //z top
// {0,1,2,3,4,5,6,7}, //t botom
// {12,13,14,15,8,9,10,11} //t top
{8,11,15,12,0,3,7,4}, //x bottom
{1,2,6,5,9,10,14,13}, //x top
{0,1,5,4,8,9,13,12}, //y bottom
{2,3,7,6,10,11,15,14}, //y top
{8,9,10,11,0,1,2,3}, // z bottom
{4,5,6,7,12,13,14,15}, //z top
{0,1,2,3,4,5,6,7}, //t botom
{12,13,14,15,8,9,10,11} //t top
};
Tesseract::Tesseract(const int *ind, int attr)
: Element(Geometry::TESSERACT)
{
attribute = attr;
for (int i = 0; i < 16; i++)
{
indices[i] = ind[i];
}
}
Tesseract::Tesseract(int ind1, int ind2, int ind3, int ind4,
int ind5, int ind6, int ind7, int ind8,
int ind9, int ind10, int ind11, int ind12,
int ind13, int ind14, int ind15, int ind16,
int attr) : Element(Geometry::TESSERACT)
{
attribute = attr;
indices[0] = ind1;
indices[1] = ind2;
indices[2] = ind3;
indices[3] = ind4;
indices[4] = ind5;
indices[5] = ind6;
indices[6] = ind7;
indices[7] = ind8;
indices[8] = ind9;
indices[9] = ind10;
indices[10] = ind11;
indices[11] = ind12;
indices[12] = ind13;
indices[13] = ind14;
indices[14] = ind15;
indices[15] = ind16;
}
// Cancelled and added new version at the end of the file (2025 November)
/*void Tesseract::GetVertices(Array<int> &v) const
{
v.SetSize(16);
for (int i = 0; i < 16; i++)
{
v[i] = indices[i];
}
}*/
void Tesseract::GetVertices(Array<int> &v) const
{
v.SetSize(16);
std::copy(indices, indices + 16, v.begin());
}
void Tesseract::SetVertices(const Array<int> &v)
{
MFEM_ASSERT(v.Size() == 16, "!");
std::copy(v.begin(), v.end(), indices);
}
void Tesseract::SetVertices(const int *ind)
{
std::copy(ind, ind + 16, indices);
}
QuadLinear4DFiniteElement TesseractFE;
}
-90
View File
@@ -1,90 +0,0 @@
// Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at
// the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights
// reserved. See file COPYRIGHT for details.
//
// This file is part of the MFEM library. For more information and source code
// availability see http://mfem.googlecode.com.
//
// MFEM is free software; you can redistribute it and/or modify it under the
// terms of the GNU Lesser General Public License (as published by the Free
// Software Foundation) version 2.1 dated February 1999.
#ifndef MFEM_TESSERACT
#define MFEM_TESSERACT
#include "../config/config.hpp"
#include "element.hpp"
namespace mfem
{
/// Data type tesseract element
class Tesseract : public Element
{
protected:
int indices[16];
public:
static const int edges[32][2];
static const int faces[8][8]; // same as Mesh::tes_faces
Tesseract() : Element(Geometry::TESSERACT) { }
/// Constructs hexahedron by specifying the indices and the attribute.
Tesseract(const int *ind, int attr = 1);
/// Constructs hexahedron by specifying the indices and the attribute.
Tesseract(int ind1, int ind2, int ind3, int ind4,
int ind5, int ind6, int ind7, int ind8,
int ind9, int ind10, int ind11, int ind12,
int ind13, int ind14, int ind15, int ind16, int attr = 1);
/// Return element's type
Type GetType() const { return Element::TESSERACT; }
// Cancelled and added new version at the end of the file (2025 November)
// /// Returns the indices of the element's vertices.
// virtual void GetVertices(Array<int> &v) const;
//
// virtual int *GetVertices() { return indices; }
virtual int GetNVertices() const { return 16; }
virtual int GetNEdges() const { return 32; }
virtual int GetNFaces() const { return 8; }
virtual int GetNFaceVertices(int fi) const { return 8; }
virtual const int *GetEdgeVertices(int ei) const
{ return edges[ei]; }
virtual int GetNFaces(int &nFaceVertices) const
{ nFaceVertices = 8; return 8; }
virtual const int *GetFaceVertices(int fi) const
{ return faces[fi]; }
virtual Element *Duplicate(Mesh *m) const
{ return new Tesseract(indices, attribute); }
/// Get the indices defining the vertices.
void GetVertices(Array<int> &v) const override;
/// Set the indices defining the vertices.
void SetVertices(const Array<int> &v) override;
/// @note The returned array should NOT be deleted by the caller.
int * GetVertices () override { return indices; }
/// Set the indices defining the vertices.
void SetVertices(const int *ind) override;
virtual ~Tesseract() { }
};
extern QuadLinear4DFiniteElement TesseractFE;
}
#endif
+6 -7
View File
@@ -22,18 +22,17 @@ namespace mfem
class Vertex
{
protected:
real_t coord[4];
real_t coord[3];
public:
Vertex() = default;
// Trivial copy constructor and trivial copy assignment operator
Vertex(real_t *xx, int dim);
Vertex(real_t x, real_t y) { coord[0] = x; coord[1] = y; coord[2] = 0.; coord[3] = 0.;}
Vertex(real_t x, real_t y) { coord[0] = x; coord[1] = y; coord[2] = 0.; }
Vertex(real_t x, real_t y, real_t z)
{ coord[0] = x; coord[1] = y; coord[2] = z; coord[3] = 0.;}
Vertex(real_t x, real_t y, real_t z, real_t t)
{ coord[0] = x; coord[1] = y; coord[2] = z; coord[3] = t;}
{ coord[0] = x; coord[1] = y; coord[2] = z; }
/// Returns pointer to the coordinates of the vertex.
inline real_t * operator() () const { return (real_t*)coord; }
@@ -46,8 +45,8 @@ public:
/// (DEPRECATED) Set the coordinates of the Vertex.
/** @deprecated This old version of SetCoords is not always memory safe. */
MFEM_DEPRECATED void SetCoords(const double *p)
{ coord[0] = p[0]; coord[1] = p[1]; coord[2] = p[2]; coord[3] = p[3]; }
MFEM_DEPRECATED void SetCoords(const real_t *p)
{ coord[0] = p[0]; coord[1] = p[1]; coord[2] = p[2]; }
/// Sets vertex location based on given point p
void SetCoords(int dim, const real_t *p)
+1
View File
@@ -37,3 +37,4 @@ add_subdirectory(tribol)
add_subdirectory(hooke)
add_subdirectory(dpg)
add_subdirectory(hdiv-linear-solver)
add_subdirectory(stabilized)
+5 -5
View File
@@ -15,11 +15,11 @@
//
// Sample runs
//
// acoustics -ref 4 -o 1 -rnum 1.0
// acoustics -m ../../data/inline-tri.mesh -ref 4 -o 2 -sc -rnum 3.0
// acoustics -m ../../data/amr-quad.mesh -ref 3 -o 3 -sc -rnum 4.5 -prob 1
// acoustics -m ../../data/inline-quad.mesh -ref 2 -o 4 -sc -rnum 11.5 -prob 1
// acoustics -m ../../data/inline-hex.mesh -ref 1 -o 2 -sc -rnum 1.0
// acoustics -ref 4 -o 1 -rnum 1.0
// acoustics -m ../../data/inline-tri.mesh -ref 4 -o 2 -sc -rnum 3.0
// acoustics -m ../../data/amr-quad.mesh -ref 3 -o 3 -sc -rnum 4.5 -prob 1
// acoustics -m ../../data/inline-quad.mesh -ref 2 -o 4 -sc -rnum 11.5 -prob 1
// acoustics -m ../../data/inline-hex.mesh -ref 1 -o 2 -sc -rnum 1.0
// Description:
// This example code demonstrates the use of MFEM to define and solve
+6 -6
View File
@@ -14,14 +14,14 @@
// Compile with: make convection-diffusion
//
// sample runs
// convection-diffusion -m ../../data/star.mesh -o 2 -ref 2 -theta 0.0 -eps 1e-1 -beta '2 3'
// convection-diffusion -m ../../data/beam-hex.mesh -o 2 -ref 2 -theta 0.0 -eps 1e0 -beta '1 0 2'
// convection-diffusion -m ../../data/inline-tri.mesh -o 3 -ref 2 -theta 0.0 -eps 1e-2 -beta '4 2' -sc
// convection-diffusion -m ../../data/star.mesh -o 2 -ref 2 -theta 0.0 -eps 1e-1 -beta '2 3'
// convection-diffusion -m ../../data/beam-hex.mesh -o 2 -ref 2 -theta 0.0 -eps 1e0 -beta '1 0 2'
// convection-diffusion -m ../../data/inline-tri.mesh -o 3 -ref 2 -theta 0.0 -eps 1e-2 -beta '4 2' -sc
// AMR runs
// convection-diffusion -o 3 -ref 5 -prob 1 -eps 1e-1 -theta 0.75
// convection-diffusion -o 2 -ref 9 -prob 1 -eps 1e-2 -theta 0.75
// convection-diffusion -o 3 -ref 9 -prob 1 -eps 1e-3 -theta 0.75 -sc
// convection-diffusion -o 3 -ref 5 -prob 1 -eps 1e-1 -theta 0.75
// convection-diffusion -o 2 -ref 9 -prob 1 -eps 1e-2 -theta 0.75
// convection-diffusion -o 3 -ref 9 -prob 1 -eps 1e-3 -theta 0.75 -sc
// Description:
// This example code demonstrates the use of MFEM to define and solve
+4 -4
View File
@@ -14,10 +14,10 @@
// Compile with: make maxwell
//
// Sample runs
// maxwell -m ../../data/inline-tri.mesh -ref 4 -o 1 -rnum 1.0
// maxwell -m ../../data/amr-quad.mesh -ref 3 -o 2 -rnum 1.6 -sc
// maxwell -m ../../data/inline-quad.mesh -ref 2 -o 3 -rnum 4.2 -sc
// maxwell -m ../../data/inline-hex.mesh -ref 1 -o 2 -sc -rnum 1.0
// maxwell -m ../../data/inline-tri.mesh -ref 4 -o 1 -rnum 1.0
// maxwell -m ../../data/amr-quad.mesh -ref 3 -o 2 -rnum 1.6 -sc
// maxwell -m ../../data/inline-quad.mesh -ref 2 -o 3 -rnum 4.2 -sc
// maxwell -m ../../data/inline-hex.mesh -ref 1 -o 2 -sc -rnum 1.0
// Description:
// This example code demonstrates the use of MFEM to define and solve
+11 -11
View File
@@ -15,19 +15,19 @@
//
// sample runs
// mpirun -np 4 pacoustics -o 3 -m ../../data/star.mesh -sref 1 -pref 2 -rnum 1.9 -sc -prob 0
// mpirun -np 4 pacoustics -o 3 -m ../../data/inline-quad.mesh -sref 1 -pref 2 -rnum 5.2 -sc -prob 1
// mpirun -np 4 pacoustics -o 4 -m ../../data/inline-tri.mesh -sref 1 -pref 2 -rnum 7.1 -sc -prob 1
// mpirun -np 4 pacoustics -o 2 -m ../../data/inline-hex.mesh -sref 0 -pref 1 -rnum 1.9 -sc -prob 0
// mpirun -np 4 pacoustics -o 3 -m ../../data/inline-quad.mesh -sref 2 -pref 1 -rnum 7.1 -sc -prob 2
// mpirun -np 4 pacoustics -o 2 -m ../../data/inline-hex.mesh -sref 0 -pref 1 -rnum 4.1 -sc -prob 2
// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 7.1 -sc -prob 3
// mpirun -np 4 pacoustics -o 4 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 10.1 -sc -prob 4
// mpirun -np 4 pacoustics -o 4 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 12.1 -sc -prob 5
// mpirun -np 4 pacoustics -o 3 -m ../../data/star.mesh -sref 1 -pref 2 -rnum 1.9 -sc -prob 0
// mpirun -np 4 pacoustics -o 3 -m ../../data/inline-quad.mesh -sref 1 -pref 2 -rnum 5.2 -sc -prob 1
// mpirun -np 4 pacoustics -o 4 -m ../../data/inline-tri.mesh -sref 1 -pref 2 -rnum 7.1 -sc -prob 1
// mpirun -np 4 pacoustics -o 2 -m ../../data/inline-hex.mesh -sref 0 -pref 1 -rnum 1.9 -sc -prob 0
// mpirun -np 4 pacoustics -o 3 -m ../../data/inline-quad.mesh -sref 2 -pref 1 -rnum 7.1 -sc -prob 2
// mpirun -np 4 pacoustics -o 2 -m ../../data/inline-hex.mesh -sref 0 -pref 1 -rnum 4.1 -sc -prob 2
// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 7.1 -sc -prob 3
// mpirun -np 4 pacoustics -o 4 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 10.1 -sc -prob 4
// mpirun -np 4 pacoustics -o 4 -m meshes/scatter.mesh -sref 1 -pref 1 -rnum 12.1 -sc -prob 5
// AMR runs
// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 0 -pref 7 -theta 0.75 -rnum 10.1 -sc -prob 3
// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 0 -pref 12 -theta 0.75 -rnum 20.1 -sc -prob 3
// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 0 -pref 7 -theta 0.75 -rnum 10.1 -sc -prob 3
// mpirun -np 4 pacoustics -o 3 -m meshes/scatter.mesh -sref 0 -pref 12 -theta 0.75 -rnum 20.1 -sc -prob 3
// Description:
// This example code demonstrates the use of MFEM to define and solve
+7 -7
View File
@@ -11,17 +11,17 @@
//
// MFEM Ultraweak DPG parallel example for convection-diffusion
//
// Compile with: make pconvection-diffusion
// Compile with: make pconvection-diffusion
//
// sample runs
// mpirun -np 4 pconvection-diffusion -o 2 -ref 3 -prob 0 -eps 1e-1 -beta '4 2' -theta 0.0
// mpirun -np 4 pconvection-diffusion -o 3 -ref 3 -prob 0 -eps 1e-2 -beta '2 3' -theta 0.0
// mpirun -np 4 pconvection-diffusion -m ../../data/inline-hex.mesh -o 2 -ref 1 -prob 0 -sc -eps 1e-1 -theta 0.0
// mpirun -np 4 pconvection-diffusion -o 2 -ref 3 -prob 0 -eps 1e-1 -beta '4 2' -theta 0.0
// mpirun -np 4 pconvection-diffusion -o 3 -ref 3 -prob 0 -eps 1e-2 -beta '2 3' -theta 0.0
// mpirun -np 4 pconvection-diffusion -m ../../data/inline-hex.mesh -o 2 -ref 1 -prob 0 -sc -eps 1e-1 -theta 0.0
// AMR runs
// mpirun -np 4 pconvection-diffusion -o 3 -ref 10 -prob 1 -eps 1e-3 -beta '1 0' -theta 0.7 -sc
// mpirun -np 4 pconvection-diffusion -o 3 -ref 15 -prob 2 -eps 5e-3 -theta 0.7 -sc
// mpirun -np 4 pconvection-diffusion -o 2 -ref 12 -prob 3 -eps 1e-2 -beta '1 2' -theta 0.7 -sc
// mpirun -np 4 pconvection-diffusion -o 3 -ref 10 -prob 1 -eps 1e-3 -beta '1 0' -theta 0.7 -sc
// mpirun -np 4 pconvection-diffusion -o 3 -ref 15 -prob 2 -eps 5e-3 -theta 0.7 -sc
// mpirun -np 4 pconvection-diffusion -o 2 -ref 12 -prob 3 -eps 1e-2 -beta '1 2' -theta 0.7 -sc
// Description:
// This example code demonstrates the use of MFEM to define and solve a parallel
+7 -7
View File
@@ -14,18 +14,18 @@
// Compile with: make pdiffusion
//
// Sample runs
// mpirun -np 4 pdiffusion -m ../../data/inline-quad.mesh -o 3 -sref 1 -pref 2 -theta 0.0 -prob 0
// mpirun -np 4 pdiffusion -m ../../data/inline-hex.mesh -o 2 -sref 0 -pref 1 -theta 0.0 -prob 0 -sc
// mpirun -np 4 pdiffusion -m ../../data/beam-tet.mesh -o 3 -sref 0 -pref 2 -theta 0.0 -prob 0 -sc
// mpirun -np 4 pdiffusion -m ../../data/inline-quad.mesh -o 3 -sref 1 -pref 2 -theta 0.0 -prob 0
// mpirun -np 4 pdiffusion -m ../../data/inline-hex.mesh -o 2 -sref 0 -pref 1 -theta 0.0 -prob 0 -sc
// mpirun -np 4 pdiffusion -m ../../data/beam-tet.mesh -o 3 -sref 0 -pref 2 -theta 0.0 -prob 0 -sc
// L-shape runs
// Note: uniform ref are expected to give sub-optimal rate for the L-shape problem (rate = 2/3)
// mpirun -np 4 pdiffusion -o 2 -sref 1 -pref 5 -theta 0.0 -prob 1
// mpirun -np 4 pdiffusion -o 2 -sref 1 -pref 5 -theta 0.0 -prob 1
// L-shape AMR runs
// mpirun -np 4 pdiffusion -o 1 -sref 1 -pref 10 -theta 0.8 -prob 1
// mpirun -np 4 pdiffusion -o 2 -sref 1 -pref 8 -theta 0.75 -prob 1 -sc
// mpirun -np 4 pdiffusion -o 3 -sref 1 -pref 6 -theta 0.75 -prob 1 -sc -do 2
// mpirun -np 4 pdiffusion -o 1 -sref 1 -pref 10 -theta 0.8 -prob 1
// mpirun -np 4 pdiffusion -o 2 -sref 1 -pref 8 -theta 0.75 -prob 1 -sc
// mpirun -np 4 pdiffusion -o 3 -sref 1 -pref 6 -theta 0.75 -prob 1 -sc -do 2
// Description:
// This example code demonstrates the use of MFEM to define and solve
+7 -7
View File
@@ -14,16 +14,16 @@
// Compile with: make pmaxwell
//
// sample run
// mpirun -np 4 pmaxwell -m ../../data/star.mesh -o 2 -sref 0 -pref 3 -rnum 0.5 -prob 0
// mpirun -np 4 pmaxwell -m ../../data/inline-quad.mesh -o 3 -sref 0 -pref 3 -rnum 4.8 -sc -prob 0
// mpirun -np 4 pmaxwell -m ../../data/inline-hex.mesh -o 2 -sref 0 -pref 1 -rnum 0.8 -sc -prob 0
// mpirun -np 4 pmaxwell -m ../../data/inline-quad.mesh -o 3 -sref 1 -pref 3 -rnum 4.8 -sc -prob 2
// mpirun -np 4 pmaxwell -o 3 -sref 1 -pref 2 -rnum 11.8 -sc -prob 3
// mpirun -np 4 pmaxwell -o 3 -sref 1 -pref 2 -rnum 9.8 -sc -prob 4
// mpirun -np 4 pmaxwell -m ../../data/star.mesh -o 2 -sref 0 -pref 3 -rnum 0.5 -prob 0
// mpirun -np 4 pmaxwell -m ../../data/inline-quad.mesh -o 3 -sref 0 -pref 3 -rnum 4.8 -sc -prob 0
// mpirun -np 4 pmaxwell -m ../../data/inline-hex.mesh -o 2 -sref 0 -pref 1 -rnum 0.8 -sc -prob 0
// mpirun -np 4 pmaxwell -m ../../data/inline-quad.mesh -o 3 -sref 1 -pref 3 -rnum 4.8 -sc -prob 2
// mpirun -np 4 pmaxwell -o 3 -sref 1 -pref 2 -rnum 11.8 -sc -prob 3
// mpirun -np 4 pmaxwell -o 3 -sref 1 -pref 2 -rnum 9.8 -sc -prob 4
// AMR run. Note that this is a computationally intensive sample run.
// We recommend trying it on a large machine with more mpi ranks
// mpirun -np 4 pmaxwell -o 3 -sref 0 -pref 15 -prob 1 -theta 0.7 -sc
// mpirun -np 4 pmaxwell -o 3 -sref 0 -pref 15 -prob 1 -theta 0.7 -sc
// Description:
// This example code demonstrates the use of MFEM to define and solve

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