Skip to content

[BUG] The natural boundary condition is not working on the internal boundary #162

Description

@NengLu

The natural boundary condition is not working on the internal boundary.

Here is a simple test: uniform viscosity, 0 body force, traction boundary condition on internal boundary, no slip on other boundaries.

uw3

import underworld3 as uw
import numpy as np
import sympy
xmin, xmax = 0, 1
ymin, yint,ymax = 0,0.5,1
xres, yres = 32,32
yresa,yresb = 16,16
mesh = mesh = uw.meshing.BoxInternalBoundary(elementRes=(xres,yres),zelementRes=(yresa,yresb),minCoords=(xmin,ymin),maxCoords=(xmax, ymax),zintCoord=yint,degree=1,qdegree=2)
v = uw.discretisation.MeshVariable("V", mesh, mesh.dim, degree=2,continuous=True)
p = uw.discretisation.MeshVariable("P", mesh, 1, degree=1,continuous=True)
stokes = uw.systems.Stokes(mesh, velocityField=v, pressureField=p)
stokes.constitutive_model = uw.constitutive_models.ViscousFlowModel
stokes.bodyforce = sympy.Matrix([0., 0.])
stokes.constitutive_model.Parameters.shear_viscosity_0 = 1.0
stokes.saddle_preconditioner = 1.0 / stokes.constitutive_model.Parameters.shear_viscosity_0
for wall in ("Left", "Right", "Bottom", "Top"):
    stokes.add_essential_bc((0.0, 0.0), wall)
stokes.add_natural_bc(sympy.Matrix([1.0, 0.0]), "Internal")
stokes.tolerance = 1.0e-6
stokes.petsc_options["ksp_rtol"] = 1.0e-6
stokes.petsc_options["ksp_atol"] = 1.0e-6
stokes.petsc_options["snes_converged_reason"] = None
stokes.petsc_options["snes_monitor_short"] = None
stokes.solve(zero_init_guess=False)
print("u just below y=0.5:", uw.function.evaluate(v,np.array([0.5,0.499])))
print("u just above y=0.5:", uw.function.evaluate(v,np.array([0.5,0.501])))

The solver did not converge.

same case using FEniCS

from dolfin import *
import numpy as np
mesh = UnitSquareMesh(32, 32)
OUTER     = 1
INTERFACE = 2
boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0)
class OuterBoundary(SubDomain):
    def inside(self, x, on_boundary):
        return on_boundary
class Interface(SubDomain):
    def inside(self, x, on_boundary):
        return near(x[1], 0.5)   
OuterBoundary().mark(boundaries, OUTER)
Interface().mark(boundaries, INTERFACE)
dx  = Measure("dx",  domain=mesh)
#ds  = Measure("ds",  domain=mesh, subdomain_data=boundaries)  # exterior facets
dS  = Measure("dS",  domain=mesh, subdomain_data=boundaries)  # interior facets
P2 = VectorElement("P", mesh.ufl_cell(), 2)
P1 = FiniteElement("P", mesh.ufl_cell(), 1)
W  = FunctionSpace(mesh, MixedElement([P2, P1]))
(u, p) = TrialFunctions(W)
(v, q) = TestFunctions(W)
mu = Constant(1.0)
f  = Constant((0.0, 0.0))
def eps(u):
    return sym(grad(u))
a = (inner(2*mu*eps(u), eps(v))*dx
     - p*div(v)*dx
     - q*div(u)*dx )
L = inner(f, v)*dx
# Traction on interior interface y = 0.5 
t = Constant((1.0, 0.0))  # horizontal shear traction
L += dot(t, v('+')) * dS(INTERFACE)
# No-slip on outer boundary
bc_noslip = DirichletBC(W.sub(0), Constant((0.0, 0.0)), boundaries, OUTER)
# remove the null space
bc_pressure = DirichletBC(W.sub(1), Constant(0.0),"x[0] < DOLFIN_EPS && x[1] < DOLFIN_EPS","pointwise")
bcs = [bc_noslip, bc_pressure]
w = Function(W)
solve(a == L, w, bcs,
      solver_parameters={"linear_solver":  "mumps"})
(u_sol, p_sol) = w.split(deepcopy=True)
print("u just below y=0.5:", u_sol(0.5, 0.499))
print("u just above y=0.5:", u_sol(0.5, 0.501))

The output is:

u just below y=0.5: [5.65310750e-02 6.15222229e-09]
u just above y=0.5: [5.65310750e-02 6.15222231e-09]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions