--- /srv/rebuilderd/tmp/rebuilderd3xaDig/inputs/dolfinx-doc_0.10.0.post5-7_all.deb +++ /srv/rebuilderd/tmp/rebuilderd3xaDig/out/dolfinx-doc_0.10.0.post5-7_all.deb ├── file list │ @@ -1,3 +1,3 @@ │ -rw-r--r-- 0 0 0 4 2026-02-20 14:09:54.000000 debian-binary │ --rw-r--r-- 0 0 0 23212 2026-02-20 14:09:54.000000 control.tar.xz │ +-rw-r--r-- 0 0 0 23208 2026-02-20 14:09:54.000000 control.tar.xz │ -rw-r--r-- 0 0 0 9027916 2026-02-20 14:09:54.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-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/cpp/search/variables_b.js │ │ │ -rw-r--r-- 0 root (0) root (0) 7571 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/cpp/tabs.css │ │ │ -rw-r--r-- 0 root (0) root (0) 3657 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/cpp/topics.html │ │ │ -rw-r--r-- 0 root (0) root (0) 3859 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/index.html │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/ │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/ │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/01cebb598a9eb6f964554459de25ce7c/ │ │ │ --rw-r--r-- 0 root (0) root (0) 6930 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/01cebb598a9eb6f964554459de25ce7c/demo_stokes.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 6932 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/01cebb598a9eb6f964554459de25ce7c/demo_stokes.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08143fa77f77a4782d22e85e7aebc523/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3083 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08143fa77f77a4782d22e85e7aebc523/demo_mixed-topology.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3078 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08143fa77f77a4782d22e85e7aebc523/demo_mixed-topology.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/082c4b6b2083855631db76b9eac6b348/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2720 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/082c4b6b2083855631db76b9eac6b348/demo_pyamg.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2721 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/082c4b6b2083855631db76b9eac6b348/demo_pyamg.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08f65cab6d6efa886b6e864593d5544d/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2940 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08f65cab6d6efa886b6e864593d5544d/demo_comm-pattern.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2942 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/08f65cab6d6efa886b6e864593d5544d/demo_comm-pattern.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0aed751cd0874b28f5ae7bdc73e1060e/ │ │ │ --rw-r--r-- 0 root (0) root (0) 4227 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0aed751cd0874b28f5ae7bdc73e1060e/demo_biharmonic.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 4225 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0aed751cd0874b28f5ae7bdc73e1060e/demo_biharmonic.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0ff7b5905586c05f3ded87f72380f93b/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3183 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0ff7b5905586c05f3ded87f72380f93b/demo_lagrange_variants.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3181 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/0ff7b5905586c05f3ded87f72380f93b/demo_lagrange_variants.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/14903818ff63fe77ad13ebe2fd3c2bfa/ │ │ │ -rw-r--r-- 0 root (0) root (0) 16870 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/14903818ff63fe77ad13ebe2fd3c2bfa/demo_half_loaded_waveguide.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/16ae5ee96f6630d2b709d4fae5801c3a/ │ │ │ -rw-r--r-- 0 root (0) root (0) 6740 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/16ae5ee96f6630d2b709d4fae5801c3a/demo_mixed-topology.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1a16c2f4b29ea3e52acc5e0c69e7d325/ │ │ │ -rw-r--r-- 0 root (0) root (0) 26254 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1a16c2f4b29ea3e52acc5e0c69e7d325/demo_axis.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1a19850a673ac0912099149a21b82fe9/ │ │ │ -rw-r--r-- 0 root (0) root (0) 28277 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1a19850a673ac0912099149a21b82fe9/demo_scattering_boundary_conditions.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1c10919af1d1c2689ff1982d6e82b898/ │ │ │ --rw-r--r-- 0 root (0) root (0) 5457 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1c10919af1d1c2689ff1982d6e82b898/demo_navier-stokes.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 5459 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/1c10919af1d1c2689ff1982d6e82b898/demo_navier-stokes.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/244d514e5e2d1484e9f045150ae16a27/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2883 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/244d514e5e2d1484e9f045150ae16a27/demo_gmsh.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2886 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/244d514e5e2d1484e9f045150ae16a27/demo_gmsh.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/2582f4d86e9cdad523ac798f84ed8877/ │ │ │ -rw-r--r-- 0 root (0) root (0) 9311 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/2582f4d86e9cdad523ac798f84ed8877/demo_biharmonic.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3013bc98771f29691ef96d816a24e9b5/ │ │ │ -rw-r--r-- 0 root (0) root (0) 8437 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3013bc98771f29691ef96d816a24e9b5/demo_poisson_matrix_free.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3a2e8b3062e32f7fa335a0116fae9bef/ │ │ │ --rw-r--r-- 0 root (0) root (0) 4264 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3a2e8b3062e32f7fa335a0116fae9bef/demo_hdg.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 4267 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3a2e8b3062e32f7fa335a0116fae9bef/demo_hdg.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3e7291d3b77b3f22251cd7795a639a00/ │ │ │ -rw-r--r-- 0 root (0) root (0) 8703 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3e7291d3b77b3f22251cd7795a639a00/demo_hdg.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3f4304da118cf34f94b5991c582738c4/ │ │ │ -rw-r--r-- 0 root (0) root (0) 7065 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/3f4304da118cf34f94b5991c582738c4/demo_pyamg.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4108f87eb9b678931168ffba26e2c302/ │ │ │ -rw-r--r-- 0 root (0) root (0) 13078 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4108f87eb9b678931168ffba26e2c302/demo_mixed-poisson.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/44f4041e8551d8a922a8c3a49107aaf9/ │ │ │ @@ -914,61 +914,61 @@ │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4805c30fd9f5602435f2b34dad232ba2/ │ │ │ -rw-r--r-- 0 root (0) root (0) 8745 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4805c30fd9f5602435f2b34dad232ba2/demo_lagrange_variants.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4cfcffe5891ed56ed48568fb00a06e67/ │ │ │ -rw-r--r-- 0 root (0) root (0) 10324 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/4cfcffe5891ed56ed48568fb00a06e67/demo_static-condensation.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/51e819842c2534ea5d902f847c84b6ee/ │ │ │ -rw-r--r-- 0 root (0) root (0) 5121 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/51e819842c2534ea5d902f847c84b6ee/demo_helmholtz.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5261c2fbfdb83b277c92e92bde061504/ │ │ │ --rw-r--r-- 0 root (0) root (0) 8858 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5261c2fbfdb83b277c92e92bde061504/demo_axis.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 8863 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5261c2fbfdb83b277c92e92bde061504/demo_axis.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/56ce7e71d8c71b4d8ef7c699176dd4fd/ │ │ │ -rw-r--r-- 0 root (0) root (0) 22619 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/56ce7e71d8c71b4d8ef7c699176dd4fd/demo_stokes.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5dc7fa0449730e3256bb33fc2b2d403b/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3093 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5dc7fa0449730e3256bb33fc2b2d403b/demo_poisson.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3098 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/5dc7fa0449730e3256bb33fc2b2d403b/demo_poisson.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/67f8546536727bd5386a27073bd16e12/ │ │ │ -rw-r--r-- 0 root (0) root (0) 7983 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/67f8546536727bd5386a27073bd16e12/demo_elasticity.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/69c686705c3e4103e036ace87972a971/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2783 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/69c686705c3e4103e036ace87972a971/demo_types.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2786 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/69c686705c3e4103e036ace87972a971/demo_types.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6ad57720b461988475bd5c9286e3f111/ │ │ │ -rw-r--r-- 0 root (0) root (0) 7579 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6ad57720b461988475bd5c9286e3f111/demo_types.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6bd0b7dbffc1fd43f16bc5cd2cfeed74/ │ │ │ --rw-r--r-- 0 root (0) root (0) 4733 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6bd0b7dbffc1fd43f16bc5cd2cfeed74/demo_static-condensation.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 4734 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/6bd0b7dbffc1fd43f16bc5cd2cfeed74/demo_static-condensation.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7742577adb1c8360c8a19eea719713fc/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3759 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7742577adb1c8360c8a19eea719713fc/demo_pyvista.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3758 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7742577adb1c8360c8a19eea719713fc/demo_pyvista.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7fc5387c9d660ce24e2f50b0f79aad08/ │ │ │ -rw-r--r-- 0 root (0) root (0) 6811 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/7fc5387c9d660ce24e2f50b0f79aad08/demo_comm-pattern.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/911a7569fd30f814e5e3d622695b49c1/ │ │ │ -rw-r--r-- 0 root (0) root (0) 27719 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/911a7569fd30f814e5e3d622695b49c1/demo_pml.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/94dc1fa896703fdd4c54729bdfbf969a/ │ │ │ --rw-r--r-- 0 root (0) root (0) 10156 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/94dc1fa896703fdd4c54729bdfbf969a/demo_pml.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 10165 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/94dc1fa896703fdd4c54729bdfbf969a/demo_pml.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9561cf6cd1a70079b986f4eb31580cbd/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3870 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9561cf6cd1a70079b986f4eb31580cbd/demo_poisson_matrix_free.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3878 2026-02-20 14:09:54.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-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9b362df2c2031d4138a5021a53979414/ │ │ │ --rw-r--r-- 0 root (0) root (0) 5167 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9b362df2c2031d4138a5021a53979414/demo_cahn-hilliard.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 5163 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9b362df2c2031d4138a5021a53979414/demo_cahn-hilliard.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9ed4657d08dda04de30e6463e2f58d75/ │ │ │ --rw-r--r-- 0 root (0) root (0) 5640 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9ed4657d08dda04de30e6463e2f58d75/demo_mixed-poisson.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 5644 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/9ed4657d08dda04de30e6463e2f58d75/demo_mixed-poisson.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/a5df6747d3300b9568f25507c7fb2517/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2109 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/a5df6747d3300b9568f25507c7fb2517/demo_interpolation-io.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2105 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/a5df6747d3300b9568f25507c7fb2517/demo_interpolation-io.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b3f0523386e0521f7e6a5599627be9fc/ │ │ │ --rw-r--r-- 0 root (0) root (0) 7046 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b3f0523386e0521f7e6a5599627be9fc/demo_half_loaded_waveguide.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 7048 2026-02-20 14:09:54.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-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b94ac7be61dc3726ca331afd20f195d2/ │ │ │ -rw-r--r-- 0 root (0) root (0) 6231 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/b94ac7be61dc3726ca331afd20f195d2/demo_poisson.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c13ef8eb7697276d5c6443a7049d2298/ │ │ │ -rw-r--r-- 0 root (0) root (0) 12043 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c13ef8eb7697276d5c6443a7049d2298/demo_pyvista.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c202a2458472f1e0e385ed9afdc3da0f/ │ │ │ --rw-r--r-- 0 root (0) root (0) 2702 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c202a2458472f1e0e385ed9afdc3da0f/demo_helmholtz.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 2706 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/c202a2458472f1e0e385ed9afdc3da0f/demo_helmholtz.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e5597ff2b0334295de2749391a1ffbe1/ │ │ │ --rw-r--r-- 0 root (0) root (0) 4513 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e5597ff2b0334295de2749391a1ffbe1/demo_tnt-elements.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 4518 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e5597ff2b0334295de2749391a1ffbe1/demo_tnt-elements.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e8140d02a100265518e126a3cfe79d8e/ │ │ │ -rw-r--r-- 0 root (0) root (0) 4245 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e8140d02a100265518e126a3cfe79d8e/demo_interpolation-io.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e8b180b39a27d7b04c2f666d14475ee3/ │ │ │ -rw-r--r-- 0 root (0) root (0) 11391 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/e8b180b39a27d7b04c2f666d14475ee3/demo_cahn-hilliard.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/eb193fc2ce46146f29b3c38146a5a3cb/ │ │ │ --rw-r--r-- 0 root (0) root (0) 10147 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/eb193fc2ce46146f29b3c38146a5a3cb/demo_scattering_boundary_conditions.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 10154 2026-02-20 14:09:54.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-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f60c5654312263c726a60c7d3dcc6729/ │ │ │ --rw-r--r-- 0 root (0) root (0) 3935 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f60c5654312263c726a60c7d3dcc6729/demo_elasticity.ipynb.gz │ │ │ +-rw-r--r-- 0 root (0) root (0) 3941 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f60c5654312263c726a60c7d3dcc6729/demo_elasticity.ipynb.gz │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f6f3cc4d9540871af057920d1ddb5561/ │ │ │ -rw-r--r-- 0 root (0) root (0) 11682 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_downloads/f6f3cc4d9540871af057920d1ddb5561/demo_tnt-elements.py │ │ │ drwxr-xr-x 0 root (0) root (0) 0 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_images/ │ │ │ -rw-r--r-- 0 root (0) root (0) 67993 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_images/demo_lagrange_variants_equispaced_10.png │ │ │ -rw-r--r-- 0 root (0) root (0) 41664 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_images/demo_lagrange_variants_gll_10.png │ │ │ -rw-r--r-- 0 root (0) root (0) 42191 2026-02-20 14:09:54.000000 ./usr/share/doc/dolfinx-doc/python/_images/demo_lagrange_variants_interpolation_equispaced.png │ │ │ -rw-r--r-- 0 root (0) root (0) 41221 2026-02-20 14:09:54.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': '7e75ec17'}, 1: {'id': 'd33cf09e'}, 2: {'id': '1d650531'}, 3: {'id': " │ │ │ │ │┄ "'1cd62235'}, 4: {'id': '33112c57'}, 5: {'id': 'ef7cebfe'}, 6: {'id': 'be6fa851'}, 7: " │ │ │ │ │┄ "{'id': 'bbd01f94'}, 8: {'id': '0fbab7f8'}, 9: {'id': '45033c79'}, 10: {'id': " │ │ │ │ │┄ "'39580bf7'}, 11: {'id': '335415a6'}, 12: {'id': '9ca00932'}, 13: {'id': 'cb9c4a4e'}, " │ │ │ │ │┄ "14: {'id': '3f8ba706'}, 15: {'id': '4125e595'}, 16: {'id': '1cb24820'}, 17: {'id': " │ │ │ │ │┄ "'f1453f8b'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "93aa2e87", │ │ │ │ │ + "id": "7e75ec17", │ │ │ │ │ "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": "cfe17512", │ │ │ │ │ + "id": "d33cf09e", │ │ │ │ │ "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": "e2c77f0d", │ │ │ │ │ + "id": "1d650531", │ │ │ │ │ "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": "5a75929a", │ │ │ │ │ + "id": "1cd62235", │ │ │ │ │ "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": "590f28bf", │ │ │ │ │ + "id": "33112c57", │ │ │ │ │ "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": "2dd60921", │ │ │ │ │ + "id": "ef7cebfe", │ │ │ │ │ "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": "5b2d0b0d", │ │ │ │ │ + "id": "be6fa851", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Boundary conditions for the velocity field are defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "192ed7d3", │ │ │ │ │ + "id": "bbd01f94", │ │ │ │ │ "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": "3b0dda2b", │ │ │ │ │ + "id": "0fbab7f8", │ │ │ │ │ "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": "fbb57bc7", │ │ │ │ │ + "id": "45033c79", │ │ │ │ │ "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": "7ac6b822", │ │ │ │ │ + "id": "39580bf7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "A block-diagonal preconditioner will be used with the iterative\n", │ │ │ │ │ "solvers for this problem:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4b859d4b", │ │ │ │ │ + "id": "335415a6", │ │ │ │ │ "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": "6619d504", │ │ │ │ │ + "id": "9ca00932", │ │ │ │ │ "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": "41c3f2fb", │ │ │ │ │ + "id": "cb9c4a4e", │ │ │ │ │ "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": "1e38ee6b", │ │ │ │ │ + "id": "3f8ba706", │ │ │ │ │ "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": "e9617948", │ │ │ │ │ + "id": "4125e595", │ │ │ │ │ "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": "7ab83a18", │ │ │ │ │ + "id": "1cb24820", │ │ │ │ │ "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": "21365443", │ │ │ │ │ + "id": "f1453f8b", │ │ │ │ │ "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": "58ab06b8", │ │ │ │ │ + "id": "e3fc164f", │ │ │ │ │ "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": "2004d6fc", │ │ │ │ │ + "id": "211df15f", │ │ │ │ │ "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": "850bbb62", │ │ │ │ │ + "id": "89e77741", │ │ │ │ │ "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": "cd8d2084", │ │ │ │ │ + "id": "3bab38ea", │ │ │ │ │ "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": "aa2e46c5", │ │ │ │ │ + "id": "9bbb4343", │ │ │ │ │ "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": "3953c73a", │ │ │ │ │ + "id": "79a72f08", │ │ │ │ │ "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": "92ae1d73", │ │ │ │ │ + "id": "52dfe8fc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using LinearProblem class" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "3c5423c8", │ │ │ │ │ + "id": "9a05d814", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "norm_u_0, norm_p_0 = nested_iterative_solver_high_level()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c9bc13b8", │ │ │ │ │ + "id": "c2f8c268", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using PETSc MatNest" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e290fc82", │ │ │ │ │ + "id": "532e7827", │ │ │ │ │ "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": "d9561ef3", │ │ │ │ │ + "id": "019c6493", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using PETSc block matrices and an iterative solver" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "34178ca9", │ │ │ │ │ + "id": "676d8dad", │ │ │ │ │ "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": "5a3e95cd", │ │ │ │ │ + "id": "7c923d8e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using PETSc block matrices and an LU solver" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "cafb7923", │ │ │ │ │ + "id": "36bcd64e", │ │ │ │ │ "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": "2b227832", │ │ │ │ │ + "id": "14b4d4c7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve using a non-blocked matrix and an LU solver" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c299f333", │ │ │ │ │ + "id": "169908f9", │ │ │ │ │ "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': 'fa0a8dee'}, 1: {'id': 'f538404e'}, 2: {'id': '033744d7'}, 3: {'id': " │ │ │ │ │┄ "'addec1d1'}, 4: {'id': '43ea39c2'}, 5: {'id': '3c69c68c'}, 6: {'id': 'a84fbbcc'}, 7: " │ │ │ │ │┄ "{'id': '24e30c90'}, 8: {'id': 'a45f6194'}, 9: {'id': 'def55614'}, 10: {'id': " │ │ │ │ │┄ "'8564c698'}, 11: {'id': '7c92d45a'}, 12: {'id': 'e768a0af'}, 13: {'id': '72b292a2'}, " │ │ │ │ │┄ "14: {'id': '33ad3a9e'}, 15: {'id': '5376a8bc'}, 16: {'id': '8b44cc06'}, 17: {'id': " │ │ │ │ │┄ "'e1023e7f'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1e60cb09", │ │ │ │ │ + "id": "fa0a8dee", │ │ │ │ │ "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": "1275e56a", │ │ │ │ │ + "id": "f538404e", │ │ │ │ │ "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": "3177bc88", │ │ │ │ │ + "id": "033744d7", │ │ │ │ │ "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": "024f819c", │ │ │ │ │ + "id": "addec1d1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Create a mixed-topology mesh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "a5fb14c3", │ │ │ │ │ + "id": "43ea39c2", │ │ │ │ │ "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": "2f705a17", │ │ │ │ │ + "id": "3c69c68c", │ │ │ │ │ "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": "0ac40915", │ │ │ │ │ + "id": "a84fbbcc", │ │ │ │ │ "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": "c3e3f761", │ │ │ │ │ + "id": "24e30c90", │ │ │ │ │ "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": "a27a3f97", │ │ │ │ │ + "id": "a45f6194", │ │ │ │ │ "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": "12ebd00e", │ │ │ │ │ + "id": "def55614", │ │ │ │ │ "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": "3d69490b", │ │ │ │ │ + "id": "8564c698", │ │ │ │ │ "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": "5b164640", │ │ │ │ │ + "id": "7c92d45a", │ │ │ │ │ "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": "0e1d3042", │ │ │ │ │ + "id": "e768a0af", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "A = assemble_matrix(a_form)\n", │ │ │ │ │ "b = assemble_vector(L_form)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "63b229c6", │ │ │ │ │ + "id": "72b292a2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We use {py:func}`scipy.sparse.linalg.spsolve` to solve the\n", │ │ │ │ │ "resulting linear system" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "cb766ebb", │ │ │ │ │ + "id": "33ad3a9e", │ │ │ │ │ "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": "52098525", │ │ │ │ │ + "id": "5376a8bc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "print(f\"Solution vector norm {np.linalg.norm(x)}\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "59e09e58", │ │ │ │ │ + "id": "8b44cc06", │ │ │ │ │ "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": "1239472a", │ │ │ │ │ + "id": "e1023e7f", │ │ │ │ │ "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': '769be130'}, 1: {'id': '56de42cd'}, 2: {'id': '09a7276c'}, 3: {'id': " │ │ │ │ │┄ "'377148b6'}, 4: {'id': '4e52b3dc'}, 5: {'id': 'ec2b065d'}, 6: {'id': '0fd773c9'}, 7: " │ │ │ │ │┄ "{'id': '6d46e8c2'}, 8: {'id': '6c0d3475'}, 9: {'id': 'e311c5f5'}, 10: {'id': " │ │ │ │ │┄ "'9702cf32'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c5d2d2cc", │ │ │ │ │ + "id": "769be130", │ │ │ │ │ "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": "6495879b", │ │ │ │ │ + "id": "56de42cd", │ │ │ │ │ "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": "7a65962f", │ │ │ │ │ + "id": "09a7276c", │ │ │ │ │ "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": "1e4660d0", │ │ │ │ │ + "id": "377148b6", │ │ │ │ │ "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": "74c2ffda", │ │ │ │ │ + "id": "4e52b3dc", │ │ │ │ │ "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": "cc0a5ad3", │ │ │ │ │ + "id": "ec2b065d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve Poission problem with different scalar types" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "01e786f7", │ │ │ │ │ + "id": "0fd773c9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "poisson_problem(np.float32, \"ruge_stuben\")\n", │ │ │ │ │ "poisson_problem(np.float64, \"ruge_stuben\")" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "bff10f38", │ │ │ │ │ + "id": "6d46e8c2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "For complex, pyamg requires smoothed aggregation multigrid" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "27ba9832", │ │ │ │ │ + "id": "6c0d3475", │ │ │ │ │ "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": "fda61554", │ │ │ │ │ + "id": "e311c5f5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve elasticity problem with different scalar types" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b8baad18", │ │ │ │ │ + "id": "9702cf32", │ │ │ │ │ "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': 'aa70553d'}, 1: {'id': '754f6139'}, 2: {'id': 'fb90472c'}, 3: {'id': " │ │ │ │ │┄ "'0f9c5de8'}, 4: {'id': '264569f3'}, 5: {'id': '1d66ef9b'}, 6: {'id': 'ba8391cf'}, 7: " │ │ │ │ │┄ "{'id': '847f5c22'}, 8: {'id': '4cd400ec'}, 9: {'id': '5f76104d'}, 10: {'id': " │ │ │ │ │┄ "'8364c4bc'}, 11: {'id': 'c1874320'}, 12: {'id': '8aecc307'}, 13: {'id': 'f6e0a252'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "bbdb53dc", │ │ │ │ │ + "id": "aa70553d", │ │ │ │ │ "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": "42093952", │ │ │ │ │ + "id": "754f6139", │ │ │ │ │ "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": "1a186e2e", │ │ │ │ │ + "id": "fb90472c", │ │ │ │ │ "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": "af5c00cc", │ │ │ │ │ + "id": "0f9c5de8", │ │ │ │ │ "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": "cc0f279b", │ │ │ │ │ + "id": "264569f3", │ │ │ │ │ "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": "d72f1a3f", │ │ │ │ │ + "id": "1d66ef9b", │ │ │ │ │ "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": "105ce471", │ │ │ │ │ + "id": "ba8391cf", │ │ │ │ │ "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": "ce48d633", │ │ │ │ │ + "id": "847f5c22", │ │ │ │ │ "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": "e4d837de", │ │ │ │ │ + "id": "4cd400ec", │ │ │ │ │ "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": "b1274bb4", │ │ │ │ │ + "id": "5f76104d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "comm_graph = graph.comm_graph(V.dofmap.index_map)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c61d230b", │ │ │ │ │ + "id": "8364c4bc", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "A function for printing some communication graph metrics:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "31a48f68", │ │ │ │ │ + "id": "c1874320", │ │ │ │ │ "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": "8c3820bb", │ │ │ │ │ + "id": "8aecc307", │ │ │ │ │ "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": "838020fe", │ │ │ │ │ + "id": "f6e0a252", │ │ │ │ │ "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': '20097682'}, 1: {'id': 'a01c2f84'}, 2: {'id': '0b663b98'}, 3: {'id': " │ │ │ │ │┄ "'27d18974'}, 4: {'id': 'd535d22f'}, 5: {'id': 'adc956bc'}, 6: {'id': '2a925d0f'}, 7: " │ │ │ │ │┄ "{'id': 'b861b6b0'}, 8: {'id': 'eecc34d1'}, 9: {'id': '14754a84'}, 10: {'id': " │ │ │ │ │┄ "'3733555f'}, 11: {'id': '4aea963b'}, 12: {'id': '8ecea6ba'}, 13: {'id': '964f773d'}, " │ │ │ │ │┄ "14: {'id': '62b508e9'}, 15: {'id': '2fe5e974'}, 16: {'id': '4dc92d2e'}, 17: {'id': " │ │ │ │ │┄ "'c9764053'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3272d60e", │ │ │ │ │ + "id": "20097682", │ │ │ │ │ "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": "ea118159", │ │ │ │ │ + "id": "a01c2f84", │ │ │ │ │ "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": "bf9e59a5", │ │ │ │ │ + "id": "0b663b98", │ │ │ │ │ "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": "801e19ed", │ │ │ │ │ + "id": "27d18974", │ │ │ │ │ "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": "5f8e2bff", │ │ │ │ │ + "id": "d535d22f", │ │ │ │ │ "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": "71977f8e", │ │ │ │ │ + "id": "adc956bc", │ │ │ │ │ "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": "05de097b", │ │ │ │ │ + "id": "2a925d0f", │ │ │ │ │ "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": "2750cda7", │ │ │ │ │ + "id": "b861b6b0", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dofs = fem.locate_dofs_topological(V=V, entity_dim=1, entities=facets)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "585e5771", │ │ │ │ │ + "id": "eecc34d1", │ │ │ │ │ "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": "197f434e", │ │ │ │ │ + "id": "14754a84", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc = fem.dirichletbc(value=ScalarType(0), dofs=dofs, V=V)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "cc7112d8", │ │ │ │ │ + "id": "3733555f", │ │ │ │ │ "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": "67542280", │ │ │ │ │ + "id": "4aea963b", │ │ │ │ │ "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": "4542e544", │ │ │ │ │ + "id": "8ecea6ba", │ │ │ │ │ "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": "228ffa41", │ │ │ │ │ + "id": "964f773d", │ │ │ │ │ "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": "18f8c132", │ │ │ │ │ + "id": "62b508e9", │ │ │ │ │ "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": "376568b2", │ │ │ │ │ + "id": "2fe5e974", │ │ │ │ │ "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": "0ff96c6e", │ │ │ │ │ + "id": "4dc92d2e", │ │ │ │ │ "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": "2f819636", │ │ │ │ │ + "id": "c9764053", │ │ │ │ │ "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": "6cdf4d11", │ │ │ │ │ + "id": "a2c5e955", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and displayed using [pyvista](https://docs.pyvista.org/)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6422721b", │ │ │ │ │ + "id": "faa673a7", │ │ │ │ │ "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': '7d69c669'}, 1: {'id': '1298dca1'}, 2: {'id': '99cd6e2c'}, 3: {'id': " │ │ │ │ │┄ "'1e0e498b'}, 4: {'id': '2c05ecaa'}, 5: {'id': '57d292be'}, 6: {'id': 'b7738be6'}, 7: " │ │ │ │ │┄ "{'id': 'd79ae0ee'}, 8: {'id': '126f7909'}, 9: {'id': 'c511d8ab'}, 10: {'id': " │ │ │ │ │┄ "'af1271e8'}, 11: {'id': 'f2d7317a'}, 12: {'id': '4250b7bd'}, 13: {'id': 'cd8c68fe'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "97d2e905", │ │ │ │ │ + "id": "7d69c669", │ │ │ │ │ "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": "42d7fff8", │ │ │ │ │ + "id": "1298dca1", │ │ │ │ │ "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": "96978e2b", │ │ │ │ │ + "id": "99cd6e2c", │ │ │ │ │ "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": "770366cc", │ │ │ │ │ + "id": "1e0e498b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "N = 20" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d772ee21", │ │ │ │ │ + "id": "2c05ecaa", │ │ │ │ │ "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": "b9e59c43", │ │ │ │ │ + "id": "57d292be", │ │ │ │ │ "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": "22b8a6a4", │ │ │ │ │ + "id": "b7738be6", │ │ │ │ │ "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": "8728e872", │ │ │ │ │ + "id": "d79ae0ee", │ │ │ │ │ "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": "09ab80c8", │ │ │ │ │ + "id": "126f7909", │ │ │ │ │ "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": "c70b0388", │ │ │ │ │ + "id": "c511d8ab", │ │ │ │ │ "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": "1bd5b10e", │ │ │ │ │ + "id": "af1271e8", │ │ │ │ │ "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": "4b62f346", │ │ │ │ │ + "id": "f2d7317a", │ │ │ │ │ "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": "ebe6d818", │ │ │ │ │ + "id": "4250b7bd", │ │ │ │ │ "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": "e2501f73", │ │ │ │ │ + "id": "cd8c68fe", │ │ │ │ │ "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': '4ce621bf'}, 1: {'id': '4b3506b2'}, 2: {'id': '987496cd'}, 3: {'id': " │ │ │ │ │┄ "'e769685c'}, 4: {'id': '3907f26c'}, 5: {'id': '76263fac'}, 6: {'id': '5ecede48'}, 7: " │ │ │ │ │┄ "{'id': 'a09dcaca'}, 8: {'id': 'f548b97e'}, 9: {'id': 'fb9f9f91'}, 10: {'id': " │ │ │ │ │┄ "'197bbe50'}, 11: {'id': '3c145801'}, 12: {'id': 'a15325a9'}, 13: {'id': '56cfa42d'}, " │ │ │ │ │┄ "14: {'id': 'b6c2babc'}, 15: {'id': 'e8f2bf6c'}, 16: {'id': 'b4b421fc'}, 17: {'id': " │ │ │ │ │┄ "'31cb53e1'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e1068fa3", │ │ │ │ │ + "id": "4ce621bf", │ │ │ │ │ "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": "b9de601e", │ │ │ │ │ + "id": "4b3506b2", │ │ │ │ │ "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": "2c0c7d6f", │ │ │ │ │ + "id": "987496cd", │ │ │ │ │ "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": "72ffb532", │ │ │ │ │ + "id": "e769685c", │ │ │ │ │ "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": "86ac49fa", │ │ │ │ │ + "id": "3907f26c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We define some simulation parameters" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4c9f786d", │ │ │ │ │ + "id": "76263fac", │ │ │ │ │ "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": "c17c9afc", │ │ │ │ │ + "id": "5ecede48", │ │ │ │ │ "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": "a31e5e7e", │ │ │ │ │ + "id": "a09dcaca", │ │ │ │ │ "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": "3eefd4c7", │ │ │ │ │ + "id": "f548b97e", │ │ │ │ │ "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": "14f261e9", │ │ │ │ │ + "id": "fb9f9f91", │ │ │ │ │ "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": "4b2e2675", │ │ │ │ │ + "id": "197bbe50", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create the {py:class}`Dirichlet boundary condition\n", │ │ │ │ │ "`" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "86adfd8f", │ │ │ │ │ + "id": "3c145801", │ │ │ │ │ "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": "41f13721", │ │ │ │ │ + "id": "a15325a9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and solve the problem for the initial condition" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e906a05e", │ │ │ │ │ + "id": "56cfa42d", │ │ │ │ │ "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": "97419faa", │ │ │ │ │ + "id": "b6c2babc", │ │ │ │ │ "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": "f6916ea5", │ │ │ │ │ + "id": "e8f2bf6c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "p_h.x.array[:] -= domain_average(msh, p_h)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9745388f", │ │ │ │ │ + "id": "b4b421fc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Write initial condition to file" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1621bbce", │ │ │ │ │ + "id": "31cb53e1", │ │ │ │ │ "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": "7f08dc58", │ │ │ │ │ + "id": "1f583845", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create function to store solution and previous time step" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "b6be84c9", │ │ │ │ │ + "id": "e26539c5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "u_n = fem.Function(V, name=\"u_prev\")\n", │ │ │ │ │ "u_n.x.array[:] = u_h.x.array" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "be8262da", │ │ │ │ │ + "id": "13cce945", │ │ │ │ │ "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": "c72a1065", │ │ │ │ │ + "id": "789e95be", │ │ │ │ │ "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": "72878f6d", │ │ │ │ │ + "id": "c4744359", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We perform the time-stepping as a for-loop" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "59aab3f2", │ │ │ │ │ + "id": "0e707450", │ │ │ │ │ "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": "317f0630", │ │ │ │ │ + "id": "0d3431a9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we compare the computed solution to the exact solution" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4d316a70", │ │ │ │ │ + "id": "723bd754", │ │ │ │ │ "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": "2a46c598", │ │ │ │ │ + "id": "d952d7b8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "This scheme conserves mass exactly, so we check this" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ad84ecc3", │ │ │ │ │ + "id": "4cf158ab", │ │ │ │ │ "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': 'acf85520'}, 1: {'id': '38f9d69f'}, 2: {'id': 'eda4a47a'}, 3: {'id': " │ │ │ │ │┄ "'07576532'}, 4: {'id': '540275d6'}, 5: {'id': '07f43f3c'}, 6: {'id': 'c1046fa7'}, 7: " │ │ │ │ │┄ "{'id': '4efcd322'}, 8: {'id': '32f1a860'}, 9: {'id': 'b8a166d5'}, 10: {'id': " │ │ │ │ │┄ "'2944e5fa'}, 11: {'id': 'cdee1451'}, 12: {'id': '7a0adb5c'}, 13: {'id': '693b30d6'}, " │ │ │ │ │┄ "14: {'id': '2ff9ce64'}, 15: {'id': '98a63a1d'}, 16: {'id': 'dacd25c7'}, 17: {'id': " │ │ │ │ │┄ "'39595a2f'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "990bfd25", │ │ │ │ │ + "id": "acf85520", │ │ │ │ │ "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": "5d125322", │ │ │ │ │ + "id": "38f9d69f", │ │ │ │ │ "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": "349342f8", │ │ │ │ │ + "id": "eda4a47a", │ │ │ │ │ "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": "f105700c", │ │ │ │ │ + "id": "07576532", │ │ │ │ │ "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": "bc97e6da", │ │ │ │ │ + "id": "540275d6", │ │ │ │ │ "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": "df8ed27c", │ │ │ │ │ + "id": "07f43f3c", │ │ │ │ │ "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": "92bedea1", │ │ │ │ │ + "id": "c1046fa7", │ │ │ │ │ "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": "11b7a8c6", │ │ │ │ │ + "id": "4efcd322", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Generate meshes" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "17a8598b", │ │ │ │ │ + "id": "32f1a860", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a Gmsh model and set the verbosity level." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ed90113a", │ │ │ │ │ + "id": "b8a166d5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "gmsh.initialize()\n", │ │ │ │ │ "gmsh.option.setNumber(\"General.Terminal\", 0)\n", │ │ │ │ │ "\n", │ │ │ │ │ "# Create model\n", │ │ │ │ │ "model = gmsh.model()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "a8f75bc2", │ │ │ │ │ + "id": "2944e5fa", │ │ │ │ │ "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": "5cf680ea", │ │ │ │ │ + "id": "cdee1451", │ │ │ │ │ "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": "d911c1cb", │ │ │ │ │ + "id": "7a0adb5c", │ │ │ │ │ "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": "9fd771e0", │ │ │ │ │ + "id": "693b30d6", │ │ │ │ │ "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": "9e1d624b", │ │ │ │ │ + "id": "2ff9ce64", │ │ │ │ │ "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": "dadcdb20", │ │ │ │ │ + "id": "98a63a1d", │ │ │ │ │ "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": "eca5e16e", │ │ │ │ │ + "id": "dacd25c7", │ │ │ │ │ "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": "ab40fdb3", │ │ │ │ │ + "id": "39595a2f", │ │ │ │ │ "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": "ba7e9196", │ │ │ │ │ + "id": "e57ed7f5", │ │ │ │ │ "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': '360a25af'}, 1: {'id': 'cc99fa17'}, 2: {'id': '76d331d3'}, 3: {'id': " │ │ │ │ │┄ "'e74c3498'}, 4: {'id': 'a338ef32'}, 5: {'id': 'd8055dbc'}, 6: {'id': '528e3ceb'}, 7: " │ │ │ │ │┄ "{'id': '485d1751'}, 8: {'id': '668d949f'}, 9: {'id': 'bbc294df'}, 10: {'id': " │ │ │ │ │┄ "'d4d4e8a9'}, 11: {'id': '21a76109'}, 12: {'id': '518bc7a7'}, 13: {'id': '733b7eb5'}, " │ │ │ │ │┄ "14: {'id': '520f60b6'}, 15: {'id': '1894ce9e'}, 16: {'id': 'ed1f33e5'}, 17: {'id': " │ │ │ │ │┄ "'34f5a934'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b651fef0", │ │ │ │ │ + "id": "360a25af", │ │ │ │ │ "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": "90273a2c", │ │ │ │ │ + "id": "cc99fa17", │ │ │ │ │ "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": "cf098664", │ │ │ │ │ + "id": "76d331d3", │ │ │ │ │ "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": "0d82cde9", │ │ │ │ │ + "id": "e74c3498", │ │ │ │ │ "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": "8661ec25", │ │ │ │ │ + "id": "a338ef32", │ │ │ │ │ "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": "f1b59be6", │ │ │ │ │ + "id": "d8055dbc", │ │ │ │ │ "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": "1766622d", │ │ │ │ │ + "id": "528e3ceb", │ │ │ │ │ "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": "000fd1e8", │ │ │ │ │ + "id": "485d1751", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "comm = MPI.COMM_WORLD\n", │ │ │ │ │ "rank = comm.rank\n", │ │ │ │ │ "dtype = PETSc.ScalarType" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "49896314", │ │ │ │ │ + "id": "668d949f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create the mesh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d3a882eb", │ │ │ │ │ + "id": "bbc294df", │ │ │ │ │ "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": "e3dbd860", │ │ │ │ │ + "id": "d4d4e8a9", │ │ │ │ │ "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": "1141b959", │ │ │ │ │ + "id": "21a76109", │ │ │ │ │ "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": "c78485ec", │ │ │ │ │ + "id": "518bc7a7", │ │ │ │ │ "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": "70996405", │ │ │ │ │ + "id": "733b7eb5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "facet_mesh, facet_mesh_emap = mesh.create_submesh(msh, fdim, facets)[:2]" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "39affa27", │ │ │ │ │ + "id": "520f60b6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Define function spaces" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "cac64fea", │ │ │ │ │ + "id": "1894ce9e", │ │ │ │ │ "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": "be3b0556", │ │ │ │ │ + "id": "ed1f33e5", │ │ │ │ │ "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": "598123ac", │ │ │ │ │ + "id": "34f5a934", │ │ │ │ │ "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": "ff88eac7", │ │ │ │ │ + "id": "ccf447e1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Define integration measures" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "26571fdd", │ │ │ │ │ + "id": "c089778f", │ │ │ │ │ "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": "4aff017f", │ │ │ │ │ + "id": "57f18d47", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dx_c = ufl.Measure(\"dx\", domain=msh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e9fe9a30", │ │ │ │ │ + "id": "d0461838", │ │ │ │ │ "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": "b4fd46c5", │ │ │ │ │ + "id": "2bb8ff7a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "cell_boundary_facets = compute_cell_boundary_facets(msh)\n", │ │ │ │ │ "cell_boundaries = 1 # A tag" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e46882a6", │ │ │ │ │ + "id": "93ef893d", │ │ │ │ │ "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": "f122660c", │ │ │ │ │ + "id": "df6b8b1f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a cell integral measure over the facet mesh" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6184f783", │ │ │ │ │ + "id": "2af49aa5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dx_f = ufl.Measure(\"dx\", domain=facet_mesh)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2e92c250", │ │ │ │ │ + "id": "d5c7ccca", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Variational formulation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "bc10e6a9", │ │ │ │ │ + "id": "fed6403f", │ │ │ │ │ "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": "ff4d02a8", │ │ │ │ │ + "id": "b97037a8", │ │ │ │ │ "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": "b0290a5f", │ │ │ │ │ + "id": "949fca37", │ │ │ │ │ "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": "bd0861a6", │ │ │ │ │ + "id": "602dc6a2", │ │ │ │ │ "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": "52005277", │ │ │ │ │ + "id": "ac0abe49", │ │ │ │ │ "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": "a6d42c17", │ │ │ │ │ + "id": "590ca263", │ │ │ │ │ "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": "0a40bd5e", │ │ │ │ │ + "id": "bdd02783", │ │ │ │ │ "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": "f2a10be4", │ │ │ │ │ + "id": "43ec0416", │ │ │ │ │ "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": "579590b7", │ │ │ │ │ + "id": "cdd3a4e2", │ │ │ │ │ "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": "332cd51e", │ │ │ │ │ + "id": "9ce86e0a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dofs = fem.locate_dofs_topological(V=V, entity_dim=1, entities=facets)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "8e8daeeb", │ │ │ │ │ + "id": "4f3fbea1", │ │ │ │ │ "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": "b8267abc", │ │ │ │ │ + "id": "52ca3b84", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc = fem.dirichletbc(value=ScalarType(0), dofs=dofs, V=V)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "1479a2a7", │ │ │ │ │ + "id": "60ab829b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, the variational problem is defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5dfdbc44", │ │ │ │ │ + "id": "69d136f9", │ │ │ │ │ "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": "37cddb81", │ │ │ │ │ + "id": "16c8cfc3", │ │ │ │ │ "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": "aa9e5aa3", │ │ │ │ │ + "id": "91559148", │ │ │ │ │ "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": "37469b39", │ │ │ │ │ + "id": "711d69d6", │ │ │ │ │ "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": "30ac4ebd", │ │ │ │ │ + "id": "38224386", │ │ │ │ │ "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": "7004a036", │ │ │ │ │ + "id": "fbf26aa6", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "and displayed using [pyvista](https://docs.pyvista.org/)." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "88f7228f", │ │ │ │ │ + "id": "d806afc5", │ │ │ │ │ "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': '7e7c7e7a'}, 1: {'id': '148c97db'}, 2: {'id': '421996bd'}, 3: {'id': " │ │ │ │ │┄ "'369e3ca1'}, 4: {'id': 'ce858dc2'}, 5: {'id': 'f6295e9e'}, 6: {'id': 'ec292593'}, 7: " │ │ │ │ │┄ "{'id': 'd7985385'}, 8: {'id': '2236f958'}, 9: {'id': 'cd9cf1dc'}, 10: {'id': " │ │ │ │ │┄ "'b39c482d'}, 11: {'id': 'f6ef7cdc'}, 12: {'id': '9b97ef89'}, 13: {'id': '2e5aa177'}, " │ │ │ │ │┄ "14: {'id': '4b509bf4'}, 15: {'id': '804a9182'}}"} │ │ │ │ │ @@ -1,26 +1,26 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ae9e0c26", │ │ │ │ │ + "id": "7e7c7e7a", │ │ │ │ │ "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": "ff5231d2", │ │ │ │ │ + "id": "148c97db", │ │ │ │ │ "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": "390afa09", │ │ │ │ │ + "id": "421996bd", │ │ │ │ │ "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": "d6123c01", │ │ │ │ │ + "id": "369e3ca1", │ │ │ │ │ "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": "51290298", │ │ │ │ │ + "id": "ce858dc2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "comm = MPI.COMM_SELF" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "adeb6c53", │ │ │ │ │ + "id": "f6295e9e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create an output directory for storing results and figures" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "f84f89dd", │ │ │ │ │ + "id": "ec292593", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "out_folder = Path(\"out_types\")\n", │ │ │ │ │ "out_folder.mkdir(parents=True, exist_ok=True)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "cef448b7", │ │ │ │ │ + "id": "d7985385", │ │ │ │ │ "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": "b73905dd", │ │ │ │ │ + "id": "2236f958", │ │ │ │ │ "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": "f1bc8334", │ │ │ │ │ + "id": "cd9cf1dc", │ │ │ │ │ "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": "a7cf8b16", │ │ │ │ │ + "id": "b39c482d", │ │ │ │ │ "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": "38a75da2", │ │ │ │ │ + "id": "f6ef7cdc", │ │ │ │ │ "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": "4fc68023", │ │ │ │ │ + "id": "9b97ef89", │ │ │ │ │ "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": "127775b7", │ │ │ │ │ + "id": "2e5aa177", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Solve problems for different types" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4195376c", │ │ │ │ │ + "id": "4b509bf4", │ │ │ │ │ "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": "4f43ba38", │ │ │ │ │ + "id": "804a9182", │ │ │ │ │ "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': '0e3f48e4'}, 1: {'id': 'ebf7185c'}, 2: {'id': '54c7e6b3'}, 3: {'id': " │ │ │ │ │┄ "'022e9de2'}, 4: {'id': '22a3c6fd'}, 5: {'id': '20cc1542'}, 6: {'id': '3e382db7'}, 7: " │ │ │ │ │┄ "{'id': '35ac0a68'}, 8: {'id': 'da55f873'}, 9: {'id': 'a7dbd2fb'}, 10: {'id': " │ │ │ │ │┄ "'d85765a5'}, 11: {'id': 'df9b73ef'}, 12: {'id': '08232292'}, 13: {'id': 'afcd70c1'}, " │ │ │ │ │┄ "14: {'id': '6a4a3150'}, 15: {'id': '4efd83da'}, 16: {'id': '61914f0b'}, 17: {'id': " │ │ │ │ │┄ "'b367dc8b'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "0d07714a", │ │ │ │ │ + "id": "0e3f48e4", │ │ │ │ │ "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": "77869837", │ │ │ │ │ + "id": "ebf7185c", │ │ │ │ │ "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": "c79b5b40", │ │ │ │ │ + "id": "54c7e6b3", │ │ │ │ │ "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": "c58a3c49", │ │ │ │ │ + "id": "022e9de2", │ │ │ │ │ "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": "e8b20ac9", │ │ │ │ │ + "id": "22a3c6fd", │ │ │ │ │ "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": "2e106c11", │ │ │ │ │ + "id": "20cc1542", │ │ │ │ │ "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": "0f0c64d4", │ │ │ │ │ + "id": "3e382db7", │ │ │ │ │ "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": "002b6259", │ │ │ │ │ + "id": "35ac0a68", │ │ │ │ │ "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": "fe78cf4e", │ │ │ │ │ + "id": "da55f873", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we define the trial and test functions for stress and displacement," │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "d92fd610", │ │ │ │ │ + "id": "a7dbd2fb", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "sigma, tau = ufl.TrialFunction(S), ufl.TestFunction(S)\n", │ │ │ │ │ "u, v = ufl.TrialFunction(U), ufl.TestFunction(U)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "ea2f15d8", │ │ │ │ │ + "id": "d85765a5", │ │ │ │ │ "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": "e610864e", │ │ │ │ │ + "id": "df9b73ef", │ │ │ │ │ "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": "0facf17c", │ │ │ │ │ + "id": "08232292", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we create an integration measure with the facet markers." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "fdff37d8", │ │ │ │ │ + "id": "afcd70c1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ds = ufl.Measure(\"ds\", subdomain_data=mt)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6976d4d2", │ │ │ │ │ + "id": "6a4a3150", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Homogeneous boundary condition in displacement" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "1f71ca09", │ │ │ │ │ + "id": "4efd83da", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "u_bc = Function(U)\n", │ │ │ │ │ "u_bc.x.array[:] = 0" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b689b1c3", │ │ │ │ │ + "id": "61914f0b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Displacement {py:class}`BC ` is applied to\n", │ │ │ │ │ "the left side" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2f58e0c9", │ │ │ │ │ + "id": "b367dc8b", │ │ │ │ │ "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": "60005221", │ │ │ │ │ + "id": "411fa59f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Elastic stiffness tensor and Poisson ratio" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "9ae60a5e", │ │ │ │ │ + "id": "3da4164c", │ │ │ │ │ "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": "2382adb0", │ │ │ │ │ + "id": "7fe38a9a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "With the definitions above, we can define the different blocks\n", │ │ │ │ │ "of the variational formulation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7f718beb", │ │ │ │ │ + "id": "cfcf674b", │ │ │ │ │ "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": "92bd9596", │ │ │ │ │ + "id": "5891f9d8", │ │ │ │ │ "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": "8ce4de26", │ │ │ │ │ + "id": "49c484a2", │ │ │ │ │ "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": "caded9c3", │ │ │ │ │ + "id": "eeb1a5a0", │ │ │ │ │ "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": "f2cf21ec", │ │ │ │ │ + "id": "d1e14f11", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Get local dofmap sizes for later local tensor tabulations" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e4042bf6", │ │ │ │ │ + "id": "6406f03b", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "Ssize = S.element.space_dimension\n", │ │ │ │ │ "Usize = U.element.space_dimension" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6800da44", │ │ │ │ │ + "id": "9e07b865", │ │ │ │ │ "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": "b7724471", │ │ │ │ │ + "id": "80749954", │ │ │ │ │ "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": "49b00792", │ │ │ │ │ + "id": "9900cfbc", │ │ │ │ │ "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": "eded7eea", │ │ │ │ │ + "id": "a116b5bc", │ │ │ │ │ "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": "1efd0c90", │ │ │ │ │ + "id": "835bec74", │ │ │ │ │ "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": "62ac7166", │ │ │ │ │ + "id": "336bc3ae", │ │ │ │ │ "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": "81ff32a3", │ │ │ │ │ + "id": "1df9932e", │ │ │ │ │ "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": "01122467", │ │ │ │ │ + "id": "7a48d43c", │ │ │ │ │ "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": "03a44b6b", │ │ │ │ │ + "id": "e4221cf2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We verify the condensed solution by comparing against a standard,\n", │ │ │ │ │ "pure displacement based formulation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4944fcc6", │ │ │ │ │ + "id": "7451a669", │ │ │ │ │ "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": "7e39615c", │ │ │ │ │ + "id": "1c102044", │ │ │ │ │ "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": "b8097190", │ │ │ │ │ + "id": "32b75fa3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bb_tree = geometry.bb_tree(msh, tdim, padding=0.0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "be2c86bf", │ │ │ │ │ + "id": "6d6a2df4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Check against standard table value" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "095e171a", │ │ │ │ │ + "id": "75d2b230", │ │ │ │ │ "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": "4c039a03", │ │ │ │ │ + "id": "9e68e109", │ │ │ │ │ "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": "51190d91", │ │ │ │ │ + "id": "18dc01cb", │ │ │ │ │ "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": "946e9ebf", │ │ │ │ │ + "id": "45a36b38", │ │ │ │ │ "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': '4e757177'}, 1: {'id': 'b3a82c3c'}, 2: {'id': '0f6db226'}, 3: {'id': " │ │ │ │ │┄ "'9c6dddbe'}, 4: {'id': '762dfa1b'}, 5: {'id': '0ae9c8d3'}, 6: {'id': '2d822de0'}, 7: " │ │ │ │ │┄ "{'id': '60ccdfe2'}, 8: {'id': '764ca46d'}, 9: {'id': '86f9c74a'}, 10: {'id': " │ │ │ │ │┄ "'878e3bf7'}, 11: {'id': 'f5e94cf0'}, 12: {'id': '24565e99'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "404e6c95", │ │ │ │ │ + "id": "4e757177", │ │ │ │ │ "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": "9f585deb", │ │ │ │ │ + "id": "b3a82c3c", │ │ │ │ │ "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": "05591759", │ │ │ │ │ + "id": "0f6db226", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Plotting a finite element Function using warp by scalar" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6d09d499", │ │ │ │ │ + "id": "9c6dddbe", │ │ │ │ │ "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": "56b52328", │ │ │ │ │ + "id": "762dfa1b", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "## Mesh tags and using subplots" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "9580f3af", │ │ │ │ │ + "id": "0ae9c8d3", │ │ │ │ │ "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": "39ba8b97", │ │ │ │ │ + "id": "2d822de0", │ │ │ │ │ "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": "a55ff624", │ │ │ │ │ + "id": "60ccdfe2", │ │ │ │ │ "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": "afc94bf4", │ │ │ │ │ + "id": "764ca46d", │ │ │ │ │ "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": "3ed5ff2f", │ │ │ │ │ + "id": "86f9c74a", │ │ │ │ │ "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": "4d62efca", │ │ │ │ │ + "id": "878e3bf7", │ │ │ │ │ "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": "7526a44b", │ │ │ │ │ + "id": "f5e94cf0", │ │ │ │ │ "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": "e967bdcc", │ │ │ │ │ + "id": "24565e99", │ │ │ │ │ "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': '25241089'}, 1: {'id': '4c489758'}, 2: {'id': 'd1862142'}, 3: {'id': " │ │ │ │ │┄ "'52ff9b88'}, 4: {'id': '2208fd5b'}, 5: {'id': '87ae478e'}, 6: {'id': '335e2f5d'}, 7: " │ │ │ │ │┄ "{'id': '75aec1f6'}, 8: {'id': '826b0cb1'}, 9: {'id': '947640f6'}, 10: {'id': " │ │ │ │ │┄ "'dfc3663a'}, 11: {'id': '3f6fdea4'}, 12: {'id': 'a81e5e86'}, 13: {'id': 'bb46801a'}, " │ │ │ │ │┄ "14: {'id': '997407c9'}, 15: {'id': '01d74f40'}, 16: {'id': 'baf20d01'}, 17: {'id': " │ │ │ │ │┄ "'9cb1a192'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "efa253ce", │ │ │ │ │ + "id": "25241089", │ │ │ │ │ "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": "79c0b836", │ │ │ │ │ + "id": "4c489758", │ │ │ │ │ "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": "71fe8ed2", │ │ │ │ │ + "id": "d1862142", │ │ │ │ │ "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": "74690312", │ │ │ │ │ + "id": "52ff9b88", │ │ │ │ │ "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": "e0b247fb", │ │ │ │ │ + "id": "2208fd5b", │ │ │ │ │ "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": "9b004a9a", │ │ │ │ │ + "id": "87ae478e", │ │ │ │ │ "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": "0a075734", │ │ │ │ │ + "id": "335e2f5d", │ │ │ │ │ "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": "17e73c33", │ │ │ │ │ + "id": "75aec1f6", │ │ │ │ │ "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": "3d0edba8", │ │ │ │ │ + "id": "826b0cb1", │ │ │ │ │ "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": "2a2e1d65", │ │ │ │ │ + "id": "947640f6", │ │ │ │ │ "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": "38e5d048", │ │ │ │ │ + "id": "dfc3663a", │ │ │ │ │ "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": "4dd99764", │ │ │ │ │ + "id": "3f6fdea4", │ │ │ │ │ "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": "f668fe4e", │ │ │ │ │ + "id": "a81e5e86", │ │ │ │ │ "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": "dd7e181b", │ │ │ │ │ + "id": "bb46801a", │ │ │ │ │ "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": "8094f8c9", │ │ │ │ │ + "id": "997407c9", │ │ │ │ │ "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": "7dc1a737", │ │ │ │ │ + "id": "01d74f40", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We use the following domain specific parameters:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5475a782", │ │ │ │ │ + "id": "baf20d01", │ │ │ │ │ "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": "0d8ee1cb", │ │ │ │ │ + "id": "9cb1a192", │ │ │ │ │ "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": "9978e15c", │ │ │ │ │ + "id": "41ddf242", │ │ │ │ │ "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": "38d4088b", │ │ │ │ │ + "id": "ae45c378", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We visualize the mesh and subdomains with\n", │ │ │ │ │ "[PyVista](https://docs.pyvista.org/)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7f6e30f4", │ │ │ │ │ + "id": "ec0c6982", │ │ │ │ │ "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": "67fcaa4c", │ │ │ │ │ + "id": "0a382708", │ │ │ │ │ "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": "98499f21", │ │ │ │ │ + "id": "30c22deb", │ │ │ │ │ "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": "f33b6bcc", │ │ │ │ │ + "id": "f3260e8e", │ │ │ │ │ "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": "8d8dad35", │ │ │ │ │ + "id": "f331e25f", │ │ │ │ │ "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": "25853b23", │ │ │ │ │ + "id": "40657fe2", │ │ │ │ │ "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": "8f405649", │ │ │ │ │ + "id": "212e8f11", │ │ │ │ │ "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": "6a699e68", │ │ │ │ │ + "id": "9ffd7a54", │ │ │ │ │ "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": "6734cdb9", │ │ │ │ │ + "id": "b8b66061", │ │ │ │ │ "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": "79a5650d", │ │ │ │ │ + "id": "cdc50e83", │ │ │ │ │ "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": "48f4e412", │ │ │ │ │ + "id": "e6b719e0", │ │ │ │ │ "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": "ea49b157", │ │ │ │ │ + "id": "2693c13b", │ │ │ │ │ "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": "db8feeda", │ │ │ │ │ + "id": "28579857", │ │ │ │ │ "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": "97fcf9c9", │ │ │ │ │ + "id": "7a1df922", │ │ │ │ │ "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": "6480fb8a", │ │ │ │ │ + "id": "585291dd", │ │ │ │ │ "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": "85f1da16", │ │ │ │ │ + "id": "99dbacf2", │ │ │ │ │ "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": "abd42c31", │ │ │ │ │ + "id": "59e322a0", │ │ │ │ │ "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": "75a0f0c4", │ │ │ │ │ + "id": "23d04ff9", │ │ │ │ │ "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": "7465534c", │ │ │ │ │ + "id": "81e150c2", │ │ │ │ │ "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": "0ce29725", │ │ │ │ │ + "id": "88dc7f96", │ │ │ │ │ "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": "3e7ed8b6", │ │ │ │ │ + "id": "db8077ca", │ │ │ │ │ "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": "d1294ae4", │ │ │ │ │ + "id": "9277497a", │ │ │ │ │ "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": "4ba3d6fc", │ │ │ │ │ + "id": "b656138b", │ │ │ │ │ "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": "e81c72ca", │ │ │ │ │ + "id": "cce15390", │ │ │ │ │ "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": "8a41efb7", │ │ │ │ │ + "id": "553e90d2", │ │ │ │ │ "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": "9928885b", │ │ │ │ │ + "id": "dc0880bc", │ │ │ │ │ "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": "7ad13d11", │ │ │ │ │ + "id": "c8226626", │ │ │ │ │ "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": "99da971c", │ │ │ │ │ + "id": "c461bd8b", │ │ │ │ │ "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': '3503b239'}, 1: {'id': '5acd35f4'}, 2: {'id': '3c019a98'}, 3: {'id': " │ │ │ │ │┄ "'7f0bbda5'}, 4: {'id': '65357cc6'}, 5: {'id': '32d19830'}, 6: {'id': '5747c577'}, 7: " │ │ │ │ │┄ "{'id': '144248ca'}, 8: {'id': 'a25eabbf'}, 9: {'id': 'e6f3889c'}, 10: {'id': " │ │ │ │ │┄ "'32870ee5'}, 11: {'id': '1af32e9e'}, 12: {'id': '43f7a4c2'}, 13: {'id': 'd7123820'}, " │ │ │ │ │┄ "14: {'id': 'cad5d982'}, 15: {'id': '4b3485d4'}, 16: {'id': '2cfe416a'}, 17: {'id': " │ │ │ │ │┄ "'944f67d2'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d635ee39", │ │ │ │ │ + "id": "3503b239", │ │ │ │ │ "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": "725729f8", │ │ │ │ │ + "id": "5acd35f4", │ │ │ │ │ "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": "ace7588e", │ │ │ │ │ + "id": "3c019a98", │ │ │ │ │ "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": "15cadfd4", │ │ │ │ │ + "id": "7f0bbda5", │ │ │ │ │ "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": "0da7b3b8", │ │ │ │ │ + "id": "65357cc6", │ │ │ │ │ "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": "04db2409", │ │ │ │ │ + "id": "32d19830", │ │ │ │ │ "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": "94eec0ad", │ │ │ │ │ + "id": "5747c577", │ │ │ │ │ "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": "70ac0efa", │ │ │ │ │ + "id": "144248ca", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "dofs = fem.locate_dofs_topological(V=V, entity_dim=tdim - 1, entities=facets)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "982f33a6", │ │ │ │ │ + "id": "a25eabbf", │ │ │ │ │ "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": "644866e4", │ │ │ │ │ + "id": "e6f3889c", │ │ │ │ │ "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": "3372065d", │ │ │ │ │ + "id": "32870ee5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we express the variational problem using UFL." │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6754825d", │ │ │ │ │ + "id": "1af32e9e", │ │ │ │ │ "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": "79ac41d0", │ │ │ │ │ + "id": "43f7a4c2", │ │ │ │ │ "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": "faab9eb4", │ │ │ │ │ + "id": "d7123820", │ │ │ │ │ "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": "f79fe09f", │ │ │ │ │ + "id": "cad5d982", │ │ │ │ │ "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": "b2daad4f", │ │ │ │ │ + "id": "4b3485d4", │ │ │ │ │ "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": "9b2f0b3f", │ │ │ │ │ + "id": "2cfe416a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Set BC dofs to zero on right hand side" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "64edf950", │ │ │ │ │ + "id": "944f67d2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc.set(b.array, alpha=0.0)\n", │ │ │ │ │ "b.scatter_forward()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b7d3aac8", │ │ │ │ │ + "id": "27068371", │ │ │ │ │ "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": "61997eb2", │ │ │ │ │ + "id": "43408a31", │ │ │ │ │ "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": "562d3022", │ │ │ │ │ + "id": "4f73264b", │ │ │ │ │ "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": "956f307d", │ │ │ │ │ + "id": "5c98e93d", │ │ │ │ │ "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": "a4f7a4ca", │ │ │ │ │ + "id": "b85d5bd8", │ │ │ │ │ "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": "7a36b815", │ │ │ │ │ + "id": "a9f73f6d", │ │ │ │ │ "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": "50fafab5", │ │ │ │ │ + "id": "eefc8b50", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Set BC values in the solution vector" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "001c3baa", │ │ │ │ │ + "id": "63586857", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "bc.set(u.x.array, alpha=1.0)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "05fa1b63", │ │ │ │ │ + "id": "fa607635", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Print CG iteration number and error" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "cbc5a189", │ │ │ │ │ + "id": "372349cd", │ │ │ │ │ "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': 'f1b6d18b'}, 1: {'id': '91c5f553'}, 2: {'id': 'dedbdc3c'}, 3: {'id': " │ │ │ │ │┄ "'d0b680a4'}, 4: {'id': 'd78edbd9'}, 5: {'id': '00c2d1e0'}, 6: {'id': '197d6c20'}, 7: " │ │ │ │ │┄ "{'id': '4e2de0a4'}, 8: {'id': 'd1ebba0f'}, 9: {'id': 'c6ac4939'}, 10: {'id': " │ │ │ │ │┄ "'ed5f1931'}, 11: {'id': '08c5ff75'}, 12: {'id': '2e368b5f'}, 13: {'id': '8336b047'}, " │ │ │ │ │┄ "14: {'id': 'd8d2225c'}, 15: {'id': '10e5b28e'}, 16: {'id': '52a4f37e'}, 17: {'id': " │ │ │ │ │┄ "'134a7b61'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "2651d59b", │ │ │ │ │ + "id": "f1b6d18b", │ │ │ │ │ "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": "0157a918", │ │ │ │ │ + "id": "91c5f553", │ │ │ │ │ "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": "6902e7b7", │ │ │ │ │ + "id": "dedbdc3c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, various model parameters are defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "026ebb31", │ │ │ │ │ + "id": "d0b680a4", │ │ │ │ │ "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": "3b997a03", │ │ │ │ │ + "id": "d78edbd9", │ │ │ │ │ "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": "54f9cf61", │ │ │ │ │ + "id": "00c2d1e0", │ │ │ │ │ "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": "6fa42c55", │ │ │ │ │ + "id": "197d6c20", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Trial and test functions of the space `ME` are now defined:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6de051b7", │ │ │ │ │ + "id": "4e2de0a4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "q, v = ufl.TestFunctions(ME)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "53cce86e", │ │ │ │ │ + "id": "d1ebba0f", │ │ │ │ │ "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": "92427bdf", │ │ │ │ │ + "id": "c6ac4939", │ │ │ │ │ "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": "5c953e18", │ │ │ │ │ + "id": "ed5f1931", │ │ │ │ │ "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": "c17521ad", │ │ │ │ │ + "id": "08c5ff75", │ │ │ │ │ "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": "531dbf59", │ │ │ │ │ + "id": "2e368b5f", │ │ │ │ │ "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": "eb9ff92c", │ │ │ │ │ + "id": "8336b047", │ │ │ │ │ "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": "3cb03e2d", │ │ │ │ │ + "id": "d8d2225c", │ │ │ │ │ "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": "505161c9", │ │ │ │ │ + "id": "10e5b28e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "mu_mid = (1.0 - theta) * mu0 + theta * mu # mu_(n+theta)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "774a659e", │ │ │ │ │ + "id": "52a4f37e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "which is then used in the definition of the variational forms:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "73001ad2", │ │ │ │ │ + "id": "134a7b61", │ │ │ │ │ "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": "eba77649", │ │ │ │ │ + "id": "8b7c78d4", │ │ │ │ │ "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": "0e8d148f", │ │ │ │ │ + "id": "0abfc25f", │ │ │ │ │ "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": "cf518c4d", │ │ │ │ │ + "id": "9ff62a74", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We prepare output files and pyvista for time-dependent visualization:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "0957ff42", │ │ │ │ │ + "id": "1bcc7454", │ │ │ │ │ "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": "227f7dfe", │ │ │ │ │ + "id": "861022be", │ │ │ │ │ "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": "075a2f2e", │ │ │ │ │ + "id": "58f63bff", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "V0, dofs = ME.sub(0).collapse()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "710a76f0", │ │ │ │ │ + "id": "955adb54", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Prepare viewer for plotting the solution during the computation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7814bcc3", │ │ │ │ │ + "id": "3f941fac", │ │ │ │ │ "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": "f077df76", │ │ │ │ │ + "id": "33dca212", │ │ │ │ │ "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": "0e6b9e05", │ │ │ │ │ + "id": "171ab63b", │ │ │ │ │ "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": "d60fcad0", │ │ │ │ │ + "id": "67ae7d17", │ │ │ │ │ "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": "1b628f45", │ │ │ │ │ + "id": "402f9a6c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Update plot" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "6dc9b591", │ │ │ │ │ + "id": "de33cb44", │ │ │ │ │ "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': '388f0a63'}, 1: {'id': 'fab842b4'}, 2: {'id': '941728f8'}, 3: {'id': " │ │ │ │ │┄ "'f7802d89'}, 4: {'id': '91d96910'}, 5: {'id': '91e5d108'}, 6: {'id': 'c0b9f651'}, 7: " │ │ │ │ │┄ "{'id': '95040baf'}, 8: {'id': 'b3954935'}, 9: {'id': '44b258fb'}, 10: {'id': " │ │ │ │ │┄ "'917fd34b'}, 11: {'id': '3986865b'}, 12: {'id': '473f1635'}, 13: {'id': '66126f5a'}, " │ │ │ │ │┄ "14: {'id': '2d4729a8'}, 15: {'id': 'f2e7b40b'}, 16: {'id': '20ce632b'}, 17: {'id': " │ │ │ │ │┄ "'bd85ff3e'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9ce76442", │ │ │ │ │ + "id": "388f0a63", │ │ │ │ │ "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": "56e39a72", │ │ │ │ │ + "id": "fab842b4", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "\n", │ │ │ │ │ "## Implementation\n", │ │ │ │ │ "\n", │ │ │ │ │ "Import the required modules:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5909f5dd", │ │ │ │ │ + "id": "941728f8", │ │ │ │ │ "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": "da6db833", │ │ │ │ │ + "id": "f7802d89", │ │ │ │ │ "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": "9a0a88a2", │ │ │ │ │ + "id": "91d96910", │ │ │ │ │ "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": "e88285ec", │ │ │ │ │ + "id": "91e5d108", │ │ │ │ │ "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": "35ff6c90", │ │ │ │ │ + "id": "c0b9f651", │ │ │ │ │ "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": "2837bd44", │ │ │ │ │ + "id": "95040baf", │ │ │ │ │ "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": "96464e9c", │ │ │ │ │ + "id": "b3954935", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "sigma, u = ufl.TrialFunctions(Q)\n", │ │ │ │ │ "tau, v = ufl.TestFunctions(Q)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "84b7612d", │ │ │ │ │ + "id": "44b258fb", │ │ │ │ │ "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": "f69a2ff1", │ │ │ │ │ + "id": "917fd34b", │ │ │ │ │ "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": "ffb110bb", │ │ │ │ │ + "id": "3986865b", │ │ │ │ │ "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": "ed00c8f7", │ │ │ │ │ + "id": "473f1635", │ │ │ │ │ "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": "66b21eb7", │ │ │ │ │ + "id": "66126f5a", │ │ │ │ │ "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": "b83591b9", │ │ │ │ │ + "id": "2d4729a8", │ │ │ │ │ "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": "943ee049", │ │ │ │ │ + "id": "f2e7b40b", │ │ │ │ │ "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": "3813ec7e", │ │ │ │ │ + "id": "20ce632b", │ │ │ │ │ "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": "a835e54f", │ │ │ │ │ + "id": "bd85ff3e", │ │ │ │ │ "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": "4d5007bd", │ │ │ │ │ + "id": "9f6de283", │ │ │ │ │ "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": "aac60ea1", │ │ │ │ │ + "id": "e76a8326", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We create finite element functions that will hold the $\\sigma$ and $u$\n", │ │ │ │ │ "solutions:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ad34ee8d", │ │ │ │ │ + "id": "28a83212", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "sigma, u = fem.Function(V, name=\"sigma\", dtype=dtype), fem.Function(W, name=\"u\", dtype=dtype)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "816f77af", │ │ │ │ │ + "id": "c40c593e", │ │ │ │ │ "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": "3e79d5b4", │ │ │ │ │ + "id": "6873037b", │ │ │ │ │ "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": "1b806028", │ │ │ │ │ + "id": "edb87fe2", │ │ │ │ │ "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": "b66de2f3", │ │ │ │ │ + "id": "e4f80cd4", │ │ │ │ │ "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": "95058336", │ │ │ │ │ + "id": "2155b377", │ │ │ │ │ "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": "35219f50", │ │ │ │ │ + "id": "0fa3cd1c", │ │ │ │ │ "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": "43146c95", │ │ │ │ │ + "id": "7f982d59", │ │ │ │ │ "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": "d03c3ef3", │ │ │ │ │ + "id": "52662dcc", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We save the solution `u` in VTX format:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "e1d31498", │ │ │ │ │ + "id": "69647346", │ │ │ │ │ "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': 'a59cd644'}, 1: {'id': '032a22b6'}, 2: {'id': 'dfb0aecd'}, 3: {'id': " │ │ │ │ │┄ "'f96db923'}, 4: {'id': 'c011c122'}, 5: {'id': '9e8fffa3'}, 6: {'id': '87bd4883'}, 7: " │ │ │ │ │┄ "{'id': 'ae5995a7'}, 8: {'id': '7aadffcd'}, 9: {'id': 'c361f118'}, 10: {'id': " │ │ │ │ │┄ "'6d6a3e55'}, 11: {'id': '4234cb64'}, 12: {'id': 'aa6d48f7'}, 13: {'id': 'ab69f8af'}, " │ │ │ │ │┄ "14: {'id': '9ef73afd'}, 15: {'id': 'ddab21de'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fe2084b8", │ │ │ │ │ + "id": "a59cd644", │ │ │ │ │ "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": "a385bc4b", │ │ │ │ │ + "id": "032a22b6", │ │ │ │ │ "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": "d9c76cbe", │ │ │ │ │ + "id": "dfb0aecd", │ │ │ │ │ "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": "95492f24", │ │ │ │ │ + "id": "f96db923", │ │ │ │ │ "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": "2d4ba08c", │ │ │ │ │ + "id": "c011c122", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a N\u00e9d\u00e9lec function space and finite element Function" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5ee09086", │ │ │ │ │ + "id": "9e8fffa3", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "V = functionspace(msh, (\"Nedelec 1st kind H(curl)\", 1))\n", │ │ │ │ │ "u = Function(V, dtype=default_scalar_type)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d2bd74a9", │ │ │ │ │ + "id": "87bd4883", │ │ │ │ │ "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": "541e9c41", │ │ │ │ │ + "id": "ae5995a7", │ │ │ │ │ "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": "808f3cfd", │ │ │ │ │ + "id": "7aadffcd", │ │ │ │ │ "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": "b96efb98", │ │ │ │ │ + "id": "c361f118", │ │ │ │ │ "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": "90651275", │ │ │ │ │ + "id": "6d6a3e55", │ │ │ │ │ "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": "9859d475", │ │ │ │ │ + "id": "4234cb64", │ │ │ │ │ "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": "7157963d", │ │ │ │ │ + "id": "aa6d48f7", │ │ │ │ │ "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": "620e0c5f", │ │ │ │ │ + "id": "ab69f8af", │ │ │ │ │ "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": "9d63f0fe", │ │ │ │ │ + "id": "9ef73afd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Plot the functions" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "c797c554", │ │ │ │ │ + "id": "ddab21de", │ │ │ │ │ "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': '9767efc1'}, 1: {'id': 'a9a99fa5'}, 2: {'id': '129b0c39'}, 3: {'id': " │ │ │ │ │┄ "'bbd4a2c6'}, 4: {'id': '55c3e83a'}, 5: {'id': '87d20ebe'}, 6: {'id': '476f6770'}, 7: " │ │ │ │ │┄ "{'id': '6bcb2c14'}, 8: {'id': '4d67201e'}, 9: {'id': 'afe98e0d'}, 10: {'id': " │ │ │ │ │┄ "'a8a44ade'}, 11: {'id': '34a05cf3'}, 12: {'id': '1c34fe09'}, 13: {'id': '3940fcf1'}, " │ │ │ │ │┄ "14: {'id': '70d334a5'}, 15: {'id': '8801b081'}, 16: {'id': '675ca212'}, 17: {'id': " │ │ │ │ │┄ "'32ed5482'}, 1 […] │ │ │ │ │ @@ -1,20 +1,20 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "efff5d93", │ │ │ │ │ + "id": "9767efc1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "# Electromagnetic modal analysis for a waveguide" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "f8e64f36", │ │ │ │ │ + "id": "a9a99fa5", │ │ │ │ │ "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": "ee764170", │ │ │ │ │ + "id": "129b0c39", │ │ │ │ │ "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": "c5437fcc", │ │ │ │ │ + "id": "bbd4a2c6", │ │ │ │ │ "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": "1a5bad17", │ │ │ │ │ + "id": "55c3e83a", │ │ │ │ │ "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": "60524d42", │ │ │ │ │ + "id": "87d20ebe", │ │ │ │ │ "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": "e8d5e4d3", │ │ │ │ │ + "id": "476f6770", │ │ │ │ │ "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": "8eb62043", │ │ │ │ │ + "id": "6bcb2c14", │ │ │ │ │ "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": "a486fa08", │ │ │ │ │ + "id": "4d67201e", │ │ │ │ │ "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": "1cedc22c", │ │ │ │ │ + "id": "afe98e0d", │ │ │ │ │ "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": "c3907fc8", │ │ │ │ │ + "id": "a8a44ade", │ │ │ │ │ "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": "3eb8472f", │ │ │ │ │ + "id": "34a05cf3", │ │ │ │ │ "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": "bce80401", │ │ │ │ │ + "id": "1c34fe09", │ │ │ │ │ "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": "9e86318c", │ │ │ │ │ + "id": "3940fcf1", │ │ │ │ │ "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": "31a5ef54", │ │ │ │ │ + "id": "70d334a5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we can define our weak form:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "0fb2ce4f", │ │ │ │ │ + "id": "8801b081", │ │ │ │ │ "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": "317887b7", │ │ │ │ │ + "id": "675ca212", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Let's add the perfect electric conductor conditions on the waveguide\n", │ │ │ │ │ "wall:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "ba34f1ef", │ │ │ │ │ + "id": "32ed5482", │ │ │ │ │ "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": "5cc04593", │ │ │ │ │ + "id": "39c2000f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Solve the problem in SLEPc" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9df31dc8", │ │ │ │ │ + "id": "20cf80ae", │ │ │ │ │ "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": "e7b41025", │ │ │ │ │ + "id": "a16bdd32", │ │ │ │ │ "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": "bb152aea", │ │ │ │ │ + "id": "3fa07535", │ │ │ │ │ "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": "ce36cc5a", │ │ │ │ │ + "id": "004ef423", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps = SLEPc.EPS().create(msh.comm)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "82cd1295", │ │ │ │ │ + "id": "f9a4ed0c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We can pass to `EPS` our matrices by using the `setOperators` routine:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "958d3bc6", │ │ │ │ │ + "id": "f4835c57", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setOperators(A, B)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "daad3d5a", │ │ │ │ │ + "id": "66ed25d1", │ │ │ │ │ "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": "3cffa3f1", │ │ │ │ │ + "id": "f78d0fb1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setProblemType(SLEPc.EPS.ProblemType.GNHEP)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "47afe3bf", │ │ │ │ │ + "id": "37ae4b45", │ │ │ │ │ "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": "870a79b1", │ │ │ │ │ + "id": "d32beff7", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "tol = 1e-9\n", │ │ │ │ │ "eps.setTolerances(tol=tol)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "36a3ffa9", │ │ │ │ │ + "id": "f47ea9c9", │ │ │ │ │ "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": "e438d31e", │ │ │ │ │ + "id": "3d9427c2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setType(SLEPc.EPS.Type.KRYLOVSCHUR)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "819af0eb", │ │ │ │ │ + "id": "64951bf8", │ │ │ │ │ "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": "0b91c3c8", │ │ │ │ │ + "id": "bfa6ffd5", │ │ │ │ │ "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": "d316d76c", │ │ │ │ │ + "id": "104e370a", │ │ │ │ │ "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": "afa5e763", │ │ │ │ │ + "id": "a2185ecd", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setWhichEigenpairs(SLEPc.EPS.Which.TARGET_REAL)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "fb573c7a", │ │ │ │ │ + "id": "5e3f591e", │ │ │ │ │ "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": "1a9af9aa", │ │ │ │ │ + "id": "bdc1d35d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setTarget(-((0.5 * k0) ** 2))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "e7a22818", │ │ │ │ │ + "id": "49b609c0", │ │ │ │ │ "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": "ad135073", │ │ │ │ │ + "id": "afe705b8", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.setDimensions(nev=1)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "add9ec46", │ │ │ │ │ + "id": "38d59686", │ │ │ │ │ "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": "b93fb7fc", │ │ │ │ │ + "id": "c42e94fa", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps.solve()\n", │ │ │ │ │ "eps.view()\n", │ │ │ │ │ "eps.errorView()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "16b091fd", │ │ │ │ │ + "id": "c51bd1eb", │ │ │ │ │ "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": "306b6e7a", │ │ │ │ │ + "id": "94bc89a1", │ │ │ │ │ "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': '59b45f28'}, 1: {'id': '8a2e9e6a'}, 2: {'id': 'dfa6546b'}, 3: {'id': " │ │ │ │ │┄ "'0dc62278'}, 4: {'id': '90fc4e0b'}, 5: {'id': 'ca8885e5'}, 6: {'id': '05fa250c'}, 7: " │ │ │ │ │┄ "{'id': 'aac445b5'}, 8: {'id': 'becf7750'}, 9: {'id': '4a02dfc2'}, 10: {'id': " │ │ │ │ │┄ "'18523b95'}, 11: {'id': '6df0050b'}, 12: {'id': 'c85e7eba'}, 13: {'id': '002feee9'}, " │ │ │ │ │┄ "14: {'id': 'f0500c94'}, 15: {'id': '5341be33'}, 16: {'id': 'ba44bbdc'}, 17: {'id': " │ │ │ │ │┄ "'ef489329'}}"} │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c61f752b", │ │ │ │ │ + "id": "59b45f28", │ │ │ │ │ "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": "5497a1d2", │ │ │ │ │ + "id": "8a2e9e6a", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We start by importing the necessary modules" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5f40185f", │ │ │ │ │ + "id": "dfa6546b", │ │ │ │ │ "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": "9b45fa71", │ │ │ │ │ + "id": "0dc62278", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "We define the necessary parameters for the discretized problem" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "34d463a2", │ │ │ │ │ + "id": "90fc4e0b", │ │ │ │ │ "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": "00bdba57", │ │ │ │ │ + "id": "ca8885e5", │ │ │ │ │ "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": "ce1988c2", │ │ │ │ │ + "id": "05fa250c", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "msh = create_unit_square(MPI.COMM_WORLD, n_elem, n_elem)\n", │ │ │ │ │ "V = functionspace(msh, (\"Lagrange\", deg))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d9af8da4", │ │ │ │ │ + "id": "aac445b5", │ │ │ │ │ "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": "ed38b2e0", │ │ │ │ │ + "id": "becf7750", │ │ │ │ │ "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": "a5c5328f", │ │ │ │ │ + "id": "4a02dfc2", │ │ │ │ │ "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": "912aea66", │ │ │ │ │ + "id": "18523b95", │ │ │ │ │ "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": "6c5937ee", │ │ │ │ │ + "id": "6df0050b", │ │ │ │ │ "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": "1610da3c", │ │ │ │ │ + "id": "c85e7eba", │ │ │ │ │ "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": "aa3ae2a8", │ │ │ │ │ + "id": "002feee9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Save solution in XDMF format (to be viewed in ParaView, for example)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "34443e54", │ │ │ │ │ + "id": "f0500c94", │ │ │ │ │ "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": "6b617927", │ │ │ │ │ + "id": "5341be33", │ │ │ │ │ "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": "36340d8e", │ │ │ │ │ + "id": "ba44bbdc", │ │ │ │ │ "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": "ec424f4c", │ │ │ │ │ + "id": "ef489329", │ │ │ │ │ "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': '13612924'}, 1: {'id': '242baf3b'}, 2: {'id': '99783bc2'}, 3: {'id': " │ │ │ │ │┄ "'aec200ac'}, 4: {'id': '65433371'}, 5: {'id': 'f38a12d2'}, 6: {'id': '0f5f34c2'}, 7: " │ │ │ │ │┄ "{'id': 'd0c1d326'}, 8: {'id': '07d44bdc'}, 9: {'id': 'c08087e2'}, 10: {'id': " │ │ │ │ │┄ "'61f80bd1'}, 11: {'id': '71676243'}, 12: {'id': '5c29f0ad'}, 13: {'id': 'bd69f3d3'}, " │ │ │ │ │┄ "14: {'id': '4243454e'}, 15: {'id': 'd9b2131a'}, 16: {'id': '8455fc9d'}, 17: {'id': " │ │ │ │ │┄ "'5b099040'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "d30695fd", │ │ │ │ │ + "id": "13612924", │ │ │ │ │ "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": "68a58f1b", │ │ │ │ │ + "id": "242baf3b", │ │ │ │ │ "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": "cd9a7576", │ │ │ │ │ + "id": "99783bc2", │ │ │ │ │ "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": "b6d3eea4", │ │ │ │ │ + "id": "aec200ac", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "wcoeffs = np.eye(8, 9)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "4afe08c5", │ │ │ │ │ + "id": "65433371", │ │ │ │ │ "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": "abf3343d", │ │ │ │ │ + "id": "f38a12d2", │ │ │ │ │ "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": "aa3a752c", │ │ │ │ │ + "id": "0f5f34c2", │ │ │ │ │ "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": "e6a1653e", │ │ │ │ │ + "id": "d0c1d326", │ │ │ │ │ "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": "0ccb2dfa", │ │ │ │ │ + "id": "07d44bdc", │ │ │ │ │ "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": "d5cef36f", │ │ │ │ │ + "id": "c08087e2", │ │ │ │ │ "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": "bf171f40", │ │ │ │ │ + "id": "61f80bd1", │ │ │ │ │ "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": "1d1b598f", │ │ │ │ │ + "id": "71676243", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "x[2].append(np.zeros([0, 2]))\n", │ │ │ │ │ "M[2].append(np.zeros([0, 1, 0, 1]))" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "cbd06e6c", │ │ │ │ │ + "id": "5c29f0ad", │ │ │ │ │ "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": "ffa711e8", │ │ │ │ │ + "id": "bd69f3d3", │ │ │ │ │ "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": "4b201445", │ │ │ │ │ + "id": "4243454e", │ │ │ │ │ "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": "875b54e6", │ │ │ │ │ + "id": "d9b2131a", │ │ │ │ │ "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": "3c69cfa1", │ │ │ │ │ + "id": "8455fc9d", │ │ │ │ │ "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": "fb4aa6e3", │ │ │ │ │ + "id": "5b099040", │ │ │ │ │ "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": "400944ec", │ │ │ │ │ + "id": "e7c4fe56", │ │ │ │ │ "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": "c057ec90", │ │ │ │ │ + "id": "4790a68a", │ │ │ │ │ "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": "ac1d876b", │ │ │ │ │ + "id": "2ffd07b5", │ │ │ │ │ "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": "b2c2e1a4", │ │ │ │ │ + "id": "a240eb8d", │ │ │ │ │ "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": "28f20d0e", │ │ │ │ │ + "id": "80f01e79", │ │ │ │ │ "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": "c6b2ee6c", │ │ │ │ │ + "id": "4d59d7aa", │ │ │ │ │ "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": "96501507", │ │ │ │ │ + "id": "1a7cb95f", │ │ │ │ │ "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': '96a03a5b'}, 1: {'id': '1b57b40e'}, 2: {'id': '06ceb0bc'}, 3: {'id': " │ │ │ │ │┄ "'6bdddb3b'}, 4: {'id': 'ffe82cbe'}, 5: {'id': 'c8141a71'}, 6: {'id': 'e206c309'}, 7: " │ │ │ │ │┄ "{'id': 'd187a028'}, 8: {'id': '0b1836a1'}, 9: {'id': '4d997875'}, 10: {'id': " │ │ │ │ │┄ "'dbcf5900'}, 11: {'id': 'f5bcd065'}, 12: {'id': '5b29649a'}, 13: {'id': 'b0c58e85'}, " │ │ │ │ │┄ "14: {'id': '7a4758cc'}, 15: {'id': '8784c0b7'}, 16: {'id': 'ef1fe993'}, 17: {'id': " │ │ │ │ │┄ "'ee67d520'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "6afca03c", │ │ │ │ │ + "id": "96a03a5b", │ │ │ │ │ "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": "861f7d06", │ │ │ │ │ + "id": "1b57b40e", │ │ │ │ │ "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": "99e2322a", │ │ │ │ │ + "id": "06ceb0bc", │ │ │ │ │ "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": "fbdebd9c", │ │ │ │ │ + "id": "6bdddb3b", │ │ │ │ │ "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": "61bb1e81", │ │ │ │ │ + "id": "ffe82cbe", │ │ │ │ │ "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": "12ae32e1", │ │ │ │ │ + "id": "c8141a71", │ │ │ │ │ "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": "a5fefd6a", │ │ │ │ │ + "id": "e206c309", │ │ │ │ │ "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": "578a87e5", │ │ │ │ │ + "id": "d187a028", │ │ │ │ │ "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": "f4d3adb6", │ │ │ │ │ + "id": "0b1836a1", │ │ │ │ │ "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": "52bd2bd0", │ │ │ │ │ + "id": "4d997875", │ │ │ │ │ "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": "69da31b9", │ │ │ │ │ + "id": "dbcf5900", │ │ │ │ │ "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": "1aa594d6", │ │ │ │ │ + "id": "f5bcd065", │ │ │ │ │ "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": "7291f21a", │ │ │ │ │ + "id": "5b29649a", │ │ │ │ │ "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": "e5495daa", │ │ │ │ │ + "id": "b0c58e85", │ │ │ │ │ "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": "4925631c", │ │ │ │ │ + "id": "7a4758cc", │ │ │ │ │ "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": "d571fdab", │ │ │ │ │ + "id": "8784c0b7", │ │ │ │ │ "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": "507dc7e3", │ │ │ │ │ + "id": "ef1fe993", │ │ │ │ │ "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": "daffd90a", │ │ │ │ │ + "id": "ee67d520", │ │ │ │ │ "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": "0c471c55", │ │ │ │ │ + "id": "37ffb476", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Now we define some other problem specific parameters:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "4a172d5b", │ │ │ │ │ + "id": "75e89789", │ │ │ │ │ "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": "423dfbe3", │ │ │ │ │ + "id": "5a5fd7da", │ │ │ │ │ "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": "ff1c808e", │ │ │ │ │ + "id": "1eb93188", │ │ │ │ │ "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": "0b1ab640", │ │ │ │ │ + "id": "81386b2e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Next, we can interpolate $\\mathbf{E}_b$ into the function space $V$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "9d717b30", │ │ │ │ │ + "id": "99b321bf", │ │ │ │ │ "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": "667d497d", │ │ │ │ │ + "id": "83372b09", │ │ │ │ │ "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": "bb58051a", │ │ │ │ │ + "id": "6ca488e2", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "eps_au = -1.0782 + 1j * 5.8089" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "714a9abb", │ │ │ │ │ + "id": "5cba8eb9", │ │ │ │ │ "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": "093d58fa", │ │ │ │ │ + "id": "45d71deb", │ │ │ │ │ "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": "d6bee509", │ │ │ │ │ + "id": "546e4ca6", │ │ │ │ │ "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": "95abc35d", │ │ │ │ │ + "id": "1661feb6", │ │ │ │ │ "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": "e68afaf1", │ │ │ │ │ + "id": "0147e06d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Solving the variational problem" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "46c26a22", │ │ │ │ │ + "id": "be8e064e", │ │ │ │ │ "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": "4bfd96f8", │ │ │ │ │ + "id": "30a8681a", │ │ │ │ │ "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": "a3015727", │ │ │ │ │ + "id": "c0e3c9a1", │ │ │ │ │ "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": "5bc4afaf", │ │ │ │ │ + "id": "6ec57e71", │ │ │ │ │ "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": "e31ba603", │ │ │ │ │ + "id": "230b9be9", │ │ │ │ │ "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": "06ad5f7a", │ │ │ │ │ + "id": "853f12fe", │ │ │ │ │ "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": "9705e477", │ │ │ │ │ + "id": "128f300b", │ │ │ │ │ "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": "4bc33969", │ │ │ │ │ + "id": "307efa27", │ │ │ │ │ "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": "21ebddbf", │ │ │ │ │ + "id": "4abf2115", │ │ │ │ │ "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": "59d88c31", │ │ │ │ │ + "id": "8b890c10", │ │ │ │ │ "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": "2892472e", │ │ │ │ │ + "id": "7903ca09", │ │ │ │ │ "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": "ec01f9d7", │ │ │ │ │ + "id": "8bd70ea9", │ │ │ │ │ "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": "f436feca", │ │ │ │ │ + "id": "c726a54f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Quantities for the calculation of efficiencies" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "87afbd00", │ │ │ │ │ + "id": "1a589f18", │ │ │ │ │ "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": "dedc79de", │ │ │ │ │ + "id": "df1c0f0f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Normalized absorption efficiency" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "223fb8ee", │ │ │ │ │ + "id": "09475162", │ │ │ │ │ "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": "2176bab0", │ │ │ │ │ + "id": "6928659d", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Normalized scattering efficiency" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "561631f6", │ │ │ │ │ + "id": "1c892818", │ │ │ │ │ "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": "f7ed62f3", │ │ │ │ │ + "id": "b72ea0f5", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Extinction efficiency" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "2cddc230", │ │ │ │ │ + "id": "73c3751f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "q_ext_fenics = q_abs_fenics + q_sca_fenics" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "b7138f57", │ │ │ │ │ + "id": "1d5ad8e9", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Error calculation" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "5487ac7a", │ │ │ │ │ + "id": "3b248fc9", │ │ │ │ │ "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": "73f5203b", │ │ │ │ │ + "id": "59f4764b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Check if errors are smaller than 1%" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "3443e981", │ │ │ │ │ + "id": "0863d2c8", │ │ │ │ │ "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': 'afb57fd5'}, 1: {'id': 'ac31f364'}, 2: {'id': '198545aa'}, 3: {'id': " │ │ │ │ │┄ "'79871109'}, 4: {'id': '70740279'}, 5: {'id': '0cace9d8'}, 6: {'id': 'f8d4b25b'}, 7: " │ │ │ │ │┄ "{'id': 'c92fa51b'}, 8: {'id': '4923517e'}, 9: {'id': '4c15ba1c'}, 10: {'id': " │ │ │ │ │┄ "'0ad4a5d9'}, 11: {'id': '3fbe22b4'}, 12: {'id': '3d0c8cc3'}, 13: {'id': '40eb0f0b'}, " │ │ │ │ │┄ "14: {'id': '4c6f1c3f'}, 15: {'id': '715fa6e6'}, 16: {'id': '346f822e'}, 17: {'id': " │ │ │ │ │┄ "'8c8fe12f'}, 1 […] │ │ │ │ │ @@ -1,12 +1,12 @@ │ │ │ │ │ { │ │ │ │ │ "cells": [ │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "9ef189cb", │ │ │ │ │ + "id": "afb57fd5", │ │ │ │ │ "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": "fed94f76", │ │ │ │ │ + "id": "ac31f364", │ │ │ │ │ "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": "92bea22f", │ │ │ │ │ + "id": "198545aa", │ │ │ │ │ "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": "61d86c19", │ │ │ │ │ + "id": "79871109", │ │ │ │ │ "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": "a2c7eb7c", │ │ │ │ │ + "id": "70740279", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "## Problem definition" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "24772a6e", │ │ │ │ │ + "id": "0cace9d8", │ │ │ │ │ "metadata": { │ │ │ │ │ "lines_to_next_cell": 2 │ │ │ │ │ }, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a {py:func}`box mesh`:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "69de18fe", │ │ │ │ │ + "id": "f8d4b25b", │ │ │ │ │ "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": "5757d04c", │ │ │ │ │ + "id": "c92fa51b", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a centripetal source term $f = \\rho \\omega^2 [x_0, \\, x_1]$:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "15b5441d", │ │ │ │ │ + "id": "4923517e", │ │ │ │ │ "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": "50fb1138", │ │ │ │ │ + "id": "4c15ba1c", │ │ │ │ │ "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": "c9713c55", │ │ │ │ │ + "id": "0ad4a5d9", │ │ │ │ │ "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": "a8eef437", │ │ │ │ │ + "id": "3fbe22b4", │ │ │ │ │ "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": "5a7f736d", │ │ │ │ │ + "id": "3d0c8cc3", │ │ │ │ │ "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": "6d15b374", │ │ │ │ │ + "id": "40eb0f0b", │ │ │ │ │ "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": "659c8938", │ │ │ │ │ + "id": "4c6f1c3f", │ │ │ │ │ "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": "ecf00805", │ │ │ │ │ + "id": "715fa6e6", │ │ │ │ │ "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": "d16df6d9", │ │ │ │ │ + "id": "346f822e", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "A = assemble_matrix(a, bcs=[bc])\n", │ │ │ │ │ "A.assemble()" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "cdbfcac5", │ │ │ │ │ + "id": "8c8fe12f", │ │ │ │ │ "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": "a6158bf0", │ │ │ │ │ + "id": "b97646c3", │ │ │ │ │ "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": "9220e284", │ │ │ │ │ + "id": "c67f7dc1", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create the near-nullspace and attach it to the PETSc matrix:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "7a9bb0a5", │ │ │ │ │ + "id": "a5d28478", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "ns = build_nullspace(V)\n", │ │ │ │ │ "A.setNearNullSpace(ns)\n", │ │ │ │ │ "A.setOption(PETSc.Mat.Option.SPD, True)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "3af22dbe", │ │ │ │ │ + "id": "f75b35a5", │ │ │ │ │ "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": "36109222", │ │ │ │ │ + "id": "e084418e", │ │ │ │ │ "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": "4130c3a1", │ │ │ │ │ + "id": "aab8a54f", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "source": [ │ │ │ │ │ "Create a solution {py:class}`Function` `uh` and\n", │ │ │ │ │ "solve:" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "code", │ │ │ │ │ "execution_count": null, │ │ │ │ │ - "id": "57c5a2d0", │ │ │ │ │ + "id": "5bb0ef5c", │ │ │ │ │ "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": "f450a9a2", │ │ │ │ │ + "id": "539c67d3", │ │ │ │ │ "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": "7ed3d960", │ │ │ │ │ + "id": "5e48330b", │ │ │ │ │ "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": "8e558091", │ │ │ │ │ + "id": "f24a977e", │ │ │ │ │ "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": "742b9736", │ │ │ │ │ + "id": "3edd1cb8", │ │ │ │ │ "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": "fd0a91f6", │ │ │ │ │ + "id": "a4aa3d58", │ │ │ │ │ "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": "45ce75b7", │ │ │ │ │ + "id": "1999aadf", │ │ │ │ │ "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": "8306d6f5", │ │ │ │ │ + "id": "e302002c", │ │ │ │ │ "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": "0fdb44a3", │ │ │ │ │ + "id": "1e075072", │ │ │ │ │ "metadata": {}, │ │ │ │ │ "outputs": [], │ │ │ │ │ "source": [ │ │ │ │ │ "unorm = la.norm(uh.x)\n", │ │ │ │ │ "if msh.comm.rank == 0:\n", │ │ │ │ │ " print(\"Solution vector norm:\", unorm)" │ │ │ │ │ ] │ │ │ │ │ }, │ │ │ │ │ { │ │ │ │ │ "cell_type": "markdown", │ │ │ │ │ - "id": "c8fd5ccc", │ │ │ │ │ + "id": "0827b1c8", │ │ │ │ │ "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)' 0x7fb5b5610000>
│ │ │ +MatSetValuesBlockedLocal = <cdata 'int(*)(void *, int32_t, int32_t *, int32_t, int32_t *, double *, int)' 0x7fa55c37b000> │ │ │

See PETSc MatSetValuesBlockedLocal │ │ │ documentation.

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

See PETSc MatSetValuesLocal │ │ │ documentation.

│ │ │
│ │ │ │ │ │
│ │ │
│ │ │ log = <nanobind.nb_func object>
│ │ │ ├── html2text {} │ │ │ │ @@ -532,18 +532,18 @@ │ │ │ │ DEBUG == 11_ │ │ │ │ ERROR == 44_ │ │ │ │ INFO == 22_ │ │ │ │ OFF == 66_ │ │ │ │ TRACE == 00_ │ │ │ │ WARNING == 33_ │ │ │ │ MatSetValuesBlockedLocal == <>_ │ │ │ │ + iinntt3322__tt,, iinntt3322__tt **,, ddoouubbllee **,, iinntt))'' 00xx77ffaa5555cc3377bb000000>>_ │ │ │ │ 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 == <>_ │ │ │ │ + iinntt3322__tt **,, ddoouubbllee **,, iinntt))'' 00xx77ffaa5555cc337700003300>>_ │ │ │ │ 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 {} │ │ │ │ @@ -5150,16 +5150,16 @@ │ │ │ │ "08": 12, │ │ │ │ "0e": [3, 5, 7, 17, 22, 23], │ │ │ │ "0e5": 16, │ │ │ │ "0e6": 26, │ │ │ │ "0e9": [7, 20], │ │ │ │ "0j": 9, │ │ │ │ "0th": 13, │ │ │ │ - "0x7fb5b5605030": 42, │ │ │ │ - "0x7fb5b5610000": 42, │ │ │ │ + "0x7fa55c370030": 42, │ │ │ │ + "0x7fa55c37b000": 42, │ │ │ │ "1": [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 26, 28, 29, 32, 34, 35, 36, 37, 40, 41, 42, 43, 44, 45, 46, 49, 50, 51, 56, 57], │ │ │ │ "10": [3, 5, 7, 13, 14, 16, 17, 18, 19, 20, 22, 25, 26, 55], │ │ │ │ "100": [3, 5, 14, 17, 22], │ │ │ │ "11": [3, 13, 14, 17, 58], │ │ │ │ "12": [3, 5, 6, 12, 14, 15, 17, 21, 22, 42, 49, 50], │ │ │ │ "13": 3, │ │ │ │ "139": 11,