Manipulating vector data of fem.Function

I am an experienced FEniCS user and a new FEniCSx user and am finally working on transitioning.

I am running into a strange issue where if I define a function

uh = dl.fem.Function(Vh)

I can then manipulate the underlying vector member data e.g., uh.vector.zeroEntries() or dl.fem.petsc.set_bc(uh.vector, bcs). However, if I define the vector directly as

uvec = dl.fem.Function(Vh).vector

and then try to manipulate it as before uvec.zeroEntries() or dl.fem.petsc.set_bc(uvec, bcs) errors are thrown, specifically I am now seeing the error free(): corrupted unsorted chunks. Any insight into why this is the case would be greatly appreciated. Any suggestions for how to define a vector that I could then use the dl.fem.petsc.set_bc function would be appreciated. Thanks in advance! See the full attached code.

import dolfinx as dl
from mpi4py import MPI
from petsc4py import PETSc
import numpy as np


comm = MPI.COMM_WORLD

# define the finite element mesh
n = 16
mesh = dl.mesh.create_unit_square(comm, n, n, dl.mesh.CellType.triangle)

# Define the finite element space V_h as the space of piecewise linear functions on the elements of the mesh.
degree = 1
Vh = dl.fem.FunctionSpace(mesh, ("CG", degree))

# ---- setup the boundary conditions
u_bc = dl.fem.Constant(mesh, PETSc.ScalarType(0.0))
facet_dim = mesh.topology.dim-1
facets_D = dl.mesh.locate_entities_boundary(mesh, dim=facet_dim, marker=lambda x: np.isclose(x[0], 0.0))
dofs_D = dl.fem.locate_dofs_topological(V=Vh, entity_dim=facet_dim, entities=facets_D)
bcs = [dl.fem.dirichletbc(u_bc, dofs_D, Vh)]

# ---- can apply boundary conditions as shown here
uh  = dl.fem.Function(Vh)
uh.vector.zeroEntries()
uh.interpolate(lambda x: x[0]*(x[0]-1)*x[1]*(x[1]-1))
dl.fem.petsc.set_bc(uh.vector, bcs)

# ---- error here 
uvec = dl.fem.Function(Vh).vector
uvec.zeroEntries()
#dl.fem.petsc.set_bc(uvec, bcs)

This behavior is not safe, as dolfinx.fem.Function(..).vector does provide a view into data stored in the dolfinx.fem.Function(Vh). This data (and the underlying vector) is deleted when dl.fem.Functon(Vh) goes out of scope, which is right away. (This is due to PETSc’s modern garbage collection (https://github.com/FEniCS/dolfinx/blob/main/python/dolfinx/fem/function.py#L288-L290, garbage collection different between petsc4py 3.17.4 and 3.18.3 (#1309) · Issues · PETSc / petsc · GitLab).
Thus, if you want to use the petsc-vector generated by a dolfinx.fem.Function, you need to do it in two steps:

u = dl.fem.Function(Vh)
uvec = u.vector

If you just want a petsc-vector (not wrapped as a DOLFINx function), you can use:
dolfinx.la.create_petsc_vector(Vh.dofmap.index_map, Vh.dofmap.index_map_bs)

1 Like

I see, if the Function goes out of scope then the vector member data is deleted by the garbage collector. Thanks for this helpful response.