Given to Functions u and v from the same FunctionSpace V, how do I merge the two (componentwise) to get a function in V*V?
Function
FunctionSpace
V*V
as_vector((u, v))
is UFL object that can be projected onto V*V or used in a different way.
Is there a way to avoid the projection? It seems unnecessary.
project
If you really need merged Function object then you probably won't avoid fiddling with DOFs. It won't be as difficult as it sounds using numpy Vector interface and helper functions in V.dofmap() and (V*V).dofmap(). If you need high efficiency you can write compiled module to do it with C++ Vector interface instead of numpy Vector interface.
Vector
V.dofmap()
(V*V).dofmap()
On the other hand if you just need to use the merged vector function in evaluations of forms, IO routines, plotting routines or whatever you can wrap two functions as members of vector Expression. In python:
Expression
class merge_functions(Expression): def __init__(self, u, v): self.u = u self.v = v def eval_cell(self, values, x, cell): self.u.eval_cell(values[0:1], x, cell) self.v.eval_cell(values[1:2], x, cell) def eval(self, values, x): self.u.eval(values[0:1], x) self.v.eval(values[1:2], x) def update(self): self.u.update() self.v.update() def value_shape(self): return (2,)
Similarly Expression.compute_vertex_values() can be overloaded for special applications. It is also pretty straightforward to rewrite this into C++. I can find (it is probably in dolfin/ale/MeshDisplacement.cpp) and post it if you're interested.
Expression.compute_vertex_values()
dolfin/ale/MeshDisplacement.cpp
Note: I have never tested overloading Expression.update() so I don't know if SWIG supports it. It is only relevant in parallel. If it din't work you would need to call merge_functions.u.update() and merge_functions.v.update() by hand. This is typically needed before assembler, VTKPlotter, IO routines start the job.
Expression.update()
merge_functions.u.update()
merge_functions.v.update()
There is also somehow halfway solution. Use Expression wrapper given above and interpolate. Maybe it save a day as projection is avoided. But still many restrict/eval calls are performed - not just DOFs copied.
interpolate
restrict
eval
There are no easy way to do this other than what jan proposed. There is a newly added, but long wanted, issue at bitbucket covering this limitation.