def F_nest(self, snes, x, F): assert x.getType() == "nest" and F.getType() == "nest" # Update solution x = x.getNestSubVecs() for x_sub, var_sub in zip(x, self.soln_vars): x_sub.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) with x_sub.localForm() as _x: var_sub.x.array[:] = _x.array_r # Assemble bcs1 = bcs_by_block(extract_function_spaces(self.a, 1), self.bcs) for L, F_sub, a in zip(self.L, F.getNestSubVecs(), self.a): with F_sub.localForm() as F_sub_local: F_sub_local.set(0.0) assemble_vector(F_sub, L) apply_lifting(F_sub, a, bcs=bcs1, x0=x, scale=-1.0) F_sub.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # Set bc value in RHS bcs0 = bcs_by_block(extract_function_spaces(self.L), self.bcs) for F_sub, bc, x_sub in zip(F.getNestSubVecs(), bcs0, x): set_bc(F_sub, bc, x_sub, -1.0) # Must assemble F here in the case of nest matrices F.assemble()
def test_extract_forms(): """Test extraction on unique function spaces for rows and columns of a block system""" mesh = create_unit_square(MPI.COMM_WORLD, 32, 31) V0 = FunctionSpace(mesh, ("Lagrange", 1)) V1 = FunctionSpace(mesh, ("Lagrange", 2)) V2 = V0.clone() V3 = V1.clone() v0, u0 = TestFunction(V0), TrialFunction(V0) v1, u1 = TestFunction(V1), TrialFunction(V1) v2, u2 = TestFunction(V2), TrialFunction(V2) v3, u3 = TestFunction(V3), TrialFunction(V3) a = form([[inner(u0, v0) * dx, inner(u1, v1) * dx], [inner(u2, v2) * dx, inner(u3, v3) * dx]]) with pytest.raises(AssertionError): extract_function_spaces(a, 0) with pytest.raises(AssertionError): extract_function_spaces(a, 1) a = form([[inner(u0, v0) * dx, inner(u2, v1) * dx], [inner(u0, v2) * dx, inner(u2, v2) * dx]]) with pytest.raises(AssertionError): extract_function_spaces(a, 0) Vc = extract_function_spaces(a, 1) assert Vc[0] is V0._cpp_object assert Vc[1] is V2._cpp_object a = form([[inner(u0, v0) * dx, inner(u1, v0) * dx], [inner(u2, v1) * dx, inner(u3, v1) * dx]]) Vr = extract_function_spaces(a, 0) assert Vr[0] is V0._cpp_object assert Vr[1] is V1._cpp_object with pytest.raises(AssertionError): extract_function_spaces(a, 1)
def nested_solve(): """Nested solver""" A = assemble_matrix_nest(form([[a00, a01], [a10, a11]]), bcs=[bc0, bc1], mat_types=[["baij", "aij"], ["aij", ""]]) A.assemble() P = assemble_matrix_nest(form([[p00, p01], [p10, p11]]), bcs=[bc0, bc1], mat_types=[["aij", "aij"], ["aij", ""]]) P.assemble() b = assemble_vector_nest(form([L0, L1])) apply_lifting_nest(b, form([[a00, a01], [a10, a11]]), [bc0, bc1]) for b_sub in b.getNestSubVecs(): b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) bcs = bcs_by_block(extract_function_spaces(form([L0, L1])), [bc0, bc1]) set_bc_nest(b, bcs) b.assemble() ksp = PETSc.KSP() ksp.create(mesh.comm) ksp.setOperators(A, P) nested_IS = P.getNestISs() ksp.setType("minres") pc = ksp.getPC() pc.setType("fieldsplit") pc.setFieldSplitIS(["u", nested_IS[0][0]], ["p", nested_IS[1][1]]) ksp_u, ksp_p = pc.getFieldSplitSubKSP() ksp_u.setType("preonly") ksp_u.getPC().setType('lu') ksp_p.setType("preonly") def monitor(ksp, its, rnorm): # print("Num it, rnorm:", its, rnorm) pass ksp.setTolerances(rtol=1.0e-8, max_it=50) ksp.setMonitor(monitor) ksp.setFromOptions() x = b.copy() ksp.solve(b, x) assert ksp.getConvergedReason() > 0 return b.norm(), x.norm(), nest_matrix_norm(A), nest_matrix_norm(P)
# Next, the right-hand side vector is assembled and then modified to # account for non-homogeneous Dirichlet boundary conditions: # + b = fem.petsc.assemble_vector_nest(L) # Modify ('lift') the RHS for Dirichlet boundary conditions fem.petsc.apply_lifting_nest(b, a, bcs=bcs) # Sum contributions from ghost entries on the owner for b_sub in b.getNestSubVecs(): b_sub.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # Set Dirichlet boundary condition values in the RHS bcs0 = fem.bcs_by_block(extract_function_spaces(L), bcs) fem.petsc.set_bc_nest(b, bcs0) # - # Ths pressure field for this problem is determined only up to a # constant. We can supply the vector that spans the nullspace and any # component of the solution in this direction will be eliminated during # the iterative linear solution process. # + # Create nullspace vector null_vec = fem.petsc.create_vector_nest(L) # Set velocity part to zero and the pressure part to a non-zero constant null_vecs = null_vec.getNestSubVecs() null_vecs[0].set(0.0), null_vecs[1].set(1.0)