According to this tutorial, the general idea of how to post-process a solution is to leverage dolfinx.fem.Expression(). What I want to do with my solution is find the gradient of my solution, then split up that gradient into its orthogonal vector components pointed in the \hat{\textbf{i}} and \hat{\textbf{j}} directions, and lastly use them to make a vector plot (I’ll know if what I have is correct if the vectors point normal to the gradient).
So, I need to know
What expression will represent the gradient?
How to split up the gradient into its vectoral components?
If your solution uh is a scalar function living in CG1, its gradient is a vectorial function living in DG0. You should define such a space and then you can access its components through function.sub(0 or 1).collapse() like the following MWE:
import dolfinx as df
import ufl
from mpi4py import MPI
from dolfinx.fem.petsc import LinearProblem
# Create domain
domain = df.mesh.create_unit_square(MPI.COMM_WORLD, 10, 10, df.mesh.CellType.quadrilateral)
# Define (continuous) functionspace
V = df.fem.functionspace(domain, ("Lagrange", 1))
# Create facet to cell connectivity required to determine boundary facets
tdim = domain.topology.dim
fdim = tdim - 1
domain.topology.create_connectivity(fdim, tdim)
boundary_facets = df.mesh.exterior_facet_indices(domain.topology)
# Locate boundaries
boundary_dofs = df.fem.locate_dofs_topological(V, fdim, boundary_facets)
# Apply boundary conditions
bc = df.fem.dirichletbc(df.default_scalar_type(0), boundary_dofs, V)
# Define Trial and Test functions
u = ufl.TrialFunction(V)
v = ufl.TestFunction(V)
# Define source
f = df.fem.Constant(domain, df.default_scalar_type(4))
# Variational form
a = ufl.dot(ufl.grad(u), ufl.grad(v)) * ufl.dx
L = f * v * ufl.dx
problem = LinearProblem(a, L, bcs=[bc], petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
uh = problem.solve()
W = df.fem.functionspace(domain, ("DG", 0, (domain.topology.dim, )))
expr = df.fem.Expression(ufl.grad(uh),W.element.interpolation_points())
u_grad = df.fem.Function(W)
u_grad.interpolate(expr)
u_grad_x = u_grad.sub(0).collapse() # x component
print(u_grad_x.x.array)
u_grad_y = u_grad.sub(1).collapse() # y component
print(u_grad_y.x.array)
Oh that’s pretty cool! So there are ways to visualize the data with matplotlib. That’s useful to know for someone like me that is very much still a beginner with all of this, but has several years of experience with matplotlib.
Yep, that result looks right. Thanks for your help!