Fenicx - Set function DOF to specific values in a point-by-point fashion

Hi Fenics community,

I am trying to use Fenics in order to solve a Poisson problem with Robin boundary conditions.

I would like to be able to extract the coordinates associated to the DOFs, perform some computations externally and then re assign the values of the DOFS on my function or another function of the same functionspace.

I know it is possible to use the interpolate method for functions which depend on the coordinates of my domain but my intermediate calculations are quite large and I would prefer to do the calculations “externally” and then plug them again “point-by-point”, i.e, for each DOF of my functions.

Is this possible to do using Fenicsx? Is it possible to extract the coordinates following the same ordering of the DOFs so that I dont have to use expensive loops to assign the values on the DOFs? (i.e, preferably, I would just like to be able to do something like function.x.set(desired_values) in where desired_values is a vector ordered in the same ordering as the DOFs)

Thanks a lot for the feedback and help

Consider for instance:

from mpi4py import MPI
import dolfinx
import numpy as np

mesh = dolfinx.mesh.create_unit_square(MPI.COMM_WORLD, 20, 15, dolfinx.cpp.mesh.CellType.triangle)

V = dolfinx.fem.functionspace(mesh, ("Lagrange", 1))
u = dolfinx.fem.Function(V)
u.name = "u"
# Fill with some data
u.interpolate(lambda x: x[0])

#Get dof coordinates
coords = V.tabulate_dof_coordinates()
# Get dof values
vals = u.x.array.copy()

# Second function to insert data into
v = dolfinx.fem.Function(V)
v.name = "v"
def external_calculation(coords, vals):
    new_vals = np.zeros_like(vals)
    for i, (val, coord) in enumerate(zip(vals, coords)):
        new_vals[i] = val if np.linalg.norm(coord) < 0.6 else 0.1
    return new_vals

v.x.array[:] = external_calculation(coords, vals)
with dolfinx.io.XDMFFile(mesh.comm, "output.xdmf", "w") as xdmf:
    xdmf.write_mesh(mesh)
    xdmf.write_function(u)
    xdmf.write_function(v)