Manipulate components of mixed functions

Given a mixed function space, how to manipulate the “coefficient array views” that underly the components of a function? I would like to do something like

a,b = u.split()
a.vector().set_local(...)  # only set the data that belongs to a
b.vector().get_local(...) # only get the data that belongs to b

But a.vector(), b.vector(), u.vector() all point to the same object:

from fenics import *
mesh = UnitIntervalMesh(10)
cell = mesh.ufl_cell()
el = MixedElement(
    FiniteElement("P", cell, 2),
    FiniteElement("P", cell, 1),
)
V = FunctionSpace(mesh, el)
u = Function(V)
a,b = u.split()
# these are the same vector:
assert id(a.vector()) == id(b.vector())
print(u.vector()) # <dolfin.cpp.la.PETScVector object at 0x7f6713c96f10>
print(a.vector()) # <dolfin.cpp.la.PETScVector object at 0x7f6713c96f10>

You’ll have to modify the following to work correctly in parallel, but here’s the gist of what you need to do:

from dolfin import *

mesh = UnitIntervalMesh(10)
cell = mesh.ufl_cell()
el = MixedElement(
    FiniteElement("P", cell, 2),
    FiniteElement("P", cell, 1),
)
V = FunctionSpace(mesh, el)

dm0 = V.sub(0).dofmap()
dm1 = V.sub(1).dofmap()

u = Function(V)
a_nodes = u.vector().vec()[dm0.dofs()]
b_nodes = u.vector().vec()[dm1.dofs()]

print(a_nodes)
print(b_nodes)
2 Likes

Ok thanks. That solves the “get” part of my problem, but not the “set” part as a_nodes is a copy. E.g.

a_nodes = u.vector().vec()[dm0.dofs()]
a_nodes[:] = range(100, 121)

assert all(u.vector().vec()[:] == 0)

Edit: Okay the following works

u.vector().vec()[dm0.dofs()] = range(100, 121)

Is that the way to go or is there something more convenient? I would prefer to have a “view” on
u[dm0.dofs()] instead of passing u and dm0.dofs() around.

If you do

a, b = u.split(deepcopy=True)

you can access and set the dof values of the individual functions with e.g.

b.vector()[0] = 1

Of course, since you now have seperate arrays, these changes are not done in the original function u.