download
raw
6.2 kB
# ---
# jupyter:
# jupytext:
# formats: ipynb,py:light
# text_representation:
# extension: .py
# format_name: light
# format_version: '1.5'
# jupytext_version: 1.18.1
# kernelspec:
# display_name: Python 3 (ipykernel)
# language: python
# name: python3
# ---
# # Implementation
#
# Author: Jørgen Schartum Dokken
#
# This implementation is an adaptation of the work in {cite}`fundamentals-FenicsTutorial` to DOLFINx.
#
# In this section, you will learn:
# - How to use the built-in meshes in DOLFINx
# - How to create a spatially varying Dirichlet boundary conditions on the whole domain boundary
# - How to define a weak formulation of your PDE
# - How to solve the resulting system of linear equations
# - How to visualize the solution using a variety of tools
# - How to compute the $L^2(\Omega)$ error and the error at mesh vertices
# The Poisson problem has so far featured a general domain $\Omega$ and general functions $u_D$ for
# the boundary conditions and $f$ for the right hand side.
# Therefore, we need to make specific choices of $\Omega, u_D$ and $f$.
# A wise choice is to construct a problem with a known analytical solution,
# so that we can check that the computed solution is correct.
# The primary candidates are lower-order polynomials.
# The continuous Galerkin finite element spaces of degree $r$ will exactly reproduce polynomials of degree $r$.
# We use this fact to construct a quadratic function in $2D$. In particular we choose
#
# $$
# \begin{align}
# u_e(x,y)=1+x^2+2y^2
# \end{align}
# $$
#
# Inserting $u_e$ in the original boundary problem, we find that
#
# $$
# \begin{align}
# f(x,y)= -6,\qquad u_D(x,y)=u_e(x,y)=1+x^2+2y^2,
# \end{align}
# $$
#
# regardless of the shape of the domain as long as we prescribe
# $u_e$ on the boundary.
#
# For simplicity, we choose the domain to be a unit square $\Omega=[0,1]\times [0,1]$
# A major difference between a traditional FEniCS code and a FEniCSx code,
# is that one is not advised to use the wildcard import.
# ## Generating simple meshes
# The next step is to define the discrete domain, _the mesh_.
# We do this by importing one of the built-in mesh generators.
# We will build a {py:func}`unit square mesh<dolfinx.mesh.create_unit_square>`, i.e. a mesh spanning $[0,1]\times[0,1]$.
from mpi4py import MPI
from dolfinx import mesh
import numpy
domain = mesh.create_unit_square(MPI.COMM_WORLD, 8, 8, mesh.CellType.quadrilateral)
# ## Defining the finite element function space
# Once the mesh has been created, we can create the finite element function space $V$.
from dolfinx import fem
V = fem.functionspace(domain, ("Lagrange", 1))
# ## Dirichlet boundary conditions
# Next, we create a function that will hold the Dirichlet boundary data, and use interpolation to
# fill it with the appropriate data.
uD = fem.Function(V)
uD.interpolate(lambda x: 1 + x[0]**2 + 2 * x[1]**2)
# Identify boundary facets and create boundary condition
tdim = domain.topology.dim
fdim = tdim - 1
domain.topology.create_connectivity(fdim, tdim)
boundary_facets = mesh.exterior_facet_indices(domain.topology)
boundary_dofs = fem.locate_dofs_topological(V, fdim, boundary_facets)
bc = fem.dirichletbc(uD, boundary_dofs)
# ## Defining the trial and test function
import ufl
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
# ## Defining the source term
from dolfinx import default_scalar_type
f = fem.Constant(domain, default_scalar_type(-6))
# ## Defining the variational problem
a = ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx
L = f * v * ufl.dx
# ## Forming and solving the linear system
from dolfinx.fem.petsc import LinearProblem
problem = LinearProblem(
a,
L,
bcs=[bc],
petsc_options={"ksp_type": "preonly", "pc_type": "lu"},
petsc_options_prefix="Poisson",
)
uh = problem.solve()
# ## Computing the error
V2 = fem.functionspace(domain, ("Lagrange", 2))
uex = fem.Function(V2, name="u_exact")
uex.interpolate(lambda x: 1 + x[0]**2 + 2 * x[1]**2)
# Compute L2 error
L2_error = fem.form(ufl.inner(uh - uex, uh - uex) * ufl.dx)
error_local = fem.assemble_scalar(L2_error)
error_L2 = numpy.sqrt(domain.comm.allreduce(error_local, op=MPI.SUM))
# Compute max error
error_max = numpy.max(numpy.abs(uD.x.array - uh.x.array))
# Print errors
if domain.comm.rank == 0:
print(f"Error_L2 : {error_L2:.2e}")
print(f"Error_max : {error_max:.2e}")
# ## Plotting the mesh using pyvista
try:
import pyvista
from dolfinx import plot
domain.topology.create_connectivity(tdim, tdim)
topology, cell_types, geometry = plot.vtk_mesh(domain, tdim)
grid = pyvista.UnstructuredGrid(topology, cell_types, geometry)
plotter = pyvista.Plotter()
plotter.add_mesh(grid, show_edges=True)
plotter.view_xy()
if not pyvista.OFF_SCREEN:
plotter.show()
else:
figure = plotter.screenshot("fundamentals_mesh.png")
print("Mesh plot saved as fundamentals_mesh.png")
# Plot the solution
u_topology, u_cell_types, u_geometry = plot.vtk_mesh(V)
u_grid = pyvista.UnstructuredGrid(u_topology, u_cell_types, u_geometry)
u_grid.point_data["u"] = uh.x.array.real
u_grid.set_active_scalars("u")
u_plotter = pyvista.Plotter()
u_plotter.add_mesh(u_grid, show_edges=True)
u_plotter.view_xy()
if not pyvista.OFF_SCREEN:
u_plotter.show()
else:
u_plotter.screenshot("fundamentals_solution.png")
print("Solution plot saved as fundamentals_solution.png")
except ImportError:
print("PyVista not available for plotting")
# ## Save results for external post-processing
from dolfinx import io
from pathlib import Path
results_folder = Path("results")
results_folder.mkdir(exist_ok=True, parents=True)
filename = results_folder / "fundamentals"
# Save using VTXWriter
with io.VTXWriter(domain.comm, filename.with_suffix(".bp"), [uh]) as vtx:
vtx.write(0.0)
# Save using XDMFFile
with io.XDMFFile(domain.comm, filename.with_suffix(".xdmf"), "w") as xdmf:
xdmf.write_mesh(domain)
xdmf.write_function(uh)
if domain.comm.rank == 0:
print("Results saved to results/fundamentals.bp and results/fundamentals.xdmf")

Xet Storage Details

Size:
6.2 kB
·
Xet hash:
f0c65e9430971a42ee303d91377b682c7c18e96408a43a7776959b28149c0582

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.