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

merge u, v into V*V

+3 votes

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?

asked Jul 9, 2013 by nschloe FEniCS User (7,120 points)

2 Answers

+1 vote
 
Best answer
as_vector((u, v))

is UFL object that can be projected onto V*V or used in a different way.

answered Jul 9, 2013 by Jan Blechta FEniCS Expert (51,420 points)
selected Jul 10, 2013 by nschloe

Is there a way to avoid the projection? It seems unnecessary.

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.

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:

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.

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.

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.

+2 votes

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.

answered Jul 10, 2013 by johanhake FEniCS Expert (22,480 points)
...