Hello everyone,
I need some help to define a function in two different subdomains. The function F has four parameters which two of them are different in each subdomain. For example, at the subdomain dx(0), no = 1 nw =1. At the subdomain dx(1), no = 2 nw = 2. For the integrals across the subdomain, dx(0) and dx(1), it is easy.
However, I don’t know how to deal with ds and dS . For example, at the stabilization term bellow we have (F(s, mu, no, nw)("+") - un("-") * F(s, mu, no, nw)("-") ) * dS. So, how can I calculate two different F function (no and nw are different according the subdomain) between the elements interface at dx(0) and dx(1) or as in a shared boundary like the next figure.
In this code s, un, un_h, u and r are trial or test function; mu = 1 sbar = 1 are constants.
Any suggestions would be very helpful.
Summarized code:
un = 0.5 * (inner(u0, n) + sqrt(inner(u0, n) * inner(u0, n)))
un_h = 0.5 * (inner(u0, n) - sqrt(inner(u0, n) * inner(u0, n)))
def F(s, mu_rel, no, nw):
return s ** nw / (s ** nw + mu_rel * (1.0 - s) ** no)
stabilisation = dt("+") * inner(
jump(r), un("+") * F(s, mu, no, nw)("+") - un("-") * F(s, mu, no, nw)("-")
) * dS + dt * r * un_h * sbar * ds(1)
L3 = (
phi * r * (s - s0) * dx(0)
+ r * (s - s0) * dx(1)
- dt * inner(grad(r), F(s, mu, no, nw) * u) * dx(0)
- dt * inner(grad(r), F(s, mu, no, nw) * u) * dx(1)
+ dt * r * F(s, mu, no, nw) * un * ds
+ stabilisation
)
# Total L
L = L1 + L2 + L3
Entire code:
# Total mobility
def lmbdainv(s, mu_rel):
return 1.0 / ((1.0 / mu_rel) * s ** 2 + (1.0 - s) ** 2)
# Fractional flow function
def F(s, mu_rel, no, nw):
return s ** nw / (s ** no + mu_rel * (1.0 - s) ** nw)
class Obstacle(SubDomain):
def inside(self, x, on_boundary):
return between(x[1], (0.3, 0.7)) and between(x[0], (0.2, 0.6))
def tensor_jump(v, n):
return ufl.outer(v, n)("+") + ufl.outer(v, n)("-")
Kinv = Constant(1 / (k_matriz))
dt = Constant(0.5)
mu = 1
mu_b = 1
phi = Constant(0.4)
t = 0.0
T = 50 * float(dt)
mesh = UnitSquareMesh(Nx, Ny, "crossed")
n = FacetNormal(mesh)
order = 1
BDM = FiniteElement("BDM", mesh.ufl_cell(), order)
DG = FiniteElement("DG", mesh.ufl_cell(), order - 1)
Element = MixedElement([BDM, DG, DG])
mixed_space = FunctionSpace(mesh, Element)
# Function spaces and functions
V = TestFunction(mixed_space)
dU = TrialFunction(mixed_space)
U = Function(mixed_space)
U0 = Function(mixed_space)
v, q, r = split(V)
u, p, s = split(U)
u0, p0, s0 = split(U0)
s_mid = 0.5 * (s0 + s)
obstacle = Obstacle()
domains = MeshFunction("size_t", mesh, mesh.topology().dim())
domains.set_all(0)
obstacle.mark(domains, 1)
boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
left = AutoSubDomain(lambda x: near(x[0], 0.0))
right = AutoSubDomain(lambda x: near(x[0], 1.0))
bottom = AutoSubDomain(lambda x: near(x[1], 0.0))
top = AutoSubDomain(lambda x: near(x[1], 1.0))
# Define boundary markers
left.mark(boundaries, 1)
top.mark(boundaries, 2)
right.mark(boundaries, 3)
bottom.mark(boundaries, 4)
ds = Measure("ds", domain=mesh, subdomain_data=boundaries)
dx = Measure("dx", domain=mesh, subdomain_data=domains)
alpha = 35
h = CellDiameter(mesh)
h2 = ufl.Min(h("+"), h("-"))
stab = (
mu * (alpha / h2) * inner(tensor_jump(u, n), tensor_jump(v, n)) * dS
- mu * inner(avg(grad(u)), tensor_jump(v, n)) * dS
- mu * inner(avg(grad(v)), tensor_jump(u, n)) * dS
)
L1 = (
mu_b * inner(grad(u), grad(v)) * dx(1)
+ inner(v, lmbdainv(s_mid, mu) * Kinv * u) * dx(0)
- div(v) * p * dx(1)
- div(v) * p * dx(0)
# + pin * dot(v, n) * ds(1)
+ pout * dot(v, n) * ds(3)
+ stab
)
L2 = q * div(u) * dx(1) + q * div(u) * dx(0)
un = 0.5 * (inner(u0, n) + sqrt(inner(u0, n) * inner(u0, n)))
un_h = 0.5 * (inner(u0, n) - sqrt(inner(u0, n) * inner(u0, n)))
stabilisation = dt("+") * inner(
jump(r), un("+") * F(s_mid, mu, no, nw)("+") - un("-") * F(s_mid, mu, no, nw)("-")
) * dS + dt * r * un_h * sbar * ds(1)
L3 = (
phi * r * (s - s0) * dx(0)
+ r * (s - s0) * dx(1)
- dt * inner(grad(r), F(s_mid, mu, no, nw) * u) * dx(0)
- dt * inner(grad(r), F(s_mid, mu, no, nw) * u) * dx(1)
+ dt * r * F(s_mid, mu, no, nw) * un * ds
+ stabilisation
)
# Total L
L = L1 + L2 + L3
# Jacobian
J = derivative(L, U, dU)
problem = NonlinearVariationalProblem(L, U, bcs=bcs, J=J)
solver = NonlinearVariationalSolver(problem)
while t < T:
t += float(dt)
U0.assign(U)
solver.solve()
u, p, s = U.split()