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!!