The usage of the functions of dolfinx

When I was reading the tutorial, I found some codes without any comment. For example, in the code of the heat equation example.

# Update the right hand side reusing the initial vector
    with b.localForm() as loc_b:
        loc_b.set(0)
    assemble_vector(b, linear_form)

    # Apply Dirichlet boundary condition to the vector
    apply_lifting(b, [bilinear_form], [[bc]])
    b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE)
    set_bc(b, [bc])

    # Solve linear problem
    solver.solve(b, uh.vector)
    uh.x.scatter_forward()

What does the “localForm”, “ghostUpdate” and “scatter_forward” do ? When should I use them ? Where can I find the detailed documentation of these function ?

2 Likes

Ghost update and scatter forward is covered in
https://scientificcomputing.github.io/mpi-tutorial/notebooks/dolfinx_MPI_tutorial.html

localForm is a petsc4py function and is a way of accessing the part of a petsc vector on your process: petsc4py.PETSc._Vec_LocalForm also covered in Questions for Solving time-dependent problem - #2 by dokken

2 Likes

OK, Thanks.
I think it will be very helpful if these external documents are also included in the tutorial.

AA
Hello, I wonder if I correctly understantd these functions. Suppose that,
the red basis function is owned by process 1.
the green basis function is owned by process 2.
To calculate the contribution to the right hand side (rhs), we should know the informations of adjacent cells, which is stored on different processes. And these cells are called ghost cells. Fenics does not handle these automatically, we have to deal with these ghost cells manually.

b.local_Form() returns the local part of b, that is, a part of b that is owned by a process. By the way, can we just set b.array = 0 ? Does the code

with b.localForm() as loc_b:
        loc_b.set(0)

just reduce the computational cost ?
After we called

assemble_vector(b, linear_form)

the local part of b is calculated without considering the contributations from the ghost cells. So we need to use ghost_Update function

# Apply Dirichlet boundary condition to the vector
apply_lifting(b, [bilinear_form], [[bc]])
b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE)
set_bc(b, [bc])

This can be taken as a reverse operation of MPI.scatter. And we use set_bc because ghost_Update may destroy the dirichlet boundary condition?After we solve the linear system, we use scatter_forward, to let the ghost cells contain the correct values

# Solve linear problem
solver.solve(b, uh.vector)
uh.x.scatter_forward()

By the way, will the API of Fenics change a lot in the future? I tried the codes in some old tutorials and they can run, because the names of many functions or modules are changed.

This is petsc’s way of setting a local array to Zero. As DOLFINx has its own vector implementation, you can use u.x.array[:] = 0 to set all contributions (including Ghost dofs on the process to Zero).

DOLFINx does not ghost cells by default (you can set the ghost mode in mesh creation). It only ghosts degrees of freedom, facets, edges and vertices. See for instance chapter 6 and 7 (and the drawings therein) in: DOLFINx: The next generation FEniCS problem solving environment

assemble_vector will only loop over cells owned by the process. Thus it will create contributions for degrees of freedom not owned by the current process. These have to be accumulated (summed), which is why we call ghost-update add-values reverse after applying the lifting (which is a specific assembly command, see for instance: Application of Dirichlet boundary conditions — FEniCS Tutorial @ Sorbonne

Once you have accumulated the contributions on the process that owns the dofs, we set dirichlet bcs on those dofs owned by the process.
Finally, we scatter this information to the processes that has the ghosts before solving with a scatter forward.

After solving the linear system with PETSc, we have to send ghost values from their owning process to ghosting processes, as petsc doesnt do this by default.

The API of DOLFINx has been quite stable since v0.5.x/v0.6.x.
There will always be some API changes, as we keep on improving the software.