With the following code in Fenics tutorial for NS equations,
with b1.localForm() as loc_1:
loc_1.set(0)
fem.petsc.assemble_vector(b1,L1)
fem.petsc.apply_lifting(b1,[a1],[bcu])
b1.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES,mode=PETSc.ScatterMode.REVERSE)
fem.petsc.set_bc(b1,bcu)
solver1.solver(b1,u_.vector)
u_.x.scatter_forward()
I have some questions:
1.What do localForm() and set(0) do?
2.Since we already use apply_lifting() to apply Dirichlet condition for vector b1, why do we still need to use set_bc for b1?And why should we update ghost points?I comment the “b1.ghost…” line but the computation result is the same.Is this corresponding with MPI.COMM_WORLD?
Apply lifting changes the vector to b1-= A1 g
where A1 is the matrix assembled by a1, g a vector were only having nonzero entries for the dofs. This adds contributions to all the other entries, where the bc is not set. You use set_bc to overwrite any entries with bc with the corresponding value from bcu.
Because whenever you assemble into a vector, you only assemble over cells/facets owned by the process. For dofs shared between processes, you need to add up contributions from all of them. See
for instance DOLFINx in Parallel with MPI — NewFrac FEniCSx Training
By this you mean dofs w.r.t boundary condtion or dofs w.r.t all nodes?And what is g?
I understand like this:
For example, after using a1=assemble_matrix(a1,bcs=bcu),assemble a1 will delete the row w.r.t boundary points?But b1=create_vector(L1) still considers boundary nodes and we use apply_lifting to take care of boundary conditions by subtracting boundary conditions from other dofs not corresponding with boundary points? So apply_lifting only changes dofs’ values w.r.t other dofs,not boundary dofs, while we use set_bc to change dofs w.r.t boundary terms?
This way what is the length of b1? Is its length equal to all dofs minus dofs w.r.t boundary conditions?
Imagine you have a boundary condition u=g_D on \partial \Omega_D. Then g is the setting described above is a Function in the function space of u, that is equal to g_D on all dofs on the prescribed boundary, and 0 at all other dofs.
No, a1=... will assemble a matrix of size (num_dofs x num_dofs), where all contributions from dofs in any boundary condition has been nulled out. I.e. any row or column corresponding to a bc-dof has only zeros. Then, it sets a 1 on the diagonal, making all bc rows an identity row.
b1 is of size num_dofs, and thus we use set_bc to enforce the boundary condition for those rows.