This is a read only copy of the old FEniCS QA forum. Please visit the new QA forum to ask questions

Operations between mixedfunctionspace and functionspace

+1 vote

Hey! I have a big doubt!!

I have a MixedFunctionSpace, named ME, and I define a function on it and then I split it:

V = FunctionSpace(mesh,"Lagrange",1)
ME = MixedFunctionSpace([V,V,V])
u= Function(ME)
c, mu, n = split (u) 

Then I give an initial condition (or a value) to u with the class expression. If I define a function z on V, e.g. z= Function(V), and I initialize it with a value, can I make operations between z and c (for example) ?
For example, is it right to do something like

 X = Function(V)
dof_V=V.dofmap.dofs()
dof_ME = ME.sub(0).dofmap.dofs()
for i in range (0, len(dof_V))
     X.vector()[dof_V[i]] = u.vector()[dof_ME[i]] +  z.vector()[dof_V[i]]

Thanks a lot!
Cristina

asked Mar 19, 2015 by MCri FEniCS User (1,120 points)

1 Answer

0 votes

That's an interesting question! The following indeed seems to work:

from dolfin import *
mesh = UnitSquareMesh(8,8)

V = FunctionSpace(mesh,"Lagrange",1)
ME = MixedFunctionSpace([V,V,V])
u = Function(ME)
c, mu, n = u.split() 

z = Function(V)
z.interpolate(Expression("sin(x[0]*x[1])"))

plot(z)

dof_V=V.dofmap().dofs()
dof_ME = ME.sub(0).dofmap().dofs()

for i in range (0, len(dof_V)):
    u.vector()[dof_ME[i]] = float(z.vector()[dof_V[i]])

print "The error between c and z is "+str(errornorm(c,z))
plot(c)
interactive()

But I don't know whether this is really supported behavior of fenics.
In any case, it would be interesting to know whether there is a "cleaner" way to do this, i.e. without accessing the dofs directly. For example, I expected that

c.interpolate(z)

would work as well, but it doesn't...

answered Mar 20, 2015 by Gregor Mitscha-Baude FEniCS User (2,280 points)

You claim that Fenics is enough clever to rearrange the dofs between ME and V and thus I do not have to worry about it.. I hope! It would be great!

Hi, a cleaner way is to use the FunctionAssigner

# to ME0 from V
assigner0 = FunctionAssigner(ME.sub(0), V)
# assign to c function z
assigner0.assign(c, z)

Ok thanks.. but what I actually want to do is not a simple assigner between c and z (as Gregor has done) but I have a function z on V, a function x on V and a function u on ME, which is splitted in c, mu and n.
I need to define x as x = 2*c -z. How do I do this?
I think I have to work in ME since I need to solve a coupled system :

A1 = c*v*dx + dt * inner(grad(mu), grad(v))*dx 
A2 = c*w *dx + inner(grad(c),grad(w))*dx - mu *w*dx 

L1 = u0*v*dx + dt *inner(grad(mu0),grad(v))*dx 
L2 = x *w*dx   #here for example I use x, but it is define on V .. Is it right??? 

A = A1+ A2 
L = L1 + L2 

et cetera..

For your first question, assign c to some function cc in V and then do

x = 2*cc - z

which are just operations between functions in V.
For your second question, I don't think you have to change anything in the definition of the coupled system. For the linear forms, it is only the test funcions that have to come from the right function space. The coefficients, such as the x in your L2, can be basically "anything".

...