Compare commits
239
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b09b5dbab5 | ||
|
|
ece1b1fd3d | ||
|
|
86f72cd22e | ||
|
|
97c4aed444 | ||
|
|
03199fe1fd | ||
|
|
aed9945c40 | ||
|
|
25d65f4275 | ||
|
|
05989d5d29 | ||
|
|
5d762f7cb5 | ||
|
|
bf5c6ebd23 | ||
|
|
8153d11274 | ||
|
|
827ed64113 | ||
|
|
ef9f02ba53 | ||
|
|
e9a0b0620a | ||
|
|
4d9d444248 | ||
|
|
6e2badecca | ||
|
|
99b45fcb02 | ||
|
|
9a327eeca6 | ||
|
|
a1d003aec0 | ||
|
|
fa87595f9a | ||
|
|
c4697ba253 | ||
|
|
5e01a5433d | ||
|
|
4833b17636 | ||
|
|
34378ffc5b | ||
|
|
a6e3e8e695 | ||
|
|
8af34d985e | ||
|
|
0f55696c69 | ||
|
|
f4a6f33284 | ||
|
|
781efd2d50 | ||
|
|
9035279bcb | ||
|
|
262fa6173d | ||
|
|
e4b8584a16 | ||
|
|
7912d6915d | ||
|
|
293d9009ae | ||
|
|
51bde67bb1 | ||
|
|
45e2636921 | ||
|
|
613a55d318 | ||
|
|
35225e045e | ||
|
|
22c1087503 | ||
|
|
732e3c33f4 | ||
|
|
0586c0feee | ||
|
|
7e1186afd2 | ||
|
|
ffd3088722 | ||
|
|
cd5d2f7c04 | ||
|
|
cbae29ad06 | ||
|
|
4c1d842c72 | ||
|
|
4aa0ed52af | ||
|
|
8712d02570 | ||
|
|
e5fec6279b | ||
|
|
e90e96f9a5 | ||
|
|
cc00ef7d90 | ||
|
|
62c535d0ee | ||
|
|
17829d1c38 | ||
|
|
dd198ce3f9 | ||
|
|
b9f36468ba | ||
|
|
d5b127caff | ||
|
|
76bcd044d0 | ||
|
|
a2132dac0c | ||
|
|
28916b23a4 | ||
|
|
7476c00f2b | ||
|
|
7a0137c496 | ||
|
|
4267b2af05 | ||
|
|
e37daad5eb | ||
|
|
289a241f81 | ||
|
|
d0850268e3 | ||
|
|
133bf60546 | ||
|
|
9f13192930 | ||
|
|
20b4b72071 | ||
|
|
ddf80492c5 | ||
|
|
60d70b7d3d | ||
|
|
7f946e0920 | ||
|
|
0456014a32 | ||
|
|
77d98d68c3 | ||
|
|
f8d18cd4be | ||
|
|
994d83dd80 | ||
|
|
f218efae09 | ||
|
|
9bea5c01b7 | ||
|
|
9dbc125598 | ||
|
|
af24eaea27 | ||
|
|
8adb7461b0 | ||
|
|
716e370d35 | ||
|
|
37c0768fe3 | ||
|
|
51860e9192 | ||
|
|
e81ad14586 | ||
|
|
ef1d5f86bf | ||
|
|
6c5cfbfc65 | ||
|
|
2bd8bb4c3b | ||
|
|
1c38648d5f | ||
|
|
875b5f3f52 | ||
|
|
be1f36a523 | ||
|
|
d4c7dd3490 | ||
|
|
637854fd90 | ||
|
|
e55fb21538 | ||
|
|
a966b0502f | ||
|
|
1bac61ad1c | ||
|
|
c7451115d8 | ||
|
|
72ae003a00 | ||
|
|
d67098b8f8 | ||
|
|
0e6dbaf050 | ||
|
|
32afc8565c | ||
|
|
48ace60875 | ||
|
|
9b6ee6fcad | ||
|
|
1a1639b87e | ||
|
|
3735aa504b | ||
|
|
367dda6794 | ||
|
|
e4a85f79cd | ||
|
|
678101938b | ||
|
|
9a3aa18c62 | ||
|
|
5a3ba1424a | ||
|
|
3bb8419a96 | ||
|
|
ce29282f63 | ||
|
|
9575299ae3 | ||
|
|
995ceca6c2 | ||
|
|
6abd0e6002 | ||
|
|
656e3062b4 | ||
|
|
9c9c519175 | ||
|
|
8300809562 | ||
|
|
cce7296ffe | ||
|
|
a445ad00da | ||
|
|
4db7e1a107 | ||
|
|
c51a1c4aa9 | ||
|
|
d489908e50 | ||
|
|
c4eda188d5 | ||
|
|
677eb4c876 | ||
|
|
69a4aa70b9 | ||
|
|
f07c2f460d | ||
|
|
09c557bdd7 | ||
|
|
e487da01c5 | ||
|
|
b6b6843ad2 | ||
|
|
66a1379947 | ||
|
|
546ba6c11e | ||
|
|
67ba63c2f4 | ||
|
|
99c2967920 | ||
|
|
2dc419f1ae | ||
|
|
450d6cea6d | ||
|
|
75df4ad3e6 | ||
|
|
4048d46443 | ||
|
|
b03cf507be | ||
|
|
066dc9b078 | ||
|
|
70854254e7 | ||
|
|
646df28ac8 | ||
|
|
73d4f987e4 | ||
|
|
c59d519c89 | ||
|
|
1ec2cba9e8 | ||
|
|
26cc1f8387 | ||
|
|
b57fa2b127 | ||
|
|
596909138a | ||
|
|
c11a76f2c1 | ||
|
|
51d32ad293 | ||
|
|
a433e9e0b4 | ||
|
|
abac61f5b5 | ||
|
|
a121a9d186 | ||
|
|
58ecbf6150 | ||
|
|
bad5ae41d1 | ||
|
|
e773e07373 | ||
|
|
c3ded3c003 | ||
|
|
76e04c4606 | ||
|
|
83ccf77d2f | ||
|
|
a0d53975d8 | ||
|
|
1252c0fbb9 | ||
|
|
04acf613ae | ||
|
|
c8bddb8035 | ||
|
|
467e83da31 | ||
|
|
8b29ef1335 | ||
|
|
1076700714 | ||
|
|
978f1155c5 | ||
|
|
3096d9d9cb | ||
|
|
ffea75abb2 | ||
|
|
a44a8b8789 | ||
|
|
05106096c3 | ||
|
|
ba7fd7a9a9 | ||
|
|
9b0e4e0085 | ||
|
|
3cb64f7f7e | ||
|
|
6642857437 | ||
|
|
91f00d643a | ||
|
|
ce8b62cfe7 | ||
|
|
4064bda60d | ||
|
|
4a21554986 | ||
|
|
165968dc26 | ||
|
|
9eb70f7be0 | ||
|
|
8797a9cb00 | ||
|
|
8366a5a6d6 | ||
|
|
63a9d5749b | ||
|
|
0e6aa41245 | ||
|
|
bbcb054814 | ||
|
|
2e5a86db7a | ||
|
|
057b15cefb | ||
|
|
7c06741f36 | ||
|
|
3a0c42aea5 | ||
|
|
75d5555a5f | ||
|
|
10c1ac9a66 | ||
|
|
692e15c088 | ||
|
|
6be9665bfb | ||
|
|
9be617d754 | ||
|
|
ec4f37fe25 | ||
|
|
6bb4ae9d50 | ||
|
|
c7a3f188c0 | ||
|
|
8e44509585 | ||
|
|
787954715b | ||
|
|
9f03260dd2 | ||
|
|
5c3a3f7fdf | ||
|
|
6693b22c83 | ||
|
|
49c7f60a57 | ||
|
|
ace4608f10 | ||
|
|
3899dfcc64 | ||
|
|
2dc98e9153 | ||
|
|
90f8a2409f | ||
|
|
92dc0db889 | ||
|
|
d8fc48e608 | ||
|
|
611802f990 | ||
|
|
606df86b0a | ||
|
|
2f7d38e6f6 | ||
|
|
b90d665ced | ||
|
|
50dd77ffd4 | ||
|
|
5e5b79783c | ||
|
|
c815114661 | ||
|
|
93f6a53201 | ||
|
|
a3ee0cfe79 | ||
|
|
95b0178514 | ||
|
|
afacf3db45 | ||
|
|
4a80321420 | ||
|
|
9295c69249 | ||
|
|
893f04967c | ||
|
|
fa410a6e02 | ||
|
|
aed2687743 | ||
|
|
978c0d10bc | ||
|
|
25b540e804 | ||
|
|
9aa58cd5c2 | ||
|
|
691be01bcc | ||
|
|
402ed45ee4 | ||
|
|
07dfcd83b9 | ||
|
|
9845dfda2c | ||
|
|
da5ee77e61 | ||
|
|
e1d2966e42 | ||
|
|
17428ce198 | ||
|
|
e87e790215 | ||
|
|
a6d4e17911 | ||
|
|
bde7846b5a | ||
|
|
01283767a6 |
+11
@@ -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
|
||||
|
||||
@@ -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
@@ -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>
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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++)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
@@ -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));
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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[])
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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 (11‐12) 1407-1422
|
||||
|
||||
[2] John A Evans, Thomas JR Hughes
|
||||
"Isogeometric divergence-conforming B-splines for the unsteady Navier–Stokes 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 (11‐12) 1407-1422
|
||||
|
||||
[2] John A Evans, Thomas JR Hughes
|
||||
"Isogeometric divergence-conforming B-splines for the unsteady
|
||||
Navier–Stokes 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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ list(APPEND HDRS
|
||||
handle.hpp
|
||||
invariants.hpp
|
||||
kernels.hpp
|
||||
lapack.hpp
|
||||
linalg.hpp
|
||||
matrix.hpp
|
||||
ode.hpp
|
||||
|
||||
+20
-138
@@ -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
|
||||
// Cholesky–Crout 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
File diff suppressed because it is too large
Load Diff
+24
-8
@@ -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();
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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, ¬rans, &nounit,
|
||||
#elif defined MFEM_USE_DOUBLE
|
||||
dtrsm_(&lside, &upper, ¬rans, &nounit,
|
||||
#endif
|
||||
&n_glob, &ione, &fone,
|
||||
mat_qr_data.GetData(), &m,
|
||||
vec1.GetData(), &n_glob);
|
||||
MFEM_LAPACK_PREFIX(trsm_)(&lside, &upper, ¬rans, &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_(¬rans, &m, &n_glob, &fmone,
|
||||
#elif defined MFEM_USE_DOUBLE
|
||||
dgemv_(¬rans, &m, &n_glob, &fmone,
|
||||
#endif
|
||||
mat_0_data.GetData(), &m,
|
||||
soln_nz_glob.GetData(), &ione, &fone,
|
||||
res_glob.GetData(), &ione);
|
||||
MFEM_LAPACK_PREFIX(gemv_)(¬rans, &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, ¬rans, &m, &ione, &n_glob, mat_qr_data.GetData(), &m,
|
||||
#elif defined MFEM_USE_DOUBLE
|
||||
dormqr_(&lside, ¬rans, &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, ¬rans, &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, ¬rans, &m, &ione, &n_glob, mat_qr_data.GetData(), &m,
|
||||
#elif defined MFEM_USE_DOUBLE
|
||||
dormqr_(&lside, ¬rans, &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, ¬rans, &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
@@ -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
@@ -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
File diff suppressed because it is too large
Load Diff
+4
-155
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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]; }
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+1
-64
@@ -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;
|
||||
|
||||
///@}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -37,3 +37,4 @@ add_subdirectory(tribol)
|
||||
add_subdirectory(hooke)
|
||||
add_subdirectory(dpg)
|
||||
add_subdirectory(hdiv-linear-solver)
|
||||
add_subdirectory(stabilized)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user