Hi Community,
I am solving the 2D Stokes flow similar to what was done in this post. However, instead of having periodic BCs on all four boundaries, I am prescribing pressures on the inlet and outlet (x=-12 and x=24 in my case) and having periodic BCs on y=0 and y=12. Here’s my MWE modified from demo_stokes.py and several dolfinx_mpc demos:
from mpi4py import MPI
from petsc4py import PETSc
import numpy as np
import ufl
from basix.ufl import element, mixed_element
from dolfinx import fem, default_scalar_type
from dolfinx.fem import (Constant, Function, dirichletbc,form, functionspace,
locate_dofs_topological)
import dolfinx.fem.petsc
from dolfinx.mesh import CellType, create_rectangle, locate_entities, meshtags, locate_entities_boundary
from ufl import div, dx, ds, grad, inner, Measure, FacetNormal
# Define params
x_range = [-12,24]
y_range = [0,12]
p_in = 800
p_out = 0
mu = 3.6
# Create mesh
msh = create_rectangle(MPI.COMM_WORLD, [np.array([x_range[0], y_range[0]]), np.array([x_range[1], y_range[1]])],
[300, 100], CellType.triangle)
# Function to mark periodic boundaries
def periodic_boundary(x):
return np.isclose(x[1], y_range[1], atol=1e-8)
def periodic_relation(x):
out_x = np.zeros_like(x)
out_x[0] = x[0]
out_x[1] = y_range[1] - x[1]
#out_x[2] = x[2]
return out_x
# Function to mark the inflow
def inflow(x):
return np.isclose(x[0], x_range[0])
# Function to mark the outflow
def outflow(x):
return np.isclose(x[0], x_range[1])
boundaries = [(1, periodic_boundary),
(2, inflow),
(3, outflow)] # (boundary_marker, locator)
# We now loop through all the boundary conditions and create `MeshTags` identifying the facets for each boundary condition.
facet_indices, facet_markers = [], []
gdim = msh.topology.dim
fdim = gdim - 1
for (marker, locator) in boundaries:
facets = locate_entities(msh, fdim, locator)
facet_indices.append(facets)
facet_markers.append(np.full_like(facets, marker))
facet_indices = np.hstack(facet_indices).astype(np.int32)
facet_markers = np.hstack(facet_markers).astype(np.int32)
sorted_facets = np.argsort(facet_indices)
facet_tag = meshtags(msh, fdim, facet_indices[sorted_facets], facet_markers[sorted_facets])
msh.topology.create_connectivity(msh.topology.dim-1, msh.topology.dim)
"""
# Verify Boundaries
from dolfinx.io import XDMFFile
with XDMFFile(msh.comm, "facet_tags_verify.xdmf", "w") as xdmf:
xdmf.write_mesh(msh)
xdmf.write_meshtags(facet_tag, msh.geometry)
"""
# Define Surface Integral for Nuemann Conditions
ds = Measure("ds", domain=msh, subdomain_data=facet_tag)
# `P2` corresponds to a continuous piecewise quadratic basis (vector) and
# `P1` to a continuous piecewise linear basis (scalar).
P2 = element("Lagrange", msh.basix_cell(), 2, shape=(msh.geometry.dim,))
P1 = element("Lagrange", msh.basix_cell(), 1)
# Create the Taylor-Hood function space
TH = mixed_element([P2, P1])
W = functionspace(msh, TH)
W0, _ = W.sub(0).collapse()
# Pressures
pressure_in = Constant(msh,PETSc.ScalarType(p_in))
pressure_out = Constant(msh,PETSc.ScalarType(p_out))
# Collect Dirichlet boundary conditions
bcs = []
# Suface Normal
n = FacetNormal(msh)
# Define variational problem
(u, p) = ufl.TrialFunctions(W)
(v, q) = ufl.TestFunctions(W)
f = Function(W0)
a = form((mu*inner(grad(u), grad(v)) - inner(p, div(v)) + inner(div(u), q)) * dx)
L = form(inner(f, v) * dx - pressure_in * inner(n,v) * ds(2) - pressure_out * inner(n,v) * ds(3))
# Set BC with mpc
from dolfinx_mpc import LinearProblem, MultiPointConstraint
mpc = MultiPointConstraint(W)
mpc.create_periodic_constraint_topological(W.sub(0), facet_tag, 1, periodic_relation, bcs, default_scalar_type(1))
mpc.create_periodic_constraint_topological(W.sub(1), facet_tag, 1, periodic_relation, bcs, default_scalar_type(1))
mpc.finalize()
# Solve
problem = LinearProblem(a, L, mpc, bcs=bcs, petsc_options={
"ksp_type": "preonly", "pc_type": "lu", "pc_factor_mat_solver_type": "mumps"}) # define linear problem
U = problem.solve()
u, p = U.sub(0).collapse(), U.sub(1).collapse()
Here are the meshtags I saved to verify boundary:
And here are the results:
that do not really make sense to me. Am I doing something wrong? Thanks in advance!