--- /srv/rebuilderd/tmp/rebuilderd6pw2hc/inputs/dolfinx-doc_0.10.0.post5-8_all.deb +++ /srv/rebuilderd/tmp/rebuilderd6pw2hc/out/dolfinx-doc_0.10.0.post5-8_all.deb ├── file list │ @@ -1,3 +1,3 @@ │ -rw-r--r-- 0 0 0 4 2026-07-23 15:29:35.000000 debian-binary │ --rw-r--r-- 0 0 0 23188 2026-07-23 15:29:35.000000 control.tar.xz │ --rw-r--r-- 0 0 0 9021140 2026-07-23 15:29:35.000000 data.tar.xz │ +-rw-r--r-- 0 0 0 23192 2026-07-23 15:29:35.000000 control.tar.xz │ +-rw-r--r-- 0 0 0 9021072 2026-07-23 15:29:35.000000 data.tar.xz ├── control.tar.xz │ ├── control.tar │ │ ├── ./md5sums │ │ │ ├── ./md5sums │ │ │ │┄ Files differ ├── data.tar.xz │ ├── data.tar │ │ ├── file list │ │ │ @@ -868,43 +868,43 @@ │ │ │ -rw-r--r-- 0 root (0) root (0) 325 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/cpp/search/variables_b.js │ │ │ -rw-r--r-- 0 root (0) root (0) 7571 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/cpp/tabs.css │ │ │ -rw-r--r-- 0 root (0) root (0) 3657 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/cpp/topics.html │ │ │ -rw-r--r-- 0 root (0) root (0) 3859 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/index.html │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/ │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/ │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/01cebb598a9eb6f964554459de25ce7c/ │ │ │ --rw-r--r-- 0 root (0) root (0) 6933 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/01cebb598a9eb6f964554459de25ce7c/demo_stokes.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 6927 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/01cebb598a9eb6f964554459de25ce7c/demo_stokes.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08143fa77f77a4782d22e85e7aebc523/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3080 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08143fa77f77a4782d22e85e7aebc523/demo_mixed-topology.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3081 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08143fa77f77a4782d22e85e7aebc523/demo_mixed-topology.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/082c4b6b2083855631db76b9eac6b348/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2721 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/082c4b6b2083855631db76b9eac6b348/demo_pyamg.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2718 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/082c4b6b2083855631db76b9eac6b348/demo_pyamg.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08f65cab6d6efa886b6e864593d5544d/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2937 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08f65cab6d6efa886b6e864593d5544d/demo_comm-pattern.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2939 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08f65cab6d6efa886b6e864593d5544d/demo_comm-pattern.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0aed751cd0874b28f5ae7bdc73e1060e/ │ │ │ --rw-r--r-- 0 root (0) root (0) 4223 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0aed751cd0874b28f5ae7bdc73e1060e/demo_biharmonic.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 4227 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0aed751cd0874b28f5ae7bdc73e1060e/demo_biharmonic.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0ff7b5905586c05f3ded87f72380f93b/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3186 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0ff7b5905586c05f3ded87f72380f93b/demo_lagrange_variants.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3178 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0ff7b5905586c05f3ded87f72380f93b/demo_lagrange_variants.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/14903818ff63fe77ad13ebe2fd3c2bfa/ │ │ │ -rw-r--r-- 0 root (0) root (0) 16870 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/14903818ff63fe77ad13ebe2fd3c2bfa/demo_half_loaded_waveguide.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/16ae5ee96f6630d2b709d4fae5801c3a/ │ │ │ -rw-r--r-- 0 root (0) root (0) 6740 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/16ae5ee96f6630d2b709d4fae5801c3a/demo_mixed-topology.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1a16c2f4b29ea3e52acc5e0c69e7d325/ │ │ │ -rw-r--r-- 0 root (0) root (0) 26254 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1a16c2f4b29ea3e52acc5e0c69e7d325/demo_axis.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1a19850a673ac0912099149a21b82fe9/ │ │ │ -rw-r--r-- 0 root (0) root (0) 28277 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1a19850a673ac0912099149a21b82fe9/demo_scattering_boundary_conditions.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1c10919af1d1c2689ff1982d6e82b898/ │ │ │ --rw-r--r-- 0 root (0) root (0) 5457 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1c10919af1d1c2689ff1982d6e82b898/demo_navier-stokes.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 5462 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1c10919af1d1c2689ff1982d6e82b898/demo_navier-stokes.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/244d514e5e2d1484e9f045150ae16a27/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2889 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/244d514e5e2d1484e9f045150ae16a27/demo_gmsh.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2880 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/244d514e5e2d1484e9f045150ae16a27/demo_gmsh.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/2582f4d86e9cdad523ac798f84ed8877/ │ │ │ -rw-r--r-- 0 root (0) root (0) 9311 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/2582f4d86e9cdad523ac798f84ed8877/demo_biharmonic.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3013bc98771f29691ef96d816a24e9b5/ │ │ │ -rw-r--r-- 0 root (0) root (0) 8437 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3013bc98771f29691ef96d816a24e9b5/demo_poisson_matrix_free.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3a2e8b3062e32f7fa335a0116fae9bef/ │ │ │ --rw-r--r-- 0 root (0) root (0) 4266 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3a2e8b3062e32f7fa335a0116fae9bef/demo_hdg.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 4269 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3a2e8b3062e32f7fa335a0116fae9bef/demo_hdg.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3e7291d3b77b3f22251cd7795a639a00/ │ │ │ -rw-r--r-- 0 root (0) root (0) 8703 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3e7291d3b77b3f22251cd7795a639a00/demo_hdg.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3f4304da118cf34f94b5991c582738c4/ │ │ │ -rw-r--r-- 0 root (0) root (0) 7065 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3f4304da118cf34f94b5991c582738c4/demo_pyamg.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4108f87eb9b678931168ffba26e2c302/ │ │ │ -rw-r--r-- 0 root (0) root (0) 13078 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4108f87eb9b678931168ffba26e2c302/demo_mixed-poisson.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/44f4041e8551d8a922a8c3a49107aaf9/ │ │ │ @@ -914,61 +914,61 @@ │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4805c30fd9f5602435f2b34dad232ba2/ │ │ │ -rw-r--r-- 0 root (0) root (0) 8745 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4805c30fd9f5602435f2b34dad232ba2/demo_lagrange_variants.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4cfcffe5891ed56ed48568fb00a06e67/ │ │ │ -rw-r--r-- 0 root (0) root (0) 10324 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4cfcffe5891ed56ed48568fb00a06e67/demo_static-condensation.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/51e819842c2534ea5d902f847c84b6ee/ │ │ │ -rw-r--r-- 0 root (0) root (0) 5121 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/51e819842c2534ea5d902f847c84b6ee/demo_helmholtz.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5261c2fbfdb83b277c92e92bde061504/ │ │ │ --rw-r--r-- 0 root (0) root (0) 8857 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5261c2fbfdb83b277c92e92bde061504/demo_axis.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 8859 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5261c2fbfdb83b277c92e92bde061504/demo_axis.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/56ce7e71d8c71b4d8ef7c699176dd4fd/ │ │ │ -rw-r--r-- 0 root (0) root (0) 22619 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/56ce7e71d8c71b4d8ef7c699176dd4fd/demo_stokes.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5dc7fa0449730e3256bb33fc2b2d403b/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3095 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5dc7fa0449730e3256bb33fc2b2d403b/demo_poisson.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3096 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5dc7fa0449730e3256bb33fc2b2d403b/demo_poisson.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/67f8546536727bd5386a27073bd16e12/ │ │ │ -rw-r--r-- 0 root (0) root (0) 7983 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/67f8546536727bd5386a27073bd16e12/demo_elasticity.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/69c686705c3e4103e036ace87972a971/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2784 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/69c686705c3e4103e036ace87972a971/demo_types.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2791 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/69c686705c3e4103e036ace87972a971/demo_types.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6ad57720b461988475bd5c9286e3f111/ │ │ │ -rw-r--r-- 0 root (0) root (0) 7579 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6ad57720b461988475bd5c9286e3f111/demo_types.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6bd0b7dbffc1fd43f16bc5cd2cfeed74/ │ │ │ --rw-r--r-- 0 root (0) root (0) 4726 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6bd0b7dbffc1fd43f16bc5cd2cfeed74/demo_static-condensation.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 4729 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6bd0b7dbffc1fd43f16bc5cd2cfeed74/demo_static-condensation.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7742577adb1c8360c8a19eea719713fc/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3758 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7742577adb1c8360c8a19eea719713fc/demo_pyvista.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3761 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7742577adb1c8360c8a19eea719713fc/demo_pyvista.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7fc5387c9d660ce24e2f50b0f79aad08/ │ │ │ -rw-r--r-- 0 root (0) root (0) 6811 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7fc5387c9d660ce24e2f50b0f79aad08/demo_comm-pattern.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/911a7569fd30f814e5e3d622695b49c1/ │ │ │ -rw-r--r-- 0 root (0) root (0) 27719 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/911a7569fd30f814e5e3d622695b49c1/demo_pml.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/94dc1fa896703fdd4c54729bdfbf969a/ │ │ │ --rw-r--r-- 0 root (0) root (0) 10156 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/94dc1fa896703fdd4c54729bdfbf969a/demo_pml.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 10157 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/94dc1fa896703fdd4c54729bdfbf969a/demo_pml.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9561cf6cd1a70079b986f4eb31580cbd/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3874 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9561cf6cd1a70079b986f4eb31580cbd/demo_poisson_matrix_free.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3872 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9561cf6cd1a70079b986f4eb31580cbd/demo_poisson_matrix_free.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9b362df2c2031d4138a5021a53979414/ │ │ │ --rw-r--r-- 0 root (0) root (0) 5168 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9b362df2c2031d4138a5021a53979414/demo_cahn-hilliard.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 5167 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9b362df2c2031d4138a5021a53979414/demo_cahn-hilliard.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9ed4657d08dda04de30e6463e2f58d75/ │ │ │ --rw-r--r-- 0 root (0) root (0) 5634 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9ed4657d08dda04de30e6463e2f58d75/demo_mixed-poisson.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 5636 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9ed4657d08dda04de30e6463e2f58d75/demo_mixed-poisson.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/a5df6747d3300b9568f25507c7fb2517/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2107 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/a5df6747d3300b9568f25507c7fb2517/demo_interpolation-io.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2109 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/a5df6747d3300b9568f25507c7fb2517/demo_interpolation-io.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b3f0523386e0521f7e6a5599627be9fc/ │ │ │ --rw-r--r-- 0 root (0) root (0) 7064 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b3f0523386e0521f7e6a5599627be9fc/demo_half_loaded_waveguide.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 7061 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b3f0523386e0521f7e6a5599627be9fc/demo_half_loaded_waveguide.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b94ac7be61dc3726ca331afd20f195d2/ │ │ │ -rw-r--r-- 0 root (0) root (0) 6231 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b94ac7be61dc3726ca331afd20f195d2/demo_poisson.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c13ef8eb7697276d5c6443a7049d2298/ │ │ │ -rw-r--r-- 0 root (0) root (0) 12043 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c13ef8eb7697276d5c6443a7049d2298/demo_pyvista.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c202a2458472f1e0e385ed9afdc3da0f/ │ │ │ -rw-r--r-- 0 root (0) root (0) 2702 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c202a2458472f1e0e385ed9afdc3da0f/demo_helmholtz.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e5597ff2b0334295de2749391a1ffbe1/ │ │ │ --rw-r--r-- 0 root (0) root (0) 4519 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e5597ff2b0334295de2749391a1ffbe1/demo_tnt-elements.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 4518 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e5597ff2b0334295de2749391a1ffbe1/demo_tnt-elements.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e8140d02a100265518e126a3cfe79d8e/ │ │ │ -rw-r--r-- 0 root (0) root (0) 4245 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e8140d02a100265518e126a3cfe79d8e/demo_interpolation-io.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e8b180b39a27d7b04c2f666d14475ee3/ │ │ │ -rw-r--r-- 0 root (0) root (0) 11391 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e8b180b39a27d7b04c2f666d14475ee3/demo_cahn-hilliard.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/eb193fc2ce46146f29b3c38146a5a3cb/ │ │ │ --rw-r--r-- 0 root (0) root (0) 10150 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/eb193fc2ce46146f29b3c38146a5a3cb/demo_scattering_boundary_conditions.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 10148 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/eb193fc2ce46146f29b3c38146a5a3cb/demo_scattering_boundary_conditions.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f60c5654312263c726a60c7d3dcc6729/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3934 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f60c5654312263c726a60c7d3dcc6729/demo_elasticity.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3932 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f60c5654312263c726a60c7d3dcc6729/demo_elasticity.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f6f3cc4d9540871af057920d1ddb5561/ │ │ │ -rw-r--r-- 0 root (0) root (0) 11682 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f6f3cc4d9540871af057920d1ddb5561/demo_tnt-elements.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_images/ │ │ │ -rw-r--r-- 0 root (0) root (0) 67993 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_images/demo_lagrange_variants_equispaced_10.png │ │ │ -rw-r--r-- 0 root (0) root (0) 41664 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_images/demo_lagrange_variants_gll_10.png │ │ │ -rw-r--r-- 0 root (0) root (0) 42191 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_images/demo_lagrange_variants_interpolation_equispaced.png │ │ │ -rw-r--r-- 0 root (0) root (0) 41221 2026-07-23 15:29:35.000000 ./usr/share/doc/dolfinx-doc/python/_images/demo_lagrange_variants_interpolation_gll_warped.png │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/01cebb598a9eb6f964554459de25ce7c/demo_stokes.ipynb.gz │ │ │ ├── demo_stokes.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666667% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '32fc3953'}, 1: {'id': 'dd72feea'}, 2: {'id': '56176e38'}, 3: {'id': " │ │ │ │ │┄ "'5e26fca5'}, 4: {'id': 'b7817f49'}, 5: {'id': 'bd9b12c5'}, 6: {'id': 'b2155a92'}, 7: " │ │ │ │ │┄ "{'id': 'a095b0ea'}, 8: {'id': '735f8dfd'}, 9: {'id': 'cdf46823'}, 10: {'id': " │ │ │ │ │┄ "'36438b59'}, 11: {'id': 'f629aa13'}, 12: {'id': 'c71c457a'}, 13: {'id': 'dd7fd0e8'}, " │ │ │ │ │┄ "14: {'id': '4bfed42f'}, 15: {'id': '27c0e3b4'}, 16: {'id': '1a7826fc'}, 17: {'id': " │ │ │ │ │┄ "'d9395d94'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "139c8e42", │ │ │ │ │ + "id": "32fc3953", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Stokes equations using Taylor-Hood elements\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_stokes.py>`\n", │ │ │ │ │ @@ -88,15 +88,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "The required modules are first imported:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "bb5bbc42", │ │ │ │ │ + "id": "dd72feea", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py import PETSc\n", │ │ │ │ │ "\n", │ │ │ │ │ "import numpy as np\n", │ │ │ │ │ @@ -125,26 +125,26 @@ │ │ │ │ │ "from dolfinx.io import XDMFFile\n", │ │ │ │ │ "from dolfinx.la.petsc import create_vector_wrap\n", │ │ │ │ │ "from dolfinx.mesh import CellType, create_rectangle, locate_entities_boundary\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e2ea12d6", │ │ │ │ │ + "id": "56176e38", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create a {py:class}`Mesh `, define functions for\n", │ │ │ │ │ "locating geometrically subsets of the boundary, and define a function\n", │ │ │ │ │ "for the velocity on the lid:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "352a7b64", │ │ │ │ │ + "id": "5e26fca5", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Create mesh\n", │ │ │ │ │ "msh = create_rectangle(\n", │ │ │ │ │ @@ -165,51 +165,51 @@ │ │ │ │ │ "# Lid velocity\n", │ │ │ │ │ "def lid_velocity_expression(x):\n", │ │ │ │ │ " return np.stack((np.ones(x.shape[1]), np.zeros(x.shape[1])))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c1f4bd1d", │ │ │ │ │ + "id": "b7817f49", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Two {py:class}`function spaces ` are\n", │ │ │ │ │ "defined using different finite elements. `P2` corresponds to a\n", │ │ │ │ │ "continuous piecewise quadratic basis (vector) and `P1` to a continuous\n", │ │ │ │ │ "piecewise linear basis (scalar)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6ba0a12c", │ │ │ │ │ + "id": "bd9b12c5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "P2 = element(\n", │ │ │ │ │ " \"Lagrange\", msh.basix_cell(), degree=2, shape=(msh.geometry.dim,), dtype=default_real_type\n", │ │ │ │ │ ")\n", │ │ │ │ │ "P1 = element(\"Lagrange\", msh.basix_cell(), degree=1, dtype=default_real_type)\n", │ │ │ │ │ "V, Q = functionspace(msh, P2), functionspace(msh, P1)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "62b842d7", │ │ │ │ │ + "id": "b2155a92", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Boundary conditions for the velocity field are defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4f4feb3d", │ │ │ │ │ + "id": "a095b0ea", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# No-slip condition on boundaries where x = 0, x = 1, and y = 0\n", │ │ │ │ │ "noslip = np.zeros(msh.geometry.dim, dtype=PETSc.ScalarType) # type: ignore\n", │ │ │ │ │ "facets = locate_entities_boundary(msh, 1, noslip_boundary)\n", │ │ │ │ │ "bc0 = dirichletbc(noslip, locate_dofs_topological(V, 1, facets), V)\n", │ │ │ │ │ @@ -222,25 +222,25 @@ │ │ │ │ │ "\n", │ │ │ │ │ "# Collect Dirichlet boundary conditions\n", │ │ │ │ │ "bcs = [bc0, bc1]" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3829c470", │ │ │ │ │ + "id": "735f8dfd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The bilinear and linear forms for the Stokes equations are defined\n", │ │ │ │ │ "using a blocked structure:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8e83a7d9", │ │ │ │ │ + "id": "cdf46823", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Define variational problem\n", │ │ │ │ │ "(u, p) = ufl.TrialFunction(V), ufl.TrialFunction(Q)\n", │ │ │ │ │ "(v, q) = ufl.TestFunction(V), ufl.TestFunction(Q)\n", │ │ │ │ │ "f = Constant(msh, (PETSc.ScalarType(0), PETSc.ScalarType(0))) # type: ignore\n", │ │ │ │ │ @@ -252,37 +252,37 @@ │ │ │ │ │ "a = form(a_ufl)\n", │ │ │ │ │ "L_ufl = [ufl.inner(f, v) * ufl.dx, ufl.ZeroBaseForm((q,))]\n", │ │ │ │ │ "L = form(L_ufl)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "967f3278", │ │ │ │ │ + "id": "36438b59", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "A block-diagonal preconditioner will be used with the iterative\n", │ │ │ │ │ "solvers for this problem:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e667859f", │ │ │ │ │ + "id": "f629aa13", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "a_p11 = form(ufl.inner(p, q) * ufl.dx)\n", │ │ │ │ │ "a_p = [[a[0][0], None], [None, a_p11]]" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "76ab8be4", │ │ │ │ │ + "id": "c71c457a", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "### High-level nested matrix solver\n", │ │ │ │ │ "\n", │ │ │ │ │ "We first use the high-level {py:class}`LinearProblem\n", │ │ │ │ │ @@ -290,15 +290,15 @@ │ │ │ │ │ "the linear problem. Details on the preconditioner setup are given in\n", │ │ │ │ │ "{py:func}`nested_iterative_solver_low_level` below." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5b00f963", │ │ │ │ │ + "id": "dd7fd0e8", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def nested_iterative_solver_high_level():\n", │ │ │ │ │ " \"\"\"Solve the Stokes problem using nest matrices and an iterative solver\n", │ │ │ │ │ @@ -360,15 +360,15 @@ │ │ │ │ │ " print(f\"(A) Norm of pressure coefficient vector (high-level nested, iterative): {norm_p}\")\n", │ │ │ │ │ "\n", │ │ │ │ │ " return norm_u, norm_p" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e1c343e4", │ │ │ │ │ + "id": "4bfed42f", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "### Low-level nested matrix solver\n", │ │ │ │ │ "\n", │ │ │ │ │ "We assemble the bilinear form into a nested matrix `A`, and call the\n", │ │ │ │ │ @@ -377,15 +377,15 @@ │ │ │ │ │ "Dirichlet boundary conditions will be zeroed by the assembler, and a\n", │ │ │ │ │ "value of 1 will be set on the diagonal for these rows." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "150b3375", │ │ │ │ │ + "id": "27c0e3b4", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def nested_iterative_solver_low_level():\n", │ │ │ │ │ " \"\"\"Solve the Stokes problem using nest matrices and an iterative\n", │ │ │ │ │ @@ -492,30 +492,30 @@ │ │ │ │ │ " print(f\"(A) Norm of pressure coefficient vector (low-level nested, iterative): {norm_p}\")\n", │ │ │ │ │ "\n", │ │ │ │ │ " return norm_u, norm_p" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "aa961610", │ │ │ │ │ + "id": "1a7826fc", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "### Monolithic block iterative solver\n", │ │ │ │ │ "\n", │ │ │ │ │ "We now solve the same Stokes problem, but using monolithic\n", │ │ │ │ │ "(non-nested) matrices. We first create a helper function for\n", │ │ │ │ │ "assembling the linear operators and the RHS vector." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fe3a46cb", │ │ │ │ │ + "id": "d9395d94", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def block_operators():\n", │ │ │ │ │ " \"\"\"Return block operators and block RHS vector for the Stokes\n", │ │ │ │ │ @@ -546,27 +546,27 @@ │ │ │ │ │ " A.setNullSpace(nsp)\n", │ │ │ │ │ "\n", │ │ │ │ │ " return A, P, b" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e4c9305e", │ │ │ │ │ + "id": "299dbb0c", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "The following function solves the Stokes problem using a\n", │ │ │ │ │ "block-diagonal preconditioner and monolithic PETSc matrices." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e2b88b71", │ │ │ │ │ + "id": "5c040444", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def block_iterative_solver():\n", │ │ │ │ │ " \"\"\"Solve the Stokes problem using blocked matrices and an iterative\n", │ │ │ │ │ @@ -630,29 +630,29 @@ │ │ │ │ │ " print(f\"(B) Norm of pressure coefficient vector (blocked, iterative): {norm_p}\")\n", │ │ │ │ │ "\n", │ │ │ │ │ " return norm_u, norm_p" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e7210164", │ │ │ │ │ + "id": "8ad411f7", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "### Monolithic block direct solver\n", │ │ │ │ │ "\n", │ │ │ │ │ "We now solve the same Stokes problem again, but using monolithic\n", │ │ │ │ │ "(non-nested) matrices and a direct (LU) solver." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "74c56f97", │ │ │ │ │ + "id": "a3023da1", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def block_direct_solver():\n", │ │ │ │ │ " \"\"\"Solve the Stokes problem using blocked matrices and a direct\n", │ │ │ │ │ @@ -696,15 +696,15 @@ │ │ │ │ │ " print(f\"(C) Norm of pressure coefficient vector (blocked, direct): {norm_p}\")\n", │ │ │ │ │ "\n", │ │ │ │ │ " return norm_u, norm_p" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "03055fa3", │ │ │ │ │ + "id": "8b91cbf4", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "### Non-blocked direct solver\n", │ │ │ │ │ "\n", │ │ │ │ │ "We now solve the Stokes problem, but using monolithic matrix with the\n", │ │ │ │ │ @@ -712,15 +712,15 @@ │ │ │ │ │ "u/p block structure in the assembled matrix. A direct (LU) solver is\n", │ │ │ │ │ "used." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c15250d7", │ │ │ │ │ + "id": "67d7b1ae", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def mixed_direct():\n", │ │ │ │ │ " # Create the Taylot-Hood function space\n", │ │ │ │ │ " TH = mixed_element([P2, P1])\n", │ │ │ │ │ " W = functionspace(msh, TH)\n", │ │ │ │ │ @@ -805,102 +805,102 @@ │ │ │ │ │ " print(f\"(D) Norm of pressure coefficient vector (monolithic, direct): {norm_p}\")\n", │ │ │ │ │ "\n", │ │ │ │ │ " return norm_u, norm_u" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8489380e", │ │ │ │ │ + "id": "617a0472", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using LinearProblem class" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ef261493", │ │ │ │ │ + "id": "c28a7f28", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "norm_u_0, norm_p_0 = nested_iterative_solver_high_level()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0211a71e", │ │ │ │ │ + "id": "39517991", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using PETSc MatNest" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "21455ae3", │ │ │ │ │ + "id": "7ed000a8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "norm_u_1, norm_p_1 = nested_iterative_solver_low_level()\n", │ │ │ │ │ "np.testing.assert_allclose(norm_u_1, norm_u_0, rtol=1e-4)\n", │ │ │ │ │ "np.testing.assert_allclose(norm_u_1, norm_u_0, rtol=1e-4)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "73064043", │ │ │ │ │ + "id": "ec5c85f5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using PETSc block matrices and an iterative solver" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1adf063d", │ │ │ │ │ + "id": "84251780", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "norm_u_2, norm_p_2 = block_iterative_solver()\n", │ │ │ │ │ "np.testing.assert_allclose(norm_u_2, norm_u_0, rtol=1e-4)\n", │ │ │ │ │ "np.testing.assert_allclose(norm_u_2, norm_u_0, rtol=1e-4)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "50874215", │ │ │ │ │ + "id": "2144e814", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using PETSc block matrices and an LU solver" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "557c9110", │ │ │ │ │ + "id": "6fc02302", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "norm_u_3, norm_p_3 = block_direct_solver()\n", │ │ │ │ │ "np.testing.assert_allclose(norm_u_3, norm_u_0, rtol=1e-4)\n", │ │ │ │ │ "np.testing.assert_allclose(norm_p_3, norm_p_0, rtol=1e-4)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "119d0242", │ │ │ │ │ + "id": "d9874dd3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using a non-blocked matrix and an LU solver" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "118c14c7", │ │ │ │ │ + "id": "79e30bcb", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "norm_u_4, norm_p_4 = mixed_direct()\n", │ │ │ │ │ "np.testing.assert_allclose(norm_u_4, norm_u_0, rtol=1e-4)" │ │ │ │ │ ] │ │ │ │ │ } │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/08143fa77f77a4782d22e85e7aebc523/demo_mixed-topology.ipynb.gz │ │ │ ├── demo_mixed-topology.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9872685185185185% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '1fc89f1d'}, 1: {'id': '834c7112'}, 2: {'id': '5b3acfe0'}, 3: {'id': " │ │ │ │ │┄ "'673b7aaa'}, 4: {'id': '3ad8f177'}, 5: {'id': '4e7c304c'}, 6: {'id': '15837f99'}, 7: " │ │ │ │ │┄ "{'id': 'dcaf40a1'}, 8: {'id': '3a1ae1d9'}, 9: {'id': '9cf609fb'}, 10: {'id': " │ │ │ │ │┄ "'f7174b0b'}, 11: {'id': 'ff4cc182'}, 12: {'id': 'e266359c'}, 13: {'id': 'bd603af9'}, " │ │ │ │ │┄ "14: {'id': '221087d8'}, 15: {'id': 'bfd7f868'}, 16: {'id': 'a238896f'}, 17: {'id': " │ │ │ │ │┄ "'d4952434'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f563b888", │ │ │ │ │ + "id": "1fc89f1d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Poisson equation\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_mixed-topology.py>`\n", │ │ │ │ │ @@ -22,15 +22,15 @@ │ │ │ │ │ "supported in DOLFINx.\n", │ │ │ │ │ "```" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7b819e36", │ │ │ │ │ + "id": "834c7112", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "\n", │ │ │ │ │ "import numpy as np\n", │ │ │ │ │ "from scipy.sparse.linalg import spsolve\n", │ │ │ │ │ @@ -51,37 +51,37 @@ │ │ │ │ │ "from dolfinx.io.utils import cell_perm_vtk\n", │ │ │ │ │ "from dolfinx.mesh import CellType, Mesh, Topology\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c6d015e4", │ │ │ │ │ + "id": "5b3acfe0", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if MPI.COMM_WORLD.size > 1:\n", │ │ │ │ │ " print(\"Not yet running in parallel\")\n", │ │ │ │ │ " exit(0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ad143a14", │ │ │ │ │ + "id": "673b7aaa", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Create a mixed-topology mesh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f2f8dab0", │ │ │ │ │ + "id": "3ad8f177", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "nx = 16\n", │ │ │ │ │ "ny = 16\n", │ │ │ │ │ "nz = 16\n", │ │ │ │ │ "n_cells = nx * ny * nz\n", │ │ │ │ │ @@ -136,25 +136,25 @@ │ │ │ │ │ "mesh = create_mesh(\n", │ │ │ │ │ " MPI.COMM_WORLD, cells_np, [hexahedron._cpp_object, prism._cpp_object], geomx, part, 2\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "aa6ca73d", │ │ │ │ │ + "id": "4e7c304c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Create a mixed-topology dofmap and function space\n", │ │ │ │ │ "Create elements and dofmaps for each cell type" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "456e4f89", │ │ │ │ │ + "id": "15837f99", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "elements = [\n", │ │ │ │ │ " basix.create_element(basix.ElementFamily.P, basix.CellType.hexahedron, 1),\n", │ │ │ │ │ " basix.create_element(basix.ElementFamily.P, basix.CellType.prism, 1),\n", │ │ │ │ │ "]\n", │ │ │ │ │ @@ -172,27 +172,27 @@ │ │ │ │ │ "V_cpp = _cpp.fem.FunctionSpace_float64(\n", │ │ │ │ │ " mesh, [e._cpp_object for e in dolfinx_elements], [dofmap._cpp_object for dofmap in dofmaps]\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8b35c36b", │ │ │ │ │ + "id": "dcaf40a1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Creating and compiling a variational formulation\n", │ │ │ │ │ "We create the variational forms for each cell type.\n", │ │ │ │ │ "FIXME: This hack is required at the moment because UFL does not yet know\n", │ │ │ │ │ "about mixed topology meshes." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fa51c057", │ │ │ │ │ + "id": "3a1ae1d9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "a = []\n", │ │ │ │ │ "L = []\n", │ │ │ │ │ "for i, cell_name in enumerate([\"hexahedron\", \"prism\"]):\n", │ │ │ │ │ " print(f\"Creating form for {cell_name}\")\n", │ │ │ │ │ @@ -205,102 +205,102 @@ │ │ │ │ │ " a += [(ufl.inner(ufl.grad(u), ufl.grad(v)) - k**2 * u * v) * ufl.dx]\n", │ │ │ │ │ " f = ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1])\n", │ │ │ │ │ " L += [f * v * ufl.dx]" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3d3bd9c8", │ │ │ │ │ + "id": "9cf609fb", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Compile the form\n", │ │ │ │ │ "FIXME: For the time being, since UFL doesn't understand mixed topology\n", │ │ │ │ │ "meshes, we have to call {py:meth}`mixed_topology_form\n", │ │ │ │ │ "` instead of form." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "aff2c9e2", │ │ │ │ │ + "id": "f7174b0b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "a_form = mixed_topology_form(a, dtype=np.float64)\n", │ │ │ │ │ "L_form = mixed_topology_form(L, dtype=np.float64)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1a8b23ef", │ │ │ │ │ + "id": "ff4cc182", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Assembling and solving the linear system\n", │ │ │ │ │ "We use the native {py:class}`matrix` and\n", │ │ │ │ │ "{py:class}`vector` format in DOLFINx to assemble\n", │ │ │ │ │ "the left and right hand side of the linear system." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c7c3c1c0", │ │ │ │ │ + "id": "e266359c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "A = assemble_matrix(a_form)\n", │ │ │ │ │ "b = assemble_vector(L_form)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "829ea14c", │ │ │ │ │ + "id": "bd603af9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We use {py:func}`scipy.sparse.linalg.spsolve` to solve the\n", │ │ │ │ │ "resulting linear system" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a9f3eb2a", │ │ │ │ │ + "id": "221087d8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "A_scipy = A.to_scipy()\n", │ │ │ │ │ "b_scipy = b.array\n", │ │ │ │ │ "x = spsolve(A_scipy, b_scipy)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b8322def", │ │ │ │ │ + "id": "bfd7f868", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "print(f\"Solution vector norm {np.linalg.norm(x)}\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e3930aa2", │ │ │ │ │ + "id": "a238896f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Mixed-topology I/O\n", │ │ │ │ │ "We manually build a ASCII XDMF file to store the mesh\n", │ │ │ │ │ "and solution\n", │ │ │ │ │ "NOTE: this should be replaced with VTKHDF" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "3484bc89", │ │ │ │ │ + "id": "d4952434", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "xdmf = \"\"\"\n", │ │ │ │ │ "\n", │ │ │ │ │ "\n", │ │ │ │ │ " \n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/082c4b6b2083855631db76b9eac6b348/demo_pyamg.ipynb.gz │ │ │ ├── demo_pyamg.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9876893939393939% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '0f2c329c'}, 1: {'id': 'dd736077'}, 2: {'id': '169054be'}, 3: {'id': " │ │ │ │ │┄ "'0f80c4b1'}, 4: {'id': 'ee020b44'}, 5: {'id': 'deb58d5c'}, 6: {'id': '053bf9ce'}, 7: " │ │ │ │ │┄ "{'id': '9768a993'}, 8: {'id': 'd8654177'}, 9: {'id': 'bb9bbf45'}, 10: {'id': " │ │ │ │ │┄ "'1bc14de8'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e22b4781", │ │ │ │ │ + "id": "0f2c329c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Solve the Poisson and linearised elasticity equations using pyamg\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_pyamg.py>`\n", │ │ │ │ │ @@ -17,15 +17,15 @@ │ │ │ │ │ "[pyamg](https://github.com/pyamg/pyamg).\n", │ │ │ │ │ "pyamg is not MPI-parallel, therefore this demo runs in serial only." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b9377e13", │ │ │ │ │ + "id": "dd736077", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "import sys\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -50,15 +50,15 @@ │ │ │ │ │ " print(\"This demo works only in serial.\")\n", │ │ │ │ │ " exit(0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8a6ccc83", │ │ │ │ │ + "id": "169054be", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2, │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def poisson_problem(dtype: npt.DTypeLike, solver_type: str) -> None:\n", │ │ │ │ │ @@ -127,15 +127,15 @@ │ │ │ │ │ " file.write_mesh(mesh)\n", │ │ │ │ │ " file.write_function(uh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e0f1839a", │ │ │ │ │ + "id": "0f80c4b1", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2, │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def nullspace_elasticty(Q: fem.FunctionSpace) -> list[np.ndarray]:\n", │ │ │ │ │ @@ -168,15 +168,15 @@ │ │ │ │ │ " B[dofs[1], 5] = -x2\n", │ │ │ │ │ " return B" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8ddfda56", │ │ │ │ │ + "id": "ee020b44", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2, │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def elasticity_problem(dtype) -> None:\n", │ │ │ │ │ @@ -247,63 +247,63 @@ │ │ │ │ │ " with io.XDMFFile(mesh.comm, f\"out_pyamg/elasticity_{dtype.__name__}.xdmf\", \"w\") as file:\n", │ │ │ │ │ " file.write_mesh(mesh)\n", │ │ │ │ │ " file.write_function(uh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "da4d8895", │ │ │ │ │ + "id": "deb58d5c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve Poission problem with different scalar types" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d357cd60", │ │ │ │ │ + "id": "053bf9ce", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "poisson_problem(np.float32, \"ruge_stuben\")\n", │ │ │ │ │ "poisson_problem(np.float64, \"ruge_stuben\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1f4e6616", │ │ │ │ │ + "id": "9768a993", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For complex, pyamg requires smoothed aggregation multigrid" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "be6b87d6", │ │ │ │ │ + "id": "d8654177", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if not sys.platform.startswith(\"win32\"):\n", │ │ │ │ │ " poisson_problem(np.complex64, \"smoothed_aggregation\")\n", │ │ │ │ │ " poisson_problem(np.complex128, \"smoothed_aggregation\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9f3cb658", │ │ │ │ │ + "id": "bb9bbf45", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve elasticity problem with different scalar types" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c130509a", │ │ │ │ │ + "id": "1bc14de8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "elasticity_problem(np.float32)\n", │ │ │ │ │ "elasticity_problem(np.float64)" │ │ │ │ │ ] │ │ │ │ │ } │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/08f65cab6d6efa886b6e864593d5544d/demo_comm-pattern.ipynb.gz │ │ │ ├── demo_comm-pattern.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666666% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': 'bf2fbab5'}, 1: {'id': '3353c28e'}, 2: {'id': '0ef73e96'}, 3: {'id': " │ │ │ │ │┄ "'0e1b0a29'}, 4: {'id': '034b0741'}, 5: {'id': '9a85771c'}, 6: {'id': '94c5b730'}, 7: " │ │ │ │ │┄ "{'id': '5f7cfb15'}, 8: {'id': '13c113d0'}, 9: {'id': '2159c975'}, 10: {'id': " │ │ │ │ │┄ "'53fc1246'}, 11: {'id': 'bb334ff7'}, 12: {'id': 'e9cfa89f'}, 13: {'id': '9262f960'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "97ec8a0c", │ │ │ │ │ + "id": "bf2fbab5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Parallel communication pattern analysis\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_comm-pattern.py>`\n", │ │ │ │ │ @@ -25,15 +25,15 @@ │ │ │ │ │ "holds information on the ranks that the calling rank will send data to\n", │ │ │ │ │ "and ranks that will send data to the caller.\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ee006452", │ │ │ │ │ + "id": "3353c28e", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "import itertools as it\n", │ │ │ │ │ "import json\n", │ │ │ │ │ @@ -45,29 +45,29 @@ │ │ │ │ │ "from matplotlib.ticker import MaxNLocator\n", │ │ │ │ │ "\n", │ │ │ │ │ "from dolfinx import fem, graph, mesh\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "a2bcd0a5", │ │ │ │ │ + "id": "0ef73e96", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "The following function plots a directed graph, with the edge weights\n", │ │ │ │ │ "labeled. Each node is an MPI rank, and an edge represents a\n", │ │ │ │ │ "communication edge. The edge weights indicate the volume of data\n", │ │ │ │ │ "communicated." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a7bd7320", │ │ │ │ │ + "id": "0e1b0a29", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def plot_graph(G: nx.MultiGraph, egde_labels=False):\n", │ │ │ │ │ " \"\"\"Plot the communication graph.\"\"\"\n", │ │ │ │ │ @@ -99,28 +99,28 @@ │ │ │ │ │ " )\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " nx.draw_networkx_edges(G, pos, width=width, edge_color=edge_color)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2658e5a3", │ │ │ │ │ + "id": "034b0741", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "The following function produces bar charts with the number of out-edges\n", │ │ │ │ │ "per rank and the sum of the out edge weights (measure of data\n", │ │ │ │ │ "volume) per rank." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "0e522fdd", │ │ │ │ │ + "id": "9a85771c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def plot_bar(G: nx.MultiGraph):\n", │ │ │ │ │ " \"\"\"Plot bars charts with the degree (number of 'out-edges') and the\n", │ │ │ │ │ " outward data volume for each rank.\n", │ │ │ │ │ " \"\"\"\n", │ │ │ │ │ @@ -142,78 +142,78 @@ │ │ │ │ │ " ax2.set_ylabel(\"sum of edge weights\")\n", │ │ │ │ │ " ax2.xaxis.set_major_locator(MaxNLocator(integer=True))\n", │ │ │ │ │ " ax2.yaxis.set_major_locator(MaxNLocator(integer=True))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ea63cf2c", │ │ │ │ │ + "id": "94c5b730", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a mesh and function space. The function space will build an\n", │ │ │ │ │ "{py:class}`IndexMap ` for the\n", │ │ │ │ │ "degree-of-freedom map. The {py:class}`IndexMap\n", │ │ │ │ │ "` describes how the degrees-of-freedom are\n", │ │ │ │ │ "distributed in parallel (across MPI ranks). From information on the\n", │ │ │ │ │ "parallel distribution we will be able to compute the communication\n", │ │ │ │ │ "graph." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b3401158", │ │ │ │ │ + "id": "5f7cfb15", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = mesh.create_box(\n", │ │ │ │ │ " comm=MPI.COMM_WORLD,\n", │ │ │ │ │ " points=[(0.0, 0.0, 0.0), (2.0, 1.0, 1.0)],\n", │ │ │ │ │ " n=(22, 36, 19),\n", │ │ │ │ │ " cell_type=mesh.CellType.tetrahedron,\n", │ │ │ │ │ ")\n", │ │ │ │ │ "V = fem.functionspace(msh, (\"Lagrange\", 2))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "31b168ef", │ │ │ │ │ + "id": "13c113d0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The function {py:func}`comm_graph ` builds a\n", │ │ │ │ │ "communication graph that represents data begin sent from the owning\n", │ │ │ │ │ "rank to ranks that ghost the data. We use the degree-of-freedom map's\n", │ │ │ │ │ "`IndexMap`. Building the communication data is collective across MPI\n", │ │ │ │ │ "ranks. However, a non-empty graph is returned only on rank 0." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e8c462d0", │ │ │ │ │ + "id": "2159c975", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "comm_graph = graph.comm_graph(V.dofmap.index_map)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3cf9e718", │ │ │ │ │ + "id": "53fc1246", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "A function for printing some communication graph metrics:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "aed24884", │ │ │ │ │ + "id": "bb334ff7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def print_stats(G):\n", │ │ │ │ │ " print(\"Communication graph data:\")\n", │ │ │ │ │ " print(f\" Num edges: {G.size()}\")\n", │ │ │ │ │ " print(f\" Num local: {G.size('local')}\")\n", │ │ │ │ │ @@ -222,15 +222,15 @@ │ │ │ │ │ " print(f\" Average edges per node: {G.size() / G.order()}\")\n", │ │ │ │ │ " if G.size() > 0:\n", │ │ │ │ │ " print(f\" Average edge weight: {G.size('weight') / G.size()}\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "25fb1848", │ │ │ │ │ + "id": "e9cfa89f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The graph data will be processed on rank 0. From the communication\n", │ │ │ │ │ "graph data, edge and node data for creating a `NetworkX`` graph is build\n", │ │ │ │ │ "using {py:fuc}`comm_graph_data `.\n", │ │ │ │ │ "\n", │ │ │ │ │ "Data for use with `NetworkX` can also be reconstructed from a JSON\n", │ │ │ │ │ @@ -239,15 +239,15 @@ │ │ │ │ │ "simulaton is executed and the graph data is written to file for later\n", │ │ │ │ │ "analysis." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ba76abd8", │ │ │ │ │ + "id": "9262f960", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if msh.comm.rank == 0:\n", │ │ │ │ │ " # To create a NetworkX directed graph we build graph data in a form\n", │ │ │ │ │ " # from which we can create a NetworkX graph. Each edge will have a\n", │ │ │ │ │ " # weight and a 'local(1)/remote(0)' memory indicator and each node\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/0aed751cd0874b28f5ae7bdc73e1060e/demo_biharmonic.ipynb.gz │ │ │ ├── demo_biharmonic.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666667% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': 'a3849ae7'}, 1: {'id': 'd1835c54'}, 2: {'id': 'ec48d03e'}, 3: {'id': " │ │ │ │ │┄ "'b15d36a2'}, 4: {'id': 'f7184ba3'}, 5: {'id': 'ca1be899'}, 6: {'id': 'e130b7ec'}, 7: " │ │ │ │ │┄ "{'id': '9d67e130'}, 8: {'id': '725fdbd1'}, 9: {'id': '1a58d92f'}, 10: {'id': " │ │ │ │ │┄ "'55fcc352'}, 11: {'id': '03c5b8f1'}, 12: {'id': '6c1cef99'}, 13: {'id': '253b4a36'}, " │ │ │ │ │┄ "14: {'id': '0cf59213'}, 15: {'id': '8fca01f2'}, 16: {'id': '26eb0c02'}, 17: {'id': " │ │ │ │ │┄ "'1bb42dc2'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e20def70", │ │ │ │ │ + "id": "a3849ae7", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "# Biharmonic equation\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ @@ -109,15 +109,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "We first import the modules and functions that the program uses:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "683bb88d", │ │ │ │ │ + "id": "d1835c54", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py.PETSc import ScalarType # type: ignore\n", │ │ │ │ │ @@ -126,28 +126,28 @@ │ │ │ │ │ "from dolfinx import fem, io, mesh, plot\n", │ │ │ │ │ "from dolfinx.fem.petsc import LinearProblem\n", │ │ │ │ │ "from dolfinx.mesh import CellType, GhostMode\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "51b47769", │ │ │ │ │ + "id": "ec48d03e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We begin by using {py:func}`create_rectangle\n", │ │ │ │ │ "` to create a rectangular\n", │ │ │ │ │ "{py:class}`Mesh ` of the domain, and creating a\n", │ │ │ │ │ "finite element {py:class}`FunctionSpace `\n", │ │ │ │ │ "$V$ on the mesh." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4f847629", │ │ │ │ │ + "id": "b15d36a2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = mesh.create_rectangle(\n", │ │ │ │ │ " comm=MPI.COMM_WORLD,\n", │ │ │ │ │ " points=((0.0, 0.0), (1.0, 1.0)),\n", │ │ │ │ │ " n=(32, 32),\n", │ │ │ │ │ @@ -155,15 +155,15 @@ │ │ │ │ │ " ghost_mode=GhostMode.shared_facet,\n", │ │ │ │ │ ")\n", │ │ │ │ │ "V = fem.functionspace(msh, (\"Lagrange\", 2))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ebbfce5c", │ │ │ │ │ + "id": "f7184ba3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The second argument to {py:func}`functionspace\n", │ │ │ │ │ "` is a tuple consisting of `(family,\n", │ │ │ │ │ "degree)`, where `family` is the finite element family, and `degree`\n", │ │ │ │ │ "specifies the polynomial degree. in this case `V` consists of\n", │ │ │ │ │ "second-order, continuous Lagrange finite element functions.\n", │ │ │ │ │ @@ -179,68 +179,68 @@ │ │ │ │ │ "{py:func}`locate_entities_boundary\n", │ │ │ │ │ "`)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e45e5ffb", │ │ │ │ │ + "id": "ca1be899", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "tdim = msh.topology.dim\n", │ │ │ │ │ "msh.topology.create_connectivity(tdim - 1, tdim)\n", │ │ │ │ │ "facets = mesh.exterior_facet_indices(msh.topology)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8a7b1e60", │ │ │ │ │ + "id": "e130b7ec", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We now find the degrees-of-freedom that are associated with the\n", │ │ │ │ │ "boundary facets using {py:func}`locate_dofs_topological\n", │ │ │ │ │ "`" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "62339806", │ │ │ │ │ + "id": "9d67e130", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dofs = fem.locate_dofs_topological(V=V, entity_dim=1, entities=facets)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9ee22b5c", │ │ │ │ │ + "id": "725fdbd1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and use {py:func}`dirichletbc ` to create a\n", │ │ │ │ │ "{py:class}`DirichletBC `\n", │ │ │ │ │ "class that represents the boundary condition. In this case, we impose\n", │ │ │ │ │ "Dirichlet boundary conditions with value $0$ on the entire boundary\n", │ │ │ │ │ "$\\partial\\Omega$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8459a5b4", │ │ │ │ │ + "id": "1a58d92f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc = fem.dirichletbc(value=ScalarType(0), dofs=dofs, V=V)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5375b20e", │ │ │ │ │ + "id": "55fcc352", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we express the variational problem using UFL.\n", │ │ │ │ │ "\n", │ │ │ │ │ "First, the penalty parameter $\\alpha$ is defined. In addition, we define\n", │ │ │ │ │ "a variable `h` for the cell diameter $h_E$, a variable `n`for the\n", │ │ │ │ │ "outward-facing normal vector $n$ and a variable `h_avg` for the\n", │ │ │ │ │ @@ -249,27 +249,27 @@ │ │ │ │ │ "`('+')` and `('-')` restricts a function to the `('+')` and `('-')`\n", │ │ │ │ │ "sides of a facet." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a53acce9", │ │ │ │ │ + "id": "03c5b8f1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "alpha = ScalarType(8.0)\n", │ │ │ │ │ "h = ufl.CellDiameter(msh)\n", │ │ │ │ │ "n = ufl.FacetNormal(msh)\n", │ │ │ │ │ "h_avg = (h(\"+\") + h(\"-\")) / 2.0" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8ab12f5f", │ │ │ │ │ + "id": "6c1cef99", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "After that, we can define the variational problem consisting of the\n", │ │ │ │ │ "bilinear form $a$ and the linear form $L$. The source term is prescribed\n", │ │ │ │ │ "as $f = 4.0 \\pi^4\\sin(\\pi x)\\sin(\\pi y)$. Note that with `dS`,\n", │ │ │ │ │ "integration is carried out over all the interior facets\n", │ │ │ │ │ "$\\mathcal{E}_h^{\\rm int}$, whereas with `ds` it would be only the facets\n", │ │ │ │ │ @@ -277,15 +277,15 @@ │ │ │ │ │ "$[\\!\\![ w ]\\!\\!] = w_{+} \\cdot n_{+} + w_{-} \\cdot n_{-}$ w.r.t. the\n", │ │ │ │ │ "outward-facing normal vector $n$ is in UFL available as `jump(w, n)`." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6f0abd47", │ │ │ │ │ + "id": "253b4a36", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Define variational problem\n", │ │ │ │ │ "u = ufl.TrialFunction(V)\n", │ │ │ │ │ "v = ufl.TestFunction(V)\n", │ │ │ │ │ "x = ufl.SpatialCoordinate(msh)\n", │ │ │ │ │ @@ -298,28 +298,28 @@ │ │ │ │ │ " + alpha / h_avg * ufl.inner(ufl.jump(ufl.grad(u), n), ufl.jump(ufl.grad(v), n)) * ufl.dS\n", │ │ │ │ │ ")\n", │ │ │ │ │ "L = ufl.inner(f, v) * ufl.dx" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "550aecd9", │ │ │ │ │ + "id": "0cf59213", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create a {py:class}`LinearProblem `\n", │ │ │ │ │ "object that brings together the variational problem, the Dirichlet\n", │ │ │ │ │ "boundary condition, and which specifies the linear solver. In this\n", │ │ │ │ │ "case we use a direct (LU) solver. The {py:func}`solve\n", │ │ │ │ │ "` will compute a solution." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "106e29f3", │ │ │ │ │ + "id": "8fca01f2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "problem = LinearProblem(\n", │ │ │ │ │ " a,\n", │ │ │ │ │ " L,\n", │ │ │ │ │ " bcs=[bc],\n", │ │ │ │ │ @@ -329,25 +329,25 @@ │ │ │ │ │ "uh = problem.solve()\n", │ │ │ │ │ "assert isinstance(uh, fem.Function)\n", │ │ │ │ │ "assert problem.solver.getConvergedReason() > 0" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "85ba6c0d", │ │ │ │ │ + "id": "26eb0c02", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The solution can be written to a {py:class}`XDMFFile\n", │ │ │ │ │ "` file visualization with ParaView or VisIt" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f7d5c3ae", │ │ │ │ │ + "id": "1bb42dc2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "out_folder = Path(\"out_biharmonic\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)\n", │ │ │ │ │ "with io.XDMFFile(msh.comm, out_folder / \"biharmonic.xdmf\", \"w\") as file:\n", │ │ │ │ │ " V1 = fem.functionspace(msh, (\"Lagrange\", 1))\n", │ │ │ │ │ @@ -355,24 +355,24 @@ │ │ │ │ │ " u1.interpolate(uh)\n", │ │ │ │ │ " file.write_mesh(msh)\n", │ │ │ │ │ " file.write_function(u1)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8023a041", │ │ │ │ │ + "id": "f6c6a2ce", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and displayed using [pyvista](https://docs.pyvista.org/)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1704e33e", │ │ │ │ │ + "id": "47302075", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "try:\n", │ │ │ │ │ " import pyvista\n", │ │ │ │ │ "\n", │ │ │ │ │ " cells, types, x = plot.vtk_mesh(V)\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/0ff7b5905586c05f3ded87f72380f93b/demo_lagrange_variants.ipynb.gz │ │ │ ├── demo_lagrange_variants.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666666% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '4005b0b7'}, 1: {'id': 'd8febeb1'}, 2: {'id': 'efc8d4e0'}, 3: {'id': " │ │ │ │ │┄ "'56651521'}, 4: {'id': '35be7f0f'}, 5: {'id': 'c0e9b7b5'}, 6: {'id': 'e9fec6d2'}, 7: " │ │ │ │ │┄ "{'id': '6a8ac6d1'}, 8: {'id': 'd3bb817e'}, 9: {'id': '6f5c10e2'}, 10: {'id': " │ │ │ │ │┄ "'de4939dd'}, 11: {'id': '5653340d'}, 12: {'id': '9aef03b2'}, 13: {'id': '29be2f03'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5d989791", │ │ │ │ │ + "id": "4005b0b7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Variants of Lagrange elements\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_lagrange_variants.py>`\n", │ │ │ │ │ @@ -19,15 +19,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "We begin this demo by importing the required modules." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "22dfe354", │ │ │ │ │ + "id": "d8febeb1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "\n", │ │ │ │ │ "import matplotlib.pylab as plt\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -35,15 +35,15 @@ │ │ │ │ │ "import basix.ufl\n", │ │ │ │ │ "import ufl\n", │ │ │ │ │ "from dolfinx import default_real_type, fem, mesh\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "90a427d1", │ │ │ │ │ + "id": "efc8d4e0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Equispaced versus Gauss--Lobatto--Legendre (GLL) points\n", │ │ │ │ │ "\n", │ │ │ │ │ "The basis functions of a Lagrange element are defined by placing\n", │ │ │ │ │ "points on the reference element, with each basis function equal to 1\n", │ │ │ │ │ "at one point and 0 at all the other points. To demonstrate the\n", │ │ │ │ │ @@ -57,25 +57,25 @@ │ │ │ │ │ "size is 1, so we take the slice `[0, :, :]` to get a 2-dimensional\n", │ │ │ │ │ "array." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8b8e8dcb", │ │ │ │ │ + "id": "56651521", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "N = 20" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c96fc85c", │ │ │ │ │ + "id": "35be7f0f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "element = basix.ufl.element(\n", │ │ │ │ │ " basix.ElementFamily.P,\n", │ │ │ │ │ " basix.CellType.interval,\n", │ │ │ │ │ " 10,\n", │ │ │ │ │ @@ -91,15 +91,15 @@ │ │ │ │ │ " plt.ylim([-1, 6])\n", │ │ │ │ │ " plt.savefig(\"demo_lagrange_variants_equispaced_10.png\")\n", │ │ │ │ │ " plt.clf()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "59e362c4", │ │ │ │ │ + "id": "c0e9b7b5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "![The basis functions of a degree 10 Lagrange space defined using\n", │ │ │ │ │ "equispaced points.](demo_lagrange_variants_equispaced_10.png)\n", │ │ │ │ │ "\n", │ │ │ │ │ "The basis functions exhibit large peaks towards the ends of the\n", │ │ │ │ │ "interval. This is known as [Runge's\n", │ │ │ │ │ @@ -112,15 +112,15 @@ │ │ │ │ │ "points](https://en.wikipedia.org/wiki/Gaussian_quadrature#Gauss%E2%80%93Lobatto_rules)\n", │ │ │ │ │ "to define the basis functions." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "46e59636", │ │ │ │ │ + "id": "e9fec6d2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "element = basix.ufl.element(\n", │ │ │ │ │ " basix.ElementFamily.P,\n", │ │ │ │ │ " basix.CellType.interval,\n", │ │ │ │ │ " 10,\n", │ │ │ │ │ @@ -135,15 +135,15 @@ │ │ │ │ │ " plt.ylim([-1, 6])\n", │ │ │ │ │ " plt.savefig(\"demo_lagrange_variants_gll_10.png\")\n", │ │ │ │ │ " plt.clf()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "004a770f", │ │ │ │ │ + "id": "6a8ac6d1", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "![The basis functions of a degree 10 Lagrange space defined using GLL\n", │ │ │ │ │ "points.](demo_lagrange_variants_gll_10.png)\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -157,38 +157,38 @@ │ │ │ │ │ "function into a finite element space. For this example, we define a\n", │ │ │ │ │ "saw tooth wave that will be interpolated." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "edf98d7e", │ │ │ │ │ + "id": "d3bb817e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def saw_tooth(x):\n", │ │ │ │ │ " f = 4 * abs(x - 0.43)\n", │ │ │ │ │ " for _ in range(8):\n", │ │ │ │ │ " f = abs(f - 0.3)\n", │ │ │ │ │ " return f" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "865cd086", │ │ │ │ │ + "id": "6f5c10e2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We begin by interpolating the saw tooth wave with the two Lagrange\n", │ │ │ │ │ "elements, and plot the finite element interpolation." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7aa47622", │ │ │ │ │ + "id": "de4939dd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = mesh.create_unit_interval(MPI.COMM_WORLD, N)\n", │ │ │ │ │ "\n", │ │ │ │ │ "x = ufl.SpatialCoordinate(msh)\n", │ │ │ │ │ "u_exact = saw_tooth(x[0])\n", │ │ │ │ │ @@ -215,15 +215,15 @@ │ │ │ │ │ " plt.title(variant.name)\n", │ │ │ │ │ " plt.savefig(f\"demo_lagrange_variants_interpolation_{variant.name}.png\")\n", │ │ │ │ │ " plt.clf()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9bf13221", │ │ │ │ │ + "id": "5653340d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "![](demo_lagrange_variants_interpolation_equispaced.png)\n", │ │ │ │ │ "![](demo_lagrange_variants_interpolation_gll_warped.png)\n", │ │ │ │ │ "\n", │ │ │ │ │ "The plots illustrate that Runge's phenomenon leads to the\n", │ │ │ │ │ "interpolation being less accurate when using the equispaced variant of\n", │ │ │ │ │ @@ -239,15 +239,15 @@ │ │ │ │ │ "variant is considerably smaller than the error for the equispaced\n", │ │ │ │ │ "variant." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "129b03b7", │ │ │ │ │ + "id": "9aef03b2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "for variant in [basix.LagrangeVariant.equispaced, basix.LagrangeVariant.gll_warped]:\n", │ │ │ │ │ " ufl_element = basix.ufl.element(\n", │ │ │ │ │ " basix.ElementFamily.P, basix.CellType.interval, 10, variant, dtype=default_real_type\n", │ │ │ │ │ " )\n", │ │ │ │ │ @@ -257,15 +257,15 @@ │ │ │ │ │ " M = fem.form((u_exact - uh) ** 2 * ufl.dx)\n", │ │ │ │ │ " error = msh.comm.allreduce(fem.assemble_scalar(M), op=MPI.SUM)\n", │ │ │ │ │ " print(f\"Computed L2 interpolation error ({variant.name}):\", error**0.5)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3ae7d51a", │ │ │ │ │ + "id": "29be2f03", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Available Lagrange variants\n", │ │ │ │ │ "\n", │ │ │ │ │ "Basix supports numerous Lagrange variants, including:\n", │ │ │ │ │ "\n", │ │ │ │ │ "- `basix.LagrangeVariant.equispaced`\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/1c10919af1d1c2689ff1982d6e82b898/demo_navier-stokes.ipynb.gz │ │ │ ├── demo_navier-stokes.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666667% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '46754ebd'}, 1: {'id': '5e885e83'}, 2: {'id': '80233d46'}, 3: {'id': " │ │ │ │ │┄ "'8adadb2c'}, 4: {'id': '834f05ae'}, 5: {'id': '79335d09'}, 6: {'id': '2c4446fd'}, 7: " │ │ │ │ │┄ "{'id': 'aac0a8e8'}, 8: {'id': '614507c4'}, 9: {'id': 'b738f487'}, 10: {'id': " │ │ │ │ │┄ "'e1719b3b'}, 11: {'id': 'b984262d'}, 12: {'id': '43a65e7b'}, 13: {'id': '8c4d0565'}, " │ │ │ │ │┄ "14: {'id': '609f5a06'}, 15: {'id': 'acb4e15a'}, 16: {'id': 'a37ecf29'}, 17: {'id': " │ │ │ │ │┄ "'e449364e'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "23bfe4d5", │ │ │ │ │ + "id": "46754ebd", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "# Divergence conforming discontinuous Galerkin method for the Navier--Stokes equations # noqa\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ @@ -174,15 +174,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "We begin by importing the required modules and functions" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "87e2546b", │ │ │ │ │ + "id": "5e885e83", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py import PETSc\n", │ │ │ │ │ @@ -196,26 +196,26 @@ │ │ │ │ │ "if np.issubdtype(PETSc.ScalarType, np.complexfloating):\n", │ │ │ │ │ " print(\"Demo should only be executed with DOLFINx real mode\")\n", │ │ │ │ │ " exit(0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fdc089d7", │ │ │ │ │ + "id": "80233d46", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "We also define some helper functions that will be used later" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4fb828f0", │ │ │ │ │ + "id": "8adadb2c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def norm_L2(comm, v):\n", │ │ │ │ │ " \"\"\"Compute the L2(\u03a9)-norm of v\"\"\"\n", │ │ │ │ │ " return np.sqrt(\n", │ │ │ │ │ " comm.allreduce(fem.assemble_scalar(fem.form(ufl.inner(v, v) * ufl.dx)), op=MPI.SUM)\n", │ │ │ │ │ @@ -254,49 +254,49 @@ │ │ │ │ │ "def f_expr(x):\n", │ │ │ │ │ " \"\"\"Expression for the applied force\"\"\"\n", │ │ │ │ │ " return np.vstack((np.zeros_like(x[0]), np.zeros_like(x[0])))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9980938b", │ │ │ │ │ + "id": "834f05ae", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We define some simulation parameters" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "87c235af", │ │ │ │ │ + "id": "79335d09", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "n = 16\n", │ │ │ │ │ "num_time_steps = 25\n", │ │ │ │ │ "t_end = 10\n", │ │ │ │ │ "Re = 25 # Reynolds Number\n", │ │ │ │ │ "k = 1 # Polynomial degree" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5eae58e3", │ │ │ │ │ + "id": "2c4446fd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we create a mesh and the required functions spaces over it.\n", │ │ │ │ │ "Since the velocity uses an $H(\\text{div})$-conforming function space,\n", │ │ │ │ │ "we also create a vector valued discontinuous Lagrange space to\n", │ │ │ │ │ "interpolate into for artifact free visualisation." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "47c4f5f6", │ │ │ │ │ + "id": "aac0a8e8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = mesh.create_unit_square(MPI.COMM_WORLD, n, n)\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Function spaces for the velocity and for the pressure\n", │ │ │ │ │ "V = fem.functionspace(msh, (\"Raviart-Thomas\", k + 1))\n", │ │ │ │ │ @@ -321,25 +321,25 @@ │ │ │ │ │ "\n", │ │ │ │ │ "def jump(phi, n):\n", │ │ │ │ │ " return ufl.outer(phi(\"+\"), n(\"+\")) + ufl.outer(phi(\"-\"), n(\"-\"))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "edb9627b", │ │ │ │ │ + "id": "614507c4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We set up the variational formulation of the Stokes problem for\n", │ │ │ │ │ "the initial condition, omitting the convective term:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "de0c33a9", │ │ │ │ │ + "id": "b738f487", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "a = (1.0 / Re) * (\n", │ │ │ │ │ " ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx\n", │ │ │ │ │ " - ufl.inner(ufl.avg(ufl.grad(u)), jump(v, n)) * ufl.dS\n", │ │ │ │ │ " - ufl.inner(jump(u, n), ufl.avg(ufl.grad(v))) * ufl.dS\n", │ │ │ │ │ @@ -360,47 +360,47 @@ │ │ │ │ │ " + (alpha / h) * ufl.inner(ufl.outer(u_D, n), ufl.outer(v, n)) * ufl.ds\n", │ │ │ │ │ ")\n", │ │ │ │ │ "L += ufl.inner(fem.Constant(msh, default_real_type(0.0)), q) * ufl.dx" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5db0f8f0", │ │ │ │ │ + "id": "e1719b3b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create the {py:class}`Dirichlet boundary condition\n", │ │ │ │ │ "`" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b39491c7", │ │ │ │ │ + "id": "b984262d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh.topology.create_connectivity(msh.topology.dim - 1, msh.topology.dim)\n", │ │ │ │ │ "boundary_facets = mesh.exterior_facet_indices(msh.topology)\n", │ │ │ │ │ "boundary_vel_dofs = fem.locate_dofs_topological(V, msh.topology.dim - 1, boundary_facets)\n", │ │ │ │ │ "bc_u = fem.dirichletbc(u_D, boundary_vel_dofs)\n", │ │ │ │ │ "bcs = [bc_u]" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "80067de7", │ │ │ │ │ + "id": "43a65e7b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and solve the problem for the initial condition" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8e3b95c7", │ │ │ │ │ + "id": "8c4d0565", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "solver_options = {\n", │ │ │ │ │ " \"ksp_type\": \"preonly\",\n", │ │ │ │ │ " \"pc_type\": \"lu\",\n", │ │ │ │ │ " \"pc_factor_mat_solver_type\": \"mumps\",\n", │ │ │ │ │ @@ -431,43 +431,43 @@ │ │ │ │ │ " exit(0)\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " raise e" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "bdcb93ee", │ │ │ │ │ + "id": "609f5a06", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Subtract the average of the pressure since it is only determined up to\n", │ │ │ │ │ "a constant" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a3802594", │ │ │ │ │ + "id": "acb4e15a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "p_h.x.array[:] -= domain_average(msh, p_h)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d08a1ac6", │ │ │ │ │ + "id": "a37ecf29", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Write initial condition to file" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "9c7ca26e", │ │ │ │ │ + "id": "e449364e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "t = 0.0\n", │ │ │ │ │ "if has_adios2:\n", │ │ │ │ │ " u_vis = fem.Function(W, name=\"u_init\")\n", │ │ │ │ │ " u_vis.interpolate(u_h)\n", │ │ │ │ │ @@ -477,45 +477,45 @@ │ │ │ │ │ " p_file.write(t)\n", │ │ │ │ │ "else:\n", │ │ │ │ │ " print(\"File output requires ADIOS2.\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b884177c", │ │ │ │ │ + "id": "894a364d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create function to store solution and previous time step" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5b3d9eeb", │ │ │ │ │ + "id": "c0822da8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "u_n = fem.Function(V, name=\"u_prev\")\n", │ │ │ │ │ "u_n.x.array[:] = u_h.x.array" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "09da17ef", │ │ │ │ │ + "id": "65d88176", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we add the time stepping and convective terms and\n", │ │ │ │ │ "set up the {py:class}`LinearProblem\n", │ │ │ │ │ "`" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "dc95a601", │ │ │ │ │ + "id": "5efe5d9c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "lmbda = ufl.conditional(ufl.gt(ufl.dot(u_n, n), 0), 1, 0)\n", │ │ │ │ │ "u_uw = lmbda(\"+\") * u(\"+\") + lmbda(\"-\") * u(\"-\")\n", │ │ │ │ │ "a += (\n", │ │ │ │ │ " ufl.inner(u / delta_t, v) * ufl.dx\n", │ │ │ │ │ @@ -539,24 +539,24 @@ │ │ │ │ │ " petsc_options_prefix=\"demo_stokes__navier_stokes_problem_\",\n", │ │ │ │ │ " petsc_options=solver_options,\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "30100c59", │ │ │ │ │ + "id": "0e58a279", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We perform the time-stepping as a for-loop" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fb3c6100", │ │ │ │ │ + "id": "5dcbe56a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "for n in range(num_time_steps):\n", │ │ │ │ │ " t += delta_t.value\n", │ │ │ │ │ "\n", │ │ │ │ │ " navier_stokes_problem.solve()\n", │ │ │ │ │ @@ -576,24 +576,24 @@ │ │ │ │ │ " p_file.close()\n", │ │ │ │ │ "except NameError:\n", │ │ │ │ │ " pass" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0d4d84fb", │ │ │ │ │ + "id": "3adf6425", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we compare the computed solution to the exact solution" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f7eb1c30", │ │ │ │ │ + "id": "0dbf61b3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Function spaces for exact velocity and pressure\n", │ │ │ │ │ "V_e = fem.functionspace(msh, (\"Lagrange\", k + 3, (gdim,)))\n", │ │ │ │ │ "Q_e = fem.functionspace(msh, (\"Lagrange\", k + 2))\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -606,24 +606,24 @@ │ │ │ │ │ "# Compute errors\n", │ │ │ │ │ "e_u = norm_L2(msh.comm, u_h - u_e)\n", │ │ │ │ │ "e_div_u = norm_L2(msh.comm, ufl.div(u_h))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6499631f", │ │ │ │ │ + "id": "42f99568", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "This scheme conserves mass exactly, so we check this" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a36de0db", │ │ │ │ │ + "id": "c57dd29a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "assert np.isclose(e_div_u, 0.0, atol=float(1.0e5 * np.finfo(default_real_type).eps))\n", │ │ │ │ │ "p_e_avg = domain_average(msh, p_e)\n", │ │ │ │ │ "e_p = norm_L2(msh.comm, p_h - (p_e - p_e_avg))\n", │ │ │ │ │ "\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/244d514e5e2d1484e9f045150ae16a27/demo_gmsh.ipynb.gz │ │ │ ├── demo_gmsh.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9865679824561404% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': 'deaba0d4'}, 1: {'id': '8b00585b'}, 2: {'id': '5a5796cc'}, 3: {'id': " │ │ │ │ │┄ "'15164940'}, 4: {'id': 'dd0fed3d'}, 5: {'id': '48ea49d9'}, 6: {'id': '51fa5f98'}, 7: " │ │ │ │ │┄ "{'id': '1dd50849'}, 8: {'id': 'b9f6068a'}, 9: {'id': '002cc4e8'}, 10: {'id': " │ │ │ │ │┄ "'b46e533a'}, 11: {'id': '7b66f4cd'}, 12: {'id': '19321096'}, 13: {'id': '1067864d'}, " │ │ │ │ │┄ "14: {'id': '4be66635'}, 15: {'id': '1533a72d'}, 16: {'id': '4400deec'}, 17: {'id': " │ │ │ │ │┄ "'17da313d'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "222e0740", │ │ │ │ │ + "id": "deaba0d4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Mesh generation with Gmsh\n", │ │ │ │ │ "\n", │ │ │ │ │ "Copyright (C) 2020-2023 Garth N. Wells and J\u00f8rgen S. Dokken\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ @@ -14,53 +14,53 @@ │ │ │ │ │ "* {download}`Python script <./demo_gmsh.py>`\n", │ │ │ │ │ "* {download}`Jupyter notebook <./demo_gmsh.ipynb>`\n", │ │ │ │ │ "```" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ee8dc007", │ │ │ │ │ + "id": "8b00585b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "This demo shows how to create meshes using the Gmsh Python interface.\n", │ │ │ │ │ "\n", │ │ │ │ │ "The Gmsh module is required for this demo." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c4302405", │ │ │ │ │ + "id": "5a5796cc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "\n", │ │ │ │ │ "import gmsh # type: ignore\n", │ │ │ │ │ "\n", │ │ │ │ │ "from dolfinx.io import XDMFFile\n", │ │ │ │ │ "from dolfinx.io import gmsh as gmshio\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "cd039f54", │ │ │ │ │ + "id": "15164940", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Gmsh model builders\n", │ │ │ │ │ "\n", │ │ │ │ │ "The following functions add Gmsh meshes to a 'model'." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5b12776c", │ │ │ │ │ + "id": "dd0fed3d", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def gmsh_sphere(model: gmsh.model, name: str) -> gmsh.model:\n", │ │ │ │ │ " \"\"\"Create a Gmsh model of a sphere and tag sub entitites\n", │ │ │ │ │ @@ -173,28 +173,28 @@ │ │ │ │ │ " model.addPhysicalGroup(3, volume_entities, tag=1)\n", │ │ │ │ │ " model.setPhysicalName(3, 1, \"Mesh volume\")\n", │ │ │ │ │ " return model" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9721a77d", │ │ │ │ │ + "id": "48ea49d9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## DOLFINx mesh creation and file output\n", │ │ │ │ │ "\n", │ │ │ │ │ "The following function creates a DOLFINx mesh from a Gmsh model, and\n", │ │ │ │ │ "cell and facets tags. The mesh and the tags are written to an XDMF file\n", │ │ │ │ │ "for visualisation, e.g. using ParaView." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "cff026b4", │ │ │ │ │ + "id": "51fa5f98", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -247,139 +247,139 @@ │ │ │ │ │ " mesh_data.mesh.geometry,\n", │ │ │ │ │ " geometry_xpath=f\"/Xdmf/Domain/Grid[@Name='{name}']/Geometry\",\n", │ │ │ │ │ " )" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "de9a9b11", │ │ │ │ │ + "id": "1dd50849", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Generate meshes" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "500efe3d", │ │ │ │ │ + "id": "b9f6068a", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a Gmsh model and set the verbosity level." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a39f7471", │ │ │ │ │ + "id": "002cc4e8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "gmsh.initialize()\n", │ │ │ │ │ "gmsh.option.setNumber(\"General.Terminal\", 0)\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Create model\n", │ │ │ │ │ "model = gmsh.model()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "7198f482", │ │ │ │ │ + "id": "b46e533a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "First, we create a Gmsh model of a sphere using tetrahedral cells\n", │ │ │ │ │ "(linear geometry), then create independent meshes on each MPI rank and\n", │ │ │ │ │ "write each mesh to an XDMF file. The MPI rank is appended to the\n", │ │ │ │ │ "filename since the meshes are not distributed." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6ce0728f", │ │ │ │ │ + "id": "7b66f4cd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "model = gmsh_sphere(model, \"Sphere\")\n", │ │ │ │ │ "model.setCurrent(\"Sphere\")\n", │ │ │ │ │ "create_mesh(MPI.COMM_SELF, model, \"sphere\", f\"out_gmsh/mesh_rank_{MPI.COMM_WORLD.rank}.xdmf\", \"w\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e295061f", │ │ │ │ │ + "id": "19321096", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we create a Gmsh model of a sphere with a box removed and using\n", │ │ │ │ │ "tetrahedral cells (linear geometry), then create a distributed mesh.\n", │ │ │ │ │ "The distributed mesh is written to file. The write option ``\"w\"`` is\n", │ │ │ │ │ "passed to create a new XDMF file." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "37bce01b", │ │ │ │ │ + "id": "1067864d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "model = gmsh_sphere_minus_box(model, \"Sphere minus box\")\n", │ │ │ │ │ "model.setCurrent(\"Sphere minus box\")\n", │ │ │ │ │ "create_mesh(MPI.COMM_WORLD, model, \"ball_d1\", \"out_gmsh/mesh.xdmf\", \"w\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2fd14eb6", │ │ │ │ │ + "id": "4be66635", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For the mesh of the sphere with a box remove, we can increase the\n", │ │ │ │ │ "degree of the geometry representation to 2 (quadratic geometry\n", │ │ │ │ │ "representation). The higher-order distributed mesh is appended to the\n", │ │ │ │ │ "XDMF file." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "de0dba7a", │ │ │ │ │ + "id": "1533a72d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "model.mesh.generate(3)\n", │ │ │ │ │ "gmsh.option.setNumber(\"General.Terminal\", 1)\n", │ │ │ │ │ "model.mesh.setOrder(2)\n", │ │ │ │ │ "gmsh.option.setNumber(\"General.Terminal\", 0)\n", │ │ │ │ │ "create_mesh(MPI.COMM_WORLD, model, \"ball_d2\", \"out_gmsh/mesh.xdmf\", \"a\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5c7d181b", │ │ │ │ │ + "id": "4400deec", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Finally, we create a distributed mesh using hexahedral cells of\n", │ │ │ │ │ "geometric degree 2, and append the mesh to the XDMF file." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d4b26888", │ │ │ │ │ + "id": "17da313d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "model = gmsh_ring(model, \"Hexahedral mesh\")\n", │ │ │ │ │ "model.setCurrent(\"Hexahedral mesh\")\n", │ │ │ │ │ "create_mesh(MPI.COMM_WORLD, model, \"hex_d2\", \"out_gmsh/mesh.xdmf\", \"a\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "63084aff", │ │ │ │ │ + "id": "e7fd7bfa", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The generated meshes can be visualised using\n", │ │ │ │ │ "[ParaView](https://www.paraview.org/)." │ │ │ │ │ ] │ │ │ │ │ } │ │ │ │ │ ], │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/3a2e8b3062e32f7fa335a0116fae9bef/demo_hdg.ipynb.gz │ │ │ ├── demo_hdg.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9871323529411764% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': 'a15d8096'}, 1: {'id': 'ffacd585'}, 2: {'id': '8d9c7ad1'}, 3: {'id': " │ │ │ │ │┄ "'4fe4ec5d'}, 4: {'id': 'e34828ce'}, 5: {'id': '76cee8e2'}, 6: {'id': '7092ebf3'}, 7: " │ │ │ │ │┄ "{'id': 'e4dd3895'}, 8: {'id': 'c6e5e212'}, 9: {'id': '449ace5c'}, 10: {'id': " │ │ │ │ │┄ "'2ab065c0'}, 11: {'id': '7476be30'}, 12: {'id': '2f8ab473'}, 13: {'id': 'c7298ad0'}, " │ │ │ │ │┄ "14: {'id': 'cb8202f5'}, 15: {'id': '6627da5f'}, 16: {'id': '05b6f49e'}, 17: {'id': " │ │ │ │ │┄ "'1d00240b'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "09346104", │ │ │ │ │ + "id": "a15d8096", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# HDG scheme for the Poisson equation\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_hdg.py>`\n", │ │ │ │ │ @@ -20,15 +20,15 @@ │ │ │ │ │ "- Use `ufl.MixedFunctionSpace` to defined blocked problems.\n", │ │ │ │ │ "- Assemble mixed systems with multiple, related meshes" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c7e0e00c", │ │ │ │ │ + "id": "ffacd585", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py import PETSc\n", │ │ │ │ │ @@ -48,43 +48,43 @@ │ │ │ │ │ " create_vector,\n", │ │ │ │ │ " set_bc,\n", │ │ │ │ │ ")\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d7521d93", │ │ │ │ │ + "id": "8d9c7ad1", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "We start by creating two convenience functions: One to compute\n", │ │ │ │ │ "the L2 norm of a UFL expression, and one to define the integration\n", │ │ │ │ │ "domains for the facets of all cells in a mesh." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "75fd24ba", │ │ │ │ │ + "id": "4fe4ec5d", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def norm_L2(v: ufl.core.expr.Expr, measure: ufl.Measure = ufl.dx) -> np.inexact:\n", │ │ │ │ │ " \"\"\"Convenience function to compute the L2 norm of a UFL expression.\"\"\"\n", │ │ │ │ │ " compiled_form = fem.form(ufl.inner(v, v) * measure)\n", │ │ │ │ │ " comm = compiled_form.mesh.comm\n", │ │ │ │ │ " return np.sqrt(comm.allreduce(fem.assemble_scalar(compiled_form), op=MPI.SUM))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b3dc79a3", │ │ │ │ │ + "id": "e34828ce", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "In DOLFINx, we represent integration domains over entities of\n", │ │ │ │ │ "codimension > 0 as a tuple `(cell_idx, local_entity_idx)`,\n", │ │ │ │ │ "where `cell_idx` is the index of the cell in the mesh\n", │ │ │ │ │ @@ -93,15 +93,15 @@ │ │ │ │ │ "integrate over the facets of each cell (for internal facets,\n", │ │ │ │ │ "there will be repeat entries, from the viewpoint of the connected cells)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "82a08f65", │ │ │ │ │ + "id": "76cee8e2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def compute_cell_boundary_facets(msh: dolfinx.mesh.Mesh) -> np.ndarray:\n", │ │ │ │ │ " \"\"\"Compute the integration entities for integrals around the\n", │ │ │ │ │ " boundaries of all cells in msh.\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -118,85 +118,85 @@ │ │ │ │ │ " n_c = msh.topology.index_map(tdim).size_local\n", │ │ │ │ │ " return np.vstack((np.repeat(np.arange(n_c), n_f), np.tile(np.arange(n_f), n_c))).T.flatten()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c2d7548a", │ │ │ │ │ + "id": "7092ebf3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def u_e(x):\n", │ │ │ │ │ " \"\"\"Exact solution.\"\"\"\n", │ │ │ │ │ " u_e = 1\n", │ │ │ │ │ " for i in range(tdim):\n", │ │ │ │ │ " u_e *= ufl.sin(ufl.pi * x[i])\n", │ │ │ │ │ " return u_e" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "605aede7", │ │ │ │ │ + "id": "e4dd3895", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "comm = MPI.COMM_WORLD\n", │ │ │ │ │ "rank = comm.rank\n", │ │ │ │ │ "dtype = PETSc.ScalarType" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0a4820ec", │ │ │ │ │ + "id": "c6e5e212", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create the mesh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7e1a5bb5", │ │ │ │ │ + "id": "449ace5c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "n = 8 # Number of elements in each direction\n", │ │ │ │ │ "msh = mesh.create_unit_cube(comm, n, n, n, ghost_mode=mesh.GhostMode.none)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "bf6279bf", │ │ │ │ │ + "id": "2ab065c0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We need to create a broken Lagrange space defined over the facets of\n", │ │ │ │ │ "the mesh. To do so, we require a sub-mesh of the all facets. We begin\n", │ │ │ │ │ "by creating a list of all of the facets in the mesh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "3a05aafe", │ │ │ │ │ + "id": "7476be30", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "tdim = msh.topology.dim\n", │ │ │ │ │ "fdim = tdim - 1\n", │ │ │ │ │ "msh.topology.create_entities(fdim)\n", │ │ │ │ │ "facet_imap = msh.topology.index_map(fdim)\n", │ │ │ │ │ "num_facets = facet_imap.size_local + facet_imap.num_ghosts\n", │ │ │ │ │ "facets = np.arange(num_facets, dtype=np.int32)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1f30db25", │ │ │ │ │ + "id": "2f8ab473", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The submesh is created with {py:func}`dolfinx.mesh.create_submesh`,\n", │ │ │ │ │ "which takes in the mesh to extract entities from, the topological\n", │ │ │ │ │ "dimension of the entities, and the set of entities to create the\n", │ │ │ │ │ "submesh (indices local to process).\n", │ │ │ │ │ "```{admonition} Note\n", │ │ │ │ │ @@ -204,157 +204,157 @@ │ │ │ │ │ "isn't necessarily the identity in parallel\n", │ │ │ │ │ "```" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c1cf3800", │ │ │ │ │ + "id": "c7298ad0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "facet_mesh, facet_mesh_emap = mesh.create_submesh(msh, fdim, facets)[:2]" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6d4986e1", │ │ │ │ │ + "id": "cb8202f5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Define function spaces" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fe32297c", │ │ │ │ │ + "id": "6627da5f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "k = 3 # Polynomial order\n", │ │ │ │ │ "V = fem.functionspace(msh, (\"Discontinuous Lagrange\", k))\n", │ │ │ │ │ "Vbar = fem.functionspace(facet_mesh, (\"Discontinuous Lagrange\", k))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "16ffffd9", │ │ │ │ │ + "id": "05b6f49e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Trial and test functions in mixed space, we use {py:class}`\n", │ │ │ │ │ "ufl.MixedFunctionSpace`\n", │ │ │ │ │ "to create a single function space object we can extract {py:func}`\n", │ │ │ │ │ "ufl.TrialFunctions`\n", │ │ │ │ │ "and {py:func}`ufl.TestFunctions` from." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e63af099", │ │ │ │ │ + "id": "1d00240b", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "W = ufl.MixedFunctionSpace(V, Vbar)\n", │ │ │ │ │ "u, ubar = ufl.TrialFunctions(W)\n", │ │ │ │ │ "v, vbar = ufl.TestFunctions(W)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "aa1b51bd", │ │ │ │ │ + "id": "706362d3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Define integration measures" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "06f18b79", │ │ │ │ │ + "id": "9fc8c3eb", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We define the integration measure over cells as we would do in any\n", │ │ │ │ │ "other UFL form." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "3dbc1ff4", │ │ │ │ │ + "id": "e2550b21", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dx_c = ufl.Measure(\"dx\", domain=msh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "31a01e1e", │ │ │ │ │ + "id": "2b27dfcf", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For the cell boundaries, we need to define an integration measure to\n", │ │ │ │ │ "integrate around the boundary of each cell. The integration entities\n", │ │ │ │ │ "can be computed using the following convenience function." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8b155f70", │ │ │ │ │ + "id": "574ec723", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "cell_boundary_facets = compute_cell_boundary_facets(msh)\n", │ │ │ │ │ "cell_boundaries = 1 # A tag" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "825e18ca", │ │ │ │ │ + "id": "6394a25a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# We pass the integration domains into the `ufl.Measure` through the\n", │ │ │ │ │ "# `subdomain_data` keyword argument.\n", │ │ │ │ │ "ds_c = ufl.Measure(\"ds\", subdomain_data=[(cell_boundaries, cell_boundary_facets)], domain=msh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1831a459", │ │ │ │ │ + "id": "50f5972e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a cell integral measure over the facet mesh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "559f4680", │ │ │ │ │ + "id": "d2e1b7d0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dx_f = ufl.Measure(\"dx\", domain=facet_mesh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6e572813", │ │ │ │ │ + "id": "55134e40", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Variational formulation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8a5251f4", │ │ │ │ │ + "id": "0bf7d789", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "h = ufl.CellDiameter(msh)\n", │ │ │ │ │ "n = ufl.FacetNormal(msh)\n", │ │ │ │ │ "gamma = 16.0 * k**2 / h # Scaled penalty parameter\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -370,184 +370,184 @@ │ │ │ │ │ "f = -ufl.div(c * ufl.grad(u_e(x))) # Manufacture a source term\n", │ │ │ │ │ "L = ufl.inner(f, v) * dx_c\n", │ │ │ │ │ "L += ufl.inner(fem.Constant(facet_mesh, dtype(0.0)), vbar) * dx_f" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b780a2f1", │ │ │ │ │ + "id": "2a69ae05", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Our bilinear form involves two domains (`msh` and `facet_mesh`). The\n", │ │ │ │ │ "mesh passed to the measure is called the \"integration domain\". For\n", │ │ │ │ │ "each additional mesh in our form, we must pass an\n", │ │ │ │ │ "{py:class}`EntityMap`\n", │ │ │ │ │ @@ -66,15 +66,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "The modules that will be used are imported:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fbb8a902", │ │ │ │ │ + "id": "90cfb0e9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py.PETSc import ScalarType # type: ignore\n", │ │ │ │ │ @@ -84,51 +84,51 @@ │ │ │ │ │ "import ufl\n", │ │ │ │ │ "from dolfinx import fem, io, mesh, plot\n", │ │ │ │ │ "from dolfinx.fem.petsc import LinearProblem\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "92621772", │ │ │ │ │ + "id": "eda11479", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Note that it is important to first `from mpi4py import MPI` to\n", │ │ │ │ │ "ensure that MPI is correctly initialised." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ab29cfda", │ │ │ │ │ + "id": "15acce8f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create a rectangular {py:class}`Mesh ` using\n", │ │ │ │ │ "{py:func}`create_rectangle `, and\n", │ │ │ │ │ "create a finite element {py:class}`function space\n", │ │ │ │ │ "` $V$ on the mesh." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7006295d", │ │ │ │ │ + "id": "1a464678", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = mesh.create_rectangle(\n", │ │ │ │ │ " comm=MPI.COMM_WORLD,\n", │ │ │ │ │ " points=((0.0, 0.0), (2.0, 1.0)),\n", │ │ │ │ │ " n=(32, 16),\n", │ │ │ │ │ " cell_type=mesh.CellType.triangle,\n", │ │ │ │ │ ")\n", │ │ │ │ │ "V = fem.functionspace(msh, (\"Lagrange\", 1))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fb950d92", │ │ │ │ │ + "id": "cdcdce93", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The second argument to {py:func}`functionspace\n", │ │ │ │ │ "` is a tuple `(family, degree)`, where\n", │ │ │ │ │ "`family` is the finite element family, and `degree` specifies the\n", │ │ │ │ │ "polynomial degree. In this case `V` is a space of continuous Lagrange\n", │ │ │ │ │ "finite elements of degree 1. For further details of how one can specify\n", │ │ │ │ │ @@ -142,106 +142,106 @@ │ │ │ │ │ "with a 'marker' function that returns `True` for points `x` on the\n", │ │ │ │ │ "boundary and `False` otherwise." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d9d3d91e", │ │ │ │ │ + "id": "3fd441ef", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "facets = mesh.locate_entities_boundary(\n", │ │ │ │ │ " msh,\n", │ │ │ │ │ " dim=(msh.topology.dim - 1),\n", │ │ │ │ │ " marker=lambda x: np.isclose(x[0], 0.0) | np.isclose(x[0], 2.0),\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e86209eb", │ │ │ │ │ + "id": "7fcd0818", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We now find the degrees-of-freedom that are associated with the\n", │ │ │ │ │ "boundary facets using {py:func}`locate_dofs_topological\n", │ │ │ │ │ "`:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2f318767", │ │ │ │ │ + "id": "497a398a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dofs = fem.locate_dofs_topological(V=V, entity_dim=1, entities=facets)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "25a508ca", │ │ │ │ │ + "id": "e4db45d5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and use {py:func}`dirichletbc ` to create a\n", │ │ │ │ │ "{py:class}`DirichletBC ` class that\n", │ │ │ │ │ "represents the boundary condition:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d5768c6f", │ │ │ │ │ + "id": "395c9a99", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc = fem.dirichletbc(value=ScalarType(0), dofs=dofs, V=V)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1678f5e8", │ │ │ │ │ + "id": "1b1df5d1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, the variational problem is defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fa8b336c", │ │ │ │ │ + "id": "ccb13c40", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "u = ufl.TrialFunction(V)\n", │ │ │ │ │ "v = ufl.TestFunction(V)\n", │ │ │ │ │ "x = ufl.SpatialCoordinate(msh)\n", │ │ │ │ │ "f = 10 * ufl.exp(-((x[0] - 0.5) ** 2 + (x[1] - 0.5) ** 2) / 0.02)\n", │ │ │ │ │ "g = ufl.sin(5 * x[0])\n", │ │ │ │ │ "a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx\n", │ │ │ │ │ "L = ufl.inner(f, v) * ufl.dx + ufl.inner(g, v) * ufl.ds" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c21aa3cb", │ │ │ │ │ + "id": "5eae5999", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "A {py:class}`LinearProblem ` object is\n", │ │ │ │ │ "created that brings together the variational problem, the Dirichlet\n", │ │ │ │ │ "boundary condition, and which specifies the linear solver. In this\n", │ │ │ │ │ "case an LU solver is used, and we ask that PETSc throws an error\n", │ │ │ │ │ "if the solver does not converge. The {py:func}`solve\n", │ │ │ │ │ "` computes the solution." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2f7aee62", │ │ │ │ │ + "id": "7932fbd6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "problem = LinearProblem(\n", │ │ │ │ │ " a,\n", │ │ │ │ │ " L,\n", │ │ │ │ │ " bcs=[bc],\n", │ │ │ │ │ @@ -250,48 +250,48 @@ │ │ │ │ │ ")\n", │ │ │ │ │ "uh = problem.solve()\n", │ │ │ │ │ "assert isinstance(uh, fem.Function)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ecc27898", │ │ │ │ │ + "id": "13950d7c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The solution can be written to a {py:class}`XDMFFile\n", │ │ │ │ │ "` file visualization with [ParaView](https://www.paraview.org/)\n", │ │ │ │ │ "or [VisIt](https://visit-dav.github.io/visit-website/):" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7e67837e", │ │ │ │ │ + "id": "31c5b0d1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "out_folder = Path(\"out_poisson\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)\n", │ │ │ │ │ "with io.XDMFFile(msh.comm, out_folder / \"poisson.xdmf\", \"w\") as file:\n", │ │ │ │ │ " file.write_mesh(msh)\n", │ │ │ │ │ " file.write_function(uh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "846be727", │ │ │ │ │ + "id": "f9cc2bb0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and displayed using [pyvista](https://docs.pyvista.org/)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "68f8e73d", │ │ │ │ │ + "id": "720a46c9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "try:\n", │ │ │ │ │ " import pyvista\n", │ │ │ │ │ "\n", │ │ │ │ │ " cells, types, x = plot.vtk_mesh(V)\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/69c686705c3e4103e036ace87972a971/demo_types.ipynb.gz │ │ │ ├── demo_types.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9873046875% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '8c55eb7a'}, 1: {'id': 'fb4410b9'}, 2: {'id': '2e62ee21'}, 3: {'id': " │ │ │ │ │┄ "'a6fab216'}, 4: {'id': 'c083546a'}, 5: {'id': 'aa1d290b'}, 6: {'id': '8152a54c'}, 7: " │ │ │ │ │┄ "{'id': 'b98db70b'}, 8: {'id': 'd123141e'}, 9: {'id': '67c8645e'}, 10: {'id': " │ │ │ │ │┄ "'f337a1a6'}, 11: {'id': 'd6d94253'}, 12: {'id': '1a3a9269'}, 13: {'id': '638d53ae'}, " │ │ │ │ │┄ "14: {'id': '010b7853'}, 15: {'id': '568696f1'}}"} │ │ │ │ │ @@ -1,26 +1,26 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "89da197c", │ │ │ │ │ + "id": "8c55eb7a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Solving PDEs with different scalar (float) types\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_types.py>`\n", │ │ │ │ │ "* {download}`Jupyter notebook <./demo_types.ipynb>`\n", │ │ │ │ │ "```" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "933dcc7c", │ │ │ │ │ + "id": "fb4410b9", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "This demo shows:\n", │ │ │ │ │ "\n", │ │ │ │ │ "- How to solve problems using different scalar types, .e.g. single or\n", │ │ │ │ │ @@ -28,15 +28,15 @@ │ │ │ │ │ "- Interfacing with [SciPy](https://scipy.org/) sparse linear algebra\n", │ │ │ │ │ " functionality" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "32a0381f", │ │ │ │ │ + "id": "2e62ee21", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "import sys\n", │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ @@ -47,66 +47,66 @@ │ │ │ │ │ "\n", │ │ │ │ │ "import ufl\n", │ │ │ │ │ "from dolfinx import fem, la, mesh, plot\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "299bcd2d", │ │ │ │ │ + "id": "a6fab216", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "SciPy solvers do not support MPI, so all computations will be\n", │ │ │ │ │ "performed on a single MPI rank" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d6bad21e", │ │ │ │ │ + "id": "c083546a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "comm = MPI.COMM_SELF" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b7411a5b", │ │ │ │ │ + "id": "aa1d290b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create an output directory for storing results and figures" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d51ffd96", │ │ │ │ │ + "id": "8152a54c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "out_folder = Path(\"out_types\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0b021fa1", │ │ │ │ │ + "id": "b98db70b", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a function that solves the Poisson equation using different\n", │ │ │ │ │ "precision float and complex scalar types for the finite element\n", │ │ │ │ │ "solution." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d06b1509", │ │ │ │ │ + "id": "d123141e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def display_scalar(u, name, filter=np.real):\n", │ │ │ │ │ " \"\"\"Plot the solution using pyvista\"\"\"\n", │ │ │ │ │ " try:\n", │ │ │ │ │ " import pyvista\n", │ │ │ │ │ @@ -126,15 +126,15 @@ │ │ │ │ │ " except ModuleNotFoundError:\n", │ │ │ │ │ " print(\"'pyvista' is required to visualise the solution\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e8422475", │ │ │ │ │ + "id": "67c8645e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def display_vector(u, name, filter=np.real):\n", │ │ │ │ │ " \"\"\"Plot the solution using pyvista\"\"\"\n", │ │ │ │ │ " try:\n", │ │ │ │ │ " import pyvista\n", │ │ │ │ │ @@ -154,15 +154,15 @@ │ │ │ │ │ " except ModuleNotFoundError:\n", │ │ │ │ │ " print(\"'pyvista' is required to visualise the solution\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6a5ff731", │ │ │ │ │ + "id": "f337a1a6", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def poisson(dtype):\n", │ │ │ │ │ " \"\"\"Poisson problem solver\n", │ │ │ │ │ @@ -225,28 +225,28 @@ │ │ │ │ │ " uh.x.array[:] = scipy.sparse.linalg.spsolve(As, b.array)\n", │ │ │ │ │ "\n", │ │ │ │ │ " return uh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "87acf4a6", │ │ │ │ │ + "id": "d6d94253", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a function that solves the linearised elasticity equation using\n", │ │ │ │ │ "different precision float and complex scalar types for the finite\n", │ │ │ │ │ "element solution." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e2d4522b", │ │ │ │ │ + "id": "1a3a9269", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def elasticity(dtype) -> fem.Function:\n", │ │ │ │ │ " \"\"\"Linearised elasticity problem solver.\"\"\"\n", │ │ │ │ │ @@ -307,26 +307,26 @@ │ │ │ │ │ " uh.x.array[:] = scipy.sparse.linalg.spsolve(As, b.array)\n", │ │ │ │ │ "\n", │ │ │ │ │ " return uh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "4310e3ac", │ │ │ │ │ + "id": "638d53ae", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve problems for different types" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "13bf640c", │ │ │ │ │ + "id": "010b7853", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "uh = poisson(dtype=np.float32)\n", │ │ │ │ │ "uh = poisson(dtype=np.float64)\n", │ │ │ │ │ @@ -336,15 +336,15 @@ │ │ │ │ │ "display_scalar(uh, \"poisson\", np.real)\n", │ │ │ │ │ "display_scalar(uh, \"poisson\", np.imag)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "094441aa", │ │ │ │ │ + "id": "568696f1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "uh = elasticity(dtype=np.float32)\n", │ │ │ │ │ "uh = elasticity(dtype=np.float64)\n", │ │ │ │ │ "if not sys.platform.startswith(\"win32\"):\n", │ │ │ │ │ " uh = elasticity(dtype=np.complex64)\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/6bd0b7dbffc1fd43f16bc5cd2cfeed74/demo_static-condensation.ipynb.gz │ │ │ ├── demo_static-condensation.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9870975378787878% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '55480a43'}, 1: {'id': 'c131af0d'}, 2: {'id': 'ec6a0bf9'}, 3: {'id': " │ │ │ │ │┄ "'bed288e0'}, 4: {'id': '4ea39623'}, 5: {'id': '0dce3a70'}, 6: {'id': 'bfd794ee'}, 7: " │ │ │ │ │┄ "{'id': 'bebe7d19'}, 8: {'id': '53e1dcd7'}, 9: {'id': 'd4a3ac84'}, 10: {'id': " │ │ │ │ │┄ "'43a7b3fa'}, 11: {'id': '26e0b920'}, 12: {'id': '4c2ef44c'}, 13: {'id': '0ef11831'}, " │ │ │ │ │┄ "14: {'id': '39a4eda2'}, 15: {'id': '52166d9b'}, 16: {'id': '99732993'}, 17: {'id': " │ │ │ │ │┄ "'7c70df90'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "97309677", │ │ │ │ │ + "id": "55480a43", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "(demo-static-condensation)=\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Static condensation of linear elasticity\n", │ │ │ │ │ "\n", │ │ │ │ │ "Copyright (C) 2020 Michal Habera and Andreas Zilian\n", │ │ │ │ │ @@ -26,25 +26,25 @@ │ │ │ │ │ " on variational forms made with UFL.\n", │ │ │ │ │ "- Extracting JIT compiled C-kernels using {py:func}`ffcx_jit\n", │ │ │ │ │ "`" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fd602d7b", │ │ │ │ │ + "id": "c131af0d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "This demo requires more modules than usual, as it uses `numba` for\n", │ │ │ │ │ "efficient static condensation." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "584b1699", │ │ │ │ │ + "id": "ec6a0bf9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py import PETSc\n", │ │ │ │ │ @@ -74,41 +74,41 @@ │ │ │ │ │ "from ffcx.codegeneration.utils import empty_void_pointer\n", │ │ │ │ │ "from ffcx.codegeneration.utils import numba_ufcx_kernel_signature as ufcx_signature\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a04e3aec", │ │ │ │ │ + "id": "bed288e0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "rtype = default_real_type\n", │ │ │ │ │ "dtype = default_scalar_type\n", │ │ │ │ │ "if np.issubdtype(rtype, np.float32): # type: ignore\n", │ │ │ │ │ " print(\"float32 not yet supported for this demo.\")\n", │ │ │ │ │ " exit(0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "defc58fd", │ │ │ │ │ + "id": "4ea39623", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We start by reading in the Cook's mesh [cooks_tri_mesh.xdmf](\n", │ │ │ │ │ "https://github.com/FEniCS/dolfinx/blob/main/python/demo/data/cooks_tri_mesh.xdmf)\n", │ │ │ │ │ "using {py:meth}`XDMFFile.read_mesh `.\n", │ │ │ │ │ "Note that the mesh is written in plain-text format, which means we use\n", │ │ │ │ │ "{py:attr}`XDMFFile.Encoding.ASCII `." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "0693a796", │ │ │ │ │ + "id": "0dce3a70", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "infile = XDMFFile(\n", │ │ │ │ │ " MPI.COMM_WORLD,\n", │ │ │ │ │ " Path(Path(__file__).parent, \"data\", \"cooks_tri_mesh.xdmf\"),\n", │ │ │ │ │ " \"r\",\n", │ │ │ │ │ @@ -116,146 +116,146 @@ │ │ │ │ │ ")\n", │ │ │ │ │ "msh = infile.read_mesh(name=\"Grid\")\n", │ │ │ │ │ "infile.close()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "039a3201", │ │ │ │ │ + "id": "bfd794ee", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create the Stress (Se) and displacement (Ue) elements and\n", │ │ │ │ │ "corresponding function spaces. Note that the stress element is symmetric." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8e3d8a76", │ │ │ │ │ + "id": "bebe7d19", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "gdim = msh.geometry.dim\n", │ │ │ │ │ "Se = element(\"DG\", msh.basix_cell(), 1, shape=(gdim, gdim), symmetry=True, dtype=rtype) # type: ignore\n", │ │ │ │ │ "Ue = element(\"Lagrange\", msh.basix_cell(), 2, shape=(gdim,), dtype=rtype) # type: ignore\n", │ │ │ │ │ "S = functionspace(msh, Se)\n", │ │ │ │ │ "U = functionspace(msh, Ue)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e193d644", │ │ │ │ │ + "id": "53e1dcd7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we define the trial and test functions for stress and displacement," │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d2ae0da5", │ │ │ │ │ + "id": "d4a3ac84", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "sigma, tau = ufl.TrialFunction(S), ufl.TestFunction(S)\n", │ │ │ │ │ "u, v = ufl.TrialFunction(U), ufl.TestFunction(U)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ac53ae19", │ │ │ │ │ + "id": "43a7b3fa", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Locate all facets at the free end and assign them value 1. Sort the\n", │ │ │ │ │ "facet indices (requirement for constructing {py:class}`MeshTags\n", │ │ │ │ │ "`)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e4a5a2f7", │ │ │ │ │ + "id": "26e0b920", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "tdim = msh.topology.dim\n", │ │ │ │ │ "free_end_facets = np.sort(locate_entities_boundary(msh, tdim - 1, lambda x: np.isclose(x[0], 48.0)))\n", │ │ │ │ │ "mt = meshtags(msh, tdim - 1, free_end_facets, 1)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d912587a", │ │ │ │ │ + "id": "4c2ef44c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we create an integration measure with the facet markers." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "881011d6", │ │ │ │ │ + "id": "0ef11831", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ds = ufl.Measure(\"ds\", subdomain_data=mt)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d388d3b7", │ │ │ │ │ + "id": "39a4eda2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Homogeneous boundary condition in displacement" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1cea06d9", │ │ │ │ │ + "id": "52166d9b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "u_bc = Function(U)\n", │ │ │ │ │ "u_bc.x.array[:] = 0" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c69f9fd9", │ │ │ │ │ + "id": "99732993", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Displacement {py:class}`BC ` is applied to\n", │ │ │ │ │ "the left side" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5615c405", │ │ │ │ │ + "id": "7c70df90", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "left_facets = locate_entities_boundary(msh, tdim - 1, lambda x: np.isclose(x[0], 0.0))\n", │ │ │ │ │ "bdofs = locate_dofs_topological(U, tdim - 1, left_facets)\n", │ │ │ │ │ "bc = dirichletbc(u_bc, bdofs)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1a0d1f49", │ │ │ │ │ + "id": "63b280bb", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Elastic stiffness tensor and Poisson ratio" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "db08d082", │ │ │ │ │ + "id": "5e47f07a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "E, nu = 1.0, 1.0 / 3.0\n", │ │ │ │ │ "\n", │ │ │ │ │ "\n", │ │ │ │ │ "def sigma_u(u):\n", │ │ │ │ │ @@ -264,51 +264,51 @@ │ │ │ │ │ " eps = 0.5 * (ufl.grad(u) + ufl.grad(u).T)\n", │ │ │ │ │ " sigma = E / (1.0 - nu**2) * ((1.0 - nu) * eps + nu * ufl.Identity(2) * ufl.tr(eps))\n", │ │ │ │ │ " return sigma" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d6cff43a", │ │ │ │ │ + "id": "e00c562a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "With the definitions above, we can define the different blocks\n", │ │ │ │ │ "of the variational formulation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ad88a8d1", │ │ │ │ │ + "id": "fee6f6ea", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "a00 = ufl.inner(sigma, tau) * ufl.dx\n", │ │ │ │ │ "a10 = -ufl.inner(sigma, ufl.grad(v)) * ufl.dx\n", │ │ │ │ │ "a01 = -ufl.inner(sigma_u(u), tau) * ufl.dx\n", │ │ │ │ │ "\n", │ │ │ │ │ "f = ufl.as_vector([0.0, 1.0 / 16])\n", │ │ │ │ │ "b1 = form(-ufl.inner(f, v) * ds(1), dtype=dtype) # type: ignore" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "dd402266", │ │ │ │ │ + "id": "8b4ca6e4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "To generate (C-code) and JIT compile the kernels, we use\n", │ │ │ │ │ "{py:func}`ffcx_jit ` for each individual block.\n", │ │ │ │ │ "We extract the kernel function from the compiled form object by\n", │ │ │ │ │ "getting the `tabulate_tensor_{dtype}` attribute of the compiled form." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "3d908688", │ │ │ │ │ + "id": "0dea8fe2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ufcx00, _, _ = ffcx_jit(msh.comm, a00, form_compiler_options={\"scalar_type\": dtype}) # type: ignore\n", │ │ │ │ │ "kernel00 = getattr(ufcx00.form_integrals[0], f\"tabulate_tensor_{np.dtype(dtype).name}\") # type: ignore\n", │ │ │ │ │ "\n", │ │ │ │ │ "ufcx01, _, _ = ffcx_jit(msh.comm, a01, form_compiler_options={\"scalar_type\": dtype}) # type: ignore\n", │ │ │ │ │ @@ -317,15 +317,15 @@ │ │ │ │ │ "ufcx10, _, _ = ffcx_jit(msh.comm, a10, form_compiler_options={\"scalar_type\": dtype}) # type: ignore\n", │ │ │ │ │ "kernel10 = getattr(ufcx10.form_integrals[0], f\"tabulate_tensor_{np.dtype(dtype).name}\") # type: ignore" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "047f346b", │ │ │ │ │ + "id": "883f4d38", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ffi = cffi.FFI()\n", │ │ │ │ │ "if np.issubdtype(dtype, np.complexfloating):\n", │ │ │ │ │ " if cffi.__version_info__ > (1, 16, 99) and cffi.__version_info__ <= (1, 17, 1):\n", │ │ │ │ │ " print(\n", │ │ │ │ │ @@ -334,50 +334,50 @@ │ │ │ │ │ " )\n", │ │ │ │ │ " exit(0)\n", │ │ │ │ │ " cffi_support.register_type(ffi.typeof(\"double _Complex\"), numba.types.complex128)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e4e94c81", │ │ │ │ │ + "id": "b2df1be1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Get local dofmap sizes for later local tensor tabulations" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "46e9a266", │ │ │ │ │ + "id": "22648da5", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "Ssize = S.element.space_dimension\n", │ │ │ │ │ "Usize = U.element.space_dimension" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "84d6706c", │ │ │ │ │ + "id": "69a73890", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we define a static condensation kernel that uses the\n", │ │ │ │ │ "previously defined kernels to compute the condensed local element\n", │ │ │ │ │ "tensor. The kernel is decorated with {py:func}`numba.cfunc` using the\n", │ │ │ │ │ "appropriate signature obtained from {py:func}`ufcx_signature`.`" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "05ac2ed3", │ │ │ │ │ + "id": "ab8892b9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "@numba.cfunc(ufcx_signature(dtype, rtype), nopython=True) # type: ignore\n", │ │ │ │ │ "def tabulate_A(A_, w_, c_, coords_, entity_local_index, permutation=ffi.NULL, custom_data=None):\n", │ │ │ │ │ " \"\"\"Element kernel that applies static condensation.\"\"\"\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -420,182 +420,182 @@ │ │ │ │ │ "\n", │ │ │ │ │ " # A = - A10 * A00^{-1} * A01\n", │ │ │ │ │ " A[:, :] = -A10 @ np.linalg.solve(A00, A01)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5ed1c6c7", │ │ │ │ │ + "id": "a6f982a8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Prepare a {py:class}`Form` with a condensed\n", │ │ │ │ │ "tabulation kernel. We specify the integration domains to be the\n", │ │ │ │ │ "cells owned by the current process" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d36e9ac5", │ │ │ │ │ + "id": "2c3f8d40", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "formtype = form_cpp_class(dtype) # type: ignore\n", │ │ │ │ │ "cells = np.arange(msh.topology.index_map(msh.topology.dim).size_local)\n", │ │ │ │ │ "integrals = {IntegralType.cell: [(0, tabulate_A.address, cells, np.array([], dtype=np.int8))]}\n", │ │ │ │ │ "a_cond = Form(\n", │ │ │ │ │ " formtype([U._cpp_object, U._cpp_object], integrals, [], [], False, [], mesh=msh._cpp_object)\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "86b1fff9", │ │ │ │ │ + "id": "870a3469", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we pass the compiled kernel to the standard {py:func}`\n", │ │ │ │ │ "assemble_matrix ` function to assemble\n", │ │ │ │ │ "to the global condensed stiffness matrix. We also assemble the right-hand\n", │ │ │ │ │ "side vector using {py:func}`assemble_vector\n", │ │ │ │ │ "` and apply the boundary conditions by\n", │ │ │ │ │ "{py:func}`applying lifting ` and\n", │ │ │ │ │ "{py:meth}`set bc`." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f604a5cf", │ │ │ │ │ + "id": "9ca02450", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "A_cond = assemble_matrix(a_cond, bcs=[bc])\n", │ │ │ │ │ "A_cond.assemble()\n", │ │ │ │ │ "b = assemble_vector(b1)\n", │ │ │ │ │ "apply_lifting(b, [a_cond], bcs=[[bc]])\n", │ │ │ │ │ "b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # type: ignore\n", │ │ │ │ │ "bc.set(b)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "13b5d061", │ │ │ │ │ + "id": "ed7780fd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We use a {py:class}`PETSc.KSP ` solver to solve the\n", │ │ │ │ │ "condensed linear system. The solution is stored in a\n", │ │ │ │ │ "{py:class}`Function`, while we pass the\n", │ │ │ │ │ "underlying data wrapped as a {py:class}`PETSc.Vec `\n", │ │ │ │ │ "to the solver by calling {py:meth}`petsc_vec\n", │ │ │ │ │ "` on the\n", │ │ │ │ │ "{py:meth}`vector ` attribute of the function." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5b8cf1af", │ │ │ │ │ + "id": "d19760bb", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "uc = Function(U, name=\"u_from_condensation\")\n", │ │ │ │ │ "solver = PETSc.KSP().create(A_cond.getComm()) # type: ignore\n", │ │ │ │ │ "solver.setOperators(A_cond)\n", │ │ │ │ │ "solver.solve(b, uc.x.petsc_vec)\n", │ │ │ │ │ "solver.destroy()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6160fc03", │ │ │ │ │ + "id": "77660c82", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We verify the condensed solution by comparing against a standard,\n", │ │ │ │ │ "pure displacement based formulation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1ed41553", │ │ │ │ │ + "id": "1a8b66e2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "a = form(-ufl.inner(sigma_u(u), ufl.grad(v)) * ufl.dx)\n", │ │ │ │ │ "A = assemble_matrix(a, bcs=[bc])\n", │ │ │ │ │ "A.assemble()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "59db9248", │ │ │ │ │ + "id": "1cf6893c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create {py:class}`BoundingBoxTree `\n", │ │ │ │ │ "using {py:meth}`bb_tree ` constructor\n", │ │ │ │ │ "for efficient computation of the ownership of a set of evaluation points" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "64e43156", │ │ │ │ │ + "id": "6d122742", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bb_tree = geometry.bb_tree(msh, tdim, padding=0.0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "be201f52", │ │ │ │ │ + "id": "efb778aa", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Check against standard table value" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4523bf90", │ │ │ │ │ + "id": "25bb648c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "p = np.array([[48.0, 52.0, 0.0]], dtype=np.float64)\n", │ │ │ │ │ "cell_candidates = geometry.compute_collisions_points(bb_tree, p)\n", │ │ │ │ │ "cells = geometry.compute_colliding_cells(msh, cell_candidates, p).array" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e4b05204", │ │ │ │ │ + "id": "672df2e3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "uc.x.scatter_forward()\n", │ │ │ │ │ "if len(cells) > 0:\n", │ │ │ │ │ " value = uc.eval(p, cells[0])\n", │ │ │ │ │ " print(value[1])\n", │ │ │ │ │ " assert np.isclose(value[1], 23.95, rtol=1.0e-2)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "34d61a58", │ │ │ │ │ + "id": "becd39b5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Check the equality of displacement based and mixed condensed global\n", │ │ │ │ │ "matrices, i.e. check that condensation is exact" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "924560b2", │ │ │ │ │ + "id": "6b9805f0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "assert np.isclose((A - A_cond).norm(), 0.0)" │ │ │ │ │ ] │ │ │ │ │ } │ │ │ │ │ ], │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/7742577adb1c8360c8a19eea719713fc/demo_pyvista.ipynb.gz │ │ │ ├── demo_pyvista.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9871794871794872% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '9ff402b3'}, 1: {'id': 'f1e00608'}, 2: {'id': 'c1f4f4c5'}, 3: {'id': " │ │ │ │ │┄ "'e94e9663'}, 4: {'id': '1323a48d'}, 5: {'id': 'd7083c40'}, 6: {'id': '5936a885'}, 7: " │ │ │ │ │┄ "{'id': '38d11245'}, 8: {'id': '4f44bbef'}, 9: {'id': '3137d1e6'}, 10: {'id': " │ │ │ │ │┄ "'74e1e152'}, 11: {'id': 'a8104c9b'}, 12: {'id': '93165a52'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2ad21cbb", │ │ │ │ │ + "id": "9ff402b3", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Copyright (C) 2021-2022 J\u00f8rgen S. Dokken and Garth N. Wells\n", │ │ │ │ │ "\n", │ │ │ │ │ "This file is part of DOLFINx ()\n", │ │ │ │ │ @@ -27,15 +27,15 @@ │ │ │ │ │ "To start, the required modules are imported and some PyVista\n", │ │ │ │ │ "parameters set." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f9dd4597", │ │ │ │ │ + "id": "f1e00608", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -51,26 +51,26 @@ │ │ │ │ │ "figsize = 800\n", │ │ │ │ │ "out_folder = Path(\"out_pyvista\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "faa363e4", │ │ │ │ │ + "id": "c1f4f4c5", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Plotting a finite element Function using warp by scalar" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "755aaa93", │ │ │ │ │ + "id": "e94e9663", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def plot_scalar():\n", │ │ │ │ │ " # We start by creating a unit square mesh and interpolating a\n", │ │ │ │ │ @@ -127,26 +127,26 @@ │ │ │ │ │ " )\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " subplotter.show()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "bf7fa310", │ │ │ │ │ + "id": "1323a48d", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Mesh tags and using subplots" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "59f3e697", │ │ │ │ │ + "id": "d7083c40", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def plot_meshtags():\n", │ │ │ │ │ " # Create a mesh\n", │ │ │ │ │ @@ -199,28 +199,28 @@ │ │ │ │ │ " )\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " subplotter.show()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "746830bc", │ │ │ │ │ + "id": "5936a885", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Higher-order Functions\n", │ │ │ │ │ "\n", │ │ │ │ │ "Higher-order finite element function can also be plotted." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "161611fd", │ │ │ │ │ + "id": "38d11245", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def plot_higher_order():\n", │ │ │ │ │ " # Create a mesh\n", │ │ │ │ │ @@ -286,29 +286,29 @@ │ │ │ │ │ " )\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " plotter.show()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fe8ad4f3", │ │ │ │ │ + "id": "4f44bbef", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Vector-element functions\n", │ │ │ │ │ "\n", │ │ │ │ │ "In this section we will consider how to plot vector-element functions,\n", │ │ │ │ │ "e.g. Raviart-Thomas or N\u00e9d\u00e9lec elements." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "cc6d6330", │ │ │ │ │ + "id": "3137d1e6", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def plot_nedelec():\n", │ │ │ │ │ " msh = create_unit_cube(\n", │ │ │ │ │ @@ -365,28 +365,28 @@ │ │ │ │ │ " )\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " plotter.show()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "55eb5684", │ │ │ │ │ + "id": "74e1e152", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Plotting streamlines\n", │ │ │ │ │ "\n", │ │ │ │ │ "In this section we illustrate how to visualize streamlines in 3D" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f65e271f", │ │ │ │ │ + "id": "a8104c9b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def plot_streamlines():\n", │ │ │ │ │ " msh = create_unit_cube(MPI.COMM_WORLD, 4, 4, 4, CellType.hexahedron, dtype=np.float64)\n", │ │ │ │ │ " gdim = msh.geometry.dim\n", │ │ │ │ │ " V = functionspace(msh, (\"Discontinuous Lagrange\", 2, (gdim,)))\n", │ │ │ │ │ @@ -423,15 +423,15 @@ │ │ │ │ │ " else:\n", │ │ │ │ │ " plotter.show()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "784a2fd7", │ │ │ │ │ + "id": "93165a52", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "plot_scalar()\n", │ │ │ │ │ "plot_meshtags()\n", │ │ │ │ │ "plot_higher_order()\n", │ │ │ │ │ "plot_nedelec()\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/94dc1fa896703fdd4c54729bdfbf969a/demo_pml.ipynb.gz │ │ │ ├── demo_pml.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666666% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': 'b94ccdd0'}, 1: {'id': 'e91429d2'}, 2: {'id': '0602ae2b'}, 3: {'id': " │ │ │ │ │┄ "'c97b8089'}, 4: {'id': 'ce0bf2bd'}, 5: {'id': 'f81aed65'}, 6: {'id': 'a95e18a3'}, 7: " │ │ │ │ │┄ "{'id': 'dde71711'}, 8: {'id': 'ba9b1e61'}, 9: {'id': 'a2cd3a8c'}, 10: {'id': " │ │ │ │ │┄ "'8f882d69'}, 11: {'id': 'ad08136a'}, 12: {'id': 'edbe4cda'}, 13: {'id': '4fecd7ec'}, " │ │ │ │ │┄ "14: {'id': '2236516e'}, 15: {'id': 'c87b1f10'}, 16: {'id': 'c17d9b66'}, 17: {'id': " │ │ │ │ │┄ "'fa93defa'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1241f836", │ │ │ │ │ + "id": "b94ccdd0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Electromagnetic scattering from a wire with PML\n", │ │ │ │ │ "\n", │ │ │ │ │ "Copyright (C) 2022 Michele Castriotta, Igor Baratta, J\u00f8rgen S. Dokken\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ @@ -22,15 +22,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "First, we import the required modules" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "3762ba04", │ │ │ │ │ + "id": "e91429d2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "import sys\n", │ │ │ │ │ "from functools import partial, reduce\n", │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -62,47 +62,47 @@ │ │ │ │ │ "except ModuleNotFoundError:\n", │ │ │ │ │ " print(\"pyvista and pyvistaqt are required to visualise the solution\")\n", │ │ │ │ │ " have_pyvista = False" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "941ebbcb", │ │ │ │ │ + "id": "0602ae2b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Since we want to solve time-harmonic Maxwell's equation, we require\n", │ │ │ │ │ "that the demo is executed with DOLFINx (PETSc) complex mode." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ef357d42", │ │ │ │ │ + "id": "c97b8089", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if not np.issubdtype(default_scalar_type, np.complexfloating):\n", │ │ │ │ │ " print(\"Demo should only be executed with DOLFINx complex mode\")\n", │ │ │ │ │ " exit(0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "66c7b8b8", │ │ │ │ │ + "id": "ce0bf2bd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Mesh generation with GMSH\n", │ │ │ │ │ "The mesh is made up by a central circle (the wire), and an external\n", │ │ │ │ │ "layer (the PML) divided in 4 rectangles and 4 squares at the corners.\n", │ │ │ │ │ "The `generate_mesh_wire` function takes as input:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6e88b403", │ │ │ │ │ + "id": "f81aed65", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "- `radius_wire`: the radius of the wire\n", │ │ │ │ │ "- `radius_scatt`: the radius of the circle where scattering efficiency\n", │ │ │ │ │ " is calculated\n", │ │ │ │ │ @@ -122,15 +122,15 @@ │ │ │ │ │ " (together with pml_tag+1 and pml_tag+2)\n", │ │ │ │ │ "\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "81f4284c", │ │ │ │ │ + "id": "a95e18a3", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def generate_mesh_wire(\n", │ │ │ │ │ " radius_wire: float,\n", │ │ │ │ │ @@ -246,29 +246,29 @@ │ │ │ │ │ "\n", │ │ │ │ │ " gmsh.model.mesh.generate(2)\n", │ │ │ │ │ " return gmsh.model" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "526dec8c", │ │ │ │ │ + "id": "dde71711", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Mathematical formulation\n", │ │ │ │ │ "Following are convenience functions for the calculation of the\n", │ │ │ │ │ "absorption, scattering and extinction efficiencies of a wire\n", │ │ │ │ │ "being hit normally by a TM-polarized electromagnetic wave.\n", │ │ │ │ │ "See {ref}`Scattering boundary conditions:\n", │ │ │ │ │ "Mathematical formulation ` for a detailed description." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2aa72260", │ │ │ │ │ + "id": "ba9b1e61", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -298,15 +298,15 @@ │ │ │ │ │ " q_ext += c * 2 * np.real(compute_a(nu, m, alpha))\n", │ │ │ │ │ " q_sca += c * 2 * np.abs(compute_a(nu, m, alpha)) ** 2\n", │ │ │ │ │ " return q_ext - q_sca, q_sca, q_ext" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1b4a018f", │ │ │ │ │ + "id": "a2cd3a8c", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Perfectly matched layers (PMLs)\n", │ │ │ │ │ "Now, let's consider an infinite metallic wire immersed in a background\n", │ │ │ │ │ "medium (e.g. vacuum or water). Let's now consider the plane cutting\n", │ │ │ │ │ @@ -347,53 +347,53 @@ │ │ │ │ │ "The function `background_field` below implements this analytical\n", │ │ │ │ │ "formula:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "28b24fde", │ │ │ │ │ + "id": "8f882d69", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def background_field(theta: float, n_b: float, k0: complex, x: np.typing.NDArray[np.float64]):\n", │ │ │ │ │ " kx = n_b * k0 * np.cos(theta)\n", │ │ │ │ │ " ky = n_b * k0 * np.sin(theta)\n", │ │ │ │ │ " phi = kx * x[0] + ky * x[1]\n", │ │ │ │ │ " return (-np.sin(theta) * np.exp(1j * phi), np.cos(theta) * np.exp(1j * phi))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f397d88d", │ │ │ │ │ + "id": "ad08136a", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "For convenience, we define the $\\nabla\\times$ operator for a 2D vector" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4cc86648", │ │ │ │ │ + "id": "edbe4cda", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def curl_2d(a: fem.Function):\n", │ │ │ │ │ " return ufl.as_vector((0, 0, a[1].dx(0) - a[0].dx(1)))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ff18a90d", │ │ │ │ │ + "id": "4fecd7ec", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Let's now see how we can implement PMLs for our problem. PMLs are\n", │ │ │ │ │ "artificial layers surrounding the real domain that gradually absorb\n", │ │ │ │ │ "waves impinging them. Mathematically, we can use a complex coordinate\n", │ │ │ │ │ @@ -410,34 +410,34 @@ │ │ │ │ │ "faster the absorption). In DOLFINx, we can define this coordinate\n", │ │ │ │ │ "transformation in the following way:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "05970685", │ │ │ │ │ + "id": "2236516e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def pml_coordinates(x: ufl.indexed.Indexed, alpha: float, k0: complex, l_dom: float, l_pml: float):\n", │ │ │ │ │ " return x + 1j * alpha / k0 * x * (ufl.algebra.Abs(x) - l_dom / 2) / (l_pml / 2 - l_dom / 2) ** 2" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d6683652", │ │ │ │ │ + "id": "c87b1f10", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We use the following domain specific parameters:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "bcd57c5e", │ │ │ │ │ + "id": "c17d9b66", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "epsilon_0 = 8.8541878128 * 10**-12\n", │ │ │ │ │ "mu_0 = 4 * np.pi * 10**-7\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Radius of the wire and of the boundary of the domain\n", │ │ │ │ │ @@ -458,26 +458,26 @@ │ │ │ │ │ "bkg_tag = 2\n", │ │ │ │ │ "scatt_tag = 3\n", │ │ │ │ │ "pml_tag = 4" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "605948fb", │ │ │ │ │ + "id": "fa93defa", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We generate the mesh using GMSH and convert it to a\n", │ │ │ │ │ "{py:class}`Mesh` using\n", │ │ │ │ │ "{py:func}`model_to_mesh `." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a084d179", │ │ │ │ │ + "id": "136db1f2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "model = None\n", │ │ │ │ │ "gmsh.initialize(sys.argv)\n", │ │ │ │ │ "if MPI.COMM_WORLD.rank == 0:\n", │ │ │ │ │ " model = generate_mesh_wire(\n", │ │ │ │ │ @@ -504,25 +504,25 @@ │ │ │ │ │ "\n", │ │ │ │ │ "gmsh.finalize()\n", │ │ │ │ │ "MPI.COMM_WORLD.barrier()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0bca1b3e", │ │ │ │ │ + "id": "a76d3373", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We visualize the mesh and subdomains with\n", │ │ │ │ │ "[PyVista](https://docs.pyvista.org/)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "cd2f7a56", │ │ │ │ │ + "id": "cd454a9d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "out_folder = Path(\"output_pml\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)\n", │ │ │ │ │ "tdim = mesh_data.mesh.topology.dim\n", │ │ │ │ │ "if have_pyvista:\n", │ │ │ │ │ @@ -540,15 +540,15 @@ │ │ │ │ │ " plotter.show(interactive=True)\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " figure = plotter.screenshot(out_folder / \"wire_mesh_pml.png\", window_size=[800, 800])" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "4c780860", │ │ │ │ │ + "id": "2530f744", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We observe five different subdomains: one for the gold wire\n", │ │ │ │ │ "(`au_tag`), one for the background medium (`bkg_tag`), one for the PML\n", │ │ │ │ │ "corners (`pml_tag`), one for the PML rectangles along $x$ (`pml_tag +\n", │ │ │ │ │ "1`), and one for the PML rectangles along $y$ (`pml_tag + 2`). These\n", │ │ │ │ │ "different PML regions have different coordinate transformation, as\n", │ │ │ │ │ @@ -567,60 +567,60 @@ │ │ │ │ │ "\n", │ │ │ │ │ "Now we define some other problem specific parameters:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5c191380", │ │ │ │ │ + "id": "e2f4cb29", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "wl0 = 0.4 # Wavelength of the background field\n", │ │ │ │ │ "n_bkg = 1 # Background refractive index\n", │ │ │ │ │ "eps_bkg = n_bkg**2 # Background relative permittivity\n", │ │ │ │ │ "k0 = 2 * np.pi / wl0 # Wavevector of the background field\n", │ │ │ │ │ "theta = 0 # Angle of incidence of the background field" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "717c4a37", │ │ │ │ │ + "id": "a5051101", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We use a degree 3\n", │ │ │ │ │ "[Nedelec (first kind)](https://defelement.org/elements/nedelec1.html)\n", │ │ │ │ │ "element to represent the electric field:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1340c1c5", │ │ │ │ │ + "id": "9efacff5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "degree = 3\n", │ │ │ │ │ "curl_el = element(\"N1curl\", mesh_data.mesh.basix_cell(), degree, dtype=default_real_type)\n", │ │ │ │ │ "V = fem.functionspace(mesh_data.mesh, curl_el)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "44264cec", │ │ │ │ │ + "id": "af4008c8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we interpolate $\\mathbf{E}_b$ into the function space $V$,\n", │ │ │ │ │ "define our trial and test function, and the integration domains:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "45993a4c", │ │ │ │ │ + "id": "793d495f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "Eb = fem.Function(V)\n", │ │ │ │ │ "f = partial(background_field, theta, n_bkg, k0)\n", │ │ │ │ │ "Eb.interpolate(f)\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -638,78 +638,78 @@ │ │ │ │ │ "dPml_xy = dx(pml_tag)\n", │ │ │ │ │ "dPml_x = dx(pml_tag + 1)\n", │ │ │ │ │ "dPml_y = dx(pml_tag + 2)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "67d20017", │ │ │ │ │ + "id": "0ece98d7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Let's now define the relative permittivity $\\varepsilon_m$ of the gold\n", │ │ │ │ │ "wire at $400nm$ (data taken from [*Olmon et al.\n", │ │ │ │ │ "2012*](https://doi.org/10.1103/PhysRevB.86.235147) , and for a quick\n", │ │ │ │ │ "reference have a look at [refractiveindex.info](\n", │ │ │ │ │ "https://refractiveindex.info/?shelf=main&book=Au&page=Olmon-sc)):" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "0de229bb", │ │ │ │ │ + "id": "fce0edd9", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Definition of relative permittivity for Au @400nm\n", │ │ │ │ │ "eps_au = -1.0782 + 1j * 5.8089" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "93323534", │ │ │ │ │ + "id": "addee600", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We can now define a space function for the permittivity $\\varepsilon$\n", │ │ │ │ │ "that takes the value $\\varepsilon_m$ for cells inside the wire, while\n", │ │ │ │ │ "it takes the value of the background permittivity $\\varepsilon_b$ in\n", │ │ │ │ │ "the background region:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "18bc214f", │ │ │ │ │ + "id": "1394547a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "D = fem.functionspace(mesh_data.mesh, (\"DG\", 0))\n", │ │ │ │ │ "eps = fem.Function(D)\n", │ │ │ │ │ "au_cells = mesh_data.cell_tags.find(au_tag)\n", │ │ │ │ │ "bkg_cells = mesh_data.cell_tags.find(bkg_tag)\n", │ │ │ │ │ "eps.x.array[au_cells] = np.full_like(au_cells, eps_au, dtype=eps.x.array.dtype)\n", │ │ │ │ │ "eps.x.array[bkg_cells] = np.full_like(bkg_cells, eps_bkg, dtype=eps.x.array.dtype)\n", │ │ │ │ │ "eps.x.scatter_forward()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ce89c1a0", │ │ │ │ │ + "id": "c32ad4cf", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we need to define our weak form in DOLFINx. Let's write the PML\n", │ │ │ │ │ "weak form first. As a first step, we can define our new complex\n", │ │ │ │ │ "coordinates as:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "13931f53", │ │ │ │ │ + "id": "4ca4fe8b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "x = ufl.SpatialCoordinate(mesh_data.mesh)\n", │ │ │ │ │ "alpha = 1\n", │ │ │ │ │ "\n", │ │ │ │ │ "# PML corners\n", │ │ │ │ │ @@ -722,15 +722,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "# PML rectangles along y\n", │ │ │ │ │ "y_pml = ufl.as_vector((x[0], pml_coordinates(x[1], alpha, k0, l_dom, l_pml)))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0c585892", │ │ │ │ │ + "id": "b4a1757a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We can then express this coordinate systems as a material\n", │ │ │ │ │ "transformation within the PML region. In other words, the PML region\n", │ │ │ │ │ "can be interpreted as a material having, in general, anisotropic,\n", │ │ │ │ │ "inhomogeneous and complex permittivity\n", │ │ │ │ │ "$\\boldsymbol{\\varepsilon}_{pml}$ and permeability\n", │ │ │ │ │ @@ -783,15 +783,15 @@ │ │ │ │ │ "$\\boldsymbol{\\varepsilon}_{pml}$ and $\\boldsymbol{\\mu}_{pml}$. The\n", │ │ │ │ │ "here below function named `create_eps_mu()` serves this purpose:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "bb72ec5f", │ │ │ │ │ + "id": "f99319b2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "\n", │ │ │ │ │ "def create_eps_mu(\n", │ │ │ │ │ " pml: ufl.tensors.ListTensor,\n", │ │ │ │ │ @@ -812,15 +812,15 @@ │ │ │ │ │ "eps_x, mu_x = create_eps_mu(x_pml, eps_bkg, 1)\n", │ │ │ │ │ "eps_y, mu_y = create_eps_mu(y_pml, eps_bkg, 1)\n", │ │ │ │ │ "eps_xy, mu_xy = create_eps_mu(xy_pml, eps_bkg, 1)\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f80620f6", │ │ │ │ │ + "id": "9bb43ab8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The final weak form in the PML region is:\n", │ │ │ │ │ "\n", │ │ │ │ │ "$$\n", │ │ │ │ │ "\\int_{\\Omega_{pml}}\\left[\\boldsymbol{\\mu}^{-1}_{pml} \\nabla \\times\n", │ │ │ │ │ "\\mathbf{E} \\right]\\cdot \\nabla \\times \\bar{\\mathbf{v}}-k_{0}^{2}\n", │ │ │ │ │ @@ -841,15 +841,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "Let's solve this equation in DOLFINx:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "41ae6491", │ │ │ │ │ + "id": "060c54e6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Definition of the weak form\n", │ │ │ │ │ "F = (\n", │ │ │ │ │ " -ufl.inner(curl_2d(Es), curl_2d(v)) * dDom\n", │ │ │ │ │ " + eps * (k0**2) * ufl.inner(Es, v) * dDom\n", │ │ │ │ │ @@ -891,52 +891,52 @@ │ │ │ │ │ ")\n", │ │ │ │ │ "Esh = problem.solve()\n", │ │ │ │ │ "assert isinstance(Esh, fem.Function)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "203639fb", │ │ │ │ │ + "id": "ca8c45a5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Let's now save the solution in a `bp`-file. In order to do so, we need\n", │ │ │ │ │ "to interpolate our solution discretized with Nedelec elements into a\n", │ │ │ │ │ "compatible discontinuous Lagrange space." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5088604b", │ │ │ │ │ + "id": "cfaf805b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "gdim = mesh_data.mesh.geometry.dim\n", │ │ │ │ │ "V_dg = fem.functionspace(mesh_data.mesh, (\"DG\", degree, (gdim,)))\n", │ │ │ │ │ "Esh_dg = fem.Function(V_dg)\n", │ │ │ │ │ "Esh_dg.interpolate(Esh)\n", │ │ │ │ │ "\n", │ │ │ │ │ "with VTXWriter(mesh_data.mesh.comm, out_folder / \"Esh.bp\", Esh_dg) as vtx:\n", │ │ │ │ │ " vtx.write(0.0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2be3642c", │ │ │ │ │ + "id": "01b59e70", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For more information about saving and visualizing vector fields\n", │ │ │ │ │ "discretized with Nedelec elements, check [this](./demo_interpolation-io)\n", │ │ │ │ │ "DOLFINx demo." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e9a6db17", │ │ │ │ │ + "id": "dfcfd6e3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if have_pyvista:\n", │ │ │ │ │ " V_cells, V_types, V_x = plot.vtk_mesh(V_dg)\n", │ │ │ │ │ " V_grid = pyvista.UnstructuredGrid(V_cells, V_types, V_x)\n", │ │ │ │ │ " Esh_values = np.zeros((V_x.shape[0], 3), dtype=np.float64)\n", │ │ │ │ │ @@ -953,25 +953,25 @@ │ │ │ │ │ " plotter.show()\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " plotter.screenshot(out_folder / \"Esh.png\", window_size=[800, 800])" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0da3273c", │ │ │ │ │ + "id": "a5b8d83f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next we can calculate the total electric field\n", │ │ │ │ │ "$\\mathbf{E}=\\mathbf{E}_s+\\mathbf{E}_b$ and save it:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "71f4ff7c", │ │ │ │ │ + "id": "5a277172", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "E = fem.Function(V)\n", │ │ │ │ │ "E.x.array[:] = Eb.x.array[:] + Esh.x.array[:]\n", │ │ │ │ │ "\n", │ │ │ │ │ "E_dg = fem.Function(V_dg)\n", │ │ │ │ │ @@ -979,53 +979,53 @@ │ │ │ │ │ "\n", │ │ │ │ │ "with VTXWriter(mesh_data.mesh.comm, out_folder / \"E.bp\", E_dg) as vtx:\n", │ │ │ │ │ " vtx.write(0.0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fd8ea43e", │ │ │ │ │ + "id": "c77a2576", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Post-processing\n", │ │ │ │ │ "\n", │ │ │ │ │ "To validate the formulation we calculate the absorption, scattering\n", │ │ │ │ │ "and extinction efficiencies, which are quantities that define how much\n", │ │ │ │ │ "light is absorbed and scattered by the wire. First of all, we\n", │ │ │ │ │ "calculate the analytical efficiencies with the\n", │ │ │ │ │ "`calculate_analytical_efficiencies` function" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ec6f31d0", │ │ │ │ │ + "id": "cb653986", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "q_abs_analyt, q_sca_analyt, q_ext_analyt = calculate_analytical_efficiencies(\n", │ │ │ │ │ " eps_au, n_bkg, wl0, radius_wire\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5da357ce", │ │ │ │ │ + "id": "e6a2fff3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We calculate the numerical efficiencies in the same way as done in\n", │ │ │ │ │ "`demo_scattering_boundary_conditions.py`, with the only difference\n", │ │ │ │ │ "that now the scattering efficiency needs to be calculated over an\n", │ │ │ │ │ "inner facet, and therefore it requires a slightly different approach:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ec6ef247", │ │ │ │ │ + "id": "186cc561", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "Z0 = np.sqrt(mu_0 / epsilon_0) # Vacuum impedance\n", │ │ │ │ │ "Hsh_3d = -1j * curl_2d(Esh) / (Z0 * k0 * n_bkg) # Magnetic field H\n", │ │ │ │ │ "Esh_3d = ufl.as_vector((Esh[0], Esh[1], 0))\n", │ │ │ │ │ "E_3d = ufl.as_vector((E[0], E[1], 0))\n", │ │ │ │ │ @@ -1090,15 +1090,15 @@ │ │ │ │ │ "PETSc.Sys.Print(f\"The numerical extinction efficiency is {q_ext_fenics}\")\n", │ │ │ │ │ "PETSc.Sys.Print(f\"The error is {err_ext * 100}%\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "03cb9442", │ │ │ │ │ + "id": "60e1c98e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Check if errors are smaller than 1%\n", │ │ │ │ │ "assert err_abs < 0.01, \"Error in absorption efficiency is too large\"\n", │ │ │ │ │ "# assert err_sca < 0.01\n", │ │ │ │ │ "assert err_ext < 0.01, \"Error in extinction efficiency is too large\"" │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/9561cf6cd1a70079b986f4eb31580cbd/demo_poisson_matrix_free.ipynb.gz │ │ │ ├── demo_poisson_matrix_free.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666667% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': 'ff1de7be'}, 1: {'id': '7286452b'}, 2: {'id': 'a460ee29'}, 3: {'id': " │ │ │ │ │┄ "'b399f0d3'}, 4: {'id': '28606e89'}, 5: {'id': '19a56cd7'}, 6: {'id': '3e8c306b'}, 7: " │ │ │ │ │┄ "{'id': '646dd2ec'}, 8: {'id': '571334c3'}, 9: {'id': '3cea18b2'}, 10: {'id': " │ │ │ │ │┄ "'abf95e97'}, 11: {'id': '0ef89127'}, 12: {'id': '58b35de0'}, 13: {'id': 'eae3a3f4'}, " │ │ │ │ │┄ "14: {'id': '0915b503'}, 15: {'id': '67c9d78d'}, 16: {'id': 'e88a6549'}, 17: {'id': " │ │ │ │ │┄ "'2d2c6a4d'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "adca5ebb", │ │ │ │ │ + "id": "ff1de7be", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Matrix-free conjugate gradient solver for the Poisson equation\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_poisson_matrix_free.py>`\n", │ │ │ │ │ @@ -71,57 +71,57 @@ │ │ │ │ │ "\n", │ │ │ │ │ "The modules that will be used are imported:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "34f1d5bd", │ │ │ │ │ + "id": "7286452b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "\n", │ │ │ │ │ "import numpy as np\n", │ │ │ │ │ "\n", │ │ │ │ │ "import dolfinx\n", │ │ │ │ │ "import ufl\n", │ │ │ │ │ "from dolfinx import fem, la\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "98d8c9da", │ │ │ │ │ + "id": "a460ee29", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We begin by using {py:func}`create_rectangle\n", │ │ │ │ │ "` to create a rectangular\n", │ │ │ │ │ "{py:class}`Mesh ` of the domain, and creating a\n", │ │ │ │ │ "finite element {py:class}`FunctionSpace `\n", │ │ │ │ │ "on the mesh." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "05a38b3a", │ │ │ │ │ + "id": "b399f0d3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dtype = dolfinx.default_scalar_type\n", │ │ │ │ │ "real_type = np.real(dtype(0.0)).dtype\n", │ │ │ │ │ "comm = MPI.COMM_WORLD\n", │ │ │ │ │ "mesh = dolfinx.mesh.create_rectangle(comm, [[0.0, 0.0], [1.0, 1.0]], (10, 10), dtype=real_type)\n", │ │ │ │ │ "degree = 2\n", │ │ │ │ │ "V = fem.functionspace(mesh, (\"Lagrange\", degree))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "94d3e902", │ │ │ │ │ + "id": "28606e89", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The second argument to {py:class}`functionspace\n", │ │ │ │ │ "` is a tuple consisting of `(family,\n", │ │ │ │ │ "degree)`, where `family` is the finite element family, and `degree`\n", │ │ │ │ │ "specifies the polynomial degree. In this case `V` consists of\n", │ │ │ │ │ "third-order, continuous Lagrange finite element functions.\n", │ │ │ │ │ @@ -133,94 +133,94 @@ │ │ │ │ │ "facets on the boundary using {py:func}`exterior_facet_indices\n", │ │ │ │ │ "`." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5af8a90b", │ │ │ │ │ + "id": "19a56cd7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "tdim = mesh.topology.dim\n", │ │ │ │ │ "mesh.topology.create_connectivity(tdim - 1, tdim)\n", │ │ │ │ │ "facets = dolfinx.mesh.exterior_facet_indices(mesh.topology)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1c8d6762", │ │ │ │ │ + "id": "3e8c306b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We now find the degrees of freedom that are associated with the boundary\n", │ │ │ │ │ "facets using\n", │ │ │ │ │ "{py:func}`locate_dofs_topological `" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5975725b", │ │ │ │ │ + "id": "646dd2ec", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dofs = fem.locate_dofs_topological(V=V, entity_dim=tdim - 1, entities=facets)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "150cdfae", │ │ │ │ │ + "id": "571334c3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and use {py:func}`dirichletbc ` to define the\n", │ │ │ │ │ "essential boundary condition. On the boundary we prescribe the\n", │ │ │ │ │ "{py:class}`Function ` `uD`, which we create by\n", │ │ │ │ │ "interpolating the expression $u_{\\rm D}$ in the finite element space\n", │ │ │ │ │ "$V$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "9d1896e6", │ │ │ │ │ + "id": "3cea18b2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "uD = fem.Function(V, dtype=dtype)\n", │ │ │ │ │ "uD.interpolate(lambda x: 1 + x[0] ** 2 + 2 * x[1] ** 2)\n", │ │ │ │ │ "bc = fem.dirichletbc(value=uD, dofs=dofs)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b9adb059", │ │ │ │ │ + "id": "abf95e97", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we express the variational problem using UFL." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ac8f97c6", │ │ │ │ │ + "id": "0ef89127", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "x = ufl.SpatialCoordinate(mesh)\n", │ │ │ │ │ "u = ufl.TrialFunction(V)\n", │ │ │ │ │ "v = ufl.TestFunction(V)\n", │ │ │ │ │ "f = fem.Constant(mesh, dtype(-6.0))\n", │ │ │ │ │ "a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx\n", │ │ │ │ │ "L = ufl.inner(f, v) * ufl.dx\n", │ │ │ │ │ "L_fem = fem.form(L, dtype=dtype)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "77d701de", │ │ │ │ │ + "id": "58b35de0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For the matrix-free solvers we also define a second linear form `M` as\n", │ │ │ │ │ "the {py:class}`action ` of the bilinear form $a$ on an\n", │ │ │ │ │ "arbitrary {py:class}`Function ` `ui`. This linear\n", │ │ │ │ │ "form is defined as\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -228,87 +228,87 @@ │ │ │ │ │ "M(v) = a(u_i, v) \\quad \\text{for} \\; \\ u_i \\in V.\n", │ │ │ │ │ "$$" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "074e4e24", │ │ │ │ │ + "id": "eae3a3f4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ui = fem.Function(V, dtype=dtype)\n", │ │ │ │ │ "M = ufl.action(a, ui)\n", │ │ │ │ │ "M_fem = fem.form(M, dtype=dtype)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9fd0c719", │ │ │ │ │ + "id": "0915b503", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "### Matrix-free conjugate gradient solver\n", │ │ │ │ │ "\n", │ │ │ │ │ "The right hand side vector $b - A x_{\\rm bc}$ is the assembly of the\n", │ │ │ │ │ "linear form $L$ where the essential Dirichlet boundary conditions are\n", │ │ │ │ │ "implemented using lifting. Since we want to avoid assembling the matrix\n", │ │ │ │ │ "`A`, we compute the necessary matrix-vector product using the linear form\n", │ │ │ │ │ "`M` explicitly." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4f069f54", │ │ │ │ │ + "id": "67c9d78d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Apply lifting: b <- b - A * x_bc\n", │ │ │ │ │ "b = fem.assemble_vector(L_fem)\n", │ │ │ │ │ "ui.x.array[:] = 0.0\n", │ │ │ │ │ "bc.set(ui.x.array, alpha=-1.0)\n", │ │ │ │ │ "fem.assemble_vector(b.array, M_fem)\n", │ │ │ │ │ "b.scatter_reverse(la.InsertMode.add)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "abbd8153", │ │ │ │ │ + "id": "e88a6549", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Set BC dofs to zero on right hand side" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "55bd30c9", │ │ │ │ │ + "id": "2d2c6a4d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc.set(b.array, alpha=0.0)\n", │ │ │ │ │ "b.scatter_forward()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "bc3637df", │ │ │ │ │ + "id": "82ad051b", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "To implement the matrix-free CG solver using *DOLFINx* vectors, we\n", │ │ │ │ │ "define the function `action_A` to compute the matrix-vector product $y\n", │ │ │ │ │ "= A x$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c47615d5", │ │ │ │ │ + "id": "e4327daa", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def action_A(x, y):\n", │ │ │ │ │ " # Set coefficient vector of the linear form M and ensure it is\n", │ │ │ │ │ @@ -323,15 +323,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ " # Set BC dofs to zero\n", │ │ │ │ │ " bc.set(y.array, alpha=0.0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "86c3e55b", │ │ │ │ │ + "id": "7572ce1c", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "### Basic conjugate gradient solver\n", │ │ │ │ │ "\n", │ │ │ │ │ "Solves the problem `A x = b`, using the function `action_A` as the\n", │ │ │ │ │ @@ -339,15 +339,15 @@ │ │ │ │ │ "right hand side vector. `comm` is the MPI Communicator, `max_iter` is\n", │ │ │ │ │ "the maximum number of iterations, `rtol` is the relative tolerance." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "41a847f0", │ │ │ │ │ + "id": "6a77a79a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def cg(comm, action_A, x: la.Vector, b: la.Vector, max_iter: int = 200, rtol: float = 1e-6):\n", │ │ │ │ │ " rtol2 = rtol**2\n", │ │ │ │ │ "\n", │ │ │ │ │ " nr = b.index_map.size_local\n", │ │ │ │ │ @@ -385,66 +385,66 @@ │ │ │ │ │ " p.array[:] = beta * p.array + r\n", │ │ │ │ │ "\n", │ │ │ │ │ " raise RuntimeError(f\"Solver exceeded max iterations ({max_iter}).\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3bf2fb04", │ │ │ │ │ + "id": "9ca21b6b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "This matrix-free solver is now used to compute the finite element\n", │ │ │ │ │ "solution. The finite element solution's approximation error as\n", │ │ │ │ │ "compared with the exact solution is measured in the $L_2$-norm." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e3d1dd5a", │ │ │ │ │ + "id": "65dc0067", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "rtol = 1e-6\n", │ │ │ │ │ "u = fem.Function(V, dtype=dtype)\n", │ │ │ │ │ "iter_cg1 = cg(mesh.comm, action_A, u.x, b, max_iter=200, rtol=rtol)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c2a8db1b", │ │ │ │ │ + "id": "63ff5e2f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Set BC values in the solution vector" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "475e208c", │ │ │ │ │ + "id": "022a6299", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc.set(u.x.array, alpha=1.0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "497f6897", │ │ │ │ │ + "id": "f9408971", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Print CG iteration number and error" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a2f6b367", │ │ │ │ │ + "id": "1e284da1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def L2Norm(u):\n", │ │ │ │ │ " val = fem.assemble_scalar(fem.form(ufl.inner(u, u) * ufl.dx, dtype=dtype))\n", │ │ │ │ │ " return np.sqrt(comm.allreduce(val, op=MPI.SUM))\n", │ │ │ │ │ "\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/9b362df2c2031d4138a5021a53979414/demo_cahn-hilliard.ipynb.gz │ │ │ ├── demo_cahn-hilliard.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9870631720430108% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '5dfc178f'}, 1: {'id': '6d31e994'}, 2: {'id': 'a470edc0'}, 3: {'id': " │ │ │ │ │┄ "'6ca99b0a'}, 4: {'id': '50fda1e9'}, 5: {'id': 'baa06397'}, 6: {'id': '7324fea4'}, 7: " │ │ │ │ │┄ "{'id': 'fafb813f'}, 8: {'id': '003584b3'}, 9: {'id': '6ec10486'}, 10: {'id': " │ │ │ │ │┄ "'a47415ce'}, 11: {'id': '7d14bec5'}, 12: {'id': 'ab5e4002'}, 13: {'id': '8bf93fd3'}, " │ │ │ │ │┄ "14: {'id': 'c3d802f1'}, 15: {'id': '8f80d03e'}, 16: {'id': '6d97a734'}, 17: {'id': " │ │ │ │ │┄ "'e19ab69e'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "17356e16", │ │ │ │ │ + "id": "5dfc178f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Cahn-Hilliard equation\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_cahn-hilliard.py>`\n", │ │ │ │ │ @@ -114,15 +114,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "## Implementation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "652eabeb", │ │ │ │ │ + "id": "6d31e994", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "import os\n", │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ @@ -150,77 +150,77 @@ │ │ │ │ │ "\n", │ │ │ │ │ "# Save all logging to file\n", │ │ │ │ │ "log.set_output_file(\"log.txt\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c1fcd658", │ │ │ │ │ + "id": "a470edc0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, various model parameters are defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "df209071", │ │ │ │ │ + "id": "6ca99b0a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "lmbda = 1.0e-02 # surface parameter\n", │ │ │ │ │ "dt = 5.0e-06 # time step\n", │ │ │ │ │ "theta = 0.5 # time stepping family, e.g. theta=1 -> backward Euler, theta=0.5 -> Crank-Nicholson\n", │ │ │ │ │ "t = 0.0 # Current time" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "40b1e155", │ │ │ │ │ + "id": "50fda1e9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "A unit square mesh with 96 cells edges in each direction is created,\n", │ │ │ │ │ "and on this mesh a\n", │ │ │ │ │ "{py:class}`FunctionSpace ` `ME` is built\n", │ │ │ │ │ "using a pair of linear Lagrange elements." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c8474361", │ │ │ │ │ + "id": "baa06397", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = create_unit_square(MPI.COMM_WORLD, 96, 96, CellType.triangle)\n", │ │ │ │ │ "P1 = element(\"Lagrange\", msh.basix_cell(), 1, dtype=default_real_type)\n", │ │ │ │ │ "ME = functionspace(msh, mixed_element([P1, P1]))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "359dab3b", │ │ │ │ │ + "id": "7324fea4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Trial and test functions of the space `ME` are now defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5af5537d", │ │ │ │ │ + "id": "fafb813f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "q, v = ufl.TestFunctions(ME)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8e004d2a", │ │ │ │ │ + "id": "003584b3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "```{index} split functions\n", │ │ │ │ │ "```\n", │ │ │ │ │ "\n", │ │ │ │ │ "For the test functions, {py:func}`TestFunctions` (note the 's' at the end) is used to\n", │ │ │ │ │ @@ -229,29 +229,29 @@ │ │ │ │ │ "are defined to represent $u = (c_{n+1}, \\mu_{n+1})$ and $u0 = (c_{n},\n", │ │ │ │ │ "\\mu_{n})$, and these are then split into sub-functions:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fe1604dc", │ │ │ │ │ + "id": "6ec10486", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "u = Function(ME) # current solution\n", │ │ │ │ │ "u0 = Function(ME) # solution from previous converged step\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Split mixed functions\n", │ │ │ │ │ "c, mu = ufl.split(u)\n", │ │ │ │ │ "c0, mu0 = ufl.split(u0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0f75bb89", │ │ │ │ │ + "id": "a47415ce", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The line `c, mu = split(u)` permits direct access to the\n", │ │ │ │ │ "components of a mixed function. Note that `c` and `mu` are references\n", │ │ │ │ │ "for components of `u`, and not copies.\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{index} single: interpolating functions; (in Cahn-Hilliard demo)\n", │ │ │ │ │ @@ -259,28 +259,28 @@ │ │ │ │ │ "\n", │ │ │ │ │ "The initial conditions are interpolated into a finite element space:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "aeae6d20", │ │ │ │ │ + "id": "7d14bec5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "# Interpolate initial condition\n", │ │ │ │ │ "rng = np.random.default_rng(42)\n", │ │ │ │ │ "u.sub(0).interpolate(lambda x: 0.63 + 0.02 * (0.5 - rng.random(x.shape[1])))\n", │ │ │ │ │ "u.x.scatter_forward()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0cee75c9", │ │ │ │ │ + "id": "ab5e4002", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The first line creates an object of type `InitialConditions`. The\n", │ │ │ │ │ "following two lines make `u` and `u0` interpolants of `u_init` (since\n", │ │ │ │ │ "`u` and `u0` are finite element functions, they may not be able to\n", │ │ │ │ │ "represent a given function exactly, but the function can be\n", │ │ │ │ │ "approximated by interpolating it in a finite element space).\n", │ │ │ │ │ @@ -291,59 +291,59 @@ │ │ │ │ │ "The chemical potential $df/dc$ is computed using UFL automatic\n", │ │ │ │ │ "differentiation:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "bc15d4fe", │ │ │ │ │ + "id": "8bf93fd3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Compute the chemical potential df/dc\n", │ │ │ │ │ "c = ufl.variable(c)\n", │ │ │ │ │ "f = 100 * c**2 * (1 - c) ** 2\n", │ │ │ │ │ "dfdc = ufl.diff(f, c)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "485a1654", │ │ │ │ │ + "id": "c3d802f1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The first line declares that `c` is a variable that some function can\n", │ │ │ │ │ "be differentiated with respect to. The next line is the function $f$\n", │ │ │ │ │ "defined in the problem statement, and the third line performs the\n", │ │ │ │ │ "differentiation of `f` with respect to the variable `c`.\n", │ │ │ │ │ "\n", │ │ │ │ │ "It is convenient to introduce an expression for $\\mu_{n+\\theta}$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "78084f09", │ │ │ │ │ + "id": "8f80d03e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "mu_mid = (1.0 - theta) * mu0 + theta * mu # mu_(n+theta)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5671c4cc", │ │ │ │ │ + "id": "6d97a734", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "which is then used in the definition of the variational forms:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4798e258", │ │ │ │ │ + "id": "e19ab69e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Weak statement of the equations\n", │ │ │ │ │ "F0 = (\n", │ │ │ │ │ " ufl.inner(c, q) * ufl.dx\n", │ │ │ │ │ " - ufl.inner(c0, q) * ufl.dx\n", │ │ │ │ │ @@ -355,15 +355,15 @@ │ │ │ │ │ " - lmbda * ufl.inner(ufl.grad(c), ufl.grad(v)) * ufl.dx\n", │ │ │ │ │ ")\n", │ │ │ │ │ "F = F0 + F1" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "86a57096", │ │ │ │ │ + "id": "5b91fb80", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "This is a statement of the time-discrete equations presented as part\n", │ │ │ │ │ "of the problem statement, using UFL syntax.\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{index} single: Newton solver; (in Cahn-Hilliard demo)\n", │ │ │ │ │ "```\n", │ │ │ │ │ @@ -378,15 +378,15 @@ │ │ │ │ │ "[`SNES convegence tests`](https://petsc.org/release/manual/snes/#convergence-tests)\n", │ │ │ │ │ "for further details." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4ee02651", │ │ │ │ │ + "id": "2bfbc84c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "use_superlu = PETSc.IntType == np.int64 # or PETSc.ScalarType == np.complex64\n", │ │ │ │ │ "sys = PETSc.Sys() # type: ignore\n", │ │ │ │ │ "if sys.hasExternalPackage(\"mumps\") and not use_superlu:\n", │ │ │ │ │ " linear_solver = \"mumps\"\n", │ │ │ │ │ @@ -408,65 +408,65 @@ │ │ │ │ │ "problem = NonlinearProblem(\n", │ │ │ │ │ " F, u, petsc_options_prefix=\"demo_cahn-hilliard_\", petsc_options=petsc_options\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "a015b2a1", │ │ │ │ │ + "id": "b912440b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We prepare output files and pyvista for time-dependent visualization:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5775f05d", │ │ │ │ │ + "id": "6daf2662", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "out_folder = Path(\"demo_ch\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)\n", │ │ │ │ │ "file = XDMFFile(MPI.COMM_WORLD, out_folder / \"output.xdmf\", \"w\") # Output file\n", │ │ │ │ │ "file.write_mesh(msh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "a8a51f05", │ │ │ │ │ + "id": "3e45b30d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Get the sub-space for c and the corresponding dofs in the mixed space\n", │ │ │ │ │ "vector. This is used for visualization on the collapsed subspace with\n", │ │ │ │ │ "pyvista." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d75dc631", │ │ │ │ │ + "id": "d84deaa8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "V0, dofs = ME.sub(0).collapse()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f2800147", │ │ │ │ │ + "id": "b08f905b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Prepare viewer for plotting the solution during the computation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "21a73303", │ │ │ │ │ + "id": "96f89585", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if have_pyvista:\n", │ │ │ │ │ " # Create a VTK 'mesh' with 'nodes' at the function dofs\n", │ │ │ │ │ @@ -482,38 +482,38 @@ │ │ │ │ │ " p.view_xy(negative=True)\n", │ │ │ │ │ " p.add_text(f\"time: {t}\", font_size=12, name=\"timelabel\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "01ec4cd5", │ │ │ │ │ + "id": "b6e0f558", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Reduce run time if on test (CI) server\n", │ │ │ │ │ "if \"CI\" in os.environ.keys() or \"GITHUB_ACTIONS\" in os.environ.keys():\n", │ │ │ │ │ " T = 3 * dt\n", │ │ │ │ │ "else:\n", │ │ │ │ │ " T = 50 * dt" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "4ff78eed", │ │ │ │ │ + "id": "1be018bf", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The solver is advanced in time from $t_{n}$ to\n", │ │ │ │ │ "$t_{n+1}$ until a terminal time $T$ is reached" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d1618979", │ │ │ │ │ + "id": "c9e1e2ca", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "c = u.sub(0)\n", │ │ │ │ │ "u0.x.array[:] = u.x.array\n", │ │ │ │ │ "step = 0\n", │ │ │ │ │ "while t < T:\n", │ │ │ │ │ @@ -538,24 +538,24 @@ │ │ │ │ │ " p.app.processEvents()\n", │ │ │ │ │ "\n", │ │ │ │ │ "file.close()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "eca15d0d", │ │ │ │ │ + "id": "706fb225", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Update plot" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d0f597fc", │ │ │ │ │ + "id": "a3c2c313", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if have_pyvista:\n", │ │ │ │ │ " grid.point_data[\"c\"] = u.x.array[dofs].real\n", │ │ │ │ │ " screenshot = out_folder / \"ch.png\" if pv.OFF_SCREEN else None\n", │ │ │ │ │ " pv.plot(grid, show_edges=True, screenshot=screenshot)" │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/9ed4657d08dda04de30e6463e2f58d75/demo_mixed-poisson.ipynb.gz │ │ │ ├── demo_mixed-poisson.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666667% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': 'dd1ac30f'}, 1: {'id': 'bf8faef7'}, 2: {'id': '1b850a43'}, 3: {'id': " │ │ │ │ │┄ "'264230c3'}, 4: {'id': '0f1fd6ff'}, 5: {'id': '02c568ee'}, 6: {'id': '9f331b0e'}, 7: " │ │ │ │ │┄ "{'id': '704a31ea'}, 8: {'id': 'e0635767'}, 9: {'id': 'a26ce800'}, 10: {'id': " │ │ │ │ │┄ "'be395ccc'}, 11: {'id': '9608c6e0'}, 12: {'id': 'e6e2a40f'}, 13: {'id': 'a09c8218'}, " │ │ │ │ │┄ "14: {'id': '2d2b3de8'}, 15: {'id': '6c363e01'}, 16: {'id': '386f4094'}, 17: {'id': " │ │ │ │ │┄ "'f99e4ce2'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "420fa7a9", │ │ │ │ │ + "id": "dd1ac30f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Mixed formulation of the Poisson equation with a block-preconditioner/solver # noqa\n", │ │ │ │ │ "\n", │ │ │ │ │ "This demo illustrates how to solve the Poisson equation using a mixed\n", │ │ │ │ │ "(two-field) formulation and a block-preconditioned iterative solver.\n", │ │ │ │ │ "In particular, it illustrates how to\n", │ │ │ │ │ @@ -83,27 +83,27 @@ │ │ │ │ │ "iterative method with a block-diagonal preconditioner that is based on\n", │ │ │ │ │ "the Riesz map, see for example this\n", │ │ │ │ │ "[paper](https://doi.org/10.1002/(SICI)1099-1506(199601/02)3:1%3C1::AID-NLA67%3E3.0.CO;2-E)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c672074f", │ │ │ │ │ + "id": "bf8faef7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "## Implementation\n", │ │ │ │ │ "\n", │ │ │ │ │ "Import the required modules:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "503a73d6", │ │ │ │ │ + "id": "1b850a43", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py import PETSc\n", │ │ │ │ │ "\n", │ │ │ │ │ "import numpy as np\n", │ │ │ │ │ @@ -119,38 +119,38 @@ │ │ │ │ │ "# types\n", │ │ │ │ │ "dtype = dolfinx.default_scalar_type\n", │ │ │ │ │ "xdtype = dolfinx.default_real_type" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c2c9ef1f", │ │ │ │ │ + "id": "264230c3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a two-dimensional mesh. The iterative solver constructed\n", │ │ │ │ │ "later requires special construction that is specific to two\n", │ │ │ │ │ "dimensions. Application in three-dimensions would require a number of\n", │ │ │ │ │ "changes to the linear solver." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "0f47f6bf", │ │ │ │ │ + "id": "0f1fd6ff", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 0 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = create_unit_square(MPI.COMM_WORLD, 96, 96, CellType.triangle, dtype=xdtype)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3c7ed42f", │ │ │ │ │ + "id": "02c568ee", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "Here we construct compatible function spaces for the mixed Poisson\n", │ │ │ │ │ "problem. The `V` Raviart-Thomas ($\\mathbb{RT}$) space is a\n", │ │ │ │ │ "vector-valued $H({\\rm div})$ conforming space. The `W` space is a\n", │ │ │ │ │ "space of discontinuous Lagrange function of degree `k`.\n", │ │ │ │ │ @@ -161,81 +161,81 @@ │ │ │ │ │ "In the lowest-order case $k=1$. It can be increased, by the\n", │ │ │ │ │ "convergence of the iterative solver will degrade." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "402435cd", │ │ │ │ │ + "id": "9f331b0e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "k = 1\n", │ │ │ │ │ "V = fem.functionspace(msh, element(\"RT\", msh.basix_cell(), k, dtype=xdtype))\n", │ │ │ │ │ "W = fem.functionspace(msh, element(\"Discontinuous Lagrange\", msh.basix_cell(), k - 1, dtype=xdtype))\n", │ │ │ │ │ "Q = ufl.MixedFunctionSpace(V, W)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "4260a9c5", │ │ │ │ │ + "id": "704a31ea", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Trial functions for $\\sigma$ and $u$ are declared on the space $V$ and\n", │ │ │ │ │ "$W$, with corresponding test functions $\\tau$ and $v$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d17b69b6", │ │ │ │ │ + "id": "e0635767", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "sigma, u = ufl.TrialFunctions(Q)\n", │ │ │ │ │ "tau, v = ufl.TestFunctions(Q)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "365320a3", │ │ │ │ │ + "id": "a26ce800", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The source function is set to be $f = 10\\exp(-((x_{0} - 0.5)^2 +\n", │ │ │ │ │ "(x_{1} - 0.5)^2) / 0.02)$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2af54908", │ │ │ │ │ + "id": "be395ccc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "x = ufl.SpatialCoordinate(msh)\n", │ │ │ │ │ "f = 10 * ufl.exp(-((x[0] - 0.5) * (x[0] - 0.5) + (x[1] - 0.5) * (x[1] - 0.5)) / 0.02)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "271de4a7", │ │ │ │ │ + "id": "9608c6e0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We now declare the blocked bilinear and linear forms. We use\n", │ │ │ │ │ "`ufl.extract_blocks` to extract the block structure of the bilinear\n", │ │ │ │ │ "and linear form. For the first block of the right-hand side, we provide\n", │ │ │ │ │ "a form that efficiently is 0. We do this to preserve knowledge of the\n", │ │ │ │ │ "test space in the block. *Note that the defined `L` corresponds to\n", │ │ │ │ │ "$u_{0} = 0$ on $\\Gamma_{D}$.*" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "24e99ee6", │ │ │ │ │ + "id": "e6e2a40f", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dx = ufl.Measure(\"dx\", msh)\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -243,15 +243,15 @@ │ │ │ │ │ " ufl.inner(sigma, tau) * dx + ufl.inner(u, ufl.div(tau)) * dx + ufl.inner(ufl.div(sigma), v) * dx\n", │ │ │ │ │ ")\n", │ │ │ │ │ "L = [ufl.ZeroBaseForm((tau,)), -ufl.inner(f, v) * dx]\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1fa43baa", │ │ │ │ │ + "id": "a09c8218", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "In preparation for Dirichlet boundary conditions, we use the function\n", │ │ │ │ │ "{py:func}`locate_entities_boundary\n", │ │ │ │ │ "` to locate mesh entities\n", │ │ │ │ │ "(facets) with which degree-of-freedoms to be constrained are\n", │ │ │ │ │ "associated with, and then use {py:func}`locate_dofs_topological\n", │ │ │ │ │ @@ -260,52 +260,52 @@ │ │ │ │ │ "degree-of-freedom in `V` on the (i) top ($x_{1} = 1$)\n", │ │ │ │ │ "and (ii) bottom ($x_{1} = 0$) of the mesh/domain." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "969a3f1e", │ │ │ │ │ + "id": "2d2b3de8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "fdim = msh.topology.dim - 1\n", │ │ │ │ │ "facets_top = mesh.locate_entities_boundary(msh, fdim, lambda x: np.isclose(x[1], 1.0))\n", │ │ │ │ │ "facets_bottom = mesh.locate_entities_boundary(msh, fdim, lambda x: np.isclose(x[1], 0.0))\n", │ │ │ │ │ "dofs_top = fem.locate_dofs_topological(V, fdim, facets_top)\n", │ │ │ │ │ "dofs_bottom = fem.locate_dofs_topological(V, fdim, facets_bottom)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "97402f70", │ │ │ │ │ + "id": "6c363e01", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now, we create Dirichlet boundary objects for the condition $\\sigma\n", │ │ │ │ │ "\\cdot n = \\sin(5 x_(0)$ on the top and bottom boundaries:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fd6e8085", │ │ │ │ │ + "id": "386f4094", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "cells_top_ = mesh.compute_incident_entities(msh.topology, facets_top, fdim, fdim + 1)\n", │ │ │ │ │ "cells_bottom = mesh.compute_incident_entities(msh.topology, facets_bottom, fdim, fdim + 1)\n", │ │ │ │ │ "g = fem.Function(V, dtype=dtype)\n", │ │ │ │ │ "g.interpolate(lambda x: np.vstack((np.zeros_like(x[0]), np.sin(5 * x[0]))), cells0=cells_top_)\n", │ │ │ │ │ "g.interpolate(lambda x: np.vstack((np.zeros_like(x[0]), -np.sin(5 * x[0]))), cells0=cells_bottom)\n", │ │ │ │ │ "bcs = [fem.dirichletbc(g, dofs_top), fem.dirichletbc(g, dofs_bottom)]" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "dd34c8b3", │ │ │ │ │ + "id": "f99e4ce2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Rather than solving the linear system $A x = b$, we will solve the\n", │ │ │ │ │ "preconditioned problem $P^{-1} A x = P^{-1} b$. Commonly $P = A$, but\n", │ │ │ │ │ "this does not lead to efficient solvers for saddle point problems.\n", │ │ │ │ │ "\n", │ │ │ │ │ "For this problem, we introduce the preconditioner\n", │ │ │ │ │ @@ -319,60 +319,60 @@ │ │ │ │ │ "\n", │ │ │ │ │ "and assemble it into the matrix `P`:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ad267963", │ │ │ │ │ + "id": "08f081c2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "a_p = ufl.extract_blocks(\n", │ │ │ │ │ " ufl.inner(sigma, tau) * dx + ufl.inner(ufl.div(sigma), ufl.div(tau)) * dx + ufl.inner(u, v) * dx\n", │ │ │ │ │ ")\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e077b6d7", │ │ │ │ │ + "id": "82ce868e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create finite element functions that will hold the $\\sigma$ and $u$\n", │ │ │ │ │ "solutions:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f0af568a", │ │ │ │ │ + "id": "f7a91daf", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "sigma, u = fem.Function(V, name=\"sigma\", dtype=dtype), fem.Function(W, name=\"u\", dtype=dtype)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2af85eed", │ │ │ │ │ + "id": "1b4e7d77", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "We now create a linear problem solver for the mixed problem.\n", │ │ │ │ │ "As we will use different preconditions for the individual blocks of\n", │ │ │ │ │ "the saddle point problem, we specify the matrix kind to be \"nest\",\n", │ │ │ │ │ "so that we can use [`fieldsplit`](https://petsc.org/release/manual/ksp/#sec-block-matrices)\n", │ │ │ │ │ "(block) type and set the 'splits' between the $\\sigma$ and $u$ fields." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b3a26cec", │ │ │ │ │ + "id": "1d658816", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "problem = fem.petsc.LinearProblem(\n", │ │ │ │ │ @@ -393,27 +393,27 @@ │ │ │ │ │ " },\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7e719a13", │ │ │ │ │ + "id": "c1780ac2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ksp = problem.solver\n", │ │ │ │ │ "ksp.setMonitor(\n", │ │ │ │ │ " lambda _, its, rnorm: PETSc.Sys.Print(f\"Iteration: {its:>4d}, residual: {rnorm:.3e}\")\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "763e4b09", │ │ │ │ │ + "id": "b9058e58", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For the $P_{11}$ block, which is the discontinuous Lagrange mass\n", │ │ │ │ │ "matrix, we let the preconditioner be the default, which is incomplete\n", │ │ │ │ │ "LU factorisation and which can solve the block exactly in one\n", │ │ │ │ │ "iteration. The $P_{00}$ requires careful handling as $H({\\rm div})$\n", │ │ │ │ │ "problems require special preconditioners to be efficient.\n", │ │ │ │ │ @@ -425,15 +425,15 @@ │ │ │ │ │ "$H({\\rm div})$ and $H({\\rm curl})$ spaces are effectively the same in\n", │ │ │ │ │ "two-dimensions, just rotated by $\\pi/2." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a69a6a0f", │ │ │ │ │ + "id": "d497056a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ksp_sigma, ksp_u = ksp.getPC().getFieldSplitSubKSP()\n", │ │ │ │ │ "pc_sigma = ksp_sigma.getPC()\n", │ │ │ │ │ "if PETSc.Sys().hasExternalPackage(\"hypre\") and not np.issubdtype(dtype, np.complexfloating):\n", │ │ │ │ │ " pc_sigma.setType(\"hypre\")\n", │ │ │ │ │ @@ -485,49 +485,49 @@ │ │ │ │ │ " pc_sigma.setFactorSolverType(\"mumps\")\n", │ │ │ │ │ " elif PETSc.Sys().hasExternalPackage(\"superlu_dist\"):\n", │ │ │ │ │ " pc_sigma.setFactorSolverType(\"superlu_dist\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "296c3f47", │ │ │ │ │ + "id": "07b109b2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Once we have set the preconditioners for the two blocks, we can\n", │ │ │ │ │ "solve the linear system.\n", │ │ │ │ │ "{py:class}`LinearProblem` will\n", │ │ │ │ │ "automatically assemble the linear system, apply the boundary\n", │ │ │ │ │ "conditions, call the Krylov solver and update the solution\n", │ │ │ │ │ "vectors `u` and `sigma`." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "daeb674c", │ │ │ │ │ + "id": "22e74de6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "problem.solve()\n", │ │ │ │ │ "converged_reason = problem.solver.getConvergedReason()\n", │ │ │ │ │ "assert converged_reason > 0, f\"Krylov solver has not converged, reason: {converged_reason}.\"" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "00ac555b", │ │ │ │ │ + "id": "3048c647", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We save the solution `u` in VTX format:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d9934748", │ │ │ │ │ + "id": "b96413ea", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if dolfinx.has_adios2:\n", │ │ │ │ │ " from dolfinx.io import VTXWriter\n", │ │ │ │ │ "\n", │ │ │ │ │ " with VTXWriter(msh.comm, \"output_mixed_poisson.bp\", u) as f:\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/a5df6747d3300b9568f25507c7fb2517/demo_interpolation-io.ipynb.gz │ │ │ ├── demo_interpolation-io.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666666% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '4317957f'}, 1: {'id': '32ce4529'}, 2: {'id': 'cfba4155'}, 3: {'id': " │ │ │ │ │┄ "'0e008bee'}, 4: {'id': 'f5ff0898'}, 5: {'id': '69c05c96'}, 6: {'id': 'a606992c'}, 7: " │ │ │ │ │┄ "{'id': '3749bacf'}, 8: {'id': '740055a5'}, 9: {'id': 'ab5e87e6'}, 10: {'id': " │ │ │ │ │┄ "'59d9646a'}, 11: {'id': '991a636b'}, 12: {'id': '6bf30c3a'}, 13: {'id': 'de4f5d93'}, " │ │ │ │ │┄ "14: {'id': 'd53985e8'}, 15: {'id': '66842690'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "461a8f22", │ │ │ │ │ + "id": "4317957f", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "# Interpolation and IO\n", │ │ │ │ │ "\n", │ │ │ │ │ "Copyright (C) 2022 Garth N. Wells\n", │ │ │ │ │ @@ -26,15 +26,15 @@ │ │ │ │ │ "these special finite elements in discontinuous Lagrange spaces for\n", │ │ │ │ │ "artifact-free visualisation." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8ac5125e", │ │ │ │ │ + "id": "32ce4529", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -44,128 +44,128 @@ │ │ │ │ │ "from dolfinx import default_scalar_type, has_adios2, plot\n", │ │ │ │ │ "from dolfinx.fem import Function, functionspace\n", │ │ │ │ │ "from dolfinx.mesh import CellType, create_rectangle, locate_entities\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c5d3f979", │ │ │ │ │ + "id": "cfba4155", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a mesh. For later in the demo we need to ensure that a boundary\n", │ │ │ │ │ "between cells is located at $x_0=0.5$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b091195c", │ │ │ │ │ + "id": "0e008bee", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = create_rectangle(MPI.COMM_WORLD, ((0.0, 0.0), (1.0, 1.0)), (16, 16), CellType.triangle)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "13b74f42", │ │ │ │ │ + "id": "f5ff0898", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a N\u00e9d\u00e9lec function space and finite element Function" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d15895be", │ │ │ │ │ + "id": "69c05c96", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "V = functionspace(msh, (\"Nedelec 1st kind H(curl)\", 1))\n", │ │ │ │ │ "u = Function(V, dtype=default_scalar_type)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2e3c6391", │ │ │ │ │ + "id": "a606992c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Find cells with *all* vertices (0) $x_0 <= 0.5$ or (1) $x_0 >= 0.5$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "275f4ec1", │ │ │ │ │ + "id": "3749bacf", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "tdim = msh.topology.dim\n", │ │ │ │ │ "cells0 = locate_entities(msh, tdim, lambda x: x[0] <= 0.5)\n", │ │ │ │ │ "cells1 = locate_entities(msh, tdim, lambda x: x[0] >= 0.5)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "dd44b2c0", │ │ │ │ │ + "id": "740055a5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Interpolate in the N\u00e9d\u00e9lec/H(curl) space a vector-valued expression\n", │ │ │ │ │ "`f`, where $f \\cdot n$ is discontinuous at $x_0 = 0.5$ and $f \\cdot\n", │ │ │ │ │ "e$ is continuous." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5df19bca", │ │ │ │ │ + "id": "ab5e87e6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "u.interpolate(lambda x: np.vstack((x[0], x[1])), cells0)\n", │ │ │ │ │ "u.interpolate(lambda x: np.vstack((x[0] + 1, x[1])), cells1)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "702bd6a9", │ │ │ │ │ + "id": "59d9646a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a vector-valued discontinuous Lagrange space and function, and\n", │ │ │ │ │ "interpolate the $H({\\rm curl})$ function `u`" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7a68e6d0", │ │ │ │ │ + "id": "991a636b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "gdim = msh.geometry.dim\n", │ │ │ │ │ "V0 = functionspace(msh, (\"Discontinuous Lagrange\", 1, (gdim,)))\n", │ │ │ │ │ "u0 = Function(V0, dtype=default_scalar_type)\n", │ │ │ │ │ "u0.interpolate(u)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "78cd7172", │ │ │ │ │ + "id": "6bf30c3a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We save the interpolated function `u0` in VTX format. When visualising\n", │ │ │ │ │ "the field, at $x_0 = 0.5$ the $x_0$-component should appear\n", │ │ │ │ │ "discontinuous and the $x_1$-component should appear continuous.\n", │ │ │ │ │ "We use the {py:class}`dolfinx.io.VTXWriter` to store the data." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "03ca2480", │ │ │ │ │ + "id": "de4f5d93", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "out_folder = Path(\"output_nedelec\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)\n", │ │ │ │ │ @@ -176,24 +176,24 @@ │ │ │ │ │ " f.write(0.0)\n", │ │ │ │ │ "else:\n", │ │ │ │ │ " print(\"ADIOS2 required for VTX output\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1536a970", │ │ │ │ │ + "id": "d53985e8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Plot the functions" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "499382a5", │ │ │ │ │ + "id": "66842690", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "try:\n", │ │ │ │ │ " import pyvista\n", │ │ │ │ │ "\n", │ │ │ │ │ " cells, types, x = plot.vtk_mesh(V0)\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/b3f0523386e0521f7e6a5599627be9fc/demo_half_loaded_waveguide.ipynb.gz │ │ │ ├── demo_half_loaded_waveguide.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869186046511628% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': 'ce511dad'}, 1: {'id': '8abc90b1'}, 2: {'id': '807db7c7'}, 3: {'id': " │ │ │ │ │┄ "'f068415b'}, 4: {'id': 'e039d7a4'}, 5: {'id': 'cd9b98e2'}, 6: {'id': '1b328180'}, 7: " │ │ │ │ │┄ "{'id': '4c00a4b6'}, 8: {'id': 'a82f4287'}, 9: {'id': '8b11392c'}, 10: {'id': " │ │ │ │ │┄ "'cf8b4bbd'}, 11: {'id': 'b786b87e'}, 12: {'id': '6154c004'}, 13: {'id': '645f22de'}, " │ │ │ │ │┄ "14: {'id': 'f1c7d8b9'}, 15: {'id': '22835975'}, 16: {'id': 'a2e9c4d3'}, 17: {'id': " │ │ │ │ │┄ "'24c18dc2'}, 1 […] │ │ │ │ │ @@ -1,20 +1,20 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8cf05789", │ │ │ │ │ + "id": "ce511dad", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Electromagnetic modal analysis for a waveguide" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "36b2cfc4", │ │ │ │ │ + "id": "8abc90b1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Copyright (C) 2022 Michele Castriotta, Igor Baratta, J\u00f8rgen S. Dokken\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ ":class: download\n", │ │ │ │ │ "* {download}`Python script <./demo_half_loaded_waveguide.py>`\n", │ │ │ │ │ @@ -37,15 +37,15 @@ │ │ │ │ │ "First of all, let's import the modules we need for solving the\n", │ │ │ │ │ "problem:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6f2ff587", │ │ │ │ │ + "id": "807db7c7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py import PETSc\n", │ │ │ │ │ @@ -80,15 +80,15 @@ │ │ │ │ │ "except ImportError:\n", │ │ │ │ │ " print(\"VTXWriter not available, solution will not be saved.\")\n", │ │ │ │ │ " has_vtx = False" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "861ab015", │ │ │ │ │ + "id": "f068415b", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Analytical solutions for the half-loaded waveguide\n", │ │ │ │ │ "\n", │ │ │ │ │ "The analytical solutions for the half-loaded waveguide with perfect\n", │ │ │ │ │ @@ -136,40 +136,40 @@ │ │ │ │ │ "\n", │ │ │ │ │ "Let's define the set of equations with the $\\tan$ and $\\cot$ function:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ef6571ed", │ │ │ │ │ + "id": "e039d7a4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def TMx_condition(\n", │ │ │ │ │ " kx_d: complex, kx_v: complex, eps_d: complex, eps_v: complex, d: float, h: float\n", │ │ │ │ │ ") -> float:\n", │ │ │ │ │ " return kx_d / eps_d * np.tan(kx_d * d) + kx_v / eps_v * np.tan(kx_v * (h - d))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a14e077b", │ │ │ │ │ + "id": "cd9b98e2", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def TEx_condition(kx_d: complex, kx_v: complex, d: float, h: float) -> float:\n", │ │ │ │ │ " return kx_d / np.tan(kx_d * d) + kx_v / np.tan(kx_v * (h - d))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b0d83ec4", │ │ │ │ │ + "id": "1b328180", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Then, we can define the `verify_mode` function, to check whether a\n", │ │ │ │ │ "certain $k_z$ satisfy the equations (below a certain threshold). In\n", │ │ │ │ │ "other words, we provide a certain $k_z$, together with the geometrical\n", │ │ │ │ │ @@ -177,15 +177,15 @@ │ │ │ │ │ "whether the last equations for the $\\mathrm{TE}_x$ or $\\mathrm{TM}_x$\n", │ │ │ │ │ "modes are close to $0$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "15c9c9e0", │ │ │ │ │ + "id": "4c00a4b6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def verify_mode(\n", │ │ │ │ │ " kz: complex,\n", │ │ │ │ │ " w: float,\n", │ │ │ │ │ " h: float,\n", │ │ │ │ │ @@ -205,26 +205,26 @@ │ │ │ │ │ " f_tm = TMx_condition(kx_d, kx_v, eps_d, eps_v, d, h)\n", │ │ │ │ │ " f_te = TEx_condition(kx_d, kx_v, d, h)\n", │ │ │ │ │ " return np.isclose(f_tm, 0, atol=threshold) or np.isclose(f_te, 0, atol=threshold)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "126ec255", │ │ │ │ │ + "id": "a82f4287", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We now define the domain. It is a rectangular domain with width $w$\n", │ │ │ │ │ "and height $h = 0.45w$, with the dielectric medium filling the\n", │ │ │ │ │ "lower-half of the domain, with a height of $d=0.5h$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7a8915d0", │ │ │ │ │ + "id": "8b11392c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "w = 1\n", │ │ │ │ │ "h = 0.45 * w\n", │ │ │ │ │ "d = 0.5 * h\n", │ │ │ │ │ "nx = 300\n", │ │ │ │ │ @@ -232,26 +232,26 @@ │ │ │ │ │ "\n", │ │ │ │ │ "msh = create_rectangle(MPI.COMM_WORLD, np.array([[0, 0], [w, h]]), (nx, ny), CellType.quadrilateral)\n", │ │ │ │ │ "msh.topology.create_connectivity(msh.topology.dim - 1, msh.topology.dim)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "90340662", │ │ │ │ │ + "id": "cf8b4bbd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we can define the dielectric permittivity $\\varepsilon_r$ over the\n", │ │ │ │ │ "domain as $\\varepsilon_r = \\varepsilon_v = 1$ in the vacuum, and as\n", │ │ │ │ │ "$\\varepsilon_r = \\varepsilon_d = 2.45$ in the dielectric:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "faa41115", │ │ │ │ │ + "id": "b786b87e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps_v = 1\n", │ │ │ │ │ "eps_d = 2.45\n", │ │ │ │ │ "\n", │ │ │ │ │ "D = fem.functionspace(msh, (\"DQ\", 0))\n", │ │ │ │ │ @@ -261,15 +261,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "eps.x.array[:] = eps_v\n", │ │ │ │ │ "eps.x.array[cells_d] = eps_d" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "012fdfc1", │ │ │ │ │ + "id": "6154c004", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "In order to find the weak form of our problem, the starting point are\n", │ │ │ │ │ "Maxwell's equation and the perfect electric conductor condition on the\n", │ │ │ │ │ "waveguide wall:\n", │ │ │ │ │ "\n", │ │ │ │ │ "$$\n", │ │ │ │ │ @@ -349,36 +349,36 @@ │ │ │ │ │ "Lagrange elements. This hybrid formulation is implemented with\n", │ │ │ │ │ "`mixed_element`:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2e877535", │ │ │ │ │ + "id": "645f22de", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "degree = 1\n", │ │ │ │ │ "RTCE = element(\"RTCE\", msh.basix_cell(), degree, dtype=PETSc.RealType)\n", │ │ │ │ │ "Q = element(\"Lagrange\", msh.basix_cell(), degree, dtype=PETSc.RealType)\n", │ │ │ │ │ "V = fem.functionspace(msh, mixed_element([RTCE, Q]))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "55bdae4b", │ │ │ │ │ + "id": "f1c7d8b9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we can define our weak form:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "39145cdb", │ │ │ │ │ + "id": "22835975", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "lmbd0 = h / 0.2\n", │ │ │ │ │ "k0 = 2 * np.pi / lmbd0\n", │ │ │ │ │ "\n", │ │ │ │ │ "et, ez = ufl.TrialFunctions(V)\n", │ │ │ │ │ @@ -392,150 +392,150 @@ │ │ │ │ │ "\n", │ │ │ │ │ "a = fem.form(a_tt)\n", │ │ │ │ │ "b = fem.form(b_tt + b_tz + b_zt + b_zz)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "427e91b4", │ │ │ │ │ + "id": "a2e9c4d3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Let's add the perfect electric conductor conditions on the waveguide\n", │ │ │ │ │ "wall:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a92e8271", │ │ │ │ │ + "id": "24c18dc2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc_facets = exterior_facet_indices(msh.topology)\n", │ │ │ │ │ "bc_dofs = fem.locate_dofs_topological(V, msh.topology.dim - 1, bc_facets)\n", │ │ │ │ │ "u_bc = fem.Function(V)\n", │ │ │ │ │ "with u_bc.x.petsc_vec.localForm() as loc:\n", │ │ │ │ │ " loc.set(0)\n", │ │ │ │ │ "bc = fem.dirichletbc(u_bc, bc_dofs)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "581ae09e", │ │ │ │ │ + "id": "9a310ab8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Solve the problem in SLEPc" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fb7a745b", │ │ │ │ │ + "id": "6351f7a1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we can solve the problem with SLEPc. First of all, we need to\n", │ │ │ │ │ "assemble our $A$ and $B$ matrices with PETSc in this way:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "80b23526", │ │ │ │ │ + "id": "210a121f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "A = assemble_matrix(a, bcs=[bc])\n", │ │ │ │ │ "A.assemble()\n", │ │ │ │ │ "B = assemble_matrix(b, bcs=[bc])\n", │ │ │ │ │ "B.assemble()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ae082c83", │ │ │ │ │ + "id": "26b95f89", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now, we need to create the eigenvalue problem in SLEPc. Our problem is\n", │ │ │ │ │ "a linear eigenvalue problem, that in SLEPc is solved with the `EPS`\n", │ │ │ │ │ "module. We can initialize this solver in the following way:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b9361f5c", │ │ │ │ │ + "id": "11e822c9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps = SLEPc.EPS().create(msh.comm)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "cb45806d", │ │ │ │ │ + "id": "0576269e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We can pass to `EPS` our matrices by using the `setOperators` routine:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "87fb2398", │ │ │ │ │ + "id": "34f14687", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setOperators(A, B)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1d913d62", │ │ │ │ │ + "id": "cca4352c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "If the matrices in the problem have known properties (e.g.\n", │ │ │ │ │ "hermiticity) we can use this information in SLEPc to accelerate the\n", │ │ │ │ │ "calculation with the `setProblemType` function. For this problem,\n", │ │ │ │ │ "there is no property that can be exploited, and therefore we define it\n", │ │ │ │ │ "as a generalized non-Hermitian eigenvalue problem with the\n", │ │ │ │ │ "`SLEPc.EPS.ProblemType.GNHEP` object:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7d616ab7", │ │ │ │ │ + "id": "a610c7af", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setProblemType(SLEPc.EPS.ProblemType.GNHEP)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "663d9a8f", │ │ │ │ │ + "id": "e514bc15", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we need to specify a tolerance for the iterative solver, so that\n", │ │ │ │ │ "it knows when to stop:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "952f7461", │ │ │ │ │ + "id": "e7e6fe85", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "tol = 1e-9\n", │ │ │ │ │ "eps.setTolerances(tol=tol)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3353d003", │ │ │ │ │ + "id": "8e5d422b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we need to set the eigensolver for our problem. SLEPc offers\n", │ │ │ │ │ "different built-in algorithms, and also wrappers to external\n", │ │ │ │ │ "libraries. Some of these can only solve Hermitian problems and/or\n", │ │ │ │ │ "problems with eigenvalues in a certain portion of the spectrum.\n", │ │ │ │ │ "However, the choice of the particular method to choose to solve a\n", │ │ │ │ │ @@ -545,51 +545,51 @@ │ │ │ │ │ "problem, we will use the Krylov-Schur method, which we can set by\n", │ │ │ │ │ "calling the `setType` function:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "47173d62", │ │ │ │ │ + "id": "7fc8e46a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setType(SLEPc.EPS.Type.KRYLOVSCHUR)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1331c6b8", │ │ │ │ │ + "id": "a54f0566", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "In order to accelerate the calculation of our solutions, we can also\n", │ │ │ │ │ "use a so-called *spectral transformation*, a technique which maps the\n", │ │ │ │ │ "original eigenvalues into another position of the spectrum without\n", │ │ │ │ │ "affecting the eigenvectors. In our case, we can use the\n", │ │ │ │ │ "shift-and-invert transformation with the `SLEPc.ST.Type.SINVERT`\n", │ │ │ │ │ "object:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6356786a", │ │ │ │ │ + "id": "50a0e296", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Get ST context from eps\n", │ │ │ │ │ "st = eps.getST()\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Set shift-and-invert transformation\n", │ │ │ │ │ "st.setType(SLEPc.ST.Type.SINVERT)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6f7dcf44", │ │ │ │ │ + "id": "70d8b0ee", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The spectral transformation needs a target value for the eigenvalues\n", │ │ │ │ │ "we are looking for. Since the eigenvalues for our problem can be\n", │ │ │ │ │ "complex numbers, we need to specify whether we are searching for\n", │ │ │ │ │ "specific values in the real part, in the imaginary part, or in the\n", │ │ │ │ │ "magnitude. In our case, we are interested in propagating modes, and\n", │ │ │ │ │ @@ -598,101 +598,101 @@ │ │ │ │ │ "real part of the eigenvalue, with the `SLEPc.EPS.Which.TARGET_REAL`\n", │ │ │ │ │ "object:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "46423a53", │ │ │ │ │ + "id": "538b7a56", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setWhichEigenpairs(SLEPc.EPS.Which.TARGET_REAL)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "470c987e", │ │ │ │ │ + "id": "8fcdd04d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For specifying the target value, we can use the `setTarget` function.\n", │ │ │ │ │ "Even though we cannot know a good target value a priori, we can guess\n", │ │ │ │ │ "that $k_z$ will be quite close to $k_0$ in value, for instance $k_z =\n", │ │ │ │ │ "0.5k_0^2$. Therefore, we can set a target value of $-(0.5k_0^2)$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "98e6ec6f", │ │ │ │ │ + "id": "4fb56075", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setTarget(-((0.5 * k0) ** 2))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "40ed475a", │ │ │ │ │ + "id": "630de244", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Then, we need to define the number of eigenvalues we want to\n", │ │ │ │ │ "calculate. We can do this with the `setDimensions` function, where we\n", │ │ │ │ │ "specify that we are looking for just one eigenvalue:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "df585fa5", │ │ │ │ │ + "id": "545a4fd8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setDimensions(nev=1)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "48029119", │ │ │ │ │ + "id": "9bf78211", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We can finally solve the problem with the `solve` function. To gain a\n", │ │ │ │ │ "deeper insight over the simulation, we also print an output message\n", │ │ │ │ │ "from SLEPc by calling the `view` and `errorView` function:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "497ffd49", │ │ │ │ │ + "id": "4299a032", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.solve()\n", │ │ │ │ │ "eps.view()\n", │ │ │ │ │ "eps.errorView()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8d43ca37", │ │ │ │ │ + "id": "ea54e16a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Verification of computed eigenvalues\n", │ │ │ │ │ "Now we can get the eigenvalues and eigenvectors calculated by SLEPc\n", │ │ │ │ │ "with the following code. We also verify if the numerical $k_z$ are\n", │ │ │ │ │ "consistent with the analytical equations of the half-loaded waveguide\n", │ │ │ │ │ "modes, with the `verify_mode()` function defined in\n", │ │ │ │ │ "`analytical_modes.py`:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "78e7be9e", │ │ │ │ │ + "id": "d32bb7fc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Save the kz\n", │ │ │ │ │ "vals = [(i, np.sqrt(-eps.getEigenvalue(i))) for i in range(eps.getConverged())]\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Sort kz by real part\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/c202a2458472f1e0e385ed9afdc3da0f/demo_helmholtz.ipynb.gz │ │ │ ├── demo_helmholtz.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9869791666666666% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '2509a42b'}, 1: {'id': 'da2d4a6f'}, 2: {'id': '04a2784b'}, 3: {'id': " │ │ │ │ │┄ "'65d154de'}, 4: {'id': 'f80f4e8c'}, 5: {'id': 'f6ecab71'}, 6: {'id': 'c94288b0'}, 7: " │ │ │ │ │┄ "{'id': '45e932fb'}, 8: {'id': 'bb4305e0'}, 9: {'id': 'd8265199'}, 10: {'id': " │ │ │ │ │┄ "'28bfe213'}, 11: {'id': 'd20e2ba5'}, 12: {'id': '7466e627'}, 13: {'id': 'cb3b1b26'}, " │ │ │ │ │┄ "14: {'id': 'e8a58727'}, 15: {'id': '3ba4f651'}, 16: {'id': '4fc424ef'}, 17: {'id': " │ │ │ │ │┄ "'a154a2ff'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "425ff2c7", │ │ │ │ │ + "id": "2509a42b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Helmholtz equation\n", │ │ │ │ │ "\n", │ │ │ │ │ "Copyright (C) 2018-2025 Samuel Groth and J\u00f8rgen S. Dokken\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ @@ -26,24 +26,24 @@ │ │ │ │ │ "In real mode, the exact solution corresponds to\n", │ │ │ │ │ "the real part of the plane wave (a sin function which also solves the\n", │ │ │ │ │ "homogeneous Helmholtz equation)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1f48e5a8", │ │ │ │ │ + "id": "da2d4a6f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We start by importing the necessary modules" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "19cd40f1", │ │ │ │ │ + "id": "04a2784b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py import PETSc\n", │ │ │ │ │ "\n", │ │ │ │ │ "import numpy as np\n", │ │ │ │ │ @@ -61,56 +61,56 @@ │ │ │ │ │ "from dolfinx.fem.petsc import LinearProblem\n", │ │ │ │ │ "from dolfinx.io import XDMFFile\n", │ │ │ │ │ "from dolfinx.mesh import create_unit_square\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "4c08c368", │ │ │ │ │ + "id": "65d154de", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We define the necessary parameters for the discretized problem" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2def7e23", │ │ │ │ │ + "id": "f80f4e8c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "k0 = 4 * np.pi # Wavenumber\n", │ │ │ │ │ "deg = 1 # Approximation space polynomial degree\n", │ │ │ │ │ "n_elem = 64 # Number of elements in each direction of the mesh\n", │ │ │ │ │ "A = 1 # Source amplitude" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "46ecd5c0", │ │ │ │ │ + "id": "f6ecab71", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we create the discrete domain, a unit square and set up the\n", │ │ │ │ │ "discrete function space." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "9d7bf2f6", │ │ │ │ │ + "id": "c94288b0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = create_unit_square(MPI.COMM_WORLD, n_elem, n_elem)\n", │ │ │ │ │ "V = functionspace(msh, (\"Lagrange\", deg))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2a774d8b", │ │ │ │ │ + "id": "45e932fb", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Define variational problem.\n", │ │ │ │ │ "The Helmholtz equation can be discretized in the same way for both the\n", │ │ │ │ │ "real and complex valued formulation. However, note that we use\n", │ │ │ │ │ "`ufl.inner` instead of `ufl.dot` or the ` * ` operator between\n", │ │ │ │ │ "the test and trial function, and that the test-function is\n", │ │ │ │ │ @@ -119,38 +119,38 @@ │ │ │ │ │ "one requires a sesquilinear two-form, with the inner product being\n", │ │ │ │ │ "$(a,b)=\\int_\\Omega a \\cdot \\bar{b}~\\mathrm{d}x$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "cd6fa715", │ │ │ │ │ + "id": "bb4305e0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "u, v = ufl.TrialFunction(V), ufl.TestFunction(V)\n", │ │ │ │ │ "a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx - k0**2 * ufl.inner(u, v) * ufl.dx" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c73d08c9", │ │ │ │ │ + "id": "d8265199", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "We solve for plane wave with mixed Dirichlet and Neumann BCs.\n", │ │ │ │ │ "We use ufl to manufacture an exact solution and corresponding\n", │ │ │ │ │ "boundary conditions." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "efc18f34", │ │ │ │ │ + "id": "28bfe213", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "theta = np.pi / 4\n", │ │ │ │ │ "V_exact = functionspace(\n", │ │ │ │ │ " msh, (\"Lagrange\", deg + 3)\n", │ │ │ │ │ ") # Exact solution should be in a higher order space\n", │ │ │ │ │ @@ -167,26 +167,26 @@ │ │ │ │ │ "u_bc = Function(V)\n", │ │ │ │ │ "u_bc.interpolate(Expression(u_exact, V.element.interpolation_points))\n", │ │ │ │ │ "bcs = [dirichletbc(u_bc, dofs_D)]" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f0a45c39", │ │ │ │ │ + "id": "d20e2ba5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "In this problem, we rely on PETSc as the linear algebra backend.\n", │ │ │ │ │ "PETSc can only be configured for a either real of complex valued matrices\n", │ │ │ │ │ "and vectors. We can check how PETSc is configured by calling" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7f191e85", │ │ │ │ │ + "id": "7466e627", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "is_complex_mode = np.issubdtype(PETSc.ScalarType, np.complexfloating)\n", │ │ │ │ │ "PETSc.Sys.Print(f\"PETSc is configured in complex mode: {is_complex_mode}\")\n", │ │ │ │ │ "\n", │ │ │ │ │ "uh = Function(V)\n", │ │ │ │ │ @@ -200,48 +200,48 @@ │ │ │ │ │ " petsc_options={\"ksp_type\": \"preonly\", \"pc_type\": \"lu\", \"ksp_error_if_not_converged\": True},\n", │ │ │ │ │ ")\n", │ │ │ │ │ "_ = problem.solve()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "242c569a", │ │ │ │ │ + "id": "cb3b1b26", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Save solution in XDMF format (to be viewed in ParaView, for example)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a9124c46", │ │ │ │ │ + "id": "e8a58727", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "with XDMFFile(\n", │ │ │ │ │ " MPI.COMM_WORLD, \"out_helmholtz/plane_wave.xdmf\", \"w\", encoding=XDMFFile.Encoding.HDF5\n", │ │ │ │ │ ") as file:\n", │ │ │ │ │ " file.write_mesh(msh)\n", │ │ │ │ │ " file.write_function(uh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "a170a9ea", │ │ │ │ │ + "id": "3ba4f651", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Calculate $L_2$ and $H_0^1$ errors of FEM solution and best\n", │ │ │ │ │ "approximation. This demonstrates the error bounds given in Ihlenburg.\n", │ │ │ │ │ "Pollution errors are evident for high wavenumbers." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "02ab861d", │ │ │ │ │ + "id": "4fc424ef", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "diff = uh - u_exact\n", │ │ │ │ │ "H1_diff = msh.comm.allreduce(\n", │ │ │ │ │ " assemble_scalar(form(ufl.inner(ufl.grad(diff), ufl.grad(diff)) * ufl.dx)), op=MPI.SUM\n", │ │ │ │ │ ")\n", │ │ │ │ │ @@ -250,15 +250,15 @@ │ │ │ │ │ ")\n", │ │ │ │ │ "PETSc.Sys.Print(\"Relative H1 error of FEM solution:\", abs(np.sqrt(H1_diff) / np.sqrt(H1_exact)))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "80968816", │ │ │ │ │ + "id": "a154a2ff", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "L2_diff = msh.comm.allreduce(assemble_scalar(form(ufl.inner(diff, diff) * ufl.dx)), op=MPI.SUM)\n", │ │ │ │ │ "L2_exact = msh.comm.allreduce(\n", │ │ │ │ │ " assemble_scalar(form(ufl.inner(u_exact, u_exact) * ufl.dx)), op=MPI.SUM\n", │ │ │ │ │ ")\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/e5597ff2b0334295de2749391a1ffbe1/demo_tnt-elements.ipynb.gz │ │ │ ├── demo_tnt-elements.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.986875% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '16c6697c'}, 1: {'id': '32b23e21'}, 2: {'id': '7eb4ca37'}, 3: {'id': " │ │ │ │ │┄ "'f0122ccc'}, 4: {'id': 'cb53b0ab'}, 5: {'id': '65f62e18'}, 6: {'id': '8219854e'}, 7: " │ │ │ │ │┄ "{'id': 'd981f341'}, 8: {'id': '5dfe7e14'}, 9: {'id': '0a696df3'}, 10: {'id': " │ │ │ │ │┄ "'984973b4'}, 11: {'id': '331f6d81'}, 12: {'id': '1c1d4de6'}, 13: {'id': '2c4889f5'}, " │ │ │ │ │┄ "14: {'id': 'aab5dc3c'}, 15: {'id': '132c1b98'}, 16: {'id': 'a1126062'}, 17: {'id': " │ │ │ │ │┄ "'e4d2f119'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "aaf4916d", │ │ │ │ │ + "id": "16c6697c", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "# Creating TNT elements using Basix's custom element interface\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ @@ -24,15 +24,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "We begin this demo by importing the required modules." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "0186900c", │ │ │ │ │ + "id": "32b23e21", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "\n", │ │ │ │ │ "import matplotlib as mpl\n", │ │ │ │ │ "import matplotlib.pylab as plt\n", │ │ │ │ │ @@ -45,15 +45,15 @@ │ │ │ │ │ "from dolfinx.fem.petsc import LinearProblem\n", │ │ │ │ │ "\n", │ │ │ │ │ "mpl.use(\"agg\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8c88f36a", │ │ │ │ │ + "id": "7eb4ca37", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Defining a degree 1 TNT element\n", │ │ │ │ │ "\n", │ │ │ │ │ "We will define [tiniest tensor\n", │ │ │ │ │ "(TNT)](https://defelement.org/elements/tnt.html) elements on a\n", │ │ │ │ │ "quadrilateral ([Commuting diagrams for the TNT elements on cubes\n", │ │ │ │ │ @@ -73,24 +73,24 @@ │ │ │ │ │ "in the polynomial sets for each cell can be found in the [Basix\n", │ │ │ │ │ "documentation](https://docs.fenicsproject.org/basix/main/polyset-order.html)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a7608f2e", │ │ │ │ │ + "id": "f0122ccc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "wcoeffs = np.eye(8, 9)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f6430304", │ │ │ │ │ + "id": "cb53b0ab", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For elements where the coefficients matrix is not an identity, we can\n", │ │ │ │ │ "use the properties of orthonormal polynomials to compute `wcoeffs`.\n", │ │ │ │ │ "Let $\\{q_0, q_1,\\dots\\}$ be the orthonormal polynomials of a given\n", │ │ │ │ │ "degree for a given cell, and suppose that we're trying to represent a\n", │ │ │ │ │ "function $f_i\\in\\operatorname{span}\\{q_1, q_2,\\dots\\}$ (as\n", │ │ │ │ │ @@ -101,15 +101,15 @@ │ │ │ │ │ "$a_{ij}=\\int_R f_iq_j\\,\\mathrm{d}\\mathbf{x}$.\n", │ │ │ │ │ "Hence we could compute `wcoeffs` as follows:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "74f4db84", │ │ │ │ │ + "id": "65f62e18", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "wcoeffs2 = np.empty((8, 9))\n", │ │ │ │ │ "pts, wts = basix.make_quadrature(basix.CellType.quadrilateral, 4)\n", │ │ │ │ │ "evals = basix.tabulate_polynomials(\n", │ │ │ │ │ " basix.PolynomialType.legendre, basix.CellType.quadrilateral, 2, pts\n", │ │ │ │ │ @@ -122,28 +122,28 @@ │ │ │ │ │ " wcoeffs2[3, j] = sum(v * pts[:, 0] * pts[:, 1] * wts) # xy\n", │ │ │ │ │ " wcoeffs2[4, j] = sum(v * pts[:, 0] * pts[:, 1] ** 2 * wts) # xy^2\n", │ │ │ │ │ " wcoeffs2[5, j] = sum(v * pts[:, 0] ** 2 * pts[:, 1] * wts) # x^2y" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "cbc1cfc9", │ │ │ │ │ + "id": "8219854e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "### Interpolation operators\n", │ │ │ │ │ "\n", │ │ │ │ │ "We provide the information that defines the DOFs associated with each\n", │ │ │ │ │ "sub-entity of the cell. First, we associate a point evaluation with\n", │ │ │ │ │ "each vertex." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b451a07d", │ │ │ │ │ + "id": "d981f341", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "geometry = basix.geometry(basix.CellType.quadrilateral)\n", │ │ │ │ │ "topology = basix.topology(basix.CellType.quadrilateral)\n", │ │ │ │ │ "x = [[], [], [], []] # type: ignore [var-annotated]\n", │ │ │ │ │ "M = [[], [], [], []] # type: ignore [var-annotated]\n", │ │ │ │ │ @@ -151,27 +151,27 @@ │ │ │ │ │ "for v in topology[0]:\n", │ │ │ │ │ " x[0].append(np.array(geometry[v]))\n", │ │ │ │ │ " M[0].append(np.array([[[[1.0]]]]))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "95604324", │ │ │ │ │ + "id": "5dfe7e14", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For each edge, we define points and a matrix that represent the\n", │ │ │ │ │ "integral of the function along that edge. We do this by mapping\n", │ │ │ │ │ "quadrature points to the edge and putting quadrature points in the\n", │ │ │ │ │ "matrix." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a9345ac6", │ │ │ │ │ + "id": "0a696df3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "pts, wts = basix.make_quadrature(basix.CellType.interval, 2)\n", │ │ │ │ │ "for e in topology[1]:\n", │ │ │ │ │ " v0 = geometry[e[0]]\n", │ │ │ │ │ " v1 = geometry[e[1]]\n", │ │ │ │ │ @@ -181,48 +181,48 @@ │ │ │ │ │ " mat = np.zeros((1, 1, pts.shape[0], 1))\n", │ │ │ │ │ " mat[0, 0, :, 0] = wts\n", │ │ │ │ │ " M[1].append(mat)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b1c1bd99", │ │ │ │ │ + "id": "984973b4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "There are no DOFs associated with the interior of the cell for the\n", │ │ │ │ │ "lowest order TNT element, so we associate an empty list of points and\n", │ │ │ │ │ "an empty matrix with the interior." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "118e259e", │ │ │ │ │ + "id": "331f6d81", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "x[2].append(np.zeros([0, 2]))\n", │ │ │ │ │ "M[2].append(np.zeros([0, 1, 0, 1]))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "4923b25b", │ │ │ │ │ + "id": "1c1d4de6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "### Creating the Basix element\n", │ │ │ │ │ "\n", │ │ │ │ │ "We now create the element. Using the Basix UFL interface, we can wrap\n", │ │ │ │ │ "this element so that it can be used with FFCx/DOLFINx." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4c7f15d0", │ │ │ │ │ + "id": "2c4889f5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "tnt_degree1 = basix.ufl.custom_element(\n", │ │ │ │ │ " basix.CellType.quadrilateral,\n", │ │ │ │ │ " [],\n", │ │ │ │ │ " wcoeffs,\n", │ │ │ │ │ @@ -236,29 +236,29 @@ │ │ │ │ │ " 2,\n", │ │ │ │ │ " dtype=default_real_type,\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "46b0b24a", │ │ │ │ │ + "id": "aab5dc3c", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Creating higher degree TNT elements\n", │ │ │ │ │ "\n", │ │ │ │ │ "The following function follows the same method as above to define\n", │ │ │ │ │ "arbitrary degree TNT elements." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c3d82471", │ │ │ │ │ + "id": "132c1b98", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def create_tnt_quad(degree):\n", │ │ │ │ │ " assert degree > 1\n", │ │ │ │ │ @@ -336,15 +336,15 @@ │ │ │ │ │ " degree + 1,\n", │ │ │ │ │ " dtype=default_real_type,\n", │ │ │ │ │ " )" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0364049f", │ │ │ │ │ + "id": "a1126062", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Comparing TNT elements and Q elements\n", │ │ │ │ │ "\n", │ │ │ │ │ "We now use the code above to compare TNT elements and\n", │ │ │ │ │ @@ -353,15 +353,15 @@ │ │ │ │ │ "as input, and solves a Poisson problem and returns the $L_2$ error of\n", │ │ │ │ │ "the solution." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c487146f", │ │ │ │ │ + "id": "e4d2f119", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def poisson_error(V: fem.FunctionSpace):\n", │ │ │ │ │ " msh = V.mesh\n", │ │ │ │ │ " u, v = ufl.TrialFunction(V), ufl.TestFunction(V)\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -401,27 +401,27 @@ │ │ │ │ │ " M = fem.form(M)\n", │ │ │ │ │ " error = msh.comm.allreduce(fem.assemble_scalar(M), op=MPI.SUM)\n", │ │ │ │ │ " return error**0.5" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "35078942", │ │ │ │ │ + "id": "469a05b0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create a mesh, then solve the Poisson problem using our TNT\n", │ │ │ │ │ "elements of degree 1 to 8. We then do the same with Q elements of\n", │ │ │ │ │ "degree 1 to 9. For the TNT elements, we store a number 1 larger than\n", │ │ │ │ │ "the degree as this is the highest degree polynomial in the space." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6300a7f8", │ │ │ │ │ + "id": "b7b14fd6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = mesh.create_unit_square(MPI.COMM_WORLD, 15, 15, mesh.CellType.quadrilateral)\n", │ │ │ │ │ "\n", │ │ │ │ │ "tnt_ndofs = []\n", │ │ │ │ │ "tnt_degrees = []\n", │ │ │ │ │ @@ -448,26 +448,26 @@ │ │ │ │ │ " q_ndofs.append(V.dofmap.index_map.size_global)\n", │ │ │ │ │ " q_errors.append(poisson_error(V))\n", │ │ │ │ │ " print(f\"Q degree {degree} error: {q_errors[-1]}\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8e07389c", │ │ │ │ │ + "id": "ff7e3a9f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We now plot the data that we have obtained. First we plot the error\n", │ │ │ │ │ "against the polynomial degree for the two elements. The two elements\n", │ │ │ │ │ "appear to perform equally well." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4ee7c1b8", │ │ │ │ │ + "id": "00305799", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if MPI.COMM_WORLD.rank == 0: # Only plot on one rank\n", │ │ │ │ │ " plt.plot(q_degrees, q_errors, \"bo-\")\n", │ │ │ │ │ " plt.plot(tnt_degrees, tnt_errors, \"gs-\")\n", │ │ │ │ │ " plt.yscale(\"log\")\n", │ │ │ │ │ @@ -476,29 +476,29 @@ │ │ │ │ │ " plt.legend([\"Q\", \"TNT\"])\n", │ │ │ │ │ " plt.savefig(\"demo_tnt-elements_degrees_vs_error.png\")\n", │ │ │ │ │ " plt.clf()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9b92752f", │ │ │ │ │ + "id": "ac437745", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "![](demo_tnt-elements_degrees_vs_error.png)\n", │ │ │ │ │ "\n", │ │ │ │ │ "A key advantage of TNT elements is that for a given degree, they span\n", │ │ │ │ │ "a smaller polynomial space than Q elements. This can be observed in\n", │ │ │ │ │ "the following diagram, where we plot the error against the square root\n", │ │ │ │ │ "of the number of DOFs (providing a measure of cell size in 2D)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4c5a9ef8", │ │ │ │ │ + "id": "816a82de", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if MPI.COMM_WORLD.rank == 0: # Only plot on one rank\n", │ │ │ │ │ " plt.plot(np.sqrt(q_ndofs), q_errors, \"bo-\")\n", │ │ │ │ │ " plt.plot(np.sqrt(tnt_ndofs), tnt_errors, \"gs-\")\n", │ │ │ │ │ " plt.yscale(\"log\")\n", │ │ │ │ │ @@ -507,15 +507,15 @@ │ │ │ │ │ " plt.legend([\"Q\", \"TNT\"])\n", │ │ │ │ │ " plt.savefig(\"demo_tnt-elements_ndofs_vs_error.png\")\n", │ │ │ │ │ " plt.clf()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f9157e47", │ │ │ │ │ + "id": "5a72e8f4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "![](demo_tnt-elements_ndofs_vs_error.png)" │ │ │ │ │ ] │ │ │ │ │ } │ │ │ │ │ ], │ │ │ │ │ "metadata": { │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/eb193fc2ce46146f29b3c38146a5a3cb/demo_scattering_boundary_conditions.ipynb.gz │ │ │ ├── demo_scattering_boundary_conditions.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9870265151515152% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '67febb55'}, 1: {'id': 'ab3ed755'}, 2: {'id': '3f743ba4'}, 3: {'id': " │ │ │ │ │┄ "'8553f485'}, 4: {'id': 'b788f370'}, 5: {'id': '853d0190'}, 6: {'id': '365f3c2d'}, 7: " │ │ │ │ │┄ "{'id': '7aec1bab'}, 8: {'id': 'be13db3b'}, 9: {'id': '0daee686'}, 10: {'id': " │ │ │ │ │┄ "'42654d00'}, 11: {'id': 'fadc8ebe'}, 12: {'id': 'c6f3ca2b'}, 13: {'id': '86315e26'}, " │ │ │ │ │┄ "14: {'id': '697b3b97'}, 15: {'id': '449e71f8'}, 16: {'id': '8f65839d'}, 17: {'id': " │ │ │ │ │┄ "'accae234'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "83042d9b", │ │ │ │ │ + "id": "67febb55", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Electromagnetic scattering from a wire with scattering BCs\n", │ │ │ │ │ "\n", │ │ │ │ │ "Copyright (C) 2022 Michele Castriotta, Igor Baratta, J\u00f8rgen S. Dokken\n", │ │ │ │ │ "\n", │ │ │ │ │ "```{admonition} Download sources\n", │ │ │ │ │ @@ -25,15 +25,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "First of all, let's import the modules that will be used:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "bd97ac3e", │ │ │ │ │ + "id": "ab3ed755", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "import sys\n", │ │ │ │ │ "from pathlib import Path\n", │ │ │ │ │ "\n", │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ @@ -61,15 +61,15 @@ │ │ │ │ │ " # Note: when PETSc.IntType == np.int32, superlu_dist is used rather\n", │ │ │ │ │ " # than MUMPS and does not trigger memory failures.\n", │ │ │ │ │ " exit(0)\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e3768544", │ │ │ │ │ + "id": "3f743ba4", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Mesh generation\n", │ │ │ │ │ "First, we define the `generate_mesh_wire` function, which is used to\n", │ │ │ │ │ "generate the mesh used for scattering boundary conditions demo. The\n", │ │ │ │ │ @@ -96,15 +96,15 @@ │ │ │ │ │ "scattering efficiency calculation) while keenp.ping a coarser size over\n", │ │ │ │ │ "the rest of the domain." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d07d8062", │ │ │ │ │ + "id": "8553f485", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def generate_mesh_wire(\n", │ │ │ │ │ " radius_wire: float,\n", │ │ │ │ │ @@ -157,15 +157,15 @@ │ │ │ │ │ " gmsh.model.mesh.generate(2)\n", │ │ │ │ │ "\n", │ │ │ │ │ " return gmsh.model" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9621ac4a", │ │ │ │ │ + "id": "b788f370", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "(em_efficiencies)=\n", │ │ │ │ │ "## Mathematical formulation\n", │ │ │ │ │ "Next, we define the mathematical formulation for the calculation of the\n", │ │ │ │ │ @@ -214,15 +214,15 @@ │ │ │ │ │ "& q_{\\mathrm{abs}} = q_{\\mathrm{ext}} - q_{\\mathrm{sca}}\n", │ │ │ │ │ "$$" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "73eaec0b", │ │ │ │ │ + "id": "853d0190", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 0 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# The functions that we import from `scipy.special` correspond to:\n", │ │ │ │ │ "#\n", │ │ │ │ │ @@ -243,15 +243,15 @@ │ │ │ │ │ "# final calculation of the efficiencies, the summation over the different\n", │ │ │ │ │ "# orders of the Bessel functions is truncated at $\\nu=50$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ec8dbdf3", │ │ │ │ │ + "id": "365f3c2d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def compute_a(nu: int, m: complex, alpha: float) -> float:\n", │ │ │ │ │ " J_nu_alpha = jv(nu, alpha)\n", │ │ │ │ │ " J_nu_malpha = jv(nu, m * alpha)\n", │ │ │ │ │ " J_nu_alpha_p = jvp(nu, alpha, 1)\n", │ │ │ │ │ @@ -277,39 +277,39 @@ │ │ │ │ │ " q_ext += c * 2 * np.real(compute_a(nu, m, alpha))\n", │ │ │ │ │ " q_sca += c * 2 * np.abs(compute_a(nu, m, alpha)) ** 2\n", │ │ │ │ │ " return q_ext - q_sca, q_sca, q_ext" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f63a5b42", │ │ │ │ │ + "id": "7aec1bab", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Since we want to solve time-harmonic Maxwell's equation, we need to\n", │ │ │ │ │ "solve a complex-valued PDE, and therefore need to use PETSc compiled\n", │ │ │ │ │ "with complex numbers." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b33855ed", │ │ │ │ │ + "id": "be13db3b", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if not np.issubdtype(default_scalar_type, np.complexfloating):\n", │ │ │ │ │ " print(\"Demo should only be executed with DOLFINx complex mode\")\n", │ │ │ │ │ " exit(0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d2430dac", │ │ │ │ │ + "id": "0daee686", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now, let's consider an infinite metallic wire immersed in a background\n", │ │ │ │ │ "medium (e.g. vacuum or water). Let's now consider the plane cutting\n", │ │ │ │ │ "the wire perpendicularly to its axis at a generic point. Such plane\n", │ │ │ │ │ "$\\Omega=\\Omega_{m} \\cup\\Omega_{b}$ is formed by the cross-section of\n", │ │ │ │ │ "the wire $\\Omega_m$ and the background medium $\\Omega_{b}$ surrounding\n", │ │ │ │ │ @@ -346,15 +346,15 @@ │ │ │ │ │ "function are the angle $\\theta$, the background refractive index $n_b$\n", │ │ │ │ │ "and the vacuum wavevector $k_0$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "bb4d4a30", │ │ │ │ │ + "id": "42654d00", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -372,15 +372,15 @@ │ │ │ │ │ " phi = kx * x[0] + ky * x[1]\n", │ │ │ │ │ " ax, ay = np.sin(self.theta), np.cos(self.theta)\n", │ │ │ │ │ " return (-ax * np.exp(1j * phi), ay * np.exp(1j * phi))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c662ee6b", │ │ │ │ │ + "id": "fadc8ebe", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "The Maxwell's equation for scattering problems takes the following\n", │ │ │ │ │ "form:\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -432,15 +432,15 @@ │ │ │ │ │ "The radial distance function $r(x)$ and $\\nabla \\times$ operator for a\n", │ │ │ │ │ "2D vector (in UFL syntax) is defined below.\n" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fcaafe1d", │ │ │ │ │ + "id": "c6f3ca2b", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def radial_distance(x: ufl.SpatialCoordinate):\n", │ │ │ │ │ " \"\"\"Returns the radial distance from the origin\"\"\"\n", │ │ │ │ │ @@ -450,27 +450,27 @@ │ │ │ │ │ "def curl_2d(f: fem.Function):\n", │ │ │ │ │ " \"\"\"Returns the curl of two 2D vectors as a 3D vector\"\"\"\n", │ │ │ │ │ " return ufl.as_vector((0, 0, f[1].dx(0) - f[0].dx(1)))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "7cc6a51c", │ │ │ │ │ + "id": "86315e26", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Next we define some mesh specific parameters. Please notice that the\n", │ │ │ │ │ "length units are normalized with respect to $1\\mu m$." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ac3ddf66", │ │ │ │ │ + "id": "697b3b97", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "pi = np.pi\n", │ │ │ │ │ "epsilon_0 = 8.8541878128 * 10**-12\n", │ │ │ │ │ "mu_0 = 4 * pi * 10**-7\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -497,26 +497,26 @@ │ │ │ │ │ "au_tag = 1 # gold wire\n", │ │ │ │ │ "bkg_tag = 2 # background\n", │ │ │ │ │ "boundary_tag = 3 # boundary" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "461afa4f", │ │ │ │ │ + "id": "449e71f8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We generate the mesh using GMSH and convert it to a\n", │ │ │ │ │ "{py:class}`Mesh` using\n", │ │ │ │ │ "{py:func}`model_to_mesh `." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "97a33ae4", │ │ │ │ │ + "id": "8f65839d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "model = None\n", │ │ │ │ │ "gmsh.initialize(sys.argv)\n", │ │ │ │ │ "if MPI.COMM_WORLD.rank == 0:\n", │ │ │ │ │ " model = generate_mesh_wire(\n", │ │ │ │ │ @@ -539,15 +539,15 @@ │ │ │ │ │ "gmsh.finalize()\n", │ │ │ │ │ "MPI.COMM_WORLD.barrier()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2fd93446", │ │ │ │ │ + "id": "accae234", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# The mesh is visualized with [PyVista](https://docs.pyvista.org/)\n", │ │ │ │ │ "out_folder = Path(\"out_scattering_boundary_conditions\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)\n", │ │ │ │ │ "if have_pyvista:\n", │ │ │ │ │ @@ -565,68 +565,68 @@ │ │ │ │ │ " plotter.show()\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " figure = plotter.screenshot(out_folder / \"wire_mesh.png\", window_size=[8000, 8000])" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "367635a4", │ │ │ │ │ + "id": "8abc05e3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we define some other problem specific parameters:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7ae267af", │ │ │ │ │ + "id": "fe4c9a8b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "wl0 = 0.4 # Wavelength of the background field\n", │ │ │ │ │ "n_bkg = 1.33 # Background refractive index\n", │ │ │ │ │ "eps_bkg = n_bkg**2 # Background relative permittivity\n", │ │ │ │ │ "k0 = 2 * np.pi / wl0 # Wavevector of the background field\n", │ │ │ │ │ "theta = np.pi / 4 # Angle of incidence of the background field" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "7db47651", │ │ │ │ │ + "id": "749eb1a1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We use a function space consisting of degree 3 [Nedelec (first\n", │ │ │ │ │ "kind)](https://defelement.org/elements/nedelec1.html) elements to\n", │ │ │ │ │ "represent the electric field" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7471ad09", │ │ │ │ │ + "id": "5bbfbd42", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "degree = 3\n", │ │ │ │ │ "curl_el = element(\"N1curl\", mesh_data.mesh.basix_cell(), degree, dtype=default_real_type)\n", │ │ │ │ │ "V = fem.functionspace(mesh_data.mesh, curl_el)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "72db2f3f", │ │ │ │ │ + "id": "b6cf82c9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we can interpolate $\\mathbf{E}_b$ into the function space $V$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "351b3d32", │ │ │ │ │ + "id": "d8c0322b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "f = BackgroundElectricField(theta, n_bkg, k0)\n", │ │ │ │ │ "Eb = fem.Function(V)\n", │ │ │ │ │ "Eb.interpolate(f.eval)\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -650,64 +650,64 @@ │ │ │ │ │ "# Normal to the boundary\n", │ │ │ │ │ "n = ufl.FacetNormal(mesh_data.mesh)\n", │ │ │ │ │ "n_3d = ufl.as_vector((n[0], n[1], 0))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "deccdfc5", │ │ │ │ │ + "id": "3c6b8ba8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We turn our focus to the permittivity $\\varepsilon$. First, we define\n", │ │ │ │ │ "the relative permittivity $\\varepsilon_m$ of the gold wire at $400nm$.\n", │ │ │ │ │ "This data can be found in [*Olmon et al.\n", │ │ │ │ │ "2012*](https://doi.org/10.1103/PhysRevB.86.235147) or at\n", │ │ │ │ │ "[refractiveindex.info](\n", │ │ │ │ │ "https://refractiveindex.info/?shelf=main&book=Au&page=Olmon-sc)):" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "436089d7", │ │ │ │ │ + "id": "001c5f42", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps_au = -1.0782 + 1j * 5.8089" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "013f4e48", │ │ │ │ │ + "id": "9ee37667", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We define a permittivity function $\\varepsilon$ that takes the value\n", │ │ │ │ │ "of the gold permittivity $\\varepsilon_m$ for cells inside the wire,\n", │ │ │ │ │ "while it takes the value of the background permittivity otherwise:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ef29e5a5", │ │ │ │ │ + "id": "7f6b6a9a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "D = fem.functionspace(mesh_data.mesh, (\"DG\", 0))\n", │ │ │ │ │ "eps = fem.Function(D)\n", │ │ │ │ │ "au_cells = mesh_data.cell_tags.find(au_tag)\n", │ │ │ │ │ "bkg_cells = mesh_data.cell_tags.find(bkg_tag)\n", │ │ │ │ │ "eps.x.array[au_cells] = np.full_like(au_cells, eps_au, dtype=eps.x.array.dtype)\n", │ │ │ │ │ "eps.x.array[bkg_cells] = np.full_like(bkg_cells, eps_bkg, dtype=eps.x.array.dtype)\n", │ │ │ │ │ "eps.x.scatter_forward()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "822c3bc7", │ │ │ │ │ + "id": "1b3fffa9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "### Derivation of the weak formulation\n", │ │ │ │ │ "Next we derive the weak formulation of the Maxwell's equation plus\n", │ │ │ │ │ "with scattering boundary conditions. First, we take the inner products\n", │ │ │ │ │ "of the equations with a complex test function $\\mathbf{v}$, and\n", │ │ │ │ │ "integrate the terms over the corresponding domains:\n", │ │ │ │ │ @@ -785,15 +785,15 @@ │ │ │ │ │ "We use the [UFL](https://github.com/FEniCS/ufl/) to implement the\n", │ │ │ │ │ "residual" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e6ef577e", │ │ │ │ │ + "id": "8b3a5b14", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Weak form\n", │ │ │ │ │ "F = (\n", │ │ │ │ │ " -ufl.inner(ufl.curl(Es), ufl.curl(v)) * dDom\n", │ │ │ │ │ " + eps * (k0**2) * ufl.inner(Es, v) * dDom\n", │ │ │ │ │ @@ -802,34 +802,34 @@ │ │ │ │ │ " * ufl.inner(ufl.cross(Es_3d, n_3d), ufl.cross(v_3d, n_3d))\n", │ │ │ │ │ " * dsbc\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b32447b4", │ │ │ │ │ + "id": "db467c84", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Solving the variational problem" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "651320fa", │ │ │ │ │ + "id": "22182a12", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We split the residual into a sesquilinear (lhs) and linear (rhs) form\n", │ │ │ │ │ "and solve the problem. We store the scattered field $\\mathbf{E}_s$ as\n", │ │ │ │ │ "`Esh`:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c1b3d572", │ │ │ │ │ + "id": "0d64ec8b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "a, L = ufl.lhs(F), ufl.rhs(F)\n", │ │ │ │ │ "problem = LinearProblem(\n", │ │ │ │ │ " a,\n", │ │ │ │ │ " L,\n", │ │ │ │ │ @@ -839,28 +839,28 @@ │ │ │ │ │ ")\n", │ │ │ │ │ "Esh = problem.solve()\n", │ │ │ │ │ "assert problem.solver.getConvergedReason() > 0" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ae4087ac", │ │ │ │ │ + "id": "9f68ec79", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We save the solution as an [ADIOS2\n", │ │ │ │ │ "bp](https://adios2.readthedocs.io/en/latest/ecosystem/visualization.html)\n", │ │ │ │ │ "folder. In order to do so, we need to interpolate our solution\n", │ │ │ │ │ "discretized with Nedelec elements into a suitable discontinuous\n", │ │ │ │ │ "Lagrange space." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "32b78688", │ │ │ │ │ + "id": "f5e45ac9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "gdim = mesh_data.mesh.geometry.dim\n", │ │ │ │ │ "V_dg = fem.functionspace(mesh_data.mesh, (\"Discontinuous Lagrange\", degree, (gdim,)))\n", │ │ │ │ │ "Esh_dg = fem.Function(V_dg)\n", │ │ │ │ │ "assert isinstance(Esh, fem.Function)\n", │ │ │ │ │ @@ -871,28 +871,28 @@ │ │ │ │ │ " vtx.write(0.0)\n", │ │ │ │ │ "else:\n", │ │ │ │ │ " print(\"Cannot write Esh.bp: VTXWriter (adios2) is not available\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d1e37f8e", │ │ │ │ │ + "id": "47dc526e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We visualize the solution using PyVista. For more information about\n", │ │ │ │ │ "saving and visualizing vector fields discretized with Nedelec\n", │ │ │ │ │ "elements, check [this](\n", │ │ │ │ │ "https://docs.fenicsproject.org/dolfinx/main/python/demos/demo_interpolation-io.html)\n", │ │ │ │ │ "DOLFINx demo." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2513a951", │ │ │ │ │ + "id": "d29228dc", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "if have_pyvista:\n", │ │ │ │ │ " V_cells, V_types, V_x = plot.vtk_mesh(V_dg)\n", │ │ │ │ │ @@ -913,25 +913,25 @@ │ │ │ │ │ " plotter.screenshot(out_folder / \"Esh.png\", window_size=[800, 800])\n", │ │ │ │ │ " else:\n", │ │ │ │ │ " plotter.show()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5087d0d6", │ │ │ │ │ + "id": "1402b4dc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next we can calculate the total electric field\n", │ │ │ │ │ "$\\mathbf{E}=\\mathbf{E}_s+\\mathbf{E}_b$ and save it." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "28f1a348", │ │ │ │ │ + "id": "9c08c7db", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "E = fem.Function(V)\n", │ │ │ │ │ "E.x.array[:] = Eb.x.array[:] + Esh.x.array[:]\n", │ │ │ │ │ "E_dg = fem.Function(V_dg)\n", │ │ │ │ │ "E_dg.interpolate(E)\n", │ │ │ │ │ @@ -940,41 +940,41 @@ │ │ │ │ │ " vtx.write(0.0)\n", │ │ │ │ │ "else:\n", │ │ │ │ │ " print(\"Cannot write E.bp: VTXWriter (adios2) is not available\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0f190dae", │ │ │ │ │ + "id": "94dec226", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We validate our numerical solution by computing the absorption,\n", │ │ │ │ │ "scattering and extinction efficiencies, which are quantities that\n", │ │ │ │ │ "define how much light is absorbed and scattered by the wire. First of\n", │ │ │ │ │ "all, we calculate the analytical efficiencies with the\n", │ │ │ │ │ "`calculate_analytical_efficiencies` function defined in a separate\n", │ │ │ │ │ "file:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6b51a2a9", │ │ │ │ │ + "id": "0b9451fc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Calculation of analytical efficiencies\n", │ │ │ │ │ "q_abs_analyt, q_sca_analyt, q_ext_analyt = calculate_analytical_efficiencies(\n", │ │ │ │ │ " eps_au, n_bkg, wl0, radius_wire\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6b6b1844", │ │ │ │ │ + "id": "4af89e3f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Calculation of the numerical efficiencies\n", │ │ │ │ │ "Now we can calculate the numerical efficiencies. The formula for the\n", │ │ │ │ │ "absorption, scattering and extinction are:\n", │ │ │ │ │ "\n", │ │ │ │ │ "$$\n", │ │ │ │ │ @@ -1006,15 +1006,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "We can calculate these values in the following way:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ecd8e4ee", │ │ │ │ │ + "id": "e140fe71", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "Z0 = np.sqrt(mu_0 / epsilon_0) # Vacuum impedance\n", │ │ │ │ │ "Hsh_3d = -1j * curl_2d(Esh) / (Z0 * k0 * n_bkg) # Magnetic field H\n", │ │ │ │ │ "Esh_3d = ufl.as_vector((Esh[0], Esh[1], 0))\n", │ │ │ │ │ "E_3d = ufl.as_vector((E[0], E[1], 0))\n", │ │ │ │ │ @@ -1023,120 +1023,120 @@ │ │ │ │ │ "# np.sqrt(ax**2 + ay**2) = 1, see background_electric_field\n", │ │ │ │ │ "I0 = 0.5 / Z0\n", │ │ │ │ │ "gcs = 2 * radius_wire # Geometrical cross section of the wire" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "a14ac903", │ │ │ │ │ + "id": "bc8eb791", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Quantities for the calculation of efficiencies" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a7dff1d8", │ │ │ │ │ + "id": "224d245b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "P = 0.5 * ufl.inner(ufl.cross(Esh_3d, ufl.conj(Hsh_3d)), n_3d)\n", │ │ │ │ │ "Q = 0.5 * np.imag(eps_au) * k0 * (ufl.inner(E_3d, E_3d)) / Z0 / n_bkg" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "468b1e0f", │ │ │ │ │ + "id": "3676243d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Normalized absorption efficiency" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "090166c0", │ │ │ │ │ + "id": "210fe941", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dAu = dx(au_tag) # Define integration domain for the wire\n", │ │ │ │ │ "q_abs_fenics_proc = (fem.assemble_scalar(fem.form(Q * dAu)) / gcs / I0).real\n", │ │ │ │ │ "q_abs_fenics = mesh_data.mesh.comm.allreduce(q_abs_fenics_proc, op=MPI.SUM)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0a0dff5e", │ │ │ │ │ + "id": "8eab4994", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Normalized scattering efficiency" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4989cf9f", │ │ │ │ │ + "id": "4f5fc5cd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "q_sca_fenics_proc = (fem.assemble_scalar(fem.form(P * dsbc)) / gcs / I0).real\n", │ │ │ │ │ "q_sca_fenics = mesh_data.mesh.comm.allreduce(q_sca_fenics_proc, op=MPI.SUM)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "5c65c482", │ │ │ │ │ + "id": "0721483a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Extinction efficiency" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "40af88c6", │ │ │ │ │ + "id": "d91aefd1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "q_ext_fenics = q_abs_fenics + q_sca_fenics" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "4e873c33", │ │ │ │ │ + "id": "010d5404", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Error calculation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f8b3c614", │ │ │ │ │ + "id": "8d02d35e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "err_abs = np.abs(q_abs_analyt - q_abs_fenics) / q_abs_analyt\n", │ │ │ │ │ "err_sca = np.abs(q_sca_analyt - q_sca_fenics) / q_sca_analyt\n", │ │ │ │ │ "err_ext = np.abs(q_ext_analyt - q_ext_fenics) / q_ext_analyt" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fa6e0286", │ │ │ │ │ + "id": "34e2bf73", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Check if errors are smaller than 1%" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8eff55b6", │ │ │ │ │ + "id": "4ffbb81b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "assert err_abs < 0.01, \"Error in absorption efficiency is too large\"\n", │ │ │ │ │ "assert err_sca < 0.01, \"Error in scattering efficiency is too large\"\n", │ │ │ │ │ "assert err_ext < 0.01, \"Error in Extinction efficiency is too large\"\n", │ │ │ │ │ "\n", │ │ ├── ./usr/share/doc/dolfinx-doc/python/_downloads/f60c5654312263c726a60c7d3dcc6729/demo_elasticity.ipynb.gz │ │ │ ├── demo_elasticity.ipynb │ │ │ │ ├── Pretty-printed │ │ │ │ │┄ Similarity: 0.9868259803921569% │ │ │ │ │┄ Differences: {"'cells'": "{0: {'id': '79bdc3af'}, 1: {'id': 'a3d0a19c'}, 2: {'id': '24888fd5'}, 3: {'id': " │ │ │ │ │┄ "'12e8c722'}, 4: {'id': '274fcb6e'}, 5: {'id': '61bdfd59'}, 6: {'id': 'b48ceeeb'}, 7: " │ │ │ │ │┄ "{'id': 'db0b06af'}, 8: {'id': '43db0b60'}, 9: {'id': '34d8acab'}, 10: {'id': " │ │ │ │ │┄ "'292a90f1'}, 11: {'id': '50170ef6'}, 12: {'id': 'b57db624'}, 13: {'id': 'f830ed67'}, " │ │ │ │ │┄ "14: {'id': '5309f532'}, 15: {'id': 'adc774a1'}, 16: {'id': '049d05c0'}, 17: {'id': " │ │ │ │ │┄ "'fdfd33be'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fdbc1488", │ │ │ │ │ + "id": "79bdc3af", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "# Elasticity using algebraic multigrid\n", │ │ │ │ │ "\n", │ │ │ │ │ "Copyright \u00a9 2020-2022 Garth N. Wells and Michal Habera\n", │ │ │ │ │ @@ -25,15 +25,15 @@ │ │ │ │ │ "\n", │ │ │ │ │ "The required modules are first imported:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1f163449", │ │ │ │ │ + "id": "a3d0a19c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "from mpi4py import MPI\n", │ │ │ │ │ "from petsc4py import PETSc\n", │ │ │ │ │ "\n", │ │ │ │ │ "import numpy as np\n", │ │ │ │ │ @@ -54,15 +54,15 @@ │ │ │ │ │ "from dolfinx.mesh import CellType, GhostMode, create_box, locate_entities_boundary\n", │ │ │ │ │ "\n", │ │ │ │ │ "dtype = PETSc.ScalarType" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0004f2c0", │ │ │ │ │ + "id": "24888fd5", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Create the operator near-nullspace\n", │ │ │ │ │ "\n", │ │ │ │ │ "Smooth aggregation algebraic multigrid solvers require the so-called\n", │ │ │ │ │ @@ -72,15 +72,15 @@ │ │ │ │ │ "spanned by six vectors -- three translation modes and three rotation\n", │ │ │ │ │ "modes." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "db9f9a50", │ │ │ │ │ + "id": "12e8c722", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "def build_nullspace(V: FunctionSpace):\n", │ │ │ │ │ " \"\"\"Build PETSc nullspace for 3D elasticity\"\"\"\n", │ │ │ │ │ @@ -115,79 +115,79 @@ │ │ │ │ │ " PETSc.Vec().createWithArray(x[: bs * length0], bsize=3, comm=V.mesh.comm) for x in b\n", │ │ │ │ │ " ]\n", │ │ │ │ │ " return PETSc.NullSpace().create(vectors=basis_petsc)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "55dec4e0", │ │ │ │ │ + "id": "274fcb6e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Problem definition" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3192f617", │ │ │ │ │ + "id": "61bdfd59", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a {py:func}`box mesh`:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1f1f5d9a", │ │ │ │ │ + "id": "b48ceeeb", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = create_box(\n", │ │ │ │ │ " MPI.COMM_WORLD,\n", │ │ │ │ │ " [np.array([0.0, 0.0, 0.0]), np.array([2.0, 1.0, 1.0])],\n", │ │ │ │ │ " (16, 16, 16),\n", │ │ │ │ │ " CellType.tetrahedron,\n", │ │ │ │ │ " ghost_mode=GhostMode.shared_facet,\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e71f49fe", │ │ │ │ │ + "id": "db0b06af", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a centripetal source term $f = \\rho \\omega^2 [x_0, \\, x_1]$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4eb5e7bd", │ │ │ │ │ + "id": "43db0b60", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "\u03c9, \u03c1 = 300.0, 10.0\n", │ │ │ │ │ "x = ufl.SpatialCoordinate(msh)\n", │ │ │ │ │ "f = ufl.as_vector((\u03c1 * \u03c9**2 * x[0], \u03c1 * \u03c9**2 * x[1], 0.0))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "aed5b92f", │ │ │ │ │ + "id": "34d8acab", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Define the elasticity parameters and create a function that computes\n", │ │ │ │ │ "an expression for the stress given a displacement field." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "59474946", │ │ │ │ │ + "id": "292a90f1", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_end_of_cell_marker": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "E = 1.0e9\n", │ │ │ │ │ "\u03bd = 0.3\n", │ │ │ │ │ @@ -198,144 +198,144 @@ │ │ │ │ │ "def \u03c3(v):\n", │ │ │ │ │ " \"\"\"Return an expression for the stress \u03c3 given a displacement field\"\"\"\n", │ │ │ │ │ " return 2.0 * \u03bc * ufl.sym(ufl.grad(v)) + \u03bb * ufl.tr(ufl.sym(ufl.grad(v))) * ufl.Identity(len(v))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "166f0e57", │ │ │ │ │ + "id": "50170ef6", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "A function space space is created and the elasticity variational\n", │ │ │ │ │ "problem defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "8a670bbb", │ │ │ │ │ + "id": "b57db624", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "V = functionspace(msh, (\"Lagrange\", 1, (msh.geometry.dim,)))\n", │ │ │ │ │ "u, v = ufl.TrialFunction(V), ufl.TestFunction(V)\n", │ │ │ │ │ "a = form(ufl.inner(\u03c3(u), ufl.grad(v)) * ufl.dx)\n", │ │ │ │ │ "L = form(ufl.inner(f, v) * ufl.dx)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8f12fd39", │ │ │ │ │ + "id": "f830ed67", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "A homogeneous (zero) boundary condition is created on $x_0 = 0$ and\n", │ │ │ │ │ "$x_1 = 1$ by finding all facets on these boundaries, and then creating\n", │ │ │ │ │ "a Dirichlet boundary condition object." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a2f35105", │ │ │ │ │ + "id": "5309f532", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "facets = locate_entities_boundary(\n", │ │ │ │ │ " msh, dim=2, marker=lambda x: np.isclose(x[0], 0.0) | np.isclose(x[1], 1.0)\n", │ │ │ │ │ ")\n", │ │ │ │ │ "bc = dirichletbc(\n", │ │ │ │ │ " np.zeros(3, dtype=dtype), locate_dofs_topological(V, entity_dim=2, entities=facets), V=V\n", │ │ │ │ │ ")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b93ff6fc", │ │ │ │ │ + "id": "adc774a1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Assemble and solve\n", │ │ │ │ │ "\n", │ │ │ │ │ "The bilinear form `a` is assembled into a matrix `A`, with\n", │ │ │ │ │ "modifications for the Dirichlet boundary conditions. The call\n", │ │ │ │ │ "`A.assemble()` completes any parallel communication required to\n", │ │ │ │ │ "compute the matrix." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4b471b67", │ │ │ │ │ + "id": "049d05c0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "A = assemble_matrix(a, bcs=[bc])\n", │ │ │ │ │ "A.assemble()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0a096099", │ │ │ │ │ + "id": "fdfd33be", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The linear form `L` is assembled into a vector `b`, and then modified\n", │ │ │ │ │ "by {py:func}`apply_lifting ` to\n", │ │ │ │ │ "account for the Dirichlet boundary conditions. After calling\n", │ │ │ │ │ "{py:func}`apply_lifting `, the method\n", │ │ │ │ │ "`ghostUpdate` accumulates entries on the owning rank, and this is\n", │ │ │ │ │ "followed by setting the boundary values in `b`." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "821f3625", │ │ │ │ │ + "id": "3bb56c48", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "b = assemble_vector(L)\n", │ │ │ │ │ "apply_lifting(b, [a], bcs=[[bc]])\n", │ │ │ │ │ "b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)\n", │ │ │ │ │ "bc.set(b.array_w)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "90ff798b", │ │ │ │ │ + "id": "725a6612", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create the near-nullspace and attach it to the PETSc matrix:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ff087b3d", │ │ │ │ │ + "id": "d3caaafd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ns = build_nullspace(V)\n", │ │ │ │ │ "A.setNearNullSpace(ns)\n", │ │ │ │ │ "A.setOption(PETSc.Mat.Option.SPD, True)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3ede0287", │ │ │ │ │ + "id": "84ba5c78", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Set PETSc solver options, create a PETSc Krylov solver, and attach the\n", │ │ │ │ │ "matrix `A` to the solver:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5380e5e3", │ │ │ │ │ + "id": "2e32154f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "# Set solver options\n", │ │ │ │ │ "opts = PETSc.Options()\n", │ │ │ │ │ "opts[\"ksp_type\"] = \"cg\"\n", │ │ │ │ │ "opts[\"ksp_rtol\"] = 1.0e-8\n", │ │ │ │ │ @@ -354,25 +354,25 @@ │ │ │ │ │ "\n", │ │ │ │ │ "# Set matrix operator\n", │ │ │ │ │ "solver.setOperators(A)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b8c6bce4", │ │ │ │ │ + "id": "506acd5c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a solution {py:class}`Function` `uh` and\n", │ │ │ │ │ "solve:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5e204771", │ │ │ │ │ + "id": "7de962a0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "uh = Function(V)\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Set a monitor, solve linear system, and display the solver\n", │ │ │ │ │ "# configuration\n", │ │ │ │ │ @@ -382,71 +382,71 @@ │ │ │ │ │ "\n", │ │ │ │ │ "# Scatter forward the solution vector to update ghost values\n", │ │ │ │ │ "uh.x.scatter_forward()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "71ee6c50", │ │ │ │ │ + "id": "27effa18", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Post-processing\n", │ │ │ │ │ "\n", │ │ │ │ │ "The computed solution is now post-processed. Expressions for the\n", │ │ │ │ │ "deviatoric and Von Mises stress are defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2b8d1acf", │ │ │ │ │ + "id": "3746d03f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "sigma_dev = \u03c3(uh) - (1 / 3) * ufl.tr(\u03c3(uh)) * ufl.Identity(len(uh))\n", │ │ │ │ │ "sigma_vm = ufl.sqrt((3 / 2) * ufl.inner(sigma_dev, sigma_dev))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e57788ac", │ │ │ │ │ + "id": "e8e39c80", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, the Von Mises stress is interpolated in a piecewise-constant\n", │ │ │ │ │ "space by creating an {py:class}`Expression`\n", │ │ │ │ │ "that is interpolated into the\n", │ │ │ │ │ "{py:class}`Function` `sigma_vm_h`." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4b6d21fb", │ │ │ │ │ + "id": "718a85ab", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "W = functionspace(msh, (\"Discontinuous Lagrange\", 0))\n", │ │ │ │ │ "sigma_vm_expr = Expression(sigma_vm, W.element.interpolation_points)\n", │ │ │ │ │ "sigma_vm_h = Function(W)\n", │ │ │ │ │ "sigma_vm_h.interpolate(sigma_vm_expr)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0e48a6fe", │ │ │ │ │ + "id": "3c33fecd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Save displacement field `uh` and the Von Mises stress `sigma_vm_h` in\n", │ │ │ │ │ "XDMF format files." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f900c0e5", │ │ │ │ │ + "id": "aa3d37ef", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "with XDMFFile(msh.comm, \"out_elasticity/displacements.xdmf\", \"w\") as file:\n", │ │ │ │ │ " file.write_mesh(msh)\n", │ │ │ │ │ " file.write_function(uh)\n", │ │ │ │ │ "\n", │ │ │ │ │ @@ -454,38 +454,38 @@ │ │ │ │ │ "with XDMFFile(msh.comm, \"out_elasticity/von_mises_stress.xdmf\", \"w\") as file:\n", │ │ │ │ │ " file.write_mesh(msh)\n", │ │ │ │ │ " file.write_function(sigma_vm_h)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "29215cad", │ │ │ │ │ + "id": "23fcbb5c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Finally, we compute the $L^2$ norm of the displacement solution\n", │ │ │ │ │ "vector. This is a collective operation (i.e., the method\n", │ │ │ │ │ "{py:func}`norm` must be called from all MPI ranks),\n", │ │ │ │ │ "but we print the norm only on rank 0." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b6e99c2a", │ │ │ │ │ + "id": "8c66db28", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "unorm = la.norm(uh.x)\n", │ │ │ │ │ "if msh.comm.rank == 0:\n", │ │ │ │ │ " print(\"Solution vector norm:\", unorm)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "7410e6e9", │ │ │ │ │ + "id": "ef436bb5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "The solution vector norm can be a useful check that the solver is\n", │ │ │ │ │ "computing the same result when running in serial and in parallel." │ │ │ │ │ ] │ │ │ │ │ } │ │ │ │ │ ], │ │ ├── ./usr/share/doc/dolfinx-doc/python/generated/dolfinx.fem.petsc.html │ │ │ @@ -952,22 +952,22 @@ │ │ │ WARNING = 3 │ │ │
│ │ │ │ │ │ │ │ │ │ │ │
│ │ │
│ │ │ -MatSetValuesBlockedLocal = <cdata 'int(*)(void *, int32_t, int32_t *, int32_t, int32_t *, double *, int)' 0x7f23aaeb6130>
│ │ │ +MatSetValuesBlockedLocal = <cdata 'int(*)(void *, int32_t, int32_t *, int32_t, int32_t *, double *, int)' 0x7f96d4185130> │ │ │

See PETSc MatSetValuesBlockedLocal │ │ │ documentation.

│ │ │
│ │ │ │ │ │
│ │ │
│ │ │ -MatSetValuesLocal = <cdata 'int(*)(void *, int32_t, int32_t *, int32_t, int32_t *, double *, int)' 0x7f23aaeaa7b0>
│ │ │ +MatSetValuesLocal = <cdata 'int(*)(void *, int32_t, int32_t *, int32_t, int32_t *, double *, int)' 0x7f96d41797b0> │ │ │

See PETSc MatSetValuesLocal │ │ │ documentation.

│ │ │
│ │ │ │ │ │
│ │ │
│ │ │ log = <nanobind.nb_func object>
│ │ │ ├── html2text {} │ │ │ │ @@ -535,18 +535,18 @@ │ │ │ │ DEBUG = 1_ │ │ │ │ ERROR = 4_ │ │ │ │ INFO = 2_ │ │ │ │ OFF = 6_ │ │ │ │ TRACE = 0_ │ │ │ │ WARNING = 3_ │ │ │ │ MatSetValuesBlockedLocal = _ │ │ │ │ + int32_t, int32_t *, double *, int)' 0x7f96d4185130>_ │ │ │ │ See PETSc _M_a_t_S_e_t_V_a_l_u_e_s_B_l_o_c_k_e_d_L_o_c_a_l documentation. │ │ │ │ MatSetValuesLocal = _ │ │ │ │ + int32_t *, double *, int)' 0x7f96d41797b0>_ │ │ │ │ See PETSc _M_a_t_S_e_t_V_a_l_u_e_s_L_o_c_a_l documentation. │ │ │ │ log = _ │ │ │ │ dolfinx.fem.petsc.create_matrix(aa:: _FF_oo_rr_mm || _SS_ee_qq_uu_ee_nn_cc_ee[[_SS_ee_qq_uu_ee_nn_cc_ee[[_FF_oo_rr_mm]]]], kkiinndd:: ssttrr │ │ │ │ || _SS_ee_qq_uu_ee_nn_cc_ee[[_SS_ee_qq_uu_ee_nn_cc_ee[[ssttrr]]]] || NNoonnee == NNoonnee) → _M_a_t_[_s_o_u_r_c_e_]_ │ │ │ │ Create a PETSc matrix that is compatible with the (sequence) of bilinear │ │ │ │ form(s). │ │ │ │ Three cases are supported: │ │ ├── ./usr/share/doc/dolfinx-doc/python/searchindex.js │ │ │ ├── js-beautify {} │ │ │ │ @@ -5137,16 +5137,16 @@ │ │ │ │ "terms": { │ │ │ │ "0e": [3, 5, 7, 17, 22, 23], │ │ │ │ "0e5": 16, │ │ │ │ "0e6": 26, │ │ │ │ "0e9": [7, 20], │ │ │ │ "0j": 9, │ │ │ │ "0th": 13, │ │ │ │ - "0x7f23aaeaa7b0": 42, │ │ │ │ - "0x7f23aaeb6130": 42, │ │ │ │ + "0x7f96d41797b0": 42, │ │ │ │ + "0x7f96d4185130": 42, │ │ │ │ "1d": 42, │ │ │ │ "1e": [5, 9, 14, 19, 20, 24, 41, 49], │ │ │ │ "1e2": 25, │ │ │ │ "1j": [3, 9, 11, 17, 22, 26], │ │ │ │ "1st": 12, │ │ │ │ "2_0": 16, │ │ │ │ "2d": [8, 17, 22, 25, 41, 42, 46, 49],