I broke it down to the following minimal example:
from fenics import *
import numpy as np
mesh = UnitSquareMesh(20, 20)
dx = Measure('dx', mesh)
V1 = FunctionSpace(mesh, 'CG', 1)
V2 = FunctionSpace(mesh, 'CG', 2)
boundaries = MeshFunction('size_t', mesh, dim=1)
left = CompiledSubDomain('near(x[0], 0)')
right = CompiledSubDomain('near(x[0], 1)')
top = CompiledSubDomain('near(x[1], 1)')
bottom = CompiledSubDomain('near(x[1], 0)')
left.mark(boundaries, 1)
right.mark(boundaries, 2)
top.mark(boundaries, 3)
bottom.mark(boundaries, 4)
bc1 = DirichletBC(V1, Constant(1), boundaries, 1)
bc2 = DirichletBC(V1, Constant(2), boundaries, 2)
bc3 = DirichletBC(V1, Constant(3), boundaries, 3)
bc4 = DirichletBC(V1, Constant(4), boundaries, 4)
bcs_list = [bc1, bc2, bc3, bc4]
def get_subdx(V, idx, ls):
if V.id()==idx:
return ls
if V.num_sub_spaces() > 1:
for i in range(V.num_sub_spaces()):
ans = get_subdx(V.sub(i), idx, ls + [i])
if ans is not None:
return ans
else:
return None
bcs_list_copy = [None for i in range(len(bcs_list))]
for i, bc in enumerate(bcs_list):
idx = bc.function_space().id()
subdx = get_subdx(V1, idx, ls=[])
W = V2
for num in subdx:
W = W.sub(num)
shape = W.ufl_element().value_shape()
try:
bcs_list_copy[i] = DirichletBC(W, bcs_list[i].value(), bc.domain_args[0], bc.domain_args[1])
except AttributeError:
bcs_list_copy[i] = DirichletBC(W, bcs_list[i].value(), bc.sub_domain)
u1 = Function(V1)
u2 = Function(V2)
[bc.apply(u1.vector()) for bc in bcs_list]
[bc.apply(u2.vector()) for bc in bcs_list_copy]
I hope that the code it obvious enough, I needed it to be more general purpose (with all possibilities for subspaces)
Could you perhaps tell me if this will work in all circumstances, i.e., if my assumption about the identifier .id() is correct?
Thanks.