Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Implementation

import ufl
from dolfinx import mesh, fem, io, default_scalar_type, plot
from dolfinx.fem.petsc import LinearProblem
from mpi4py import MPI
import numpy as np
import basix
import pyvista
pyvista.set_jupyter_backend('static')

# Mesh
domain = mesh.create_unit_square(
    MPI.COMM_WORLD, 8, 8
)  # coarse to exaggerate oscillations

# Elements
order = 2
V_el = basix.ufl.element("BDM", domain.basix_cell(), order)  # flux q
P_el = basix.ufl.element("DG", domain.basix_cell(), order - 1)  # pressure p
W = fem.functionspace(domain, basix.ufl.mixed_element([V_el, P_el]))

(q, p) = ufl.TrialFunctions(W)
(q_, p_) = ufl.TestFunctions(W)

# Material
kappa = 1e-10  # very low permeability
mu_f = 1.0  # fluid viscosity


# Boundary conditions: pressure on left/right
def left(x):
    return np.isclose(x[0], 0.0)


def right(x):
    return np.isclose(x[0], 1.0)


def top(x):
    return np.isclose(x[1], 1.0)


def bottom(x):
    return np.isclose(x[1], 0.0)


left_facets = mesh.locate_entities_boundary(domain, 1, left)
right_facets = mesh.locate_entities_boundary(domain, 1, right)
top_facets = mesh.locate_entities_boundary(domain, 1, top)
bottom_facets = mesh.locate_entities_boundary(domain, 1, bottom)
Q, _ = W.sub(0).collapse()
top_dofs_q = fem.locate_dofs_topological((W.sub(0), Q), 1, top_facets)
bottom_dofs_q = fem.locate_dofs_topological((W.sub(0), Q), 1, bottom_facets)

bc_top = fem.dirichletbc(fem.Function(Q), top_dofs_q, W.sub(0))
bc_bottom = fem.dirichletbc(fem.Function(Q), bottom_dofs_q, W.sub(0))

facet_tags = mesh.meshtags(domain, 1, left_facets, np.full_like(left_facets, 1))
ds = ufl.Measure("ds", domain=domain, subdomain_data=facet_tags)

# Weak form (Darcy)
a = (
    ufl.inner((mu_f / kappa) * q, q_) * ufl.dx
    - ufl.inner(p, ufl.div(q_)) * ufl.dx
    + ufl.inner(ufl.div(q), p_) * ufl.dx
)
n = ufl.FacetNormal(domain)
L = -ufl.inner(fem.Constant(domain, default_scalar_type(2.0)), ufl.dot(q_, n)) * ds(1)

bcs = [bc_top, bc_bottom]

# Solve
problem = LinearProblem(a, L, bcs=bcs)
w = problem.solve()
CG1 = fem.functionspace(domain, ("CG", 1))
p_h = fem.Function(CG1, name="Pressure")
p_h.interpolate(w.sub(1).collapse())

pyvista.start_xvfb()
u_topology, u_cell_types, u_geometry = plot.vtk_mesh(CG1)
u_grid = pyvista.UnstructuredGrid(u_topology, u_cell_types, u_geometry)
u_grid.point_data["u"] = p_h.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()
u_plotter.show()
<PIL.Image.Image image mode=RGB size=1024x768>