Scale vector function by scalar function

Hi,

I want to scale vector-valued function with a scalar function. Since function spaces of those functions are different, I confused how can I implement that. Here is the MWE;

from dolfinx.fem import Function, FunctionSpace, Expression
from ufl import dx, VectorElement
from mpi4py import MPI
from dolfinx.mesh import create_unit_square

n_elem = 4
mesh= create_unit_square(MPI.COMM_WORLD, n_elem, n_elem)

V = FunctionSpace(mesh, ('CG',1))

f = Function(V)
f.interpolate(lambda x: x[0]**2)

v_cg = VectorElement("CG", mesh.ufl_cell(), 2)
Q = FunctionSpace(mesh, v_cg)

# I tried to interpolate f onto the vector function space;
f_vector = Function(Q)
f_expr = Expression(f, Q.element.interpolation_points())
f_vector.interpolate(f_expr) 

v = Function(Q)
v.interpolate(lambda x: (-x[1], x[0]))

result_vector = Function(Q)
result_vector.x.array[:] = v.x.array[:]/f_vector.x.array[:]

I get this error below;

File "/home/ee331/Dev/Venvs/v060/lib/python3.8/dist-packages/dolfinx/fem/function.py", line 361, in _
    self._cpp_object.interpolate(expr._cpp_object, cells)
RuntimeError: Function value size not equal to Expression value size

Any help would be much appreciated!

Consider the following:

from dolfinx.fem import Function, FunctionSpace, Expression
from ufl import dx, VectorElement
from mpi4py import MPI
from dolfinx.mesh import create_unit_square

n_elem = 4
mesh = create_unit_square(MPI.COMM_WORLD, n_elem, n_elem)

V = FunctionSpace(mesh, ('CG', 1))

f = Function(V)
f.interpolate(lambda x: x[0]**2)

v_cg = VectorElement("CG", mesh.ufl_cell(), 2)
Q = FunctionSpace(mesh, v_cg)

v = Function(Q)
v.interpolate(lambda x: (-x[1], x[0]))

vs = Function(Q)
vs.interpolate(Expression(v*f, Q.element.interpolation_points()))
print(vs.x.array)

or similarly:

vs.interpolate(Expression(v/f, Q.element.interpolation_points()))

If I want to normalize the magnitude of the vector-valued function, how should I scale that; I tried the following;

from dolfinx.fem import Function, FunctionSpace, Expression
from ufl import dx, VectorElement
from mpi4py import MPI
from dolfinx.mesh import create_unit_square
import numpy as np

n_elem = 4
mesh = create_unit_square(MPI.COMM_WORLD, n_elem, n_elem)

V = FunctionSpace(mesh, ('CG', 1))

f = Function(V)
f.interpolate(lambda x: x[0]**2)

v_cg = VectorElement("CG", mesh.ufl_cell(), 2)
Q = FunctionSpace(mesh, v_cg)

v = Function(Q)
v.interpolate(lambda x: (-x[1], x[0]))

vs = Function(Q)
vs.interpolate(Expression(v*(f), Q.element.interpolation_points()))

def normalize(mesh, vs):
    array = vs.x.array
    max_temp = mesh.comm.allreduce(np.amax(array), op=MPI.MAX)
    vs.x.array[:] = array/max_temp
    return vs

vs = normalize(mesh,vs)

# Visualize
from dolfinx.io import XDMFFile
xdmf = XDMFFile(mesh.comm, "vs.xdmf", "w")
xdmf.write_mesh(mesh)
xdmf.write_function(vs)

But it didn’t work. Where am I doing wrong?

This is not the magnitude of the vector valued function.
The magnitude is

mag = ufl.sqrt(vs[0]**2 + vs[1]**2)

and can be incorporated into the the dolfinx.fem.Expression above.
If you want the max magnitude of all entries, I would interpolate the magnitude into a suitable space, take it’s max value (with allreduce), and divide by it.

Many thanks, here is the code in case anyone needs it;

from dolfinx.fem import Function, FunctionSpace, Expression
from ufl import dx, VectorElement, sqrt
from mpi4py import MPI
from dolfinx.mesh import create_unit_square
import numpy as np

n_elem = 4
mesh = create_unit_square(MPI.COMM_WORLD, n_elem, n_elem)

V = FunctionSpace(mesh, ('CG', 1))

f = Function(V)
f.interpolate(lambda x: x[0]**2)

v_cg = VectorElement("CG", mesh.ufl_cell(), 2)
Q = FunctionSpace(mesh, v_cg)

v = Function(Q)
v.interpolate(lambda x: (-x[1], x[0]))

vs = Function(Q)
vs.interpolate(Expression(v*(f), Q.element.interpolation_points()))

def normalize(mesh, vs):
    array = vs.x.array
    mag = sqrt(vs[0]**2 + vs[1]**2)
    V = FunctionSpace(mesh,("CG", 2))
    vs_mag = Function(V)
    vs_mag.interpolate(Expression(mag, V.element.interpolation_points()))
    max_mag = mesh.comm.allreduce(np.amax(vs_mag.x.array), op=MPI.MAX)

    vs.x.array[:] = array/max_mag
    return vs

vs = normalize(mesh,vs)

# Visualize
from dolfinx.io import XDMFFile
xdmf = XDMFFile(mesh.comm, "vs.xdmf", "w")
xdmf.write_mesh(mesh)
xdmf.write_function(vs)