Update Dirichlet BC of the linear problem in dolfinx

I am solving a series of linear elastic boundary value problems in which all parameters are the same except for the dirichlet boundary conditions. Now I solved the problem using the following code:

    bcs = NFSer.dirichlet_face_nodes(direc=dv, all_fs=all_fs) # my dirichlet bc list
    a, L = NFSer.vari_forms(p_density=3.)    # Define the variational form
    for ni in node_i:
        bc = [bcs[2 + ni * 5 + i] for i in range(5)]
        bc += [bcs[0], bcs[1]]
        problem = dolfinx.fem.petsc.LinearProblem(a=a, L=L, bcs=bc, petsc_options={"ksp_type": "preonly", "pc_type": "lu"})
        u_sol = problem.solve()

In the code above, each BVP needs to recreate a linear problem using dolfinx.fem.petsc.LinearProblem. But in fact for each BVP it is only necessary to change the corresponding
So my question is, is there exists a way to just update the boundary conditions in the for loop, while the rest of the parameters remain the same? And make the program run more efficiently.

See for instance Application of Dirichlet boundary conditions — FEniCS Tutorial @ Sorbonne

Thank you for your suggestion! :pray: I have read the example of the lifting approach for solving BVPs. However, it seems that this method only speeds up the efficiency of the problem when the region where the Dirichlet boundary conditions are imposed is unchanged. Because the adjustment of the system of linear equations in this way is dependent on the boundary condition degrees of freedom. But for my problem, the value and its imposed region of the Dirichlet boundary condition are all different for each BVP associated with it. So, do you have any other suggestions for my question?

In other words, although the imposed region of the Dirichlet boundary condition is the same for each BVP, the ordering of the degrees of freedom in the list variable bc of above codes is different, which results in a different order of the degrees of freedom corresponding to the submatrix I and the vector u_bc in each BVP after the matrix A and the vector b are reordered. I don’t know if I stated my question clearly.

For example, all BVPs’ Dirichlet conditions are imposed on the same following rectangular region \Omega.
image
For BVP-1, the list variable bc for dirichlet object consist of \Omega_1 and \Omega\backslash\Omega_1.
For BVP-2, the list variable bc for dirichlet object consist of \Omega_2 and \Omega\backslash\Omega_2.
For BVP-1, the list variable bc for dirichlet object consist of \Omega_3 and \Omega\backslash\Omega_3.
For BVP-1, the list variable bc for dirichlet object consist of \Omega_4 and \Omega\backslash\Omega_4.
Althogh they all impose Dirichlet BC on \Omega, the dofs of them are diiferent, which results in the difference of A_{d,bc} and g.

Assemble the matrix A without BCs, and then copy it. The apply bcs to the copy of A using something along the lines of Application of Dirichlet boundary conditions — FEniCS Tutorial @ Sorbonne

I’m not sure I understand you correctly. I change my code to the following:

    a, L = NFSer.vari_forms(p_density=3.)    # Define the variational form
    bilinear_form = dolfinx.fem.form(a)
    linear_form = dolfinx.fem.form(L)

    u_sol = dolfinx.fem.Function(NFSer.func_space['V'], name='displacement')
    # Define a linear variational solver
    solver = petsc4py.PETSc.KSP().create(mesh.comm)
    solver.setType(petsc4py.PETSc.KSP.Type.PREONLY)
    solver.getPC().setType(petsc4py.PETSc.PC.Type.LU)
    # assemble_vector without dirichletbc
    b = dolfinx.fem.petsc.assemble_vector(linear_form)
    b.ghostUpdate(addv=petsc4py.PETSc.InsertMode.ADD_VALUES, mode=petsc4py.PETSc.ScatterMode.REVERSE)
    # assemble_matrix with Dirichlet conditions
    A = dolfinx.fem.petsc.assemble_matrix(bilinear_form)
    A.assemble()
    t1 = time.time()
    for ni in node_i:
        bc = [bcs[2 + ni * 5 + i] for i in range(5)]
        bc += [bcs[0], bcs[1]]
        for j in bc:
            dofs, _ = j._cpp_object.dof_indices()
            A.zeroRowsLocal(dofs, diag=1)
        solver.setOperators(A)
        # set bc, i.e set the degrees of freedom for known dofs
        dolfinx.fem.petsc.set_bc(b, bc)
        b.ghostUpdate(addv=petsc4py.PETSc.InsertMode.INSERT_VALUES, mode=petsc4py.PETSc.ScatterMode.FORWARD)
        # Solve linear problem
        solver.solve(b, u_sol.vector)
        u_sol.x.scatter_forward()
        u_sol.vector.ghostUpdate(addv=petsc4py.PETSc.InsertMode.INSERT_VALUES, mode=petsc4py.PETSc.ScatterMode.FORWARD)

But the efficiency of the program is not obvious, I guess it is because this line “A.zeroRowsLocal(dofs, diag=1)” program is more time-consuming. It would save a lot of time if the operations on A were done outside the for loop.
Always very grateful for the help you provide.

You cannot do all operations on A outside the loop, as you are changing what degrees of freedom that should be restricted to identity rows/cols inside the loop.

It is unclear to me how you could hoist this outside the loop.

Please judge if there is anything wrong with my understanding. If the dofs of Diricilet BC for each BVP can be reordered in the same, wouldn’t I just be able to perform an adjustment operation on A only once, i.e. move the operation on A outside the loop.

Yes, it the dof indices for every simulation is the same, you could define the matrix and application of bc just once.

However, as you stated above

The imposed region of the bc changes with each bvp, ie the dof indices would change as well.

Mr. dokken, I would like to follow up with one more question. How to utilize the piecewise function when applying Dirichlet boundary conditions?
For instance, for the above issues, dirichlet bc function reads:

\begin{equation} f(x)=\left \{\begin{array} g(x), x\in\Omega_1 \\ 0, x\in \Omega\backslash\Omega_1\end{array}\right. \end{equation}

How do I make it happen?

It’s probably simplier to split the boundary marker in two parts, corresponding to the two regions. In the first region assign the function value, in the second region assign the constant zero.

I see. Thank you. I am a beginner in finicsx, can you recommend me some references or learning materials?

The demos is a good place to start:
https://docs.fenicsproject.org/dolfinx/v0.7.3/python/demos.html
I’ve made various materials at:
https://jsdokken.com/dolfinx-tutorial/
https://jsdokken.com/fenics22-tutorial/intro.html
https://jsdokken.com/FEniCS23-tutorial/README.html
https://scientificcomputing.github.io/mpi-tutorial/notebooks/dolfinx_MPI_tutorial.html

Wow~that’s wonderful, Mr. dokken. Thank you so much~