In-place update of coefficients/functions values appearing in bilinear form

Hello there Fenicsx community,

I would like to know if there is any possible way to update values for Functions in place without having to obtain a new linear system once I change the values of these functions. Let me provide a bit of more context.

I have the following UFL expression:

self.F = -self.c11*inner(grad(self.m1_fem), grad(self.test_v))*dx + ((1-self.alpha)/(self.alpha)) * inner(self.m1_fem, self.test_v) * ds + ((1-self.alpha) / (self.alpha)) * inner(self.b1, self.test_v) * ds - self.c12 * inner(grad(self.m2_prev), grad(self.test_v))*dx + inner(self.r1, grad(self.test_v))*dx

In this case m1_fem is a TrialFunction and test_v is a TestFunction. The rest of coefficients/functions appearing in the UFL expression are defined as Functions in the following way:

self.V = functionspace(domain, ("Lagrange", 2))

self.m1_fem = TrialFunction(self.V)
self.m2_fem = TrialFunction(self.V)
self.test_v = TestFunction(self.V)

self.c11 = dolfinx.fem.Function(self.V)
self.b1 = dolfinx.fem.Function(self.V)
self.c12 = dolfinx.fem.Function(self.V)
self.c22 = dolfinx.fem.Function(self.V)
self.b2 = dolfinx.fem.Function(self.V)

self.m2_prev = dolfinx.fem.Function(self.V)
self.m1_prev = dolfinx.fem.Function(self.V)

self.r12_comp = dolfinx.fem.Function(self.V)
self.r11_comp = dolfinx.fem.Function(self.V)
self.r13_comp = dolfinx.fem.Function(self.V)

self.r22_comp = dolfinx.fem.Function(self.V)
self.r21_comp = dolfinx.fem.Function(self.V)
self.r23_comp = dolfinx.fem.Function(self.V)

self.r1 = as_vector((self.r11_comp, self.r12_comp, self.r13_comp))
self.r2 = as_vector((self.r21_comp, self.r22_comp, self.r23_comp))

I then assign values to all of these Functions using: (The values are just standard numpy arrays that I compute separately)

self.m2_prev.x.array[:] = self.m2_iter             
self.c11.x.array[:] = self.c11_val                 
self.b1.x.array[:] = self.b_array[:, 0, 0]         
self.c12.x.array[:] = self.c1_d_c2_val             
                                                   
self.r11_comp.x.array[:] = self.r11                
self.r12_comp.x.array[:] = self.r12                
self.r13_comp.x.array[:] = np.zeros(self.r11.shape)

Finally, I assemble the linear system and solve as:

a = lhs(self.F)                                                 
L = rhs(self.F)                                                 
                                                                
problem = LinearProblem(a, L, bcs=[], petsc_options={           
                        "ksp_type": "preonly", "pc_type": "lu"})
                                                                
m1_h = problem.solve()                                          
                                                                
self.m1_iter = m1_h.x.array                                     

For a single evaluation this works nicely but I was wondering what should I do if I need to solve this system as part of an iterative algorithm. In my case, I need to solve the same problem on each iteration but the important things is that: the value of all of the functions involved in the UFL expression need to be updated (Most of the things that are defined as Functions).

Is there any way that I can update these values in-place and avoid all of the logic associated to the construction of the sparse matrix? (Something like lazy-operations in where all values are replaced in place in the sparse-matrix logic and the RHS vector).

In advance, thanks a lot for the comments and feedback!!

See:

which shows how to avoid having to recreate any structures. You can update the functions by interpolation, or direct manipulation (of coefficient u) of u.x.array

1 Like

Thanks a lot!

Exactly what I was looking for.

Again thanks!